win32-process 0.5.9 → 0.6.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.
- data/CHANGES +13 -0
- data/Rakefile +0 -2
- data/examples/test_create.rb +39 -0
- data/examples/test_fork_wait.rb +33 -0
- data/examples/test_fork_waitpid.rb +50 -0
- data/examples/test_kill.rb +35 -0
- data/lib/win32/process.rb +102 -85
- data/test/{tc_process.rb → test_win32_process.rb} +33 -33
- data/win32-process.gemspec +4 -4
- metadata +10 -7
data/CHANGES
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
= 0.6.0 - 31-Oct-2008
|
2
|
+
* The mandatory argument for Process.create has been switched from 'app_name'
|
3
|
+
to 'command_line', to be more in line with underlying CreateProcess API.
|
4
|
+
Note that 'command_line' will default to 'app_name' if only the latter is
|
5
|
+
set, but both may be set individually. Keep in mind that 'app_name' must
|
6
|
+
be a full path to the executable. Thanks go to Jeremy Bopp for the patch.
|
7
|
+
* Removed the deprecated ProcessError constant. Use Process::Error instead.
|
8
|
+
* Explicitly include and extend the Windows::Thread module now. Thanks go to
|
9
|
+
Qi Lu for the spot.
|
10
|
+
* Slightly more robust internal code handling for some of the other methods,
|
11
|
+
typically related to ensuring that HANDLE's are closed.
|
12
|
+
* Example programs are now included with the gem.
|
13
|
+
|
1
14
|
= 0.5.9 - 14-Jun-2008
|
2
15
|
* Added a proper implementation of Process.ppid.
|
3
16
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# test_create.rb
|
3
|
+
#
|
4
|
+
# Simple test program for the Process.create() method.
|
5
|
+
##########################################################################
|
6
|
+
Dir.chdir('..') if File.basename(Dir.pwd) == 'examples'
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
8
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
9
|
+
Dir.chdir('examples') rescue nil
|
10
|
+
|
11
|
+
require "win32/process"
|
12
|
+
|
13
|
+
p Process::WIN32_PROCESS_VERSION
|
14
|
+
|
15
|
+
struct = Process.create(
|
16
|
+
:app_name => "notepad.exe",
|
17
|
+
:creation_flags => Process::DETACHED_PROCESS,
|
18
|
+
:process_inherit => false,
|
19
|
+
:thread_inherit => true,
|
20
|
+
:cwd => "C:\\",
|
21
|
+
:inherit => true,
|
22
|
+
:environment => "SYSTEMROOT=#{ENV['SYSTEMROOT']};PATH=C:\\"
|
23
|
+
)
|
24
|
+
|
25
|
+
p struct
|
26
|
+
|
27
|
+
=begin
|
28
|
+
# Don't run this from an existing terminal
|
29
|
+
pid = Process.create(
|
30
|
+
:app_name => "cmd.exe",
|
31
|
+
:creation_flags => Process::DETACHED_PROCESS,
|
32
|
+
:startf_flags => Process::USEPOSITION,
|
33
|
+
:x => 0,
|
34
|
+
:y => 0,
|
35
|
+
:title => "Hi Dan"
|
36
|
+
)
|
37
|
+
|
38
|
+
puts "Pid of new process: #{pid}"
|
39
|
+
=end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# test_fork_wait.rb
|
3
|
+
#
|
4
|
+
# Generic test script for futzing around with the block form of fork/wait
|
5
|
+
##########################################################################
|
6
|
+
Dir.chdir('..') if File.basename(Dir.pwd) == 'examples'
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
8
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
9
|
+
Dir.chdir('examples') rescue nil
|
10
|
+
|
11
|
+
require 'win32/process'
|
12
|
+
|
13
|
+
puts "VERSION: " + Process::WIN32_PROCESS_VERSION
|
14
|
+
|
15
|
+
# In the child, using block form
|
16
|
+
fork{
|
17
|
+
7.times { |i|
|
18
|
+
puts "Child: #{i}"
|
19
|
+
sleep 1
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
# Back in the parent
|
24
|
+
4.times{ |i|
|
25
|
+
puts "Parent: #{i}"
|
26
|
+
sleep 1
|
27
|
+
}
|
28
|
+
|
29
|
+
# Wait for the children
|
30
|
+
Process.wait
|
31
|
+
|
32
|
+
# Children should be done here before continuing on
|
33
|
+
puts "Continuing on..."
|
@@ -0,0 +1,50 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# test_fork_waitpid.rb
|
3
|
+
#
|
4
|
+
# Generic test script for futzing around with the traditional form of
|
5
|
+
# fork/wait, plus waitpid and waitpid2.
|
6
|
+
##########################################################################
|
7
|
+
Dir.chdir('..') if File.basename(Dir.pwd) == 'examples'
|
8
|
+
$LOAD_PATH.unshift Dir.pwd
|
9
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
10
|
+
Dir.chdir('examples') rescue nil
|
11
|
+
|
12
|
+
require 'win32/process'
|
13
|
+
|
14
|
+
puts "VERSION: " + Process::WIN32_PROCESS_VERSION
|
15
|
+
|
16
|
+
pid = Process.fork
|
17
|
+
puts "PID1: #{pid}"
|
18
|
+
|
19
|
+
#child
|
20
|
+
if pid.nil?
|
21
|
+
7.times{ |i|
|
22
|
+
puts "Child: #{i}"
|
23
|
+
sleep 1
|
24
|
+
}
|
25
|
+
exit(-1)
|
26
|
+
end
|
27
|
+
|
28
|
+
pid2 = Process.fork
|
29
|
+
puts "PID2: #{pid2}"
|
30
|
+
|
31
|
+
#child2
|
32
|
+
if pid2.nil?
|
33
|
+
7.times{ |i|
|
34
|
+
puts "Child2: #{i}"
|
35
|
+
sleep 1
|
36
|
+
}
|
37
|
+
exit(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
#parent
|
41
|
+
2.times { |i|
|
42
|
+
puts "Parent: #{i}"
|
43
|
+
sleep 1
|
44
|
+
}
|
45
|
+
|
46
|
+
p Process.waitpid2(pid)
|
47
|
+
p Process.waitpid2(pid2)
|
48
|
+
|
49
|
+
puts "Continuing on..."
|
50
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# test_kill.rb
|
3
|
+
#
|
4
|
+
# Generic test script for futzing around Process.kill. This script
|
5
|
+
# requires the sys-proctable package (available on the RAA).
|
6
|
+
##########################################################################
|
7
|
+
Dir.chdir('..') if File.basename(Dir.pwd) == 'examples'
|
8
|
+
$LOAD_PATH.unshift Dir.pwd
|
9
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
10
|
+
Dir.chdir('examples') rescue nil
|
11
|
+
|
12
|
+
require "win32/process"
|
13
|
+
|
14
|
+
begin
|
15
|
+
require "sys/proctable"
|
16
|
+
rescue LoadError
|
17
|
+
STDERR.puts "Whoa there!"
|
18
|
+
STDERR.puts "This script requires the sys-proctable package to work."
|
19
|
+
STDERR.puts "You can find it at http://ruby-sysutils.sf.net"
|
20
|
+
STDERR.puts "Exiting..."
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
include Sys
|
24
|
+
|
25
|
+
puts "VERSION: " + Process::WIN32_PROCESS_VERSION
|
26
|
+
|
27
|
+
IO.popen("notepad")
|
28
|
+
sleep 1 # Give it a chance to start before checking for its pid
|
29
|
+
|
30
|
+
pids = []
|
31
|
+
ProcTable.ps{ |s|
|
32
|
+
pids.push(s.pid) if s.cmdline =~ /notepad/i
|
33
|
+
}
|
34
|
+
|
35
|
+
p Process.kill(9,pids.last)
|
data/lib/win32/process.rb
CHANGED
@@ -15,7 +15,8 @@ module Process
|
|
15
15
|
# Eliminates redefinition warnings.
|
16
16
|
undef_method :kill, :wait, :wait2, :waitpid, :waitpid2, :ppid
|
17
17
|
|
18
|
-
|
18
|
+
# The version of this library
|
19
|
+
WIN32_PROCESS_VERSION = '0.6.0'
|
19
20
|
|
20
21
|
include Windows::Process
|
21
22
|
include Windows::Thread
|
@@ -27,6 +28,7 @@ module Process
|
|
27
28
|
include Windows::Window
|
28
29
|
include Windows::Unicode
|
29
30
|
include Windows::ToolHelper
|
31
|
+
|
30
32
|
extend Windows::Error
|
31
33
|
extend Windows::Process
|
32
34
|
extend Windows::Thread
|
@@ -64,13 +66,14 @@ module Process
|
|
64
66
|
# TODO: update the $? global variable (if/when possible)
|
65
67
|
status = WaitForSingleObject(handle, INFINITE)
|
66
68
|
|
67
|
-
|
68
|
-
|
69
|
+
begin
|
70
|
+
unless GetExitCodeProcess(handle, exit_code)
|
71
|
+
raise Error, get_last_error
|
72
|
+
end
|
73
|
+
ensure
|
69
74
|
CloseHandle(handle)
|
70
|
-
raise Error, error
|
71
75
|
end
|
72
76
|
|
73
|
-
CloseHandle(handle)
|
74
77
|
@child_pids.delete(pid)
|
75
78
|
|
76
79
|
# TODO: update the $? global variable (if/when possible)
|
@@ -99,13 +102,14 @@ module Process
|
|
99
102
|
# TODO: update the $? global variable (if/when possible)
|
100
103
|
status = WaitForSingleObject(handle, INFINITE)
|
101
104
|
|
102
|
-
|
103
|
-
|
105
|
+
begin
|
106
|
+
unless GetExitCodeProcess(handle, exit_code)
|
107
|
+
raise Error, get_last_error
|
108
|
+
end
|
109
|
+
ensure
|
104
110
|
CloseHandle(handle)
|
105
|
-
raise Error, error
|
106
111
|
end
|
107
112
|
|
108
|
-
CloseHandle(handle)
|
109
113
|
@child_pids.delete(pid)
|
110
114
|
|
111
115
|
# TODO: update the $? global variable (if/when possible)
|
@@ -156,70 +160,70 @@ module Process
|
|
156
160
|
|
157
161
|
# No need for full access if the signal is zero
|
158
162
|
if signal == 0
|
159
|
-
access = PROCESS_QUERY_INFORMATION|PROCESS_VM_READ
|
163
|
+
access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
|
160
164
|
handle = OpenProcess(access, 0 , pid)
|
161
165
|
else
|
162
166
|
handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
|
163
167
|
end
|
164
168
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
CloseHandle(handle)
|
170
|
-
else
|
171
|
-
# If ERROR_ACCESS_DENIED is returned, we know it's running
|
172
|
-
if GetLastError() == ERROR_ACCESS_DENIED
|
169
|
+
begin
|
170
|
+
case signal
|
171
|
+
when 0
|
172
|
+
if handle != 0
|
173
173
|
killed_pids.push(pid)
|
174
174
|
else
|
175
|
-
|
175
|
+
# If ERROR_ACCESS_DENIED is returned, we know it's running
|
176
|
+
if GetLastError() == ERROR_ACCESS_DENIED
|
177
|
+
killed_pids.push(pid)
|
178
|
+
else
|
179
|
+
raise Error, get_last_error
|
180
|
+
end
|
176
181
|
end
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
if GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid)
|
184
|
-
killed_pids.push(pid)
|
185
|
-
end
|
186
|
-
when 9
|
187
|
-
if TerminateProcess(handle, pid)
|
188
|
-
CloseHandle(handle)
|
189
|
-
killed_pids.push(pid)
|
190
|
-
@child_pids.delete(pid)
|
191
|
-
else
|
192
|
-
raise Error, get_last_error
|
193
|
-
end
|
194
|
-
else
|
195
|
-
if handle != 0
|
196
|
-
thread_id = [0].pack('L')
|
197
|
-
dll = 'kernel32'
|
198
|
-
eproc = 'ExitProcess'
|
199
|
-
|
200
|
-
thread = CreateRemoteThread(
|
201
|
-
handle,
|
202
|
-
0,
|
203
|
-
0,
|
204
|
-
GetProcAddress(GetModuleHandle(dll), eproc),
|
205
|
-
0,
|
206
|
-
0,
|
207
|
-
thread_id
|
208
|
-
)
|
209
|
-
|
210
|
-
if thread
|
211
|
-
WaitForSingleObject(thread, 5)
|
212
|
-
CloseHandle(handle)
|
182
|
+
when 2
|
183
|
+
if GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid)
|
184
|
+
killed_pids.push(pid)
|
185
|
+
end
|
186
|
+
when 3
|
187
|
+
if GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid)
|
213
188
|
killed_pids.push(pid)
|
214
|
-
|
189
|
+
end
|
190
|
+
when 9
|
191
|
+
if TerminateProcess(handle, pid)
|
192
|
+
killed_pids.push(pid)
|
193
|
+
@child_pids.delete(pid)
|
215
194
|
else
|
216
|
-
CloseHandle(handle)
|
217
195
|
raise Error, get_last_error
|
218
196
|
end
|
219
197
|
else
|
220
|
-
|
221
|
-
|
222
|
-
|
198
|
+
if handle != 0
|
199
|
+
thread_id = [0].pack('L')
|
200
|
+
dll = 'kernel32'
|
201
|
+
eproc = 'ExitProcess'
|
202
|
+
|
203
|
+
thread = CreateRemoteThread(
|
204
|
+
handle,
|
205
|
+
0,
|
206
|
+
0,
|
207
|
+
GetProcAddress(GetModuleHandle(dll), eproc),
|
208
|
+
0,
|
209
|
+
0,
|
210
|
+
thread_id
|
211
|
+
)
|
212
|
+
|
213
|
+
if thread
|
214
|
+
WaitForSingleObject(thread, 5)
|
215
|
+
killed_pids.push(pid)
|
216
|
+
@child_pids.delete(pid)
|
217
|
+
else
|
218
|
+
raise Error, get_last_error
|
219
|
+
end
|
220
|
+
else
|
221
|
+
raise Error, get_last_error
|
222
|
+
end
|
223
|
+
@child_pids.delete(pid)
|
224
|
+
end
|
225
|
+
ensure
|
226
|
+
CloseHandle(handle) unless handle == INVALID_HANDLE_VALUE
|
223
227
|
end
|
224
228
|
}
|
225
229
|
|
@@ -232,7 +236,8 @@ module Process
|
|
232
236
|
# returning a ProcessInfo struct. It accepts a hash as an argument.
|
233
237
|
# There are several primary keys:
|
234
238
|
#
|
235
|
-
# *
|
239
|
+
# * command_line (mandatory)
|
240
|
+
# * app_name (default: nil)
|
236
241
|
# * inherit (default: false)
|
237
242
|
# * process_inherit (default: false)
|
238
243
|
# * thread_inherit (default: false)
|
@@ -245,7 +250,10 @@ module Process
|
|
245
250
|
# * domain (default: nil)
|
246
251
|
# * password (default: nil)
|
247
252
|
#
|
248
|
-
# Of these, the 'app_name' must be specified or an
|
253
|
+
# Of these, the 'command_line' or 'app_name' must be specified or an
|
254
|
+
# error is raised. Both may be set individually, but 'command_line' should
|
255
|
+
# be preferred if only one of them is set because it does not (necessarily)
|
256
|
+
# require an explicit path or extension to work.
|
249
257
|
#
|
250
258
|
# The 'domain' and 'password' options are only relevent in the context
|
251
259
|
# of 'with_logon'.
|
@@ -301,9 +309,9 @@ module Process
|
|
301
309
|
end
|
302
310
|
|
303
311
|
valid_keys = %w/
|
304
|
-
app_name inherit creation_flags cwd environment
|
305
|
-
thread_inherit process_inherit close_handles with_logon
|
306
|
-
password
|
312
|
+
app_name command_line inherit creation_flags cwd environment
|
313
|
+
startup_info thread_inherit process_inherit close_handles with_logon
|
314
|
+
domain password
|
307
315
|
/
|
308
316
|
|
309
317
|
valid_si_keys = %/
|
@@ -313,6 +321,7 @@ module Process
|
|
313
321
|
|
314
322
|
# Set default values
|
315
323
|
hash = {
|
324
|
+
'app_name' => nil,
|
316
325
|
'creation_flags' => 0,
|
317
326
|
'close_handles' => true
|
318
327
|
}
|
@@ -339,9 +348,15 @@ module Process
|
|
339
348
|
}
|
340
349
|
end
|
341
350
|
|
342
|
-
# The +
|
343
|
-
|
344
|
-
|
351
|
+
# The +command_line+ key is mandatory unless the +app_name+ key
|
352
|
+
# is specified.
|
353
|
+
unless hash['command_line']
|
354
|
+
if hash['app_name']
|
355
|
+
hash['command_line'] = hash['app_name']
|
356
|
+
hash['app_name'] = nil
|
357
|
+
else
|
358
|
+
raise Error, 'command_line or app_name must be specified'
|
359
|
+
end
|
345
360
|
end
|
346
361
|
|
347
362
|
# The environment string should be passed as a string of ';' separated
|
@@ -421,7 +436,8 @@ module Process
|
|
421
436
|
if hash['with_logon']
|
422
437
|
logon = multi_to_wide(hash['with_logon'])
|
423
438
|
domain = multi_to_wide(hash['domain'])
|
424
|
-
app = multi_to_wide(hash['app_name'])
|
439
|
+
app = hash['app_name'].nil? ? nil : multi_to_wide(hash['app_name'])
|
440
|
+
cmd = hash['command_line'].nil? ? nil : multi_to_wide(hash['command_line'])
|
425
441
|
cwd = multi_to_wide(hash['cwd'])
|
426
442
|
passwd = multi_to_wide(hash['password'])
|
427
443
|
|
@@ -432,8 +448,8 @@ module Process
|
|
432
448
|
domain, # Domain
|
433
449
|
passwd, # Password
|
434
450
|
LOGON_WITH_PROFILE, # Logon flags
|
435
|
-
|
436
|
-
|
451
|
+
app, # App name
|
452
|
+
cmd, # Command line
|
437
453
|
hash['creation_flags'], # Creation flags
|
438
454
|
env, # Environment
|
439
455
|
cwd, # Working directory
|
@@ -442,8 +458,8 @@ module Process
|
|
442
458
|
)
|
443
459
|
else
|
444
460
|
bool = CreateProcess(
|
445
|
-
|
446
|
-
hash['
|
461
|
+
hash['app_name'], # App name
|
462
|
+
hash['command_line'], # Command line
|
447
463
|
process_security, # Process attributes
|
448
464
|
thread_security, # Thread attributes
|
449
465
|
hash['inherit'], # Inherit handles?
|
@@ -456,7 +472,7 @@ module Process
|
|
456
472
|
end
|
457
473
|
|
458
474
|
# TODO: Close stdin, stdout and stderr handles in the si_hash unless
|
459
|
-
# they're pointing to one of the standard handles already.
|
475
|
+
# they're pointing to one of the standard handles already. [Maybe]
|
460
476
|
unless bool
|
461
477
|
raise Error, "CreateProcess() failed: ", get_last_error
|
462
478
|
end
|
@@ -610,16 +626,20 @@ module Process
|
|
610
626
|
proc_entry = 0.chr * 296 # 36 + 260
|
611
627
|
proc_entry[0, 4] = [proc_entry.size].pack('L') # Set dwSize member
|
612
628
|
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
629
|
+
begin
|
630
|
+
unless Process32First(handle, proc_entry)
|
631
|
+
error = get_last_error
|
632
|
+
raise Error, error
|
633
|
+
end
|
617
634
|
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
635
|
+
while Process32Next(handle, proc_entry)
|
636
|
+
if proc_entry[8, 4].unpack('L')[0] == Process.pid
|
637
|
+
ppid = proc_entry[24, 4].unpack('L')[0] # th32ParentProcessID
|
638
|
+
break
|
639
|
+
end
|
622
640
|
end
|
641
|
+
ensure
|
642
|
+
CloseHandle(handle)
|
623
643
|
end
|
624
644
|
|
625
645
|
ppid
|
@@ -683,9 +703,6 @@ module Process
|
|
683
703
|
module_function :ppid
|
684
704
|
end
|
685
705
|
|
686
|
-
# For backwards compatibility. Deprecated.
|
687
|
-
ProcessError = Process::Error
|
688
|
-
|
689
706
|
# Create a global fork method
|
690
707
|
module Kernel
|
691
708
|
undef_method :fork # Eliminate redefinition warning
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# Test suite for the win32-process library. This test suite will start
|
5
5
|
# at least two instances of Notepad on your system, which will then
|
6
|
-
# be killed. Requires the sys-proctable
|
6
|
+
# be killed. Requires the sys-proctable library.
|
7
7
|
#
|
8
8
|
# I haven't added a lot of test cases for fork/wait because it's difficult
|
9
9
|
# to run such tests without causing havoc with Test::Unit itself. Ideas
|
@@ -11,42 +11,36 @@
|
|
11
11
|
#
|
12
12
|
# You should run this test case via the 'rake test' task.
|
13
13
|
###############################################################################
|
14
|
+
require 'rubygems'
|
15
|
+
gem 'test-unit'
|
16
|
+
|
14
17
|
require 'test/unit'
|
15
18
|
require 'win32/process'
|
16
|
-
|
17
|
-
begin
|
18
|
-
require 'sys/proctable'
|
19
|
-
rescue LoadError => e
|
20
|
-
site = 'http://www.rubyforge.org/projects/sysutils'
|
21
|
-
msg = %Q{
|
22
|
-
Stopping! The sys-proctable library is required to run this test suite.
|
23
|
-
You can find it at #{site} or the RAA.
|
24
|
-
Or, you can just 'gem install sys-proctable' and try again.
|
25
|
-
}
|
26
|
-
STDERR.puts msg
|
27
|
-
exit!
|
28
|
-
end
|
29
|
-
|
19
|
+
require 'sys/proctable'
|
30
20
|
include Sys
|
31
21
|
|
32
|
-
|
33
|
-
IO.popen("notepad")
|
34
|
-
sleep 1
|
22
|
+
class TC_Win32Process < Test::Unit::TestCase
|
35
23
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
24
|
+
# Start two instances of notepad and give them a chance to fire up
|
25
|
+
def self.startup
|
26
|
+
IO.popen('notepad')
|
27
|
+
IO.popen('notepad')
|
28
|
+
sleep 1 # Give the notepad instances a second to startup
|
29
|
+
|
30
|
+
@@pids = []
|
31
|
+
|
32
|
+
ProcTable.ps{ |struct|
|
33
|
+
next unless struct.comm =~ /notepad/i
|
34
|
+
@@pids << struct.pid
|
35
|
+
}
|
36
|
+
end
|
41
37
|
|
42
|
-
class TC_Win32Process < Test::Unit::TestCase
|
43
38
|
def setup
|
44
|
-
@pids = $pids
|
45
39
|
@pid = nil
|
46
40
|
end
|
47
41
|
|
48
42
|
def test_version
|
49
|
-
assert_equal('0.
|
43
|
+
assert_equal('0.6.0', Process::WIN32_PROCESS_VERSION)
|
50
44
|
end
|
51
45
|
|
52
46
|
def test_kill
|
@@ -56,23 +50,23 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
56
50
|
def test_kill_expected_errors
|
57
51
|
assert_raises(ArgumentError){ Process.kill }
|
58
52
|
assert_raises(Process::Error){ Process.kill('SIGBOGUS') }
|
59
|
-
assert_raises(Process::Error){ Process.kill(0,9999999) }
|
53
|
+
assert_raises(Process::Error){ Process.kill(0, 9999999) }
|
60
54
|
end
|
61
55
|
|
62
56
|
def test_kill_signal_0
|
63
|
-
pid =
|
57
|
+
pid = @@pids.first
|
64
58
|
assert_nothing_raised{ Process.kill(0, pid) }
|
65
59
|
end
|
66
60
|
|
67
61
|
def test_kill_signal_1
|
68
|
-
pid =
|
62
|
+
pid = @@pids.shift
|
69
63
|
assert_nothing_raised{ Process.kill(1, pid) }
|
70
64
|
end
|
71
65
|
|
72
66
|
def test_kill_signal_9
|
73
|
-
pid =
|
67
|
+
pid = @@pids.pop
|
74
68
|
msg = "Could not find pid #{pid}"
|
75
|
-
assert_nothing_raised(msg){ Process.kill(9,pid) }
|
69
|
+
assert_nothing_raised(msg){ Process.kill(9, pid) }
|
76
70
|
end
|
77
71
|
|
78
72
|
def test_fork
|
@@ -81,6 +75,7 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
81
75
|
|
82
76
|
def test_create
|
83
77
|
assert_respond_to(Process, :create)
|
78
|
+
|
84
79
|
assert_nothing_raised{
|
85
80
|
@pid = Process.create(
|
86
81
|
:app_name => "notepad.exe",
|
@@ -90,6 +85,7 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
90
85
|
:cwd => "C:\\"
|
91
86
|
).process_id
|
92
87
|
}
|
88
|
+
|
93
89
|
assert_nothing_raised{ Process.kill(1, @pid) }
|
94
90
|
end
|
95
91
|
|
@@ -137,6 +133,10 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
137
133
|
end
|
138
134
|
|
139
135
|
def teardown
|
140
|
-
@
|
141
|
-
end
|
136
|
+
@pid = nil
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.shutdown
|
140
|
+
@@pids = []
|
141
|
+
end
|
142
142
|
end
|
data/win32-process.gemspec
CHANGED
@@ -3,7 +3,7 @@ require "rubygems"
|
|
3
3
|
spec = Gem::Specification.new do |gem|
|
4
4
|
desc = "Adds create, fork, wait, wait2, waitpid, and a special kill method"
|
5
5
|
gem.name = "win32-process"
|
6
|
-
gem.version = "0.
|
6
|
+
gem.version = "0.6.0"
|
7
7
|
gem.authors = ['Daniel Berger', 'Park Heesob']
|
8
8
|
gem.email = "djberg96@gmail.com"
|
9
9
|
gem.rubyforge_project = 'win32utils'
|
@@ -11,9 +11,9 @@ spec = Gem::Specification.new do |gem|
|
|
11
11
|
gem.platform = Gem::Platform::RUBY
|
12
12
|
gem.summary = desc
|
13
13
|
gem.description = desc
|
14
|
-
gem.
|
14
|
+
gem.test_files = Dir["test/*.rb"]
|
15
15
|
gem.has_rdoc = true
|
16
|
-
gem.files = Dir["lib/win32/*.rb"] + Dir["test/*"] + Dir["[A-Z]*"]
|
16
|
+
gem.files = Dir["lib/win32/*.rb"] + Dir["test/*"] + Dir["[A-Z]*"] + Dir["examples/*"]
|
17
17
|
gem.files.reject! { |fn| fn.include? "CVS" }
|
18
18
|
gem.require_path = "lib"
|
19
19
|
gem.extra_rdoc_files = ["README", "CHANGES", "MANIFEST"]
|
@@ -21,6 +21,6 @@ spec = Gem::Specification.new do |gem|
|
|
21
21
|
end
|
22
22
|
|
23
23
|
if $0 == __FILE__
|
24
|
-
Gem.manage_gems
|
24
|
+
Gem.manage_gems if Gem::RubyGemsVersion.to_f < 1.3
|
25
25
|
Gem::Builder.new(spec).build
|
26
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-process
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Berger
|
@@ -10,11 +10,12 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2008-
|
13
|
+
date: 2008-10-31 00:00:00 -06:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: windows-pr
|
18
|
+
type: :runtime
|
18
19
|
version_requirement:
|
19
20
|
version_requirements: !ruby/object:Gem::Requirement
|
20
21
|
requirements:
|
@@ -34,10 +35,8 @@ extra_rdoc_files:
|
|
34
35
|
- MANIFEST
|
35
36
|
files:
|
36
37
|
- lib/win32/process.rb
|
37
|
-
- test/
|
38
|
-
- test/tc_process.rb
|
38
|
+
- test/test_win32_process.rb
|
39
39
|
- CHANGES
|
40
|
-
- CVS
|
41
40
|
- examples
|
42
41
|
- lib
|
43
42
|
- MANIFEST
|
@@ -45,6 +44,10 @@ files:
|
|
45
44
|
- README
|
46
45
|
- test
|
47
46
|
- win32-process.gemspec
|
47
|
+
- examples/test_create.rb
|
48
|
+
- examples/test_fork_wait.rb
|
49
|
+
- examples/test_fork_waitpid.rb
|
50
|
+
- examples/test_kill.rb
|
48
51
|
has_rdoc: true
|
49
52
|
homepage: http://www.rubyforge.org/projects/win32utils
|
50
53
|
post_install_message:
|
@@ -67,9 +70,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
70
|
requirements: []
|
68
71
|
|
69
72
|
rubyforge_project: win32utils
|
70
|
-
rubygems_version: 1.
|
73
|
+
rubygems_version: 1.3.1
|
71
74
|
signing_key:
|
72
75
|
specification_version: 2
|
73
76
|
summary: Adds create, fork, wait, wait2, waitpid, and a special kill method
|
74
77
|
test_files:
|
75
|
-
- test/
|
78
|
+
- test/test_win32_process.rb
|