win32-process 0.7.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +74 -0
- data/lib/win32-process.rb +1 -0
- data/lib/win32/process.rb +210 -12
- data/lib/win32/process/constants.rb +8 -0
- data/lib/win32/process/functions.rb +21 -8
- data/lib/win32/process/helper.rb +1 -1
- data/lib/win32/process/structs.rb +101 -1
- data/test/test_win32_process.rb +18 -1
- data/test/test_win32_process_kill.rb +0 -22
- data/win32-process.gemspec +12 -17
- metadata +9 -44
- data/CHANGES +0 -250
- data/MANIFEST +0 -13
- data/README +0 -78
- data/Rakefile +0 -63
- data/examples/example_create.rb +0 -35
- data/examples/example_kill.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5f5cdcabac1da0aebf77bd252b0647899dfee2632e34e626f18a9951a9d17e62
|
4
|
+
data.tar.gz: 39382a91f43eba2e0c00f1b92e3f53de3a49b87e689b22683cf5c08f395077b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe1ba6453b70b3712322a588b83708c2eb5f657d97e443c974162be290f009488c28ddb57de1212bcb141a57006f6d0db2e59244b19583da21265df2cab35d83
|
7
|
+
data.tar.gz: b38df396da190521cbf3fa0975e8087d6f7435956996716b3fe3416ae0d5565e32787c3794a943a7f74c98cb4d31b8c704882b53f6a88d265c7e334a1da1923b
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# win32-process
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/win32-process.svg)](https://badge.fury.io/rb/win32-process)
|
4
|
+
|
5
|
+
This library provides analogues of the :getpriority, :setpriority, :getrlimit, :setrlimit and :uid methods for MS Windows. It also adds the new methods :job?, :get_affinity, and :create, and redefines the :kill method.
|
6
|
+
|
7
|
+
## Prerequisites
|
8
|
+
|
9
|
+
- ffi
|
10
|
+
- sys-proctable (dev only)
|
11
|
+
- test-unit 2 (dev only)
|
12
|
+
|
13
|
+
## Supported Platforms
|
14
|
+
|
15
|
+
This library is supported on Windows 2000 or later.
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
```
|
20
|
+
gem install win32-process
|
21
|
+
```
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'win32/process'
|
27
|
+
|
28
|
+
p Process.job? # => true or false
|
29
|
+
|
30
|
+
info = Process.create( :app_name => "notepad.exe", :creation_flags => Process::DETACHED_PROCESS, :process_inherit => false, :thread_inherit => true, :cwd => "C:\" )
|
31
|
+
|
32
|
+
p info.process_id
|
33
|
+
```
|
34
|
+
|
35
|
+
## Developer's Notes
|
36
|
+
|
37
|
+
### Removal of Process.fork in release 0.7.0
|
38
|
+
|
39
|
+
The Process.fork method was originally experimental but it has never been particularly useful in practice. On top of that, it required special implementations of the Process.waitXXX methods, so it was a maintenance issue as well.
|
40
|
+
|
41
|
+
With Ruby 1.9 now becoming standard and its addition of Process.spawn and friends (and concomitant support for the Process.waitXXX methods) I felt it was time to remove it.
|
42
|
+
|
43
|
+
You can still simulate Process.fork if you like using Process.create, which is how it was implemented internally anyway. A better solution might be to follow in the footsteps of ActiveState Perl, which uses native threads to simulate fork on Windows.
|
44
|
+
|
45
|
+
### Changes in the custom Process.kill method for 0.7.0
|
46
|
+
|
47
|
+
The Process.kill method in 0.7.0 more closely matches the spec now, but the internal method for killing processes is still nicer for most signals. With the release of 0.7.0 users can now specify options that provide finer control over how a process is killed. See the documentation for details.
|
48
|
+
|
49
|
+
## The removal of the custom Process.ppid method
|
50
|
+
|
51
|
+
This was added at some point in the Ruby 1.9 dev cycle so it was removed from this library.
|
52
|
+
|
53
|
+
## Known Issues
|
54
|
+
|
55
|
+
JRuby doesn't seem to like SIGBRK for Process.kill.
|
56
|
+
|
57
|
+
Any issues or bugs should be reported on the project page at <https://github.com/djberg96/win32-process>.
|
58
|
+
|
59
|
+
## License
|
60
|
+
|
61
|
+
Artistic 2.0
|
62
|
+
|
63
|
+
## Copyright
|
64
|
+
|
65
|
+
(C) 2003-2015 Daniel J. Berger All Rights Reserved
|
66
|
+
|
67
|
+
## Warranty
|
68
|
+
|
69
|
+
This library is provided "as is" and without any express or implied warranties, including, without limitation, the implied warranties of merchantability and fitness for a particular purpose.
|
70
|
+
|
71
|
+
## Author(s)
|
72
|
+
|
73
|
+
- Park Heesob
|
74
|
+
- Daniel J. Berger
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'win32/process'
|
data/lib/win32/process.rb
CHANGED
@@ -10,7 +10,7 @@ module Process
|
|
10
10
|
extend Process::Constants
|
11
11
|
|
12
12
|
# The version of the win32-process library.
|
13
|
-
WIN32_PROCESS_VERSION = '0.
|
13
|
+
WIN32_PROCESS_VERSION = '0.9.0'
|
14
14
|
|
15
15
|
# Disable popups. This mostly affects the Process.kill method.
|
16
16
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)
|
@@ -99,7 +99,7 @@ module Process
|
|
99
99
|
raise TypeError, int unless int.is_a?(Fixnum) # Match spec
|
100
100
|
int = Process.pid if int == 0 # Match spec
|
101
101
|
|
102
|
-
handle = OpenProcess(PROCESS_QUERY_INFORMATION,
|
102
|
+
handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, int)
|
103
103
|
|
104
104
|
if handle == 0
|
105
105
|
raise SystemCallError, FFI.errno, "OpenProcess"
|
@@ -141,7 +141,7 @@ module Process
|
|
141
141
|
raise TypeError unless int_priority.is_a?(Integer) # Match spec
|
142
142
|
int = Process.pid if int == 0 # Match spec
|
143
143
|
|
144
|
-
handle = OpenProcess(PROCESS_SET_INFORMATION,
|
144
|
+
handle = OpenProcess(PROCESS_SET_INFORMATION, 0 , int)
|
145
145
|
|
146
146
|
if handle == 0
|
147
147
|
raise SystemCallError, FFI.errno, "OpenProcess"
|
@@ -256,7 +256,7 @@ module Process
|
|
256
256
|
|
257
257
|
# Put the current process in a job if it's not already in one
|
258
258
|
if in_job && defined?(@win32_process_job_name)
|
259
|
-
handle = OpenJobObjectA(JOB_OBJECT_QUERY,
|
259
|
+
handle = OpenJobObjectA(JOB_OBJECT_QUERY, 1, @win32_process_job_name)
|
260
260
|
raise SystemCallError, FFI.errno, "OpenJobObject" if handle == 0
|
261
261
|
else
|
262
262
|
@win32_process_job_name = 'ruby_' + Process.pid.to_s
|
@@ -347,7 +347,7 @@ module Process
|
|
347
347
|
|
348
348
|
# Put the current process in a job if it's not already in one
|
349
349
|
if in_job && defined? @win32_process_job_name
|
350
|
-
handle = OpenJobObjectA(JOB_OBJECT_SET_ATTRIBUTES,
|
350
|
+
handle = OpenJobObjectA(JOB_OBJECT_SET_ATTRIBUTES, 1, @win32_process_job_name)
|
351
351
|
raise SystemCallError, FFI.errno, "OpenJobObject" if handle == 0
|
352
352
|
else
|
353
353
|
@win32_process_job_name = 'ruby_' + Process.pid.to_s
|
@@ -543,7 +543,7 @@ module Process
|
|
543
543
|
if hash['process_inherit']
|
544
544
|
process_security = SECURITY_ATTRIBUTES.new
|
545
545
|
process_security[:nLength] = 12
|
546
|
-
process_security[:bInheritHandle] =
|
546
|
+
process_security[:bInheritHandle] = 1
|
547
547
|
end
|
548
548
|
|
549
549
|
# Thread SECURITY_ATTRIBUTE structure
|
@@ -552,7 +552,7 @@ module Process
|
|
552
552
|
if hash['thread_inherit']
|
553
553
|
thread_security = SECURITY_ATTRIBUTES.new
|
554
554
|
thread_security[:nLength] = 12
|
555
|
-
thread_security[:bInheritHandle] =
|
555
|
+
thread_security[:bInheritHandle] = 1
|
556
556
|
end
|
557
557
|
|
558
558
|
# Automatically handle stdin, stdout and stderr as either IO objects
|
@@ -668,7 +668,7 @@ module Process
|
|
668
668
|
raise SystemCallError.new("CreateProcessWithLogonW", FFI.errno)
|
669
669
|
end
|
670
670
|
else
|
671
|
-
inherit
|
671
|
+
inherit = hash['inherit'] ? 1 : 0
|
672
672
|
|
673
673
|
bool = CreateProcessW(
|
674
674
|
app, # App name
|
@@ -741,8 +741,6 @@ module Process
|
|
741
741
|
# Process.kill(1, 12345, :exit_proc => 'ExitProcess', :module => 'kernel32')
|
742
742
|
#
|
743
743
|
def kill(signal, *pids)
|
744
|
-
raise SecurityError if $SAFE && $SAFE >= 2 # Match the spec
|
745
|
-
|
746
744
|
# Match the spec, require at least 2 arguments
|
747
745
|
if pids.length == 0
|
748
746
|
raise ArgumentError, "wrong number of arguments (1 for at least 2)"
|
@@ -814,7 +812,7 @@ module Process
|
|
814
812
|
end
|
815
813
|
|
816
814
|
begin
|
817
|
-
handle = OpenProcess(access,
|
815
|
+
handle = OpenProcess(access, 0, pid)
|
818
816
|
|
819
817
|
if signal != 0 && handle == 0
|
820
818
|
raise SystemCallError, FFI.errno, "OpenProcess"
|
@@ -890,7 +888,7 @@ module Process
|
|
890
888
|
# when stdin, stdout or stderr are set to custom values.
|
891
889
|
#
|
892
890
|
def get_exitcode(pid)
|
893
|
-
handle = OpenProcess(PROCESS_QUERY_INFORMATION,
|
891
|
+
handle = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
|
894
892
|
|
895
893
|
if handle == INVALID_HANDLE_VALUE
|
896
894
|
raise SystemCallError.new("OpenProcess", FFI.errno)
|
@@ -914,6 +912,75 @@ module Process
|
|
914
912
|
exitcode
|
915
913
|
end
|
916
914
|
end
|
915
|
+
|
916
|
+
# Returns a list of process information structs in the form of a hash,
|
917
|
+
# with the pid as the key, and an array of information as the value of
|
918
|
+
# that key. The type of information in that array depends on the
|
919
|
+
# +info_type+ parameter. The possible values for +info_type+, and the
|
920
|
+
# type of information they each return is as follows:
|
921
|
+
#
|
922
|
+
# :thread => ThreadSnapInfo[:thread_id, :process_id, :base_priority]
|
923
|
+
# :heap => HeapSnapInfo[:address, :block_size, :flags, :process_id, :heap_id]
|
924
|
+
# :module => ModuleSnapInfo[:process_id, :address, :module_size, :handle, :name, :path]
|
925
|
+
# :process => ProcessSnapInfo[:process_id, :threads, :parent_process_id, :priority, :flags, :path]
|
926
|
+
#
|
927
|
+
# If no argument is provided, then :thread is assumed. Note that it is up
|
928
|
+
# to you to filter by pid if you wish.
|
929
|
+
#
|
930
|
+
# Example:
|
931
|
+
#
|
932
|
+
# # Get all thread info
|
933
|
+
# Process.snapshot.each{ |pid, v|
|
934
|
+
# puts "PID: #{pid}"
|
935
|
+
# p v
|
936
|
+
# }
|
937
|
+
#
|
938
|
+
# # Get module info for just the current process
|
939
|
+
# p Process.snapshot(:module)[Process.pid]
|
940
|
+
#
|
941
|
+
# # Get heap info for just the current process
|
942
|
+
# p Process.snapshot(:heap)[Process.pid]
|
943
|
+
#
|
944
|
+
# # Show pids of all running processes
|
945
|
+
# p Process.snapshot(:process).keys
|
946
|
+
#
|
947
|
+
def snapshot(info_type = 'thread')
|
948
|
+
case info_type.to_s.downcase
|
949
|
+
when 'thread'
|
950
|
+
flag = TH32CS_SNAPTHREAD
|
951
|
+
when 'heap'
|
952
|
+
flag = TH32CS_SNAPHEAPLIST
|
953
|
+
when 'module'
|
954
|
+
flag = TH32CS_SNAPMODULE
|
955
|
+
when 'process'
|
956
|
+
flag = TH32CS_SNAPPROCESS
|
957
|
+
else
|
958
|
+
raise ArgumentError, "info_type '#{info_type}' unsupported"
|
959
|
+
end
|
960
|
+
|
961
|
+
begin
|
962
|
+
handle = CreateToolhelp32Snapshot(flag, Process.pid)
|
963
|
+
|
964
|
+
if handle == INVALID_HANDLE_VALUE
|
965
|
+
raise SystemCallError.new('CreateToolhelp32Snapshot', FFI.errno)
|
966
|
+
end
|
967
|
+
|
968
|
+
case info_type.to_s.downcase
|
969
|
+
when 'thread'
|
970
|
+
array = get_thread_info(handle)
|
971
|
+
when 'heap'
|
972
|
+
array = get_heap_info(handle)
|
973
|
+
when 'module'
|
974
|
+
array = get_module_info(handle)
|
975
|
+
when 'process'
|
976
|
+
array = get_process_info(handle)
|
977
|
+
end
|
978
|
+
|
979
|
+
array
|
980
|
+
ensure
|
981
|
+
CloseHandle(handle) if handle
|
982
|
+
end
|
983
|
+
end
|
917
984
|
end
|
918
985
|
|
919
986
|
class << self
|
@@ -926,6 +993,137 @@ module Process
|
|
926
993
|
bool ? buf.read_string : nil
|
927
994
|
end
|
928
995
|
|
996
|
+
# Return thread info for Process.snapshot
|
997
|
+
def get_thread_info(handle, pid = nil)
|
998
|
+
lpte = THREADENTRY32.new
|
999
|
+
lpte[:dwSize] = lpte.size
|
1000
|
+
|
1001
|
+
hash = Hash.new{ |h,k| h[k] = [] }
|
1002
|
+
|
1003
|
+
if Thread32First(handle, lpte)
|
1004
|
+
hash[lpte[:th32OwnerProcessID]] << ThreadSnapInfo.new(lpte[:th32ThreadID], lpte[:th32OwnerProcessID], lpte[:tpBasePri])
|
1005
|
+
else
|
1006
|
+
if FFI.errno == ERROR_NO_MORE_FILES
|
1007
|
+
return hash
|
1008
|
+
else
|
1009
|
+
raise SystemCallError.new('Thread32First', FFI.errno)
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
while Thread32Next(handle, lpte)
|
1014
|
+
hash[lpte[:th32OwnerProcessID]] << ThreadSnapInfo.new(lpte[:th32ThreadID], lpte[:th32OwnerProcessID], lpte[:tpBasePri])
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
hash
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
# Return heap info for Process.snapshot
|
1021
|
+
def get_heap_info(handle)
|
1022
|
+
hash = Hash.new{ |h,k| h[k] = [] }
|
1023
|
+
|
1024
|
+
hl = HEAPLIST32.new
|
1025
|
+
hl[:dwSize] = hl.size
|
1026
|
+
|
1027
|
+
if Heap32ListFirst(handle, hl)
|
1028
|
+
while Heap32ListNext(handle, hl)
|
1029
|
+
he = HEAPENTRY32.new
|
1030
|
+
he[:dwSize] = he.size
|
1031
|
+
|
1032
|
+
if Heap32First(he, Process.pid, hl[:th32HeapID])
|
1033
|
+
hash[he[:th32ProcessID]] << HeapSnapInfo.new(he[:dwAddress], he[:dwBlockSize], he[:dwFlags], he[:th32ProcessID], he[:th32HeapID])
|
1034
|
+
else
|
1035
|
+
if FFI.errno == ERROR_NO_MORE_FILES
|
1036
|
+
break
|
1037
|
+
else
|
1038
|
+
raise SystemCallError.new('Heap32First', FFI.errno)
|
1039
|
+
end
|
1040
|
+
end
|
1041
|
+
|
1042
|
+
while Heap32Next(he)
|
1043
|
+
hash[he[:th32ProcessID]] << HeapSnapInfo.new(he[:dwAddress], he[:dwBlockSize], he[:dwFlags], he[:th32ProcessID], he[:th32HeapID])
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
hash
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
# Return module info for Process.snapshot
|
1052
|
+
def get_module_info(handle)
|
1053
|
+
hash = Hash.new{ |h,k| h[k] = [] }
|
1054
|
+
|
1055
|
+
me = MODULEENTRY32.new
|
1056
|
+
me[:dwSize] = me.size
|
1057
|
+
|
1058
|
+
if Module32First(handle, me)
|
1059
|
+
hash[me[:th32ProcessID]] << ModuleSnapInfo.new(
|
1060
|
+
me[:th32ProcessID],
|
1061
|
+
me[:modBaseAddr].to_i,
|
1062
|
+
me[:modBaseSize],
|
1063
|
+
me[:hModule],
|
1064
|
+
me[:szModule].to_s,
|
1065
|
+
me[:szExePath].to_s
|
1066
|
+
)
|
1067
|
+
else
|
1068
|
+
if FFI.errno == ERROR_NO_MORE_FILES
|
1069
|
+
return hash
|
1070
|
+
else
|
1071
|
+
raise SystemCallError.new('Module32First', FFI.errno)
|
1072
|
+
end
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
while Module32Next(handle, me)
|
1076
|
+
hash[me[:th32ProcessID]] << ModuleSnapInfo.new(
|
1077
|
+
me[:th32ProcessID],
|
1078
|
+
me[:modBaseAddr].to_i,
|
1079
|
+
me[:modBaseSize],
|
1080
|
+
me[:hModule],
|
1081
|
+
me[:szModule].to_s,
|
1082
|
+
me[:szExePath].to_s
|
1083
|
+
)
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
hash
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
# Return process info for Process.snapshot
|
1090
|
+
def get_process_info(handle)
|
1091
|
+
hash = Hash.new{ |h,k| h[k] = [] }
|
1092
|
+
|
1093
|
+
pe = PROCESSENTRY32.new
|
1094
|
+
pe[:dwSize] = pe.size
|
1095
|
+
|
1096
|
+
if Process32First(handle, pe)
|
1097
|
+
hash[pe[:th32ProcessID]] = ProcessSnapInfo.new(
|
1098
|
+
pe[:th32ProcessID],
|
1099
|
+
pe[:cntThreads],
|
1100
|
+
pe[:th32ParentProcessID],
|
1101
|
+
pe[:pcPriClassBase],
|
1102
|
+
pe[:dwFlags],
|
1103
|
+
pe[:szExeFile].to_s
|
1104
|
+
)
|
1105
|
+
else
|
1106
|
+
if FFI.errno == ERROR_NO_MORE_FILES
|
1107
|
+
return hash
|
1108
|
+
else
|
1109
|
+
raise SystemCallError.new('Process32First', FFI.errno)
|
1110
|
+
end
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
while Process32Next(handle, pe)
|
1114
|
+
hash[pe[:th32ProcessID]] = ProcessSnapInfo.new(
|
1115
|
+
pe[:th32ProcessID],
|
1116
|
+
pe[:cntThreads],
|
1117
|
+
pe[:th32ParentProcessID],
|
1118
|
+
pe[:pcPriClassBase],
|
1119
|
+
pe[:dwFlags],
|
1120
|
+
pe[:szExeFile].to_s
|
1121
|
+
)
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
hash
|
1125
|
+
end
|
1126
|
+
|
929
1127
|
# Private method that returns the Windows major version number.
|
930
1128
|
def windows_version
|
931
1129
|
ver = OSVERSIONINFO.new
|
@@ -110,4 +110,12 @@ module Process::Constants
|
|
110
110
|
# GetExitCodeProcess
|
111
111
|
|
112
112
|
STILL_ACTIVE = 259
|
113
|
+
|
114
|
+
# Snapshot constants
|
115
|
+
|
116
|
+
TH32CS_SNAPHEAPLIST = 0x00000001
|
117
|
+
TH32CS_SNAPPROCESS = 0x00000002
|
118
|
+
TH32CS_SNAPTHREAD = 0x00000004
|
119
|
+
TH32CS_SNAPMODULE = 0x00000008
|
120
|
+
ERROR_NO_MORE_FILES = 0x00000018
|
113
121
|
end
|
@@ -7,10 +7,12 @@ require 'ffi'
|
|
7
7
|
|
8
8
|
module Process::Functions
|
9
9
|
module FFI::Library
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
unless instance_methods.include?(:attach_pfunc)
|
11
|
+
# Wrapper method for attach_function + private
|
12
|
+
def attach_pfunc(*args)
|
13
|
+
attach_function(*args)
|
14
|
+
private args[0]
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -24,6 +26,7 @@ module Process::Functions
|
|
24
26
|
ffi_lib :kernel32
|
25
27
|
|
26
28
|
attach_pfunc :CloseHandle, [:handle], :bool
|
29
|
+
attach_pfunc :CreateToolhelp32Snapshot, [:dword, :dword], :handle
|
27
30
|
attach_pfunc :GenerateConsoleCtrlEvent, [:dword, :dword], :bool
|
28
31
|
attach_pfunc :GetCurrentProcess, [], :handle
|
29
32
|
attach_pfunc :GetModuleHandle, :GetModuleHandleA, [:string], :hmodule
|
@@ -31,12 +34,22 @@ module Process::Functions
|
|
31
34
|
attach_pfunc :GetPriorityClass, [:handle], :dword
|
32
35
|
attach_pfunc :GetProcAddress, [:hmodule, :string], :pointer
|
33
36
|
attach_pfunc :GetVersionExA, [:pointer], :bool
|
37
|
+
attach_pfunc :Heap32ListFirst, [:handle, :pointer], :bool
|
38
|
+
attach_pfunc :Heap32ListNext, [:handle, :pointer], :bool
|
39
|
+
attach_pfunc :Heap32First, [:pointer, :dword, :uintptr_t], :bool
|
40
|
+
attach_pfunc :Heap32Next, [:pointer], :bool
|
41
|
+
attach_pfunc :Module32First, [:handle, :pointer], :bool
|
42
|
+
attach_pfunc :Module32Next, [:handle, :pointer], :bool
|
34
43
|
attach_pfunc :IsProcessInJob, [:handle, :pointer, :pointer], :bool # 2nd arg optional
|
35
|
-
attach_pfunc :OpenProcess, [:dword, :
|
44
|
+
attach_pfunc :OpenProcess, [:dword, :int, :dword], :handle
|
45
|
+
attach_pfunc :Process32First, [:handle, :pointer], :bool
|
46
|
+
attach_pfunc :Process32Next, [:handle, :pointer], :bool
|
36
47
|
attach_pfunc :SetHandleInformation, [:handle, :dword, :dword], :bool
|
37
48
|
attach_pfunc :SetErrorMode, [:uint], :uint
|
38
49
|
attach_pfunc :SetPriorityClass, [:handle, :dword], :bool
|
39
50
|
attach_pfunc :TerminateProcess, [:handle, :uint], :bool
|
51
|
+
attach_pfunc :Thread32First, [:handle, :pointer], :bool
|
52
|
+
attach_pfunc :Thread32Next, [:handle, :pointer], :bool
|
40
53
|
attach_pfunc :WaitForSingleObject, [:handle, :dword], :dword
|
41
54
|
|
42
55
|
attach_pfunc :CreateRemoteThread,
|
@@ -46,12 +59,12 @@ module Process::Functions
|
|
46
59
|
[:string, :pointer, :dword, :pointer, :pointer, :pointer, :pointer, :dword], :bool
|
47
60
|
|
48
61
|
attach_pfunc :CreateProcessW,
|
49
|
-
[:buffer_in, :
|
62
|
+
[:buffer_in, :buffer_inout, :pointer, :pointer, :int,
|
50
63
|
:dword, :buffer_in, :buffer_in, :pointer, :pointer], :bool
|
51
64
|
|
52
65
|
attach_pfunc :AssignProcessToJobObject, [:handle, :handle], :bool
|
53
66
|
attach_pfunc :CreateJobObjectA, [:pointer, :string], :handle
|
54
|
-
attach_pfunc :OpenJobObjectA, [:dword, :
|
67
|
+
attach_pfunc :OpenJobObjectA, [:dword, :int, :string], :handle
|
55
68
|
attach_pfunc :QueryInformationJobObject, [:handle, :int, :pointer, :dword, :pointer], :bool
|
56
69
|
attach_pfunc :SetInformationJobObject, [:handle, :int, :pointer, :dword], :bool
|
57
70
|
attach_pfunc :GetExitCodeProcess, [:handle, :pointer], :bool
|
@@ -63,7 +76,7 @@ module Process::Functions
|
|
63
76
|
attach_pfunc :OpenProcessToken, [:handle, :dword, :pointer], :bool
|
64
77
|
|
65
78
|
attach_pfunc :CreateProcessWithLogonW,
|
66
|
-
[:buffer_in, :buffer_in, :buffer_in, :dword, :buffer_in, :
|
79
|
+
[:buffer_in, :buffer_in, :buffer_in, :dword, :buffer_in, :buffer_inout,
|
67
80
|
:dword, :buffer_in, :buffer_in, :pointer, :pointer], :bool
|
68
81
|
|
69
82
|
ffi_lib FFI::Library::LIBC
|
data/lib/win32/process/helper.rb
CHANGED
@@ -60,7 +60,7 @@ module Process::Structs
|
|
60
60
|
layout(
|
61
61
|
:nLength, :dword,
|
62
62
|
:lpSecurityDescriptor, :pointer,
|
63
|
-
:bInheritHandle, :
|
63
|
+
:bInheritHandle, :int
|
64
64
|
)
|
65
65
|
end
|
66
66
|
|
@@ -108,11 +108,111 @@ module Process::Structs
|
|
108
108
|
)
|
109
109
|
end
|
110
110
|
|
111
|
+
class THREADENTRY32 < FFI::Struct
|
112
|
+
layout(
|
113
|
+
:dwSize, :dword,
|
114
|
+
:cntUsage, :dword,
|
115
|
+
:th32ThreadID, :dword,
|
116
|
+
:th32OwnerProcessID, :dword,
|
117
|
+
:tpBasePri, :long,
|
118
|
+
:tpDeltaPri, :long,
|
119
|
+
:dwFlags, :dword
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
class HEAPLIST32 < FFI::Struct
|
124
|
+
layout(
|
125
|
+
:dwSize, :size_t,
|
126
|
+
:th32ProcessID, :dword,
|
127
|
+
:th32HeapID, :uintptr_t,
|
128
|
+
:dwFlags, :dword
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
class HEAPENTRY32 < FFI::Struct
|
133
|
+
layout(
|
134
|
+
:dwSize, :size_t,
|
135
|
+
:hHandle, :handle,
|
136
|
+
:dwAddress, :uintptr_t,
|
137
|
+
:dwBlockSize, :size_t,
|
138
|
+
:dwFlags, :dword,
|
139
|
+
:dwLockCount, :dword,
|
140
|
+
:dwResvd, :dword,
|
141
|
+
:th32ProcessID, :dword,
|
142
|
+
:th32HeapID, :uintptr_t
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
class MODULEENTRY32 < FFI::Struct
|
147
|
+
layout(
|
148
|
+
:dwSize, :dword,
|
149
|
+
:th32ModuleID, :dword,
|
150
|
+
:th32ProcessID, :dword,
|
151
|
+
:GlblcntUsage, :dword,
|
152
|
+
:ProccntUsage, :dword,
|
153
|
+
:modBaseAddr, :pointer,
|
154
|
+
:modBaseSize, :dword,
|
155
|
+
:hModule, :handle,
|
156
|
+
:szModule, [:char, 256],
|
157
|
+
:szExePath, [:char, 260]
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
161
|
+
class PROCESSENTRY32 < FFI::Struct
|
162
|
+
layout(
|
163
|
+
:dwSize, :dword,
|
164
|
+
:cntUsage, :dword,
|
165
|
+
:th32ProcessID, :dword,
|
166
|
+
:th32DefaultHeapID, :uintptr_t,
|
167
|
+
:th32ModuleID, :dword,
|
168
|
+
:cntThreads, :dword,
|
169
|
+
:th32ParentProcessID, :dword,
|
170
|
+
:pcPriClassBase, :long,
|
171
|
+
:dwFlags, :dword,
|
172
|
+
:szExeFile, [:char, 260]
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
111
176
|
# Used by Process.create
|
177
|
+
|
112
178
|
ProcessInfo = Struct.new("ProcessInfo",
|
113
179
|
:process_handle,
|
114
180
|
:thread_handle,
|
115
181
|
:process_id,
|
116
182
|
:thread_id
|
117
183
|
)
|
184
|
+
|
185
|
+
# Used by Process.snapshot
|
186
|
+
|
187
|
+
ThreadSnapInfo = Struct.new("ThreadSnapInfo",
|
188
|
+
:thread_id,
|
189
|
+
:process_id,
|
190
|
+
:base_priority
|
191
|
+
)
|
192
|
+
|
193
|
+
HeapSnapInfo = Struct.new("HeapSnapInfo",
|
194
|
+
:address,
|
195
|
+
:block_size,
|
196
|
+
:flags,
|
197
|
+
:process_id,
|
198
|
+
:heap_id
|
199
|
+
)
|
200
|
+
|
201
|
+
ModuleSnapInfo = Struct.new("ModuleSnapInfo",
|
202
|
+
:process_id,
|
203
|
+
:address,
|
204
|
+
:module_size,
|
205
|
+
:handle,
|
206
|
+
:name,
|
207
|
+
:path
|
208
|
+
)
|
209
|
+
|
210
|
+
ProcessSnapInfo = Struct.new("ProcessSnapInfo",
|
211
|
+
:process_id,
|
212
|
+
:threads,
|
213
|
+
:parent_process_id,
|
214
|
+
:priority,
|
215
|
+
:flags,
|
216
|
+
:path
|
217
|
+
)
|
118
218
|
end
|
data/test/test_win32_process.rb
CHANGED
@@ -25,7 +25,7 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
25
25
|
end
|
26
26
|
|
27
27
|
test "win32-process version is set to the correct value" do
|
28
|
-
assert_equal('0.
|
28
|
+
assert_equal('0.9.0', Process::WIN32_PROCESS_VERSION)
|
29
29
|
end
|
30
30
|
|
31
31
|
test "create basic functionality" do
|
@@ -298,6 +298,23 @@ class TC_Win32Process < Test::Unit::TestCase
|
|
298
298
|
assert_not_respond_to(Process, :volume_type)
|
299
299
|
end
|
300
300
|
|
301
|
+
test "snapshot method basic functionality" do
|
302
|
+
assert_respond_to(Process, :snapshot)
|
303
|
+
assert_nothing_raised{ Process.snapshot }
|
304
|
+
assert_kind_of(Hash, Process.snapshot)
|
305
|
+
end
|
306
|
+
|
307
|
+
test "snapshot accepts :thread, :module or :heap arguments" do
|
308
|
+
assert_nothing_raised{ Process.snapshot(:thread) }
|
309
|
+
assert_nothing_raised{ Process.snapshot(:module) }
|
310
|
+
#assert_nothing_raised{ Process.snapshot(:heap) }
|
311
|
+
assert_nothing_raised{ Process.snapshot(:process) }
|
312
|
+
end
|
313
|
+
|
314
|
+
test "snapshot raises an error if an invalid argument is passed" do
|
315
|
+
assert_raise(ArgumentError){ Process.snapshot(:bogus) }
|
316
|
+
end
|
317
|
+
|
301
318
|
test "ffi functions are private" do
|
302
319
|
assert_not_respond_to(Process, :CloseHandle)
|
303
320
|
assert_not_respond_to(Process, :GetCurrentProcess)
|
@@ -116,28 +116,6 @@ class TC_Win32_Process_Kill < Test::Unit::TestCase
|
|
116
116
|
# assert_raise(Errno::EPERM){ Process.kill(9, 1) }
|
117
117
|
#end
|
118
118
|
|
119
|
-
test "kill raises a SecurityError if $SAFE level is 2 or greater" do
|
120
|
-
omit_if(@ruby == 'jruby')
|
121
|
-
assert_raise(SecurityError){
|
122
|
-
proc do
|
123
|
-
$SAFE = 2
|
124
|
-
@pid = Process.spawn(@cmd)
|
125
|
-
Process.kill(9, @pid)
|
126
|
-
end.call
|
127
|
-
}
|
128
|
-
end
|
129
|
-
|
130
|
-
test "kill works if the $SAFE level is 1 or lower" do
|
131
|
-
omit_if(@ruby == 'jruby')
|
132
|
-
assert_nothing_raised{
|
133
|
-
proc do
|
134
|
-
$SAFE = 1
|
135
|
-
@pid = Process.spawn(@cmd)
|
136
|
-
Process.kill(9, @pid)
|
137
|
-
end.call
|
138
|
-
}
|
139
|
-
end
|
140
|
-
|
141
119
|
=begin
|
142
120
|
test "kill(0) can't tell if the process ended, use get_exitcode instead" do
|
143
121
|
pid = Process.create(
|
data/win32-process.gemspec
CHANGED
@@ -1,23 +1,18 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
3
1
|
Gem::Specification.new do |spec|
|
4
|
-
spec.name =
|
5
|
-
spec.version =
|
6
|
-
spec.license =
|
7
|
-
spec.authors = [
|
8
|
-
spec.email =
|
9
|
-
spec.homepage =
|
10
|
-
spec.summary =
|
11
|
-
spec.test_files = Dir[
|
12
|
-
spec.files =
|
13
|
-
|
14
|
-
spec.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
|
2
|
+
spec.name = "win32-process"
|
3
|
+
spec.version = "0.9.0"
|
4
|
+
spec.license = "Artistic-2.0"
|
5
|
+
spec.authors = ["Daniel Berger", "Park Heesob"]
|
6
|
+
spec.email = "djberg96@gmail.com"
|
7
|
+
spec.homepage = "https://github.com/chef/win32-process"
|
8
|
+
spec.summary = "Adds and redefines several Process methods for Microsoft Windows"
|
9
|
+
spec.test_files = Dir["test/*.rb"]
|
10
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(/^(\..*|Gemfile|Rakefile|examples|test|CHANGELOG.md)/) }
|
15
11
|
|
16
|
-
spec.
|
17
|
-
spec.add_dependency('ffi', '>= 1.0.0')
|
12
|
+
spec.extra_rdoc_files = ["README.md"]
|
18
13
|
|
19
|
-
spec.
|
20
|
-
spec.
|
14
|
+
spec.required_ruby_version = "> 1.9.0"
|
15
|
+
spec.add_dependency("ffi", ">= 1.0.0")
|
21
16
|
|
22
17
|
spec.description = <<-EOF
|
23
18
|
The win32-process library implements several Process methods that are
|
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.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Berger
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-10-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -25,34 +25,6 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 1.0.0
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: rake
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - ">="
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
35
|
-
type: :development
|
36
|
-
prerelease: false
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '0'
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: test-unit
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - ">="
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: 2.4.0
|
49
|
-
type: :development
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: 2.4.0
|
56
28
|
description: |2
|
57
29
|
The win32-process library implements several Process methods that are
|
58
30
|
either unimplemented or dysfunctional in some way in the default Ruby
|
@@ -62,16 +34,10 @@ email: djberg96@gmail.com
|
|
62
34
|
executables: []
|
63
35
|
extensions: []
|
64
36
|
extra_rdoc_files:
|
65
|
-
- README
|
66
|
-
- CHANGES
|
67
|
-
- MANIFEST
|
37
|
+
- README.md
|
68
38
|
files:
|
69
|
-
-
|
70
|
-
-
|
71
|
-
- README
|
72
|
-
- Rakefile
|
73
|
-
- examples/example_create.rb
|
74
|
-
- examples/example_kill.rb
|
39
|
+
- README.md
|
40
|
+
- lib/win32-process.rb
|
75
41
|
- lib/win32/process.rb
|
76
42
|
- lib/win32/process/constants.rb
|
77
43
|
- lib/win32/process/functions.rb
|
@@ -80,9 +46,9 @@ files:
|
|
80
46
|
- test/test_win32_process.rb
|
81
47
|
- test/test_win32_process_kill.rb
|
82
48
|
- win32-process.gemspec
|
83
|
-
homepage: https://github.com/
|
49
|
+
homepage: https://github.com/chef/win32-process
|
84
50
|
licenses:
|
85
|
-
- Artistic
|
51
|
+
- Artistic-2.0
|
86
52
|
metadata: {}
|
87
53
|
post_install_message:
|
88
54
|
rdoc_options: []
|
@@ -99,11 +65,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
65
|
- !ruby/object:Gem::Version
|
100
66
|
version: '0'
|
101
67
|
requirements: []
|
102
|
-
|
103
|
-
rubygems_version: 2.4.5
|
68
|
+
rubygems_version: 3.1.2
|
104
69
|
signing_key:
|
105
70
|
specification_version: 4
|
106
|
-
summary: Adds and redefines several Process methods for
|
71
|
+
summary: Adds and redefines several Process methods for Microsoft Windows
|
107
72
|
test_files:
|
108
73
|
- test/test_win32_process.rb
|
109
74
|
- test/test_win32_process_kill.rb
|
data/CHANGES
DELETED
@@ -1,250 +0,0 @@
|
|
1
|
-
= 0.7.5 - 3-Mar-2015
|
2
|
-
* Use require_relative where possible.
|
3
|
-
* Fixed a bug in Process.setrlimit. Note that this method has been marked
|
4
|
-
as experimental until further notice.
|
5
|
-
* Minor updates to gemspec and Rakefile.
|
6
|
-
* Added known issue for JRuby and SIGBRK to the README.
|
7
|
-
|
8
|
-
= 0.7.4 - 21-Oct-2013
|
9
|
-
* Fixed the INVALID_HANDLE_VALUE constant for 64-bit versions of Ruby.
|
10
|
-
* Added Rake as a development dependency.
|
11
|
-
|
12
|
-
= 0.7.3 - 25-Sep-2013
|
13
|
-
* Added the Process.get_exitcode method. Thanks go to mthiede for the patch.
|
14
|
-
* The Process.kill method raises a SecurityError if the $SAFE level is 2
|
15
|
-
or higher. This was done to match the spec.
|
16
|
-
* Fixed a bug in our custom Process.uid method that affected 64-bit Ruby.
|
17
|
-
* A note was added to use the Process.spawn method instead of Process.create
|
18
|
-
method where practical.
|
19
|
-
|
20
|
-
= 0.7.2 - 8-Apr-2013
|
21
|
-
* Fixed a 64 bit issue caused by the fact that HANDLE's were set as ulong
|
22
|
-
instead of intptr_t. Thanks go to Crossverse the spot.
|
23
|
-
* Added some typedefs in the underlying FFI code for Windows data types.
|
24
|
-
|
25
|
-
= 0.7.1 - 3-Jan-2013
|
26
|
-
* The _get_errno function is apparently not exported on on Windows XP or
|
27
|
-
earlier. On those platforms, FFI.errno is now used instead. Thanks go
|
28
|
-
to Lars Christensen for the report.
|
29
|
-
|
30
|
-
= 0.7.0 - 22-Aug-2012
|
31
|
-
* Converted to use FFI instead of win32-api.
|
32
|
-
* Now requires Ruby 1.9.x or later.
|
33
|
-
* Removed the experimental Process.fork function. This obviated the necessity
|
34
|
-
of custom implementations of other methods, like Process.waitpid, so those
|
35
|
-
no longer have custom implementations either. These also proved to be
|
36
|
-
somewhat problematic with Ruby 1.9.x anyway.
|
37
|
-
* Removed the custom Process.ppid method because Ruby 1.9.x now supports it.
|
38
|
-
* The Process.kill method now supports the :exit_proc, :dll_module and
|
39
|
-
:wait_time options for signals 1 and 4-8.
|
40
|
-
|
41
|
-
= 0.6.5 - 27-Dec-2010
|
42
|
-
* Fixed getpriority and setpriority so that the underlying process handle is
|
43
|
-
always closed. Thanks go to Rafal Michalski for the spot and patch.
|
44
|
-
* Updated getpriority and setpriority so that there are no longer any
|
45
|
-
default arguments. This now matches the MRI spec.
|
46
|
-
* Updated Process.create so that illegal options now raise an ArgumentError
|
47
|
-
instead of a Process::Error.
|
48
|
-
* Fixed a bug in an error message in the Process.create method where the actual
|
49
|
-
error message was getting lost.
|
50
|
-
* Refactored the test suite to use test-unit 2.x features, and make tests a
|
51
|
-
little more robust in general.
|
52
|
-
|
53
|
-
= 0.6.4 - 13-Nov-2010
|
54
|
-
* Altered the wait, wait2, waitpid and waitpid2 methods to match the current
|
55
|
-
MRI interface, i.e. they accept and optional pid and flags, though the
|
56
|
-
latter is ignored. Thanks go to Robert Wahler for the spot.
|
57
|
-
* Renamed the example scripts to avoid any potential confusion with actual
|
58
|
-
test scripts and cleaned them up a bit.
|
59
|
-
* Added Rake tasks to run the example programs.
|
60
|
-
* Updated the MANIFEST.
|
61
|
-
|
62
|
-
= 0.6.3 - 9-Nov-2010
|
63
|
-
* Fixed a bug in the Process.kill method where the remote thread created
|
64
|
-
was not being properly closed. Thanks go to Ben Nagy for the spot.
|
65
|
-
* Added the Process.job? method that returns whether or not the current process
|
66
|
-
is already in a job.
|
67
|
-
* Added the Process.setrlimit method. Like the Process.getrlimit method it
|
68
|
-
only supports a limited subset of resources.
|
69
|
-
* Rakefile tweaks.
|
70
|
-
|
71
|
-
= 0.6.2 - 19-Dec-2009
|
72
|
-
* Fixed an issue where stdin, stdout and stderr might not be inheritable
|
73
|
-
even if the inherit option was set. Thanks go to Michael Buselli for the
|
74
|
-
spot and the patch.
|
75
|
-
* Added a basic implementation of Process.getrlimit.
|
76
|
-
* Added the Process.get_affinity method.
|
77
|
-
* Added test-unit 2.x and sys-proctable as development dependencies.
|
78
|
-
* Added the :uninstall and :build_gem Rake tasks to the Rakefile.
|
79
|
-
* Bumped required version of windows-pr to 1.0.6.
|
80
|
-
|
81
|
-
= 0.6.1 - 16-Jul-2009
|
82
|
-
* Added the Process.uid method. This method returns a user id (really, the RID
|
83
|
-
of the SID) by default, but can also take an optional parameter to return
|
84
|
-
a binary SID instead at the user's discretion.
|
85
|
-
* Added working implementations of Process.getpriority and Process.setpriority.
|
86
|
-
Note they they only work for processes, not process groups or users.
|
87
|
-
* Set license to Artistic 2.0, and updated the gemspec.
|
88
|
-
|
89
|
-
= 0.6.0 - 31-Oct-2008
|
90
|
-
* The mandatory argument for Process.create has been switched from 'app_name'
|
91
|
-
to 'command_line', to be more in line with underlying CreateProcess API.
|
92
|
-
Note that 'command_line' will default to 'app_name' if only the latter is
|
93
|
-
set, but both may be set individually. Keep in mind that 'app_name' must
|
94
|
-
be a full path to the executable. Thanks go to Jeremy Bopp for the patch.
|
95
|
-
* Removed the deprecated ProcessError constant. Use Process::Error instead.
|
96
|
-
* Explicitly include and extend the Windows::Thread module now. Thanks go to
|
97
|
-
Qi Lu for the spot.
|
98
|
-
* Slightly more robust internal code handling for some of the other methods,
|
99
|
-
typically related to ensuring that HANDLE's are closed.
|
100
|
-
* Example programs are now included with the gem.
|
101
|
-
|
102
|
-
= 0.5.9 - 14-Jun-2008
|
103
|
-
* Added a proper implementation of Process.ppid.
|
104
|
-
|
105
|
-
= 0.5.8 - 24-Mar-2008
|
106
|
-
* Fixed a bug in Process.create where the handles in the PROCESS_INFORMATION
|
107
|
-
struct were not closed, regardless of the 'close_handles' option. Thanks
|
108
|
-
go to Lars Christensen for the spot and the patch.
|
109
|
-
|
110
|
-
= 0.5.7 - 27-Mar-2008
|
111
|
-
* Fixed issues with thread_inherit and process_inherit in the Process.create
|
112
|
-
method. This in turn required an update to windows-pr. Thanks go to Steve
|
113
|
-
Shreeve for the spot.
|
114
|
-
* Fixed a potential issue with startf_flags and stdin/stdout/stderr handling.
|
115
|
-
Thanks again go to Steve Shreeve for the spot and the patch.
|
116
|
-
* Fixed the code so that it no longer emits redefinition warnings.
|
117
|
-
* Fixed a bug in the Rake install task (for non-gem installations).
|
118
|
-
|
119
|
-
== 0.5.6 - 13-Mar-2008
|
120
|
-
* Fixed a bug in the Process.waitpid2 method where it wasn't returning the
|
121
|
-
proper exit code. Thanks go to Jeremy Bopp for the spot and the patch.
|
122
|
-
* In the spirit of DWIM, if the 'stdin', 'stdout' or 'stderr' keys are
|
123
|
-
encountered in the startup_info hash, then the inherit flag is automatically
|
124
|
-
set to true and the startf_flags key is automatically OR'd with the
|
125
|
-
STARTF_USESTDHANDLES value. Thanks go to Sander Pool for the inspiration.
|
126
|
-
|
127
|
-
== 0.5.5 - 12-Dec-2007
|
128
|
-
* The Process.create method now automatically closes the process and thread
|
129
|
-
handles in the ProcessInfo struct before returning, unless you explicitly
|
130
|
-
tell it not to via the 'close_handles' option.
|
131
|
-
* The Process.create method now supports creating a process as another user
|
132
|
-
via the 'with_logon', 'password' and 'domain' options.
|
133
|
-
|
134
|
-
== 0.5.4 - 23-Nov-2007
|
135
|
-
* Changed ProcessError to Process::Error.
|
136
|
-
* Now requires windows-pr 0.7.3 or later because of some reorganization in
|
137
|
-
that library with regards to thread functions.
|
138
|
-
* Better cleanup of HANDLE's in a couple methods when failure occurs.
|
139
|
-
* Added an additional require/include necessitated by a change in the method
|
140
|
-
organization in the windows-pr library.
|
141
|
-
|
142
|
-
== 0.5.3 - 29-Jul-2007
|
143
|
-
* Added a Rakefile with tasks for installation and testing.
|
144
|
-
* Removed the install.rb file (now handled by the Rakefile).
|
145
|
-
* Updated the README and MANIFEST files.
|
146
|
-
|
147
|
-
== 0.5.2 - 22-Jan-2007
|
148
|
-
* The startup_info parameter for the Process.create method now accepts
|
149
|
-
'stdin', 'stdout', and 'stderr' as valid parameters, which you can pass
|
150
|
-
a Ruby IO object or a fileno in order to redirect output from the created
|
151
|
-
process.
|
152
|
-
|
153
|
-
== 0.5.1 - 24-Aug-2006
|
154
|
-
* Fixed a bug in the Process.create method where the return value for
|
155
|
-
CreateProcess() was being evaluated incorrectly. Thanks go to David Haney
|
156
|
-
for the spot.
|
157
|
-
* Added a slightly nicer error message if an invalid value is passed to the
|
158
|
-
Process.create method.
|
159
|
-
* Removed an extraneous '%' character from an error message.
|
160
|
-
|
161
|
-
== 0.5.0 - 29-Jul-2006
|
162
|
-
* The Process.create method now returns a ProcessInfo struct instead of the
|
163
|
-
pid. Note that you can still grab the pid out of the struct if needed.
|
164
|
-
* The Process.create method now allows the process_inherit and
|
165
|
-
thread_inherit options which determine whether a process or thread
|
166
|
-
object's handles are inheritable, respectively.
|
167
|
-
* The wait and wait2 methods will now work if GetProcessId() isn't defined
|
168
|
-
on your system.
|
169
|
-
* The 'inherit?' hash option was changed to just 'inherit' (no question mark).
|
170
|
-
* Minor doc correction - the 'inherit' option defaults to false, not true.
|
171
|
-
|
172
|
-
== 0.4.2 - 29-May-2006
|
173
|
-
* Fixed a typo/bug in Process.kill for signal 3, where I had accidentally
|
174
|
-
used CTRL_BRK_EVENT instead of the correct CTRL_BREAK_EVENT. Thanks go
|
175
|
-
to Luis Lavena for the spot.
|
176
|
-
|
177
|
-
== 0.4.1 - 13-May-2006
|
178
|
-
* Fixed a bug where spaces in $LOAD_PATH would cause Process.fork to fail.
|
179
|
-
Thanks go to Justin Bailey for the spot and patch.
|
180
|
-
* Added a short synopsis to the README file.
|
181
|
-
|
182
|
-
== 0.4.0 - 7-May-2006
|
183
|
-
* Now pure Ruby, courtesy of the Win32API package.
|
184
|
-
* Now comes with a gem.
|
185
|
-
* Modified Process.kill to send a signal to the current process if pid 0
|
186
|
-
is specified, as per the current 1.8 behavior.
|
187
|
-
* Process.create now accepts the 'environment' key/value, where you can
|
188
|
-
pass a semicolon-separated string as the environment for the new process.
|
189
|
-
* Moved the GUI related options of Process.create to subkeys of the
|
190
|
-
'startup_info' key. See documentation for details.
|
191
|
-
* Replaced Win32::ProcessError with just ProcessError.
|
192
|
-
|
193
|
-
== 0.3.3 - 16-Apr-2006
|
194
|
-
* Fixed a bug in Process.create with regards to creation_flags. Thanks go
|
195
|
-
to Tophe Vigny for the spot.
|
196
|
-
|
197
|
-
== 0.3.2 - 12-Aug-2005
|
198
|
-
* Fixed a bug in Process.kill where a segfault could occur. Thanks go to
|
199
|
-
Bill Atkins for the spot.
|
200
|
-
* Changed VERSION to WIN32_PROCESS_VERSION, because it's a module.
|
201
|
-
* Made the CHANGES, README and doc/process.txt documents rdoc friendly.
|
202
|
-
* Removed the process.rd file.
|
203
|
-
|
204
|
-
== 0.3.1 - 9-Dec-2004
|
205
|
-
* Modified Process.fork to return an actual PID instead of a handle. This
|
206
|
-
means that it should work with Process.kill and other methods that expect
|
207
|
-
an actual PID.
|
208
|
-
* Modified Process.kill to understand the strings "SIGINT", "INT", "SIGBRK",
|
209
|
-
"BRK", "SIGKILL" and "KILL". These correspond to signals 2, 3 and 9,
|
210
|
-
respectively.
|
211
|
-
* Added better $LOAD_PATH handling for Process.fork. Thanks go to Aslak
|
212
|
-
Hellesoy for the spot and the patch.
|
213
|
-
* Replaced all instances of rb_sys_fail(0) with rb_raise(). This is because
|
214
|
-
of a strange bug in the Windows Installer that hasn't been nailed down yet.
|
215
|
-
This means that you can't rescue Errno::ENOENT any more, but will have to
|
216
|
-
rescue StandardError. This only affects Process.kill.
|
217
|
-
* The signals that were formerly 1 and 2 and now 2 and 3. I did this because
|
218
|
-
I wanted the same signal number for SIGINT as it is on *nix.
|
219
|
-
* Added a test_kill.rb script under the examples directory.
|
220
|
-
* Other minor cleanup and corrections.
|
221
|
-
|
222
|
-
== 0.3.0 - 25-Jul-2004
|
223
|
-
* Added the create() method.
|
224
|
-
* Moved the example programs to doc/examples.
|
225
|
-
* Updated the docs, and toned down claims of fork's similarity to the Unix
|
226
|
-
version.
|
227
|
-
* Minor updates to the test suite.
|
228
|
-
|
229
|
-
== 0.2.1 - 17-May-2004
|
230
|
-
* Made all methods module functions, except fork, rather than singleton
|
231
|
-
methods.
|
232
|
-
* Minor doc changes.
|
233
|
-
|
234
|
-
== 0.2.0 - 11-May-2004
|
235
|
-
* Removed the Win32 module/namespace. You no longer 'include Win32' and you
|
236
|
-
no longer need to prefix Process with 'Win32::'.
|
237
|
-
* The fork() method is now a global function as well as a method of the
|
238
|
-
Process module. That means you can call 'fork' instead of 'Process.fork'
|
239
|
-
if you like.
|
240
|
-
* Doc updates to reflect the above changes.
|
241
|
-
|
242
|
-
== 0.1.1 - 6-Mar-2004
|
243
|
-
* Fixed bug where spaces in the directory name caused the fork() method to
|
244
|
-
fail (Park).
|
245
|
-
* Normalized tc_process.rb somewhat to make it easier to run outside of the
|
246
|
-
test directory if desired.
|
247
|
-
* Fixed up tc_process.rb a bit.
|
248
|
-
|
249
|
-
== 0.1.0 - 19-Feb-2004
|
250
|
-
* Initial release
|
data/MANIFEST
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
* CHANGES
|
2
|
-
* README
|
3
|
-
* MANIFEST
|
4
|
-
* Rakefile
|
5
|
-
* win32-process.gemspec
|
6
|
-
* examples/example_create.rb
|
7
|
-
* examples/example_kill.rb
|
8
|
-
* lib/win32/process.rb
|
9
|
-
* lib/win32/process/constants.rb
|
10
|
-
* lib/win32/process/functions.rb
|
11
|
-
* lib/win32/process/helper.rb
|
12
|
-
* lib/win32/process/structs.rb
|
13
|
-
* test/test_process.rb
|
data/README
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
= Description
|
2
|
-
This library provides analogues of the :getpriority, :setpriority, :getrlimit,
|
3
|
-
:setrlimit and :uid methods for MS Windows. It also adds the new methods :job?,
|
4
|
-
:get_affinity, and :create, and redefines the :kill method.
|
5
|
-
|
6
|
-
= Prerequisites
|
7
|
-
* ffi
|
8
|
-
* sys-proctable (dev only)
|
9
|
-
* test-unit 2 (dev only)
|
10
|
-
|
11
|
-
= Supported Platforms
|
12
|
-
This library is supported on Windows 2000 or later.
|
13
|
-
|
14
|
-
= Installation
|
15
|
-
gem install win32-process
|
16
|
-
|
17
|
-
= Synopsis
|
18
|
-
require 'win32/process'
|
19
|
-
|
20
|
-
p Process.job? # => true or false
|
21
|
-
|
22
|
-
info = Process.create(
|
23
|
-
:app_name => "notepad.exe",
|
24
|
-
:creation_flags => Process::DETACHED_PROCESS,
|
25
|
-
:process_inherit => false,
|
26
|
-
:thread_inherit => true,
|
27
|
-
:cwd => "C:\\"
|
28
|
-
)
|
29
|
-
|
30
|
-
p info.process_id
|
31
|
-
|
32
|
-
= Developer's Notes
|
33
|
-
== Removal of Process.fork in release 0.7.0
|
34
|
-
The Process.fork method was originally experimental but it has never
|
35
|
-
been particularly useful in practice. On top of that, it required special
|
36
|
-
implementations of the Process.waitXXX methods, so it was a maintenance
|
37
|
-
issue as well.
|
38
|
-
|
39
|
-
With Ruby 1.9 now becoming standard and its addition of Process.spawn
|
40
|
-
and friends (and concomitant support for the Process.waitXXX methods) I
|
41
|
-
felt it was time to remove it.
|
42
|
-
|
43
|
-
You can still simulate Process.fork if you like using Process.create, which
|
44
|
-
is how it was implemented internally anyway. A better solution might be
|
45
|
-
to follow in the footsteps of ActiveState Perl, which uses native threads
|
46
|
-
to simulate fork on Windows.
|
47
|
-
|
48
|
-
== Changes in the custom Process.kill method for 0.7.0
|
49
|
-
The Process.kill method in 0.7.0 more closely matches the spec now, but
|
50
|
-
the internal method for killing processes is still nicer for most signals.
|
51
|
-
With the release of 0.7.0 users can now specify options that provide finer
|
52
|
-
control over how a process is killed. See the documentation for details.
|
53
|
-
|
54
|
-
== The removal of the custom Process.ppid method
|
55
|
-
This was added at some point in the Ruby 1.9 dev cycle so it was removed
|
56
|
-
from this library.
|
57
|
-
|
58
|
-
= Known Issues
|
59
|
-
JRuby doesn't seem to like SIGBRK for Process.kill.
|
60
|
-
|
61
|
-
Any issues or bugs should be reported on the project page at
|
62
|
-
https://github.com/djberg96/win32-process.
|
63
|
-
|
64
|
-
= License
|
65
|
-
Artistic 2.0
|
66
|
-
|
67
|
-
= Copyright
|
68
|
-
(C) 2003-2015 Daniel J. Berger
|
69
|
-
All Rights Reserved
|
70
|
-
|
71
|
-
= Warranty
|
72
|
-
This library is provided "as is" and without any express or
|
73
|
-
implied warranties, including, without limitation, the implied
|
74
|
-
warranties of merchantability and fitness for a particular purpose.
|
75
|
-
|
76
|
-
= Author(s)
|
77
|
-
Park Heesob
|
78
|
-
Daniel J. Berger
|
data/Rakefile
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/clean'
|
3
|
-
require 'rake/testtask'
|
4
|
-
require 'rbconfig'
|
5
|
-
include RbConfig
|
6
|
-
|
7
|
-
CLEAN.include('**/*.gem', '**/*.rbc', '**/*.log')
|
8
|
-
|
9
|
-
namespace :gem do
|
10
|
-
desc 'Create the win32-process gem'
|
11
|
-
task :create => [:clean] do
|
12
|
-
spec = eval(IO.read('win32-process.gemspec'))
|
13
|
-
if Gem::VERSION < "2.0"
|
14
|
-
Gem::Builder.new(spec).build
|
15
|
-
else
|
16
|
-
require 'rubygems/package'
|
17
|
-
Gem::Package.build(spec)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
desc 'Install the win32-process gem'
|
22
|
-
task :install => [:create] do
|
23
|
-
file = Dir["*.gem"].first
|
24
|
-
sh "gem install -l #{file}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
namespace :example do
|
29
|
-
desc 'Run the fork + wait example'
|
30
|
-
task :fork_wait do
|
31
|
-
sh "ruby -Ilib examples/example_fork_wait.rb"
|
32
|
-
end
|
33
|
-
|
34
|
-
desc 'Run the fork + waitpid example'
|
35
|
-
task :fork_waitpid do
|
36
|
-
sh "ruby -Ilib examples/example_fork_waitpid.rb"
|
37
|
-
end
|
38
|
-
|
39
|
-
desc 'Run the kill example'
|
40
|
-
task :kill do
|
41
|
-
sh "ruby -Ilib examples/example_kill.rb"
|
42
|
-
end
|
43
|
-
|
44
|
-
desc 'Run the create example'
|
45
|
-
task :create do
|
46
|
-
sh "ruby -Ilib examples/example_create.rb"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
namespace :test do
|
51
|
-
Rake::TestTask.new(:kill) do |t|
|
52
|
-
t.verbose = true
|
53
|
-
t.warning = true
|
54
|
-
t.test_files = FileList['test/test_win32_process_kill.rb']
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
Rake::TestTask.new do |t|
|
59
|
-
t.verbose = true
|
60
|
-
t.warning = true
|
61
|
-
end
|
62
|
-
|
63
|
-
task :default => :test
|
data/examples/example_create.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
##########################################################################
|
2
|
-
# example_create.rb
|
3
|
-
#
|
4
|
-
# Simple test program for the Process.create() method. You can run this
|
5
|
-
# code via the 'example:create' task.
|
6
|
-
##########################################################################
|
7
|
-
require "win32/process"
|
8
|
-
|
9
|
-
p Process::WIN32_PROCESS_VERSION
|
10
|
-
|
11
|
-
struct = Process.create(
|
12
|
-
:app_name => "notepad.exe",
|
13
|
-
:creation_flags => Process::DETACHED_PROCESS,
|
14
|
-
:process_inherit => false,
|
15
|
-
:thread_inherit => true,
|
16
|
-
:cwd => "C:\\",
|
17
|
-
:inherit => true,
|
18
|
-
:environment => "SYSTEMROOT=#{ENV['SYSTEMROOT']};PATH=C:\\"
|
19
|
-
)
|
20
|
-
|
21
|
-
p struct
|
22
|
-
|
23
|
-
=begin
|
24
|
-
# Don't run this from an existing terminal
|
25
|
-
pid = Process.create(
|
26
|
-
:app_name => "cmd.exe",
|
27
|
-
:creation_flags => Process::DETACHED_PROCESS,
|
28
|
-
:startf_flags => Process::USEPOSITION,
|
29
|
-
:x => 0,
|
30
|
-
:y => 0,
|
31
|
-
:title => "Hi Dan"
|
32
|
-
)
|
33
|
-
|
34
|
-
puts "Pid of new process: #{pid}"
|
35
|
-
=end
|
data/examples/example_kill.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
##########################################################################
|
2
|
-
# example_kill.rb
|
3
|
-
#
|
4
|
-
# Generic test script for futzing around Process.kill. This script
|
5
|
-
# requires the sys-proctable library.
|
6
|
-
#
|
7
|
-
# You can run this example via the 'example:kill' task.
|
8
|
-
##########################################################################
|
9
|
-
require "win32/process"
|
10
|
-
|
11
|
-
begin
|
12
|
-
require "sys/proctable"
|
13
|
-
rescue LoadError
|
14
|
-
STDERR.puts "Whoa there!"
|
15
|
-
STDERR.puts "This script requires the sys-proctable package to work."
|
16
|
-
STDERR.puts "You can find it at http://ruby-sysutils.sf.net"
|
17
|
-
STDERR.puts "Exiting..."
|
18
|
-
exit
|
19
|
-
end
|
20
|
-
|
21
|
-
include Sys
|
22
|
-
|
23
|
-
puts "VERSION: " + Process::WIN32_PROCESS_VERSION
|
24
|
-
|
25
|
-
IO.popen("notepad")
|
26
|
-
sleep 1 # Give it a chance to start before checking for its pid
|
27
|
-
|
28
|
-
pids = []
|
29
|
-
|
30
|
-
ProcTable.ps{ |s|
|
31
|
-
pids.push(s.pid) if s.cmdline =~ /notepad/i
|
32
|
-
}
|
33
|
-
|
34
|
-
p Process.kill(9,pids.last)
|