clutil 2011.138.0 → 2014.304.0
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.
- metadata +47 -71
- data/cl/util/clqsend.rb +0 -86
- data/cl/util/console.rb +0 -60
- data/cl/util/cvs.maint.rb +0 -41
- data/cl/util/decide.rb +0 -69
- data/cl/util/dirsize.rb +0 -144
- data/cl/util/doc/License +0 -14
- data/cl/util/doc/Readme +0 -22
- data/cl/util/file.rb +0 -312
- data/cl/util/install.rb +0 -117
- data/cl/util/install.util.rb +0 -67
- data/cl/util/net.rb +0 -35
- data/cl/util/progress.rb +0 -104
- data/cl/util/smtp.rb +0 -170
- data/cl/util/string.rb +0 -73
- data/cl/util/test/dirsizetest.rb +0 -137
- data/cl/util/test/filetest.rb +0 -244
- data/cl/util/test/installtest.rb +0 -11
- data/cl/util/test/progresstest.rb +0 -43
- data/cl/util/test/stringtest.rb +0 -58
- data/cl/util/test/wintest.rb +0 -106
- data/cl/util/test.rb +0 -90
- data/cl/util/time.rb +0 -35
- data/cl/util/win.rb +0 -350
data/cl/util/test/stringtest.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
$LOAD_PATH << '..'
|
2
|
-
|
3
|
-
require 'test/unit'
|
4
|
-
require 'string'
|
5
|
-
|
6
|
-
class TestUtilString < Test::Unit::TestCase
|
7
|
-
def test_here_ltrim
|
8
|
-
test = <<-TEST
|
9
|
-
This is a test of the here_ltrim function.
|
10
|
-
Its purpose is to shift this whole paragraph to the left, removing
|
11
|
-
the indention.
|
12
|
-
TEST
|
13
|
-
|
14
|
-
expected = <<-EXP
|
15
|
-
This is a test of the here_ltrim function.
|
16
|
-
Its purpose is to shift this whole paragraph to the left, removing
|
17
|
-
the indention.
|
18
|
-
EXP
|
19
|
-
|
20
|
-
assert_equal(expected, here_ltrim(test))
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_here_ltrim_indent
|
24
|
-
test = <<-TEST
|
25
|
-
This is a test of the here_ltrim function.
|
26
|
-
Its purpose is to shift this whole paragraph to the left, removing
|
27
|
-
the indention.
|
28
|
-
TEST
|
29
|
-
|
30
|
-
expected = <<-EXP
|
31
|
-
This is a test of the here_ltrim function.
|
32
|
-
Its purpose is to shift this whole paragraph to the left, removing
|
33
|
-
the indention.
|
34
|
-
EXP
|
35
|
-
|
36
|
-
assert_equal(expected, here_ltrim(test, 2))
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_indent
|
40
|
-
# NOTE: empty lines are not indented - they are ignored
|
41
|
-
|
42
|
-
s = "hey\nhey\n\n"
|
43
|
-
s = indent(s, 2)
|
44
|
-
assert_equal(" hey\n hey\n\n", s)
|
45
|
-
s = indent(s, -1)
|
46
|
-
assert_equal(" hey\n hey\n\n", s)
|
47
|
-
s = indent(s, -3)
|
48
|
-
assert_equal("hey\nhey\n\n", s)
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_rbpath
|
52
|
-
assert_equal('c:/temp/dir', "c:\\temp\\dir".rbpath)
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_winpath
|
56
|
-
assert_equal('c:\\temp\\dir', "c:/temp/dir".winpath)
|
57
|
-
end
|
58
|
-
end
|
data/cl/util/test/wintest.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
# $Id: wintest.rb,v 1.6 2004/10/21 15:57:57 chrismo Exp $
|
2
|
-
=begin
|
3
|
-
--------------------------------------------------------------------------
|
4
|
-
Copyright (c) 2002, Chris Morris
|
5
|
-
All rights reserved.
|
6
|
-
|
7
|
-
Redistribution and use in source and binary forms, with or without modification,
|
8
|
-
are permitted provided that the following conditions are met:
|
9
|
-
|
10
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
11
|
-
list of conditions and the following disclaimer.
|
12
|
-
|
13
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
14
|
-
this list of conditions and the following disclaimer in the documentation and/or
|
15
|
-
other materials provided with the distribution.
|
16
|
-
|
17
|
-
3. Neither the names Chris Morris, cLabs nor the names of contributors to this
|
18
|
-
software may be used to endorse or promote products derived from this software
|
19
|
-
without specific prior written permission.
|
20
|
-
|
21
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
22
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
23
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
24
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
|
25
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
26
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
27
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
29
|
-
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
30
|
-
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
-
--------------------------------------------------------------------------------
|
32
|
-
=end
|
33
|
-
$LOAD_PATH << '..'
|
34
|
-
require 'win'
|
35
|
-
require 'test/unit'
|
36
|
-
|
37
|
-
class TestUtilWin < Test::Unit::TestCase
|
38
|
-
def testDeleteFile
|
39
|
-
fileName = "clutilwintest.test.safe.to.delete.txt"
|
40
|
-
f = File.new(fileName, File::CREAT)
|
41
|
-
f.close
|
42
|
-
File.chmod(0644, fileName)
|
43
|
-
File.delete(fileName)
|
44
|
-
assert(Dir[fileName] == [])
|
45
|
-
|
46
|
-
f = File.new(fileName, File::CREAT)
|
47
|
-
f.close
|
48
|
-
File.chmod(0444, fileName)
|
49
|
-
begin
|
50
|
-
File.delete(fileName)
|
51
|
-
fail('should have raised exception')
|
52
|
-
rescue ClUtilWinErr => e
|
53
|
-
# nada, expected exception
|
54
|
-
end
|
55
|
-
assert(Dir[fileName] != [])
|
56
|
-
File.delete_all(fileName)
|
57
|
-
assert(Dir[fileName] == [])
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_win_to_rb_path
|
61
|
-
assert_equal('c:/temp', File.win_to_rb_path("c:\\temp"))
|
62
|
-
assert_equal('c:/temp', File.rbpath("c:\\temp"))
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_rb_to_win_path
|
66
|
-
assert_equal("c:\\temp", File.rb_to_win_path("c:/temp"))
|
67
|
-
assert_equal("c:\\temp", File.winpath("c:/temp"))
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_special_folders
|
71
|
-
# quirky test, cuz the test code is the production code, but can't
|
72
|
-
# think of an easy way to have a hardcode result that would work on
|
73
|
-
# any machine. I guess I could go into the registry myself and look
|
74
|
-
# one of these up - but hey...
|
75
|
-
|
76
|
-
shell = WIN32OLE.new("WScript.Shell")
|
77
|
-
desktop = shell.SpecialFolders(File::DESKTOP)
|
78
|
-
assert_equal(desktop, File.special_folders('Desktop'))
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_drives
|
82
|
-
# does not fully evaluate output
|
83
|
-
# just runs to make sure it doesn't blow up
|
84
|
-
Windows.drives.each do |drv| puts drv.name + ' ' + drv.typedesc end
|
85
|
-
Windows.drives(Windows::Drives::DRIVE_FIXED).each do |drv|
|
86
|
-
puts drv.name + ' ' + drv.typedesc
|
87
|
-
end
|
88
|
-
|
89
|
-
Windows::Drives.drives.each do |drv| puts drv.name + ' ' + drv.typedesc end
|
90
|
-
Windows::Drives.drives(Windows::Drives::DRIVE_FIXED).each do |drv|
|
91
|
-
puts drv.name + ' ' + drv.typedesc
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class TestSystemReturnExitCode < Test::Unit::TestCase
|
97
|
-
def test_system_return_exit_code
|
98
|
-
tmpfn = File.join(File.dirname(__FILE__), '_test.child.rb')
|
99
|
-
File.delete tmpfn if File.exists?(tmpfn)
|
100
|
-
File.open(tmpfn, 'w+') do |f| f.puts 'exit(2)' end
|
101
|
-
|
102
|
-
cmd = "ruby.exe -C #{File.dirname(tmpfn)} #{File.basename(tmpfn)}"
|
103
|
-
assert_equal(2, system_return_exitcode(cmd))
|
104
|
-
File.delete tmpfn if File.exists?(tmpfn)
|
105
|
-
end
|
106
|
-
end
|
data/cl/util/test.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# $Id: test.rb,v 1.5 2005/04/22 03:59:43 chrismo Exp $
|
2
|
-
=begin
|
3
|
-
--------------------------------------------------------------------------
|
4
|
-
Copyright (c) 2001, Chris Morris
|
5
|
-
All rights reserved.
|
6
|
-
|
7
|
-
Redistribution and use in source and binary forms, with or without modification,
|
8
|
-
are permitted provided that the following conditions are met:
|
9
|
-
|
10
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
11
|
-
list of conditions and the following disclaimer.
|
12
|
-
|
13
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
14
|
-
this list of conditions and the following disclaimer in the documentation and/or
|
15
|
-
other materials provided with the distribution.
|
16
|
-
|
17
|
-
3. Neither the names Chris Morris, cLabs nor the names of contributors to this
|
18
|
-
software may be used to endorse or promote products derived from this software
|
19
|
-
without specific prior written permission.
|
20
|
-
|
21
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
22
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
23
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
24
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
|
25
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
26
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
27
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
29
|
-
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
30
|
-
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
-
--------------------------------------------------------------------------------
|
32
|
-
(based on BSD Open Source License)
|
33
|
-
=end
|
34
|
-
|
35
|
-
require File.dirname(__FILE__) + '/file'
|
36
|
-
require 'fileutils'
|
37
|
-
require 'tmpdir'
|
38
|
-
require 'test/unit'
|
39
|
-
|
40
|
-
class TempDirTest < Test::Unit::TestCase
|
41
|
-
def set_temp_dir
|
42
|
-
@temp_dir = Dir.mktmpdir
|
43
|
-
end
|
44
|
-
|
45
|
-
def setup
|
46
|
-
@file_name_inc = 0
|
47
|
-
set_temp_dir
|
48
|
-
FileUtils::makedirs(@temp_dir) if !FileTest.directory?(@temp_dir)
|
49
|
-
end
|
50
|
-
|
51
|
-
def teardown
|
52
|
-
ClUtilFile.delTree(@temp_dir)
|
53
|
-
end
|
54
|
-
|
55
|
-
# to ward off the new Test::Unit detection of classes with no test
|
56
|
-
# methods
|
57
|
-
def default_test
|
58
|
-
super unless(self.class == TempDirTest)
|
59
|
-
end
|
60
|
-
|
61
|
-
def make_sub_dir(dirname)
|
62
|
-
newdirname = File.join(@temp_dir, dirname)
|
63
|
-
FileUtils::makedirs(newdirname) if !FileTest.directory?(newdirname)
|
64
|
-
newdirname
|
65
|
-
end
|
66
|
-
|
67
|
-
def make_sample_text_file(dirname='', size=0)
|
68
|
-
crlf_length = 2
|
69
|
-
|
70
|
-
if size == 0
|
71
|
-
content = 'this is a sample file'
|
72
|
-
else
|
73
|
-
content = ''
|
74
|
-
(size - crlf_length).times do content << 'x' end
|
75
|
-
end
|
76
|
-
|
77
|
-
if dirname.empty?
|
78
|
-
sample_file_dir = @temp_dir
|
79
|
-
else
|
80
|
-
sample_file_dir = File.join(@temp_dir, dirname)
|
81
|
-
end
|
82
|
-
|
83
|
-
@file_name_inc += 1
|
84
|
-
filename = File.join(sample_file_dir, 'sample' + @file_name_inc.to_s + '.txt')
|
85
|
-
File.open(filename, 'w+') do |f|
|
86
|
-
f.puts content
|
87
|
-
end
|
88
|
-
filename
|
89
|
-
end
|
90
|
-
end
|
data/cl/util/time.rb
DELETED
@@ -1,35 +0,0 @@
|
|
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
DELETED
@@ -1,350 +0,0 @@
|
|
1
|
-
# $Id: win.rb,v 1.17 2004/10/21 17:00:57 chrismo Exp $
|
2
|
-
=begin
|
3
|
-
--------------------------------------------------------------------------
|
4
|
-
Copyright (c) 2001-2002, Chris Morris
|
5
|
-
All rights reserved.
|
6
|
-
|
7
|
-
Redistribution and use in source and binary forms, with or without modification,
|
8
|
-
are permitted provided that the following conditions are met:
|
9
|
-
|
10
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
11
|
-
list of conditions and the following disclaimer.
|
12
|
-
|
13
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
14
|
-
this list of conditions and the following disclaimer in the documentation and/or
|
15
|
-
other materials provided with the distribution.
|
16
|
-
|
17
|
-
3. Neither the names Chris Morris, cLabs nor the names of contributors to this
|
18
|
-
software may be used to endorse or promote products derived from this software
|
19
|
-
without specific prior written permission.
|
20
|
-
|
21
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
22
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
23
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
24
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
|
25
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
26
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
27
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
29
|
-
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
30
|
-
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
-
--------------------------------------------------------------------------------
|
32
|
-
=end
|
33
|
-
require 'Win32API'
|
34
|
-
require 'win32ole'
|
35
|
-
require File.dirname(__FILE__) + '/file'
|
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 takes only one argument
|
42
|
-
|
43
|
-
# code by Hee-Sob Park - posted here:
|
44
|
-
# http://ruby-talk.com/10006
|
45
|
-
def system(command)
|
46
|
-
# 2) it always set "$?" variable to false - should be working now...
|
47
|
-
|
48
|
-
# not allowed to set $?
|
49
|
-
# $? = Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
|
50
|
-
# $? == 0
|
51
|
-
|
52
|
-
# http://msdn.microsoft.com/library/en-us/vccore98/html/_crt_system.2c_._wsystem.asp
|
53
|
-
Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
|
54
|
-
end
|
55
|
-
|
56
|
-
# the system cmd in MSVC built ruby does not set $?, so no access to
|
57
|
-
# the exit code can be had. The following works, but is obtuse enough
|
58
|
-
# for me to encapsulate in this method.
|
59
|
-
# Bit slightly modified from - nobu http://ruby-talk.com/76086
|
60
|
-
def system_return_exitcode(cmd)
|
61
|
-
exitcode = nil
|
62
|
-
IO.popen(cmd) { |f|
|
63
|
-
# must bit shift by 8 to get the error code
|
64
|
-
exitcode = Process.waitpid2(f.pid)[1] >> 8
|
65
|
-
}
|
66
|
-
return exitcode
|
67
|
-
end
|
68
|
-
|
69
|
-
# MENON Jean-Francois [Jean-Francois.MENON@meteo.fr]
|
70
|
-
# http://ruby-talk.com/41583
|
71
|
-
# But I see two potential problems that make not consistent with the
|
72
|
-
# original ruby command:
|
73
|
-
# 1) it always set "$?" variable to false
|
74
|
-
|
75
|
-
# code by Hee-Sob Park - posted here:
|
76
|
-
# http://ruby-talk.com/10006
|
77
|
-
def `(command)
|
78
|
-
# http://msdn.microsoft.com/library/en-us/vccore98/HTML/_crt__popen.2c_._wpopen.asp
|
79
|
-
popen = Win32API.new("crtdll", "_popen", ['P','P'], 'L')
|
80
|
-
pclose = Win32API.new("crtdll", "_pclose", ['L'], 'L')
|
81
|
-
fread = Win32API.new("crtdll", "fread", ['P','L','L','L'], 'L')
|
82
|
-
feof = Win32API.new("crtdll", "feof", ['L'], 'L')
|
83
|
-
saved_stdout = $stdout.clone
|
84
|
-
psBuffer = " " * 128
|
85
|
-
rBuffer = ""
|
86
|
-
f = popen.Call(command,"r")
|
87
|
-
while feof.Call( f )==0
|
88
|
-
l = fread.Call( psBuffer,1,128,f )
|
89
|
-
# fix emailed direct to me from Park from 10006 code
|
90
|
-
# was:
|
91
|
-
# rBuffer += psBuffer[0..l]
|
92
|
-
rBuffer += psBuffer[0...l]
|
93
|
-
end
|
94
|
-
pclose.Call f
|
95
|
-
$stdout.reopen(saved_stdout)
|
96
|
-
rBuffer
|
97
|
-
end
|
98
|
-
|
99
|
-
P_WAIT = 0
|
100
|
-
P_NOWAIT = 1
|
101
|
-
OLD_P_OVERLAY = 2
|
102
|
-
P_NOWAITO = 3
|
103
|
-
P_DETACH = 4
|
104
|
-
|
105
|
-
def async_system(command)
|
106
|
-
# http://msdn.microsoft.com/library/en-us/vccore98/html/_crt__spawnv.2c_._wspawnv.asp
|
107
|
-
# this is working -- but frequently Segfaults ruby 1.6.6 mswin32
|
108
|
-
|
109
|
-
spawn = Win32API.new("crtdll", "_spawnvp", ['I', 'P', 'P'] ,'L')
|
110
|
-
res = spawn.Call(P_NOWAIT, command, '')
|
111
|
-
if res == -1
|
112
|
-
Win32API.new("crtdll", "perror", ['P'], 'V').call('async_system')
|
113
|
-
end
|
114
|
-
res
|
115
|
-
end
|
116
|
-
|
117
|
-
# from WinBase.h in SDK
|
118
|
-
# dwCreationFlag values
|
119
|
-
NORMAL_PRIORITY_CLASS = 0x00000020
|
120
|
-
|
121
|
-
STARTUP_INFO_SIZE = 68
|
122
|
-
PROCESS_INFO_SIZE = 16
|
123
|
-
|
124
|
-
def create_process(command)
|
125
|
-
# from WinBase.h in SDK
|
126
|
-
# Passing nil for a pointer -- I've seen it work with a P type param and
|
127
|
-
# an empty string ... here L with a 0 is the only way that works with
|
128
|
-
# CreateProcess. (see FormatMessage in raise_last_win32_error for an
|
129
|
-
# example of 'P' and '' that works)
|
130
|
-
params = [
|
131
|
-
'L', # IN LPCSTR lpApplicationName
|
132
|
-
'P', # IN LPSTR lpCommandLine
|
133
|
-
'L', # IN LPSECURITY_ATTRIBUTES lpProcessAttributes
|
134
|
-
'L', # IN LPSECURITY_ATTRIBUTES lpThreadAttributes
|
135
|
-
'L', # IN BOOL bInheritHandles
|
136
|
-
'L', # IN DWORD dwCreationFlags
|
137
|
-
'L', # IN LPVOID lpEnvironment
|
138
|
-
'L', # IN LPCSTR lpCurrentDirectory
|
139
|
-
'P', # IN LPSTARTUPINFOA lpStartupInfo
|
140
|
-
'P' # OUT LPPROCESS_INFORMATION lpProcessInformation
|
141
|
-
]
|
142
|
-
returnValue = 'I' # BOOL
|
143
|
-
|
144
|
-
startupInfo = [STARTUP_INFO_SIZE].pack('I') + ([0].pack('I') * (STARTUP_INFO_SIZE - 4))
|
145
|
-
processInfo = [0].pack('I') * PROCESS_INFO_SIZE
|
146
|
-
createProcess = Win32API.new("kernel32", "CreateProcess", params, returnValue)
|
147
|
-
if createProcess.call(0, command, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0,
|
148
|
-
startupInfo, processInfo) == 0
|
149
|
-
raise_last_win_32_error
|
150
|
-
end
|
151
|
-
processInfo
|
152
|
-
end
|
153
|
-
|
154
|
-
ERROR_SUCCESS = 0x00
|
155
|
-
FORMAT_MESSAGE_FROM_SYSTEM = 0x1000
|
156
|
-
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000
|
157
|
-
|
158
|
-
def raise_last_win_32_error
|
159
|
-
errorCode = Win32API.new("kernel32", "GetLastError", [], 'L').call
|
160
|
-
if errorCode != ERROR_SUCCESS
|
161
|
-
params = [
|
162
|
-
'L', # IN DWORD dwFlags,
|
163
|
-
'P', # IN LPCVOID lpSource,
|
164
|
-
'L', # IN DWORD dwMessageId,
|
165
|
-
'L', # IN DWORD dwLanguageId,
|
166
|
-
'P', # OUT LPSTR lpBuffer,
|
167
|
-
'L', # IN DWORD nSize,
|
168
|
-
'P', # IN va_list *Arguments
|
169
|
-
]
|
170
|
-
|
171
|
-
formatMessage = Win32API.new("kernel32", "FormatMessage", params, 'L')
|
172
|
-
msg = ' ' * 255
|
173
|
-
msgLength = formatMessage.call(FORMAT_MESSAGE_FROM_SYSTEM +
|
174
|
-
FORMAT_MESSAGE_ARGUMENT_ARRAY, '', errorCode, 0, msg, 255, '')
|
175
|
-
msg.gsub!("\\000", '')
|
176
|
-
msg.strip!
|
177
|
-
raise msg
|
178
|
-
else
|
179
|
-
raise 'GetLastError returned ERROR_SUCCESS'
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
class ClUtilWinErr < Exception
|
184
|
-
end
|
185
|
-
|
186
|
-
class << File
|
187
|
-
alias o_delete delete
|
188
|
-
|
189
|
-
def win_api_delete(filename)
|
190
|
-
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/filesio_5n8l.asp
|
191
|
-
# BOOL DeleteFile(
|
192
|
-
# LPCTSTR lpFileName // file name
|
193
|
-
# );
|
194
|
-
|
195
|
-
# delete file if not read only
|
196
|
-
fdelete = Win32API.new("kernel32", "DeleteFile", ["P"], "I")
|
197
|
-
fdelete.Call(filename) != 0
|
198
|
-
end
|
199
|
-
|
200
|
-
# def recycle
|
201
|
-
# function SHFileOperation(const lpFileOp: TSHFileOpStruct): Integer; stdcall;
|
202
|
-
# TSHFileOpStruct = packed record
|
203
|
-
# Wnd: HWND; // HWND = type LongWord; Longword 0..4294967295 unsigned 32-bit
|
204
|
-
# wFunc: UINT; // UINT = LongWord;
|
205
|
-
# pFrom: PWideChar; // pointer to unicode string
|
206
|
-
# pTo: PWideChar;
|
207
|
-
# fFlags: FILEOP_FLAGS; // FILEOP_FLAGS = Word; Word 0..65535 unsigned 16-bit
|
208
|
-
# fAnyOperationsAborted: BOOL; // BOOL = LongBool; a LongBool variable occupies four bytes (two words).
|
209
|
-
# hNameMappings: Pointer;
|
210
|
-
# lpszProgressTitle: PWideChar; { only used if FOF_SIMPLEPROGRESS }
|
211
|
-
# end;
|
212
|
-
|
213
|
-
# http://msdn.microsoft.com/en-us/shellcc/platform/shell/reference/structures/shfileopstruct.asp
|
214
|
-
# see FOF_ALLOWUNDO, specifically
|
215
|
-
# end
|
216
|
-
|
217
|
-
def win_file_ro?(filename)
|
218
|
-
fFILE_ATTRIBUTE_READONLY = 0x1
|
219
|
-
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/filesio_9pgz.asp
|
220
|
-
# DWORD GetFileAttributes(
|
221
|
-
# LPCTSTR lpFileName // name of file or directory
|
222
|
-
# );
|
223
|
-
fgetattr = Win32API.new("kernel32", "GetFileAttributes", ["P"], "N")
|
224
|
-
fattr = fgetattr.Call(filename)
|
225
|
-
(fattr & fFILE_ATTRIBUTE_READONLY) != 0
|
226
|
-
end
|
227
|
-
|
228
|
-
def delete(*files)
|
229
|
-
files.flatten!
|
230
|
-
files.each do |file|
|
231
|
-
if !win_file_ro?(file)
|
232
|
-
win_api_delete(file)
|
233
|
-
else
|
234
|
-
raise ClUtilWinErr.new(file + ' is read only, cannot delete. Use File.delete_all')
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
# I wanted to add a second param to delete, called deleteReadOnly with
|
240
|
-
# a default value of false but (a) I can't have a default value param
|
241
|
-
# after the *files param because (b) I can't have any non *param after
|
242
|
-
# the *files param. So, my compromise was a separate method
|
243
|
-
|
244
|
-
# I have no idea why I'm doing an api specific call here.
|
245
|
-
# I think when I started this journey, I thought the API
|
246
|
-
# call would delete read-only files, then when I learned
|
247
|
-
# it wouldn't, I forgot my original purpose and just
|
248
|
-
# worked around it. It's silly now -- I've moved delete_all
|
249
|
-
# to cl/util/file.rb which is a pure Ruby implementation
|
250
|
-
# of this one.
|
251
|
-
|
252
|
-
#def delete_all(*files)
|
253
|
-
# files.flatten!
|
254
|
-
# files.each do |file|
|
255
|
-
# # make writable to allow deletion
|
256
|
-
# File.chmod(0644, file)
|
257
|
-
# win_api_delete(file)
|
258
|
-
# end
|
259
|
-
#end
|
260
|
-
|
261
|
-
def create_shortcut(targetFileName, linkName)
|
262
|
-
shell = WIN32OLE.new("WScript.Shell")
|
263
|
-
scut = shell.CreateShortcut(linkName + '.lnk')
|
264
|
-
scut.TargetPath = File.expand_path(targetFileName)
|
265
|
-
scut.Save
|
266
|
-
scut
|
267
|
-
end
|
268
|
-
|
269
|
-
def win_to_rb_path(winpath)
|
270
|
-
winpath.gsub(/\\/, '/')
|
271
|
-
end
|
272
|
-
|
273
|
-
def rb_to_win_path(rbpath)
|
274
|
-
rbpath.gsub('/', "\\")
|
275
|
-
end
|
276
|
-
|
277
|
-
alias rbpath win_to_rb_path
|
278
|
-
alias winpath rb_to_win_path
|
279
|
-
|
280
|
-
def special_folders(folderName)
|
281
|
-
shell = WIN32OLE.new("WScript.Shell")
|
282
|
-
shell.SpecialFolders(folderName)
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
module Windows
|
287
|
-
def Windows.drives(typeFilter=nil)
|
288
|
-
Drives::drives(typeFilter)
|
289
|
-
end
|
290
|
-
|
291
|
-
module Drives
|
292
|
-
GetDriveType = Win32API.new("kernel32", "GetDriveTypeA", ['P'], 'L')
|
293
|
-
GetLogicalDriveStrings = Win32API.new("kernel32", "GetLogicalDriveStrings", ['L', 'P'], 'L')
|
294
|
-
|
295
|
-
DRIVE_UNKNOWN = 0 # The drive type cannot be determined.
|
296
|
-
DRIVE_NO_ROOT_DIR = 1 # The root path is invalid. For example, no volume is mounted at the path.
|
297
|
-
DRIVE_REMOVABLE = 2 # The disk can be removed from the drive.
|
298
|
-
DRIVE_FIXED = 3 # The disk cannot be removed from the drive.
|
299
|
-
DRIVE_REMOTE = 4 # The drive is a remote (network) drive.
|
300
|
-
DRIVE_CDROM = 5 # The drive is a CD-ROM drive.
|
301
|
-
DRIVE_RAMDISK = 6 # The drive is a RAM disk.
|
302
|
-
DriveTypes = {
|
303
|
-
DRIVE_UNKNOWN => 'Unknown',
|
304
|
-
DRIVE_NO_ROOT_DIR => 'Invalid',
|
305
|
-
DRIVE_REMOVABLE => 'Removable/Floppy',
|
306
|
-
DRIVE_FIXED => 'Fixed',
|
307
|
-
DRIVE_REMOTE => 'Network',
|
308
|
-
DRIVE_CDROM => 'CD',
|
309
|
-
DRIVE_RAMDISK => 'RAM'
|
310
|
-
}
|
311
|
-
|
312
|
-
Drive = Struct.new('Drive', :name, :type, :typedesc)
|
313
|
-
|
314
|
-
def Drives.drives(typeFilter=nil)
|
315
|
-
driveNames = ' ' * 255
|
316
|
-
GetLogicalDriveStrings.Call(255, driveNames)
|
317
|
-
driveNames.strip!
|
318
|
-
driveNames = driveNames.split("\000")
|
319
|
-
drivesAry = []
|
320
|
-
driveNames.each do |drv|
|
321
|
-
type = GetDriveType.Call(drv)
|
322
|
-
if (!typeFilter) || (type == typeFilter)
|
323
|
-
drive = Drive.new(drv, type, DriveTypes[type])
|
324
|
-
drivesAry << drive
|
325
|
-
end
|
326
|
-
end
|
327
|
-
drivesAry
|
328
|
-
end
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
class File
|
333
|
-
# from WSH 5.6 docs
|
334
|
-
ALLUSERSDESKTOP = "AllUsersDesktop"
|
335
|
-
ALLUSERSSTARTMENU = "AllUsersStartMenu"
|
336
|
-
ALLUSERSPROGRAMS = "AllUsersPrograms"
|
337
|
-
ALLUSERSSTARTUP = "AllUsersStartup"
|
338
|
-
DESKTOP = "Desktop"
|
339
|
-
FAVORITES = "Favorites"
|
340
|
-
FONTS = "Fonts"
|
341
|
-
MYDOCUMENTS = "MyDocuments"
|
342
|
-
NETHOOD = "NetHood"
|
343
|
-
PRINTHOOD = "PrintHood"
|
344
|
-
PROGRAMS = "Programs"
|
345
|
-
RECENT = "Recent"
|
346
|
-
SENDTO = "SendTo"
|
347
|
-
STARTMENU = "StartMenu"
|
348
|
-
STARTUP = "Startup"
|
349
|
-
TEMPLATES = "Templates"
|
350
|
-
end
|