win32-process 0.5.9 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|