win32-process 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +8 -0
- data/lib/win32/process.rb +31 -21
- data/test/tc_process.rb +6 -4
- data/win32-process.gemspec +2 -2
- metadata +51 -45
- data/test/tc_process.rb~ +0 -134
data/CHANGES
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 0.5.4 - 23-Nov-2007
|
2
|
+
* Changed ProcessError to Process::Error.
|
3
|
+
* Now requires windows-pr 0.7.3 or later because of some reorganization in
|
4
|
+
that library with regards to thread functions.
|
5
|
+
* Better cleanup of HANDLE's in a couple methods when failure occurs.
|
6
|
+
* Added an additional require/include necessitated by a change in the method
|
7
|
+
organization in the windows-pr library.
|
8
|
+
|
1
9
|
== 0.5.3 - 29-Jul-2007
|
2
10
|
* Added a Rakefile with tasks for installation and testing.
|
3
11
|
* Removed the install.rb file (now handled by the Rakefile).
|
data/lib/win32/process.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
require 'windows/error'
|
2
2
|
require 'windows/process'
|
3
|
+
require 'windows/thread'
|
3
4
|
require 'windows/synchronize'
|
4
5
|
require 'windows/handle'
|
5
6
|
require 'windows/library'
|
6
7
|
require 'windows/console'
|
7
8
|
require 'windows/window'
|
8
9
|
|
9
|
-
class ProcessError < RuntimeError; end
|
10
|
-
|
11
10
|
module Process
|
12
|
-
|
11
|
+
class Error < RuntimeError; end
|
12
|
+
|
13
|
+
WIN32_PROCESS_VERSION = '0.5.4'
|
13
14
|
|
14
15
|
include Windows::Process
|
16
|
+
include Windows::Thread
|
15
17
|
include Windows::Error
|
16
18
|
include Windows::Library
|
17
19
|
include Windows::Console
|
@@ -20,6 +22,7 @@ module Process
|
|
20
22
|
include Windows::Window
|
21
23
|
extend Windows::Error
|
22
24
|
extend Windows::Process
|
25
|
+
extend Windows::Thread
|
23
26
|
extend Windows::Synchronize
|
24
27
|
extend Windows::Handle
|
25
28
|
extend Windows::Library
|
@@ -46,14 +49,16 @@ module Process
|
|
46
49
|
handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
|
47
50
|
|
48
51
|
if handle == INVALID_HANDLE_VALUE
|
49
|
-
raise
|
52
|
+
raise Error, get_last_error
|
50
53
|
end
|
51
54
|
|
52
55
|
# TODO: update the $? global variable (if/when possible)
|
53
56
|
status = WaitForSingleObject(handle, INFINITE)
|
54
57
|
|
55
58
|
unless GetExitCodeProcess(handle, exit_code)
|
56
|
-
|
59
|
+
error = get_last_error
|
60
|
+
CloseHandle(handle)
|
61
|
+
raise Error, error
|
57
62
|
end
|
58
63
|
|
59
64
|
CloseHandle(handle)
|
@@ -76,14 +81,16 @@ module Process
|
|
76
81
|
handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
|
77
82
|
|
78
83
|
if handle == INVALID_HANDLE_VALUE
|
79
|
-
raise
|
84
|
+
raise Error, get_last_error
|
80
85
|
end
|
81
86
|
|
82
87
|
# TODO: update the $? global variable (if/when possible)
|
83
88
|
status = WaitForSingleObject(handle, INFINITE)
|
84
89
|
|
85
90
|
unless GetExitCodeProcess(handle, exit_code)
|
86
|
-
|
91
|
+
error = get_last_error
|
92
|
+
CloseHandle(handle)
|
93
|
+
raise Error, errorast_error
|
87
94
|
end
|
88
95
|
|
89
96
|
CloseHandle(handle)
|
@@ -124,7 +131,7 @@ module Process
|
|
124
131
|
when 0..9
|
125
132
|
# Do nothing
|
126
133
|
else
|
127
|
-
raise
|
134
|
+
raise Error, "Invalid signal '#{signal}'"
|
128
135
|
end
|
129
136
|
|
130
137
|
killed_pids = []
|
@@ -153,7 +160,7 @@ module Process
|
|
153
160
|
if GetLastError() == ERROR_ACCESS_DENIED
|
154
161
|
killed_pids.push(pid)
|
155
162
|
else
|
156
|
-
raise
|
163
|
+
raise Error, get_last_error
|
157
164
|
end
|
158
165
|
end
|
159
166
|
when 2
|
@@ -170,7 +177,7 @@ module Process
|
|
170
177
|
killed_pids.push(pid)
|
171
178
|
@child_pids.delete(pid)
|
172
179
|
else
|
173
|
-
raise
|
180
|
+
raise Error, get_last_error
|
174
181
|
end
|
175
182
|
else
|
176
183
|
if handle != 0
|
@@ -195,10 +202,10 @@ module Process
|
|
195
202
|
@child_pids.delete(pid)
|
196
203
|
else
|
197
204
|
CloseHandle(handle)
|
198
|
-
raise
|
205
|
+
raise Error, get_last_error
|
199
206
|
end
|
200
207
|
else
|
201
|
-
raise
|
208
|
+
raise Error, get_last_error
|
202
209
|
end
|
203
210
|
@child_pids.delete(pid)
|
204
211
|
end
|
@@ -211,7 +218,7 @@ module Process
|
|
211
218
|
#
|
212
219
|
# This is a wrapper for the CreateProcess() function. It executes a process,
|
213
220
|
# returning a ProcessInfo struct. It accepts a hash as an argument.
|
214
|
-
# There are
|
221
|
+
# There are eight primary keys:
|
215
222
|
#
|
216
223
|
# * app_name (mandatory)
|
217
224
|
# * inherit (default: false)
|
@@ -287,7 +294,7 @@ module Process
|
|
287
294
|
args.each{ |key, val|
|
288
295
|
key = key.to_s.downcase
|
289
296
|
unless valid_keys.include?(key)
|
290
|
-
raise
|
297
|
+
raise Error, "invalid key '#{key}'"
|
291
298
|
end
|
292
299
|
|
293
300
|
# Convert true to 1 and nil/false to 0.
|
@@ -308,7 +315,7 @@ module Process
|
|
308
315
|
hash['startup_info'].each{ |key, val|
|
309
316
|
key = key.to_s.downcase
|
310
317
|
unless valid_si_keys.include?(key)
|
311
|
-
raise
|
318
|
+
raise Error, "invalid startup_info key '#{key}'"
|
312
319
|
end
|
313
320
|
si_hash[key] = val
|
314
321
|
}
|
@@ -316,7 +323,7 @@ module Process
|
|
316
323
|
|
317
324
|
# The +app_name+ key is mandatory
|
318
325
|
unless hash['app_name']
|
319
|
-
raise
|
326
|
+
raise Error, 'app_name must be specified'
|
320
327
|
end
|
321
328
|
|
322
329
|
# The environment string should be passed as a string of ';' separated
|
@@ -357,7 +364,7 @@ module Process
|
|
357
364
|
end
|
358
365
|
|
359
366
|
if handle == INVALID_HANDLE_VALUE
|
360
|
-
raise
|
367
|
+
raise Error, get_last_error
|
361
368
|
end
|
362
369
|
|
363
370
|
si_hash[io] = handle
|
@@ -397,7 +404,7 @@ module Process
|
|
397
404
|
)
|
398
405
|
|
399
406
|
unless bool
|
400
|
-
raise
|
407
|
+
raise Error, "CreateProcess() failed: ", get_last_error
|
401
408
|
end
|
402
409
|
|
403
410
|
ProcessInfo.new(
|
@@ -430,7 +437,7 @@ module Process
|
|
430
437
|
|
431
438
|
if handles[i] == INVALID_HANDLE_VALUE
|
432
439
|
err = "unable to get HANDLE on process associated with pid #{pid}"
|
433
|
-
raise
|
440
|
+
raise Error, err
|
434
441
|
end
|
435
442
|
|
436
443
|
unless defined? GetProcessId
|
@@ -485,7 +492,7 @@ module Process
|
|
485
492
|
|
486
493
|
if handles[i] == INVALID_HANDLE_VALUE
|
487
494
|
err = "unable to get HANDLE on process associated with pid #{pid}"
|
488
|
-
raise
|
495
|
+
raise Error, err
|
489
496
|
end
|
490
497
|
|
491
498
|
unless defined? GetProcessId
|
@@ -565,7 +572,7 @@ module Process
|
|
565
572
|
rv = CreateProcess(0, cmd, 0, 0, 1, 0, 0, 0, startinfo, procinfo)
|
566
573
|
|
567
574
|
if rv == 0
|
568
|
-
raise
|
575
|
+
raise Error, get_last_error
|
569
576
|
end
|
570
577
|
|
571
578
|
pid = procinfo[8,4].unpack('L').first
|
@@ -577,6 +584,9 @@ module Process
|
|
577
584
|
module_function :kill, :wait, :wait2, :waitpid, :waitpid2, :create, :fork
|
578
585
|
end
|
579
586
|
|
587
|
+
# For backwards compatibility. Deprecated.
|
588
|
+
ProcessError = Process::Error
|
589
|
+
|
580
590
|
# Create a global fork method
|
581
591
|
module Kernel
|
582
592
|
def fork(&block)
|
data/test/tc_process.rb
CHANGED
@@ -43,7 +43,7 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def test_version
|
46
|
-
assert_equal('0.5.
|
46
|
+
assert_equal('0.5.4', Process::WIN32_PROCESS_VERSION)
|
47
47
|
end
|
48
48
|
|
49
49
|
def test_kill
|
@@ -52,8 +52,8 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
52
52
|
|
53
53
|
def test_kill_expected_errors
|
54
54
|
assert_raises(ArgumentError){ Process.kill }
|
55
|
-
assert_raises(
|
56
|
-
assert_raises(
|
55
|
+
assert_raises(Process::Error){ Process.kill('SIGBOGUS') }
|
56
|
+
assert_raises(Process::Error){ Process.kill(0,9999999) }
|
57
57
|
end
|
58
58
|
|
59
59
|
def test_kill_signal_0
|
@@ -92,7 +92,9 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
92
92
|
|
93
93
|
def test_create_expected_errors
|
94
94
|
assert_raises(TypeError){ Process.create("bogusapp.exe") }
|
95
|
-
assert_raises(
|
95
|
+
assert_raises(Process::Error){
|
96
|
+
Process.create(:app_name => "bogusapp.exe")
|
97
|
+
}
|
96
98
|
end
|
97
99
|
|
98
100
|
def test_wait
|
data/win32-process.gemspec
CHANGED
@@ -2,7 +2,7 @@ require "rubygems"
|
|
2
2
|
|
3
3
|
spec = Gem::Specification.new do |gem|
|
4
4
|
gem.name = "win32-process"
|
5
|
-
gem.version = "0.5.
|
5
|
+
gem.version = "0.5.4"
|
6
6
|
gem.author = "Daniel J. Berger"
|
7
7
|
gem.email = "djberg96@gmail.com"
|
8
8
|
gem.homepage = "http://www.rubyforge.org/projects/win32utils"
|
@@ -15,7 +15,7 @@ spec = Gem::Specification.new do |gem|
|
|
15
15
|
gem.files.reject! { |fn| fn.include? "CVS" }
|
16
16
|
gem.require_path = "lib"
|
17
17
|
gem.extra_rdoc_files = ["README", "CHANGES", "MANIFEST"]
|
18
|
-
gem.add_dependency("windows-pr", ">= 0.
|
18
|
+
gem.add_dependency("windows-pr", ">= 0.7.3")
|
19
19
|
end
|
20
20
|
|
21
21
|
if $0 == __FILE__
|
metadata
CHANGED
@@ -1,38 +1,40 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.4
|
3
|
-
specification_version: 1
|
4
2
|
name: win32-process
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.5.
|
7
|
-
date: 2007-07-29 00:00:00 -06:00
|
8
|
-
summary: Adds fork, wait, wait2, waitpid, waitpid2 and a special kill method
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: djberg96@gmail.com
|
12
|
-
homepage: http://www.rubyforge.org/projects/win32utils
|
13
|
-
rubyforge_project:
|
14
|
-
description: Adds fork, wait, wait2, waitpid, waitpid2 and a special kill method
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 0.5.4
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Daniel J. Berger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-11-23 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: windows-pr
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.7.3
|
23
|
+
version:
|
24
|
+
description: Adds fork, wait, wait2, waitpid, waitpid2 and a special kill method
|
25
|
+
email: djberg96@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README
|
32
|
+
- CHANGES
|
33
|
+
- MANIFEST
|
31
34
|
files:
|
32
35
|
- lib/win32/process.rb
|
33
36
|
- test/CVS
|
34
37
|
- test/tc_process.rb
|
35
|
-
- test/tc_process.rb~
|
36
38
|
- CHANGES
|
37
39
|
- CVS
|
38
40
|
- examples
|
@@ -42,27 +44,31 @@ files:
|
|
42
44
|
- README
|
43
45
|
- test
|
44
46
|
- win32-process.gemspec
|
45
|
-
|
46
|
-
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://www.rubyforge.org/projects/win32utils
|
49
|
+
post_install_message:
|
47
50
|
rdoc_options: []
|
48
51
|
|
49
|
-
|
50
|
-
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
57
66
|
requirements: []
|
58
67
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: 0.5.2
|
68
|
-
version:
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 0.9.5
|
70
|
+
signing_key:
|
71
|
+
specification_version: 2
|
72
|
+
summary: Adds fork, wait, wait2, waitpid, waitpid2 and a special kill method
|
73
|
+
test_files:
|
74
|
+
- test/tc_process.rb
|
data/test/tc_process.rb~
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
###############################################################################
|
2
|
-
# tc_process.rb
|
3
|
-
#
|
4
|
-
# Test suite for the win32-process package. This test suite will start
|
5
|
-
# at least two instances of Notepad on your system, which will then
|
6
|
-
# be killed. Requires the sys-proctable package.
|
7
|
-
#
|
8
|
-
# I haven't added a lot of test cases for fork/wait because it's difficult
|
9
|
-
# to run such tests without causing havoc with TestUnit itself. Ideas
|
10
|
-
# welcome.
|
11
|
-
###############################################################################
|
12
|
-
Dir.chdir('..') if File.basename(Dir.pwd) == 'test'
|
13
|
-
$LOAD_PATH.unshift Dir.pwd
|
14
|
-
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
15
|
-
Dir.chdir('test') rescue nil
|
16
|
-
|
17
|
-
require 'test/unit'
|
18
|
-
require 'win32/process'
|
19
|
-
|
20
|
-
begin
|
21
|
-
require 'sys/proctable'
|
22
|
-
rescue LoadError => e
|
23
|
-
site = 'http://www.rubyforge.org/projects/sysutils'
|
24
|
-
STDERR.puts "Stopping!"
|
25
|
-
STDERR.puts "The sys/proctable module is required to run this test suite."
|
26
|
-
STDERR.puts "You can find it at #{site} or the RAA"
|
27
|
-
exit!
|
28
|
-
end
|
29
|
-
|
30
|
-
include Sys
|
31
|
-
|
32
|
-
IO.popen("notepad")
|
33
|
-
IO.popen("notepad")
|
34
|
-
sleep 1
|
35
|
-
|
36
|
-
$pids = []
|
37
|
-
ProcTable.ps{ |s|
|
38
|
-
next unless s.comm =~ /notepad/i
|
39
|
-
$pids.push(s.pid)
|
40
|
-
}
|
41
|
-
|
42
|
-
class TC_Win32Process < Test::Unit::TestCase
|
43
|
-
def setup
|
44
|
-
@pids = $pids
|
45
|
-
@pid = nil
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_version
|
49
|
-
assert_equal('0.5.3', Process::WIN32_PROCESS_VERSION)
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_kill
|
53
|
-
assert_respond_to(Process, :kill)
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_kill_expected_errors
|
57
|
-
assert_raises(ArgumentError){ Process.kill }
|
58
|
-
assert_raises(ProcessError){ Process.kill('SIGBOGUS') }
|
59
|
-
assert_raises(ProcessError){ Process.kill(0,9999999) }
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_kill_signal_0
|
63
|
-
pid = @pids.first
|
64
|
-
assert_nothing_raised{ Process.kill(0, pid) }
|
65
|
-
end
|
66
|
-
|
67
|
-
def test_kill_signal_1
|
68
|
-
pid = @pids.shift
|
69
|
-
assert_nothing_raised{ Process.kill(1, pid) }
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_kill_signal_9
|
73
|
-
pid = @pids.pop
|
74
|
-
msg = "Could not find pid #{pid}"
|
75
|
-
assert_nothing_raised(msg){ Process.kill(9,pid) }
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_fork
|
79
|
-
assert_respond_to(Process, :fork)
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_create
|
83
|
-
assert_respond_to(Process, :create)
|
84
|
-
assert_nothing_raised{
|
85
|
-
@pid = Process.create(
|
86
|
-
:app_name => "notepad.exe",
|
87
|
-
:creation_flags => Process::DETACHED_PROCESS,
|
88
|
-
:process_inherit => false,
|
89
|
-
:thread_inherit => true,
|
90
|
-
:cwd => "C:\\"
|
91
|
-
).process_id
|
92
|
-
}
|
93
|
-
assert_nothing_raised{ Process.kill(1, @pid) }
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_create_expected_errors
|
97
|
-
assert_raises(TypeError){ Process.create("bogusapp.exe") }
|
98
|
-
assert_raises(ProcessError){ Process.create(:app_name => "bogusapp.exe") }
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_wait
|
102
|
-
assert_respond_to(Process, :wait)
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_wait2
|
106
|
-
assert_respond_to(Process, :wait2)
|
107
|
-
end
|
108
|
-
|
109
|
-
def test_waitpid
|
110
|
-
assert_respond_to(Process, :waitpid)
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_waitpid2
|
114
|
-
assert_respond_to(Process, :waitpid2)
|
115
|
-
end
|
116
|
-
|
117
|
-
def test_creation_constants
|
118
|
-
assert_not_nil(Process::CREATE_DEFAULT_ERROR_MODE)
|
119
|
-
assert_not_nil(Process::CREATE_NEW_CONSOLE)
|
120
|
-
assert_not_nil(Process::CREATE_NEW_PROCESS_GROUP)
|
121
|
-
assert_not_nil(Process::CREATE_NO_WINDOW)
|
122
|
-
assert_not_nil(Process::CREATE_SEPARATE_WOW_VDM)
|
123
|
-
assert_not_nil(Process::CREATE_SHARED_WOW_VDM)
|
124
|
-
assert_not_nil(Process::CREATE_SUSPENDED)
|
125
|
-
assert_not_nil(Process::CREATE_UNICODE_ENVIRONMENT)
|
126
|
-
assert_not_nil(Process::DEBUG_ONLY_THIS_PROCESS)
|
127
|
-
assert_not_nil(Process::DEBUG_PROCESS)
|
128
|
-
assert_not_nil(Process::DETACHED_PROCESS)
|
129
|
-
end
|
130
|
-
|
131
|
-
def teardown
|
132
|
-
@pids = []
|
133
|
-
end
|
134
|
-
end
|