clutil 2014.304.0 → 2014.304.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/cl/util/clqsend.rb +54 -0
- data/cl/util/console.rb +27 -0
- data/cl/util/decide.rb +69 -0
- data/cl/util/dirsize.rb +112 -0
- data/cl/util/file.rb +280 -0
- data/cl/util/install.rb +84 -0
- data/cl/util/install.util.rb +34 -0
- data/cl/util/net.rb +35 -0
- data/cl/util/progress.rb +71 -0
- data/cl/util/smtp.rb +138 -0
- data/cl/util/string.rb +38 -0
- data/cl/util/test.rb +56 -0
- data/cl/util/time.rb +35 -0
- data/cl/util/win.rb +318 -0
- metadata +18 -4
data/cl/util/time.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class Time
|
4
|
+
DAY = (60 * 60 * 24)
|
5
|
+
|
6
|
+
def days_ago(days)
|
7
|
+
self - (DAY * days)
|
8
|
+
end
|
9
|
+
|
10
|
+
def days_ahead(days)
|
11
|
+
days_ago(-days)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Date
|
16
|
+
def days_ago(days)
|
17
|
+
self - days
|
18
|
+
end
|
19
|
+
|
20
|
+
def days_ahead(days)
|
21
|
+
days_ago(-days)
|
22
|
+
end
|
23
|
+
|
24
|
+
def years_ago(years)
|
25
|
+
self << (12 * years)
|
26
|
+
end
|
27
|
+
|
28
|
+
def years_ahead(years)
|
29
|
+
years_ago(-years)
|
30
|
+
end
|
31
|
+
|
32
|
+
def mdy
|
33
|
+
"#{month}/#{day}/#{year}"
|
34
|
+
end
|
35
|
+
end
|
data/cl/util/win.rb
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'Win32API'
|
2
|
+
require 'win32ole'
|
3
|
+
require File.dirname(__FILE__) + '/file'
|
4
|
+
|
5
|
+
# MENON Jean-Francois [Jean-Francois.MENON@meteo.fr]
|
6
|
+
# http://ruby-talk.com/41583
|
7
|
+
# But I see two potential problems that make not consistent with the
|
8
|
+
# original ruby command:
|
9
|
+
# 1) it takes only one argument
|
10
|
+
|
11
|
+
# code by Hee-Sob Park - posted here:
|
12
|
+
# http://ruby-talk.com/10006
|
13
|
+
def system(command)
|
14
|
+
# 2) it always set "$?" variable to false - should be working now...
|
15
|
+
|
16
|
+
# not allowed to set $?
|
17
|
+
# $? = Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
|
18
|
+
# $? == 0
|
19
|
+
|
20
|
+
# http://msdn.microsoft.com/library/en-us/vccore98/html/_crt_system.2c_._wsystem.asp
|
21
|
+
Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
|
22
|
+
end
|
23
|
+
|
24
|
+
# the system cmd in MSVC built ruby does not set $?, so no access to
|
25
|
+
# the exit code can be had. The following works, but is obtuse enough
|
26
|
+
# for me to encapsulate in this method.
|
27
|
+
# Bit slightly modified from - nobu http://ruby-talk.com/76086
|
28
|
+
def system_return_exitcode(cmd)
|
29
|
+
exitcode = nil
|
30
|
+
IO.popen(cmd) { |f|
|
31
|
+
# must bit shift by 8 to get the error code
|
32
|
+
exitcode = Process.waitpid2(f.pid)[1] >> 8
|
33
|
+
}
|
34
|
+
return exitcode
|
35
|
+
end
|
36
|
+
|
37
|
+
# MENON Jean-Francois [Jean-Francois.MENON@meteo.fr]
|
38
|
+
# http://ruby-talk.com/41583
|
39
|
+
# But I see two potential problems that make not consistent with the
|
40
|
+
# original ruby command:
|
41
|
+
# 1) it always set "$?" variable to false
|
42
|
+
|
43
|
+
# code by Hee-Sob Park - posted here:
|
44
|
+
# http://ruby-talk.com/10006
|
45
|
+
def `(command)
|
46
|
+
# http://msdn.microsoft.com/library/en-us/vccore98/HTML/_crt__popen.2c_._wpopen.asp
|
47
|
+
popen = Win32API.new("crtdll", "_popen", ['P','P'], 'L')
|
48
|
+
pclose = Win32API.new("crtdll", "_pclose", ['L'], 'L')
|
49
|
+
fread = Win32API.new("crtdll", "fread", ['P','L','L','L'], 'L')
|
50
|
+
feof = Win32API.new("crtdll", "feof", ['L'], 'L')
|
51
|
+
saved_stdout = $stdout.clone
|
52
|
+
psBuffer = " " * 128
|
53
|
+
rBuffer = ""
|
54
|
+
f = popen.Call(command,"r")
|
55
|
+
while feof.Call( f )==0
|
56
|
+
l = fread.Call( psBuffer,1,128,f )
|
57
|
+
# fix emailed direct to me from Park from 10006 code
|
58
|
+
# was:
|
59
|
+
# rBuffer += psBuffer[0..l]
|
60
|
+
rBuffer += psBuffer[0...l]
|
61
|
+
end
|
62
|
+
pclose.Call f
|
63
|
+
$stdout.reopen(saved_stdout)
|
64
|
+
rBuffer
|
65
|
+
end
|
66
|
+
|
67
|
+
P_WAIT = 0
|
68
|
+
P_NOWAIT = 1
|
69
|
+
OLD_P_OVERLAY = 2
|
70
|
+
P_NOWAITO = 3
|
71
|
+
P_DETACH = 4
|
72
|
+
|
73
|
+
def async_system(command)
|
74
|
+
# http://msdn.microsoft.com/library/en-us/vccore98/html/_crt__spawnv.2c_._wspawnv.asp
|
75
|
+
# this is working -- but frequently Segfaults ruby 1.6.6 mswin32
|
76
|
+
|
77
|
+
spawn = Win32API.new("crtdll", "_spawnvp", ['I', 'P', 'P'] ,'L')
|
78
|
+
res = spawn.Call(P_NOWAIT, command, '')
|
79
|
+
if res == -1
|
80
|
+
Win32API.new("crtdll", "perror", ['P'], 'V').call('async_system')
|
81
|
+
end
|
82
|
+
res
|
83
|
+
end
|
84
|
+
|
85
|
+
# from WinBase.h in SDK
|
86
|
+
# dwCreationFlag values
|
87
|
+
NORMAL_PRIORITY_CLASS = 0x00000020
|
88
|
+
|
89
|
+
STARTUP_INFO_SIZE = 68
|
90
|
+
PROCESS_INFO_SIZE = 16
|
91
|
+
|
92
|
+
def create_process(command)
|
93
|
+
# from WinBase.h in SDK
|
94
|
+
# Passing nil for a pointer -- I've seen it work with a P type param and
|
95
|
+
# an empty string ... here L with a 0 is the only way that works with
|
96
|
+
# CreateProcess. (see FormatMessage in raise_last_win32_error for an
|
97
|
+
# example of 'P' and '' that works)
|
98
|
+
params = [
|
99
|
+
'L', # IN LPCSTR lpApplicationName
|
100
|
+
'P', # IN LPSTR lpCommandLine
|
101
|
+
'L', # IN LPSECURITY_ATTRIBUTES lpProcessAttributes
|
102
|
+
'L', # IN LPSECURITY_ATTRIBUTES lpThreadAttributes
|
103
|
+
'L', # IN BOOL bInheritHandles
|
104
|
+
'L', # IN DWORD dwCreationFlags
|
105
|
+
'L', # IN LPVOID lpEnvironment
|
106
|
+
'L', # IN LPCSTR lpCurrentDirectory
|
107
|
+
'P', # IN LPSTARTUPINFOA lpStartupInfo
|
108
|
+
'P' # OUT LPPROCESS_INFORMATION lpProcessInformation
|
109
|
+
]
|
110
|
+
returnValue = 'I' # BOOL
|
111
|
+
|
112
|
+
startupInfo = [STARTUP_INFO_SIZE].pack('I') + ([0].pack('I') * (STARTUP_INFO_SIZE - 4))
|
113
|
+
processInfo = [0].pack('I') * PROCESS_INFO_SIZE
|
114
|
+
createProcess = Win32API.new("kernel32", "CreateProcess", params, returnValue)
|
115
|
+
if createProcess.call(0, command, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0,
|
116
|
+
startupInfo, processInfo) == 0
|
117
|
+
raise_last_win_32_error
|
118
|
+
end
|
119
|
+
processInfo
|
120
|
+
end
|
121
|
+
|
122
|
+
ERROR_SUCCESS = 0x00
|
123
|
+
FORMAT_MESSAGE_FROM_SYSTEM = 0x1000
|
124
|
+
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000
|
125
|
+
|
126
|
+
def raise_last_win_32_error
|
127
|
+
errorCode = Win32API.new("kernel32", "GetLastError", [], 'L').call
|
128
|
+
if errorCode != ERROR_SUCCESS
|
129
|
+
params = [
|
130
|
+
'L', # IN DWORD dwFlags,
|
131
|
+
'P', # IN LPCVOID lpSource,
|
132
|
+
'L', # IN DWORD dwMessageId,
|
133
|
+
'L', # IN DWORD dwLanguageId,
|
134
|
+
'P', # OUT LPSTR lpBuffer,
|
135
|
+
'L', # IN DWORD nSize,
|
136
|
+
'P', # IN va_list *Arguments
|
137
|
+
]
|
138
|
+
|
139
|
+
formatMessage = Win32API.new("kernel32", "FormatMessage", params, 'L')
|
140
|
+
msg = ' ' * 255
|
141
|
+
msgLength = formatMessage.call(FORMAT_MESSAGE_FROM_SYSTEM +
|
142
|
+
FORMAT_MESSAGE_ARGUMENT_ARRAY, '', errorCode, 0, msg, 255, '')
|
143
|
+
msg.gsub!("\\000", '')
|
144
|
+
msg.strip!
|
145
|
+
raise msg
|
146
|
+
else
|
147
|
+
raise 'GetLastError returned ERROR_SUCCESS'
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class ClUtilWinErr < Exception
|
152
|
+
end
|
153
|
+
|
154
|
+
class << File
|
155
|
+
alias o_delete delete
|
156
|
+
|
157
|
+
def win_api_delete(filename)
|
158
|
+
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/filesio_5n8l.asp
|
159
|
+
# BOOL DeleteFile(
|
160
|
+
# LPCTSTR lpFileName // file name
|
161
|
+
# );
|
162
|
+
|
163
|
+
# delete file if not read only
|
164
|
+
fdelete = Win32API.new("kernel32", "DeleteFile", ["P"], "I")
|
165
|
+
fdelete.Call(filename) != 0
|
166
|
+
end
|
167
|
+
|
168
|
+
# def recycle
|
169
|
+
# function SHFileOperation(const lpFileOp: TSHFileOpStruct): Integer; stdcall;
|
170
|
+
# TSHFileOpStruct = packed record
|
171
|
+
# Wnd: HWND; // HWND = type LongWord; Longword 0..4294967295 unsigned 32-bit
|
172
|
+
# wFunc: UINT; // UINT = LongWord;
|
173
|
+
# pFrom: PWideChar; // pointer to unicode string
|
174
|
+
# pTo: PWideChar;
|
175
|
+
# fFlags: FILEOP_FLAGS; // FILEOP_FLAGS = Word; Word 0..65535 unsigned 16-bit
|
176
|
+
# fAnyOperationsAborted: BOOL; // BOOL = LongBool; a LongBool variable occupies four bytes (two words).
|
177
|
+
# hNameMappings: Pointer;
|
178
|
+
# lpszProgressTitle: PWideChar; { only used if FOF_SIMPLEPROGRESS }
|
179
|
+
# end;
|
180
|
+
|
181
|
+
# http://msdn.microsoft.com/en-us/shellcc/platform/shell/reference/structures/shfileopstruct.asp
|
182
|
+
# see FOF_ALLOWUNDO, specifically
|
183
|
+
# end
|
184
|
+
|
185
|
+
def win_file_ro?(filename)
|
186
|
+
fFILE_ATTRIBUTE_READONLY = 0x1
|
187
|
+
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/filesio_9pgz.asp
|
188
|
+
# DWORD GetFileAttributes(
|
189
|
+
# LPCTSTR lpFileName // name of file or directory
|
190
|
+
# );
|
191
|
+
fgetattr = Win32API.new("kernel32", "GetFileAttributes", ["P"], "N")
|
192
|
+
fattr = fgetattr.Call(filename)
|
193
|
+
(fattr & fFILE_ATTRIBUTE_READONLY) != 0
|
194
|
+
end
|
195
|
+
|
196
|
+
def delete(*files)
|
197
|
+
files.flatten!
|
198
|
+
files.each do |file|
|
199
|
+
if !win_file_ro?(file)
|
200
|
+
win_api_delete(file)
|
201
|
+
else
|
202
|
+
raise ClUtilWinErr.new(file + ' is read only, cannot delete. Use File.delete_all')
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# I wanted to add a second param to delete, called deleteReadOnly with
|
208
|
+
# a default value of false but (a) I can't have a default value param
|
209
|
+
# after the *files param because (b) I can't have any non *param after
|
210
|
+
# the *files param. So, my compromise was a separate method
|
211
|
+
|
212
|
+
# I have no idea why I'm doing an api specific call here.
|
213
|
+
# I think when I started this journey, I thought the API
|
214
|
+
# call would delete read-only files, then when I learned
|
215
|
+
# it wouldn't, I forgot my original purpose and just
|
216
|
+
# worked around it. It's silly now -- I've moved delete_all
|
217
|
+
# to cl/util/file.rb which is a pure Ruby implementation
|
218
|
+
# of this one.
|
219
|
+
|
220
|
+
#def delete_all(*files)
|
221
|
+
# files.flatten!
|
222
|
+
# files.each do |file|
|
223
|
+
# # make writable to allow deletion
|
224
|
+
# File.chmod(0644, file)
|
225
|
+
# win_api_delete(file)
|
226
|
+
# end
|
227
|
+
#end
|
228
|
+
|
229
|
+
def create_shortcut(targetFileName, linkName)
|
230
|
+
shell = WIN32OLE.new("WScript.Shell")
|
231
|
+
scut = shell.CreateShortcut(linkName + '.lnk')
|
232
|
+
scut.TargetPath = File.expand_path(targetFileName)
|
233
|
+
scut.Save
|
234
|
+
scut
|
235
|
+
end
|
236
|
+
|
237
|
+
def win_to_rb_path(winpath)
|
238
|
+
winpath.gsub(/\\/, '/')
|
239
|
+
end
|
240
|
+
|
241
|
+
def rb_to_win_path(rbpath)
|
242
|
+
rbpath.gsub('/', "\\")
|
243
|
+
end
|
244
|
+
|
245
|
+
alias rbpath win_to_rb_path
|
246
|
+
alias winpath rb_to_win_path
|
247
|
+
|
248
|
+
def special_folders(folderName)
|
249
|
+
shell = WIN32OLE.new("WScript.Shell")
|
250
|
+
shell.SpecialFolders(folderName)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
module Windows
|
255
|
+
def Windows.drives(typeFilter=nil)
|
256
|
+
Drives::drives(typeFilter)
|
257
|
+
end
|
258
|
+
|
259
|
+
module Drives
|
260
|
+
GetDriveType = Win32API.new("kernel32", "GetDriveTypeA", ['P'], 'L')
|
261
|
+
GetLogicalDriveStrings = Win32API.new("kernel32", "GetLogicalDriveStrings", ['L', 'P'], 'L')
|
262
|
+
|
263
|
+
DRIVE_UNKNOWN = 0 # The drive type cannot be determined.
|
264
|
+
DRIVE_NO_ROOT_DIR = 1 # The root path is invalid. For example, no volume is mounted at the path.
|
265
|
+
DRIVE_REMOVABLE = 2 # The disk can be removed from the drive.
|
266
|
+
DRIVE_FIXED = 3 # The disk cannot be removed from the drive.
|
267
|
+
DRIVE_REMOTE = 4 # The drive is a remote (network) drive.
|
268
|
+
DRIVE_CDROM = 5 # The drive is a CD-ROM drive.
|
269
|
+
DRIVE_RAMDISK = 6 # The drive is a RAM disk.
|
270
|
+
DriveTypes = {
|
271
|
+
DRIVE_UNKNOWN => 'Unknown',
|
272
|
+
DRIVE_NO_ROOT_DIR => 'Invalid',
|
273
|
+
DRIVE_REMOVABLE => 'Removable/Floppy',
|
274
|
+
DRIVE_FIXED => 'Fixed',
|
275
|
+
DRIVE_REMOTE => 'Network',
|
276
|
+
DRIVE_CDROM => 'CD',
|
277
|
+
DRIVE_RAMDISK => 'RAM'
|
278
|
+
}
|
279
|
+
|
280
|
+
Drive = Struct.new('Drive', :name, :type, :typedesc)
|
281
|
+
|
282
|
+
def Drives.drives(typeFilter=nil)
|
283
|
+
driveNames = ' ' * 255
|
284
|
+
GetLogicalDriveStrings.Call(255, driveNames)
|
285
|
+
driveNames.strip!
|
286
|
+
driveNames = driveNames.split("\000")
|
287
|
+
drivesAry = []
|
288
|
+
driveNames.each do |drv|
|
289
|
+
type = GetDriveType.Call(drv)
|
290
|
+
if (!typeFilter) || (type == typeFilter)
|
291
|
+
drive = Drive.new(drv, type, DriveTypes[type])
|
292
|
+
drivesAry << drive
|
293
|
+
end
|
294
|
+
end
|
295
|
+
drivesAry
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
class File
|
301
|
+
# from WSH 5.6 docs
|
302
|
+
ALLUSERSDESKTOP = "AllUsersDesktop"
|
303
|
+
ALLUSERSSTARTMENU = "AllUsersStartMenu"
|
304
|
+
ALLUSERSPROGRAMS = "AllUsersPrograms"
|
305
|
+
ALLUSERSSTARTUP = "AllUsersStartup"
|
306
|
+
DESKTOP = "Desktop"
|
307
|
+
FAVORITES = "Favorites"
|
308
|
+
FONTS = "Fonts"
|
309
|
+
MYDOCUMENTS = "MyDocuments"
|
310
|
+
NETHOOD = "NetHood"
|
311
|
+
PRINTHOOD = "PrintHood"
|
312
|
+
PROGRAMS = "Programs"
|
313
|
+
RECENT = "Recent"
|
314
|
+
SENDTO = "SendTo"
|
315
|
+
STARTMENU = "StartMenu"
|
316
|
+
STARTUP = "Startup"
|
317
|
+
TEMPLATES = "Templates"
|
318
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clutil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2014.304.
|
4
|
+
version: 2014.304.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -33,7 +33,21 @@ email:
|
|
33
33
|
executables: []
|
34
34
|
extensions: []
|
35
35
|
extra_rdoc_files: []
|
36
|
-
files:
|
36
|
+
files:
|
37
|
+
- cl/util/clqsend.rb
|
38
|
+
- cl/util/console.rb
|
39
|
+
- cl/util/decide.rb
|
40
|
+
- cl/util/dirsize.rb
|
41
|
+
- cl/util/file.rb
|
42
|
+
- cl/util/install.rb
|
43
|
+
- cl/util/install.util.rb
|
44
|
+
- cl/util/net.rb
|
45
|
+
- cl/util/progress.rb
|
46
|
+
- cl/util/smtp.rb
|
47
|
+
- cl/util/string.rb
|
48
|
+
- cl/util/test.rb
|
49
|
+
- cl/util/time.rb
|
50
|
+
- cl/util/win.rb
|
37
51
|
homepage: http://clabs.org/ruby.htm
|
38
52
|
licenses:
|
39
53
|
- MIT
|
@@ -49,7 +63,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
63
|
version: '0'
|
50
64
|
segments:
|
51
65
|
- 0
|
52
|
-
hash:
|
66
|
+
hash: 610209804871303441
|
53
67
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
68
|
none: false
|
55
69
|
requirements:
|
@@ -58,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
72
|
version: '0'
|
59
73
|
segments:
|
60
74
|
- 0
|
61
|
-
hash:
|
75
|
+
hash: 610209804871303441
|
62
76
|
requirements: []
|
63
77
|
rubyforge_project:
|
64
78
|
rubygems_version: 1.8.23.2
|