line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Win32::Process::Info - Provide process information for Windows 32 systems. |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Win32::Process::Info; |
8
|
|
|
|
|
|
|
$pi = Win32::Process::Info->new (); |
9
|
|
|
|
|
|
|
$pi->Set (elapsed_in_seconds => 0); # In clunks, not seconds. |
10
|
|
|
|
|
|
|
@pids = $pi->ListPids (); # Get all known PIDs |
11
|
|
|
|
|
|
|
@info = $pi->GetProcInfo (); # Get the max |
12
|
|
|
|
|
|
|
%subs = $pi->Subprocesses (); # Figure out subprocess relationships. |
13
|
|
|
|
|
|
|
@info = grep { |
14
|
|
|
|
|
|
|
defined $_->{Name} && |
15
|
|
|
|
|
|
|
$_->{Name} =~ m/perl/ |
16
|
|
|
|
|
|
|
} $pi->GetProcInfo (); # All processes with 'perl' in name. |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NOTICE |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
This package covers a multitude of sins - as many as Microsoft has |
21
|
|
|
|
|
|
|
invented ways to get process info and I have resources and gumption |
22
|
|
|
|
|
|
|
to code. The key to this mess is the 'variant' argument to the 'new' |
23
|
|
|
|
|
|
|
method (q.v.). |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
The WMI variant has various problems, known or suspected to be inherited |
26
|
|
|
|
|
|
|
from Win32::OLE. See L for the gory details. The worst of these |
27
|
|
|
|
|
|
|
is that if you use fork(), you B disallow WMI completely by |
28
|
|
|
|
|
|
|
loading this module as follows: |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use Win32::Process::Info qw{NT}; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
This method of controlling things must be considered experimental until |
33
|
|
|
|
|
|
|
I can confirm it causes no unexpected insurmountable problems. If I am |
34
|
|
|
|
|
|
|
forced to change it, the change will be flagged prominently in the |
35
|
|
|
|
|
|
|
documentation. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
This change is somewhat incompatible with 1.006 and earlier because it |
38
|
|
|
|
|
|
|
requires the import() method to be called in the correct place with the |
39
|
|
|
|
|
|
|
correct arguments. If you C, you B |
40
|
|
|
|
|
|
|
explicitly call Win32::Process::Info->import(). |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
See the import() documentation below for the details. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
B |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 DESCRIPTION |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
The main purpose of the Win32::Process::Info package is to get whatever |
49
|
|
|
|
|
|
|
information is convenient (for the author!) about one or more Windows |
50
|
|
|
|
|
|
|
32 processes. L is therefore the most-important |
51
|
|
|
|
|
|
|
method in the package. See it for more information. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
The process IDs made available are those returned by the variant in |
54
|
|
|
|
|
|
|
use. See the documentation to the individual variants for details, |
55
|
|
|
|
|
|
|
especially if you are a Cygwin user. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Unless explicitly stated otherwise, modules, variables, and so |
58
|
|
|
|
|
|
|
on are considered private. That is, the author reserves the right |
59
|
|
|
|
|
|
|
to make arbitrary changes in the way they work, without telling |
60
|
|
|
|
|
|
|
anyone. For methods, variables, and so on which are considered |
61
|
|
|
|
|
|
|
public, the author will make an effort keep them stable, and failing |
62
|
|
|
|
|
|
|
that to call attention to changes. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
The following methods should be considered public: |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=over 4 |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=cut |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
package Win32::Process::Info; |
71
|
|
|
|
|
|
|
|
72
|
1
|
|
|
1
|
|
1608
|
use 5.006; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
49
|
|
73
|
|
|
|
|
|
|
|
74
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
43
|
|
75
|
1
|
|
|
1
|
|
12
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
49
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
our $VERSION = '1.021'; |
78
|
|
|
|
|
|
|
|
79
|
1
|
|
|
1
|
|
3
|
use Carp; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
63
|
|
80
|
1
|
|
|
1
|
|
4
|
use File::Spec; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
20
|
|
81
|
1
|
|
|
1
|
|
484
|
use Time::Local; |
|
1
|
|
|
|
|
1288
|
|
|
1
|
|
|
|
|
520
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
our %static = ( |
84
|
|
|
|
|
|
|
elapsed_in_seconds => 1, |
85
|
|
|
|
|
|
|
variant => $ENV{PERL_WIN32_PROCESS_INFO_VARIANT}, |
86
|
|
|
|
|
|
|
); |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# The real reason for the %variant_support hash is to deal with |
89
|
|
|
|
|
|
|
# the apparant inability of Win32::API to be 'require'-d anywhere |
90
|
|
|
|
|
|
|
# but in a BEGIN block. The 'unsupported' key is intended to be |
91
|
|
|
|
|
|
|
# used as a 'necessary but not required' criterion; that is, if |
92
|
|
|
|
|
|
|
# 'unsupported' is true, there's no reason to bother; but if it's |
93
|
|
|
|
|
|
|
# false, there may still be problems of some sort. This is par- |
94
|
|
|
|
|
|
|
# ticularly true of WMI, where the full check is rather elephan- |
95
|
|
|
|
|
|
|
# tine. |
96
|
|
|
|
|
|
|
# |
97
|
|
|
|
|
|
|
# The actual 'necessary but not required' check has moved to |
98
|
|
|
|
|
|
|
# {check_support}, with {unsupported} simply holding the result of |
99
|
|
|
|
|
|
|
# the check. The {check_support} key is code to be executed when |
100
|
|
|
|
|
|
|
# the import() hook is called when the module is loaded. |
101
|
|
|
|
|
|
|
# |
102
|
|
|
|
|
|
|
# While I was at it, I decided to consolidate all the variant- |
103
|
|
|
|
|
|
|
# specific information in one spot and, while I was at it, write |
104
|
|
|
|
|
|
|
# a variant checker utility. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my %variant_support; |
107
|
|
|
|
|
|
|
BEGIN { |
108
|
|
|
|
|
|
|
# Cygwin has its own idea of what a process ID is, independent of |
109
|
|
|
|
|
|
|
# the underlying operating system. The Cygwin Perl implements this, |
110
|
|
|
|
|
|
|
# so if we're Cygwin we need to compensate. This MUST return the |
111
|
|
|
|
|
|
|
# Windows-native form under Cygwin, which means any variant which |
112
|
|
|
|
|
|
|
# needs another form must override. |
113
|
|
|
|
|
|
|
|
114
|
1
|
50
|
|
1
|
|
3
|
if ( $^O eq 'cygwin' ) { |
115
|
|
|
|
|
|
|
*My_Pid = sub { |
116
|
0
|
|
|
|
|
0
|
return Cygwin::pid_to_winpid( $$ ); |
117
|
0
|
|
|
|
|
0
|
}; |
118
|
|
|
|
|
|
|
} else { |
119
|
|
|
|
|
|
|
*My_Pid = sub { |
120
|
0
|
|
|
0
|
|
0
|
return $$; |
121
|
1
|
|
|
|
|
4
|
}; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
%variant_support = ( |
124
|
|
|
|
|
|
|
NT => { |
125
|
|
|
|
|
|
|
check_support => sub { |
126
|
1
|
|
|
|
|
2
|
local $@; |
127
|
1
|
50
|
|
|
|
1
|
eval { |
128
|
1
|
|
|
|
|
155
|
require Win32; |
129
|
0
|
0
|
|
|
|
0
|
Win32->can( 'IsWinNT' ) && Win32::IsWinNT(); |
130
|
|
|
|
|
|
|
} or return "$^O is not a member of the Windows NT family"; |
131
|
0
|
0
|
|
|
|
0
|
eval { require Win32::API; 1 } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
132
|
|
|
|
|
|
|
or return 'I can not find Win32::API'; |
133
|
0
|
|
|
|
|
0
|
my @path = File::Spec->path(); |
134
|
|
|
|
|
|
|
DLL_LOOP: |
135
|
0
|
|
|
|
|
0
|
foreach my $dll (qw{PSAPI.DLL ADVAPI32.DLL KERNEL32.DLL}) { |
136
|
0
|
|
|
|
|
0
|
foreach my $loc (@path) { |
137
|
0
|
0
|
|
|
|
0
|
next DLL_LOOP if -e File::Spec->catfile ($loc, $dll); |
138
|
|
|
|
|
|
|
} |
139
|
0
|
|
|
|
|
0
|
return "I can not find $dll"; |
140
|
|
|
|
|
|
|
} |
141
|
0
|
|
|
|
|
0
|
return 0; |
142
|
|
|
|
|
|
|
}, |
143
|
|
|
|
|
|
|
make => sub { |
144
|
0
|
|
|
|
|
0
|
require Win32::Process::Info::NT; |
145
|
0
|
|
|
|
|
0
|
Win32::Process::Info::NT->new (@_); |
146
|
|
|
|
|
|
|
}, |
147
|
1
|
|
|
|
|
12
|
unsupported => "Disallowed on load of @{[__PACKAGE__]}.", |
148
|
|
|
|
|
|
|
}, |
149
|
|
|
|
|
|
|
PT => { |
150
|
|
|
|
|
|
|
check_support => sub { |
151
|
1
|
|
|
|
|
1
|
local $@; |
152
|
1
|
|
|
|
|
157
|
return "Unable to load Proc::ProcessTable" |
153
|
1
|
50
|
|
|
|
1
|
unless eval {require Proc::ProcessTable; 1}; |
|
0
|
|
|
|
|
0
|
|
154
|
0
|
|
|
|
|
0
|
return 0; |
155
|
|
|
|
|
|
|
}, |
156
|
|
|
|
|
|
|
make => sub { |
157
|
0
|
|
|
|
|
0
|
require Win32::Process::Info::PT; |
158
|
0
|
|
|
|
|
0
|
Win32::Process::Info::PT->new (@_); |
159
|
|
|
|
|
|
|
}, |
160
|
1
|
|
|
|
|
7
|
unsupported => "Disallowed on load of @{[__PACKAGE__]}.", |
161
|
|
|
|
|
|
|
}, |
162
|
|
|
|
|
|
|
WMI => { |
163
|
|
|
|
|
|
|
check_support => sub { |
164
|
1
|
|
|
|
|
1
|
local $@; |
165
|
1
|
50
|
|
|
|
2
|
_isReactOS() |
166
|
|
|
|
|
|
|
and return 'Unsupported under ReactOS'; |
167
|
1
|
50
|
|
|
|
1
|
eval { |
168
|
1
|
|
|
|
|
1170
|
require Win32::OLE; |
169
|
0
|
|
|
|
|
0
|
1; |
170
|
|
|
|
|
|
|
} or return 'Unable to load Win32::OLE'; |
171
|
0
|
|
|
|
|
0
|
my ( $wmi, $proc ); |
172
|
0
|
|
|
|
|
0
|
my $old_warn = Win32::OLE->Option( 'Warn' ); |
173
|
0
|
|
|
|
|
0
|
eval { |
174
|
0
|
|
|
|
|
0
|
Win32::OLE->Option( Warn => 0 ); |
175
|
0
|
|
|
|
|
0
|
$wmi = Win32::OLE->GetObject( |
176
|
|
|
|
|
|
|
'winmgmts:{impersonationLevel=impersonate,(Debug)}!//./root/cimv2' |
177
|
|
|
|
|
|
|
); |
178
|
0
|
0
|
|
|
|
0
|
$wmi and $proc = $wmi->Get( |
179
|
|
|
|
|
|
|
sprintf q{Win32_Process='%s'}, __PACKAGE__->My_Pid() |
180
|
|
|
|
|
|
|
); |
181
|
|
|
|
|
|
|
}; |
182
|
0
|
|
|
|
|
0
|
Win32::OLE->Option( Warn => $old_warn ); |
183
|
0
|
0
|
|
|
|
0
|
$wmi or return 'Unable to get WMI object'; |
184
|
0
|
0
|
|
|
|
0
|
$proc or return 'WMI broken: unable to get process object'; |
185
|
0
|
|
|
|
|
0
|
return 0; |
186
|
|
|
|
|
|
|
}, |
187
|
|
|
|
|
|
|
make => sub { |
188
|
0
|
|
|
|
|
0
|
require Win32::Process::Info::WMI; |
189
|
0
|
|
|
|
|
0
|
Win32::Process::Info::WMI->new (@_); |
190
|
|
|
|
|
|
|
}, |
191
|
1
|
|
|
|
|
4
|
unsupported => "Disallowed on load of @{[__PACKAGE__]}.", |
|
1
|
|
|
|
|
1548
|
|
192
|
|
|
|
|
|
|
}, |
193
|
|
|
|
|
|
|
); |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
our %mutator = ( |
197
|
|
|
|
|
|
|
elapsed_in_seconds => sub {$_[2]}, |
198
|
|
|
|
|
|
|
variant => sub { |
199
|
|
|
|
|
|
|
ref $_[0] |
200
|
|
|
|
|
|
|
and eval { $_[0]->isa( 'Win32::Process::Info' ) } |
201
|
|
|
|
|
|
|
or croak 'Variant can not be set on an instance'; |
202
|
|
|
|
|
|
|
foreach (split '\W+', $_[2]) { |
203
|
|
|
|
|
|
|
my $status; |
204
|
|
|
|
|
|
|
$status = variant_support_status( $_ ) |
205
|
|
|
|
|
|
|
and croak "Variant '$_' unsupported on your configuration; ", |
206
|
|
|
|
|
|
|
$status; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
$_[2] |
209
|
|
|
|
|
|
|
}, |
210
|
|
|
|
|
|
|
); |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=item $pi = Win32::Process::Info->new ([machine], [variant], [hash]) |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
This method instantiates a process information object, connected |
216
|
|
|
|
|
|
|
to the given machine, and using the given variant. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
The following variants are currently supported: |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
NT - Uses the NT-native mechanism. Good on any NT, including |
221
|
|
|
|
|
|
|
Windows 2000. This variant does not support connecting to |
222
|
|
|
|
|
|
|
another machine, so the 'machine' argument must be an |
223
|
|
|
|
|
|
|
empty string (or undef, if you prefer). |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
PT - Uses Dan Urist's Proc::ProcessTable, making it possible |
226
|
|
|
|
|
|
|
(paradoxically) to use this module on other operating systems than |
227
|
|
|
|
|
|
|
Windows. Only those Proc::ProcessTable::Process fields which seem |
228
|
|
|
|
|
|
|
to correspond to WMI items are returned. B the PT variant |
229
|
|
|
|
|
|
|
is to be considered experimental, and may be changed or retracted |
230
|
|
|
|
|
|
|
in future releases. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
WMI - Uses the Windows Management Implementation. Good on Win2K, ME, |
233
|
|
|
|
|
|
|
and possibly others, depending on their vintage and whether |
234
|
|
|
|
|
|
|
WMI has been retrofitted. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
The initial default variant comes from environment variable |
237
|
|
|
|
|
|
|
PERL_WIN32_PROCESS_INFO_VARIANT. If this is not found, it will be |
238
|
|
|
|
|
|
|
'WMI,NT,PT', which means to try WMI first, NT if WMI fails, and PT as a |
239
|
|
|
|
|
|
|
last resort. This can be changed using Win32::Process::Info->Set |
240
|
|
|
|
|
|
|
(variant => whatever). |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
The hash argument is a hash reference to additional arguments, if |
243
|
|
|
|
|
|
|
any. The hash reference can actually appear anywhere in the argument |
244
|
|
|
|
|
|
|
list, though positional arguments are illegal after the hash reference. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
The following hash keys are supported: |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
variant => corresponds to the 'variant' argument (all) |
249
|
|
|
|
|
|
|
assert_debug_priv => assert debug if available (all) This |
250
|
|
|
|
|
|
|
only has effect under WMI. The NT variant always |
251
|
|
|
|
|
|
|
asserts debug. You want to be careful doing this |
252
|
|
|
|
|
|
|
under WMI if you're fetching the process owner |
253
|
|
|
|
|
|
|
information, since the script can be badly behaved |
254
|
|
|
|
|
|
|
(i.e. die horribly) for those processes whose |
255
|
|
|
|
|
|
|
ExecutablePath is only available with the debug |
256
|
|
|
|
|
|
|
privilege turned on. |
257
|
|
|
|
|
|
|
host => corresponds to the 'machine' argument (WMI) |
258
|
|
|
|
|
|
|
user => username to perform operation under (WMI) |
259
|
|
|
|
|
|
|
password => password corresponding to the given |
260
|
|
|
|
|
|
|
username (WMI) |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
ALL hash keys are optional. SOME hash keys are only supported under |
263
|
|
|
|
|
|
|
certain variants. These are indicated in parentheses after the |
264
|
|
|
|
|
|
|
description of the key. It is an error to specify a key that the |
265
|
|
|
|
|
|
|
variant in use does not support. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=cut |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
my @argnam = qw{host variant}; |
270
|
|
|
|
|
|
|
sub new { |
271
|
0
|
|
|
0
|
1
|
0
|
my ($class, @params) = @_; |
272
|
0
|
0
|
|
|
|
0
|
$class = ref $class if ref $class; |
273
|
0
|
|
|
|
|
0
|
my %arg; |
274
|
0
|
|
|
|
|
0
|
my ( $self, @probs ); |
275
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
0
|
my $inx = 0; |
277
|
0
|
|
|
|
|
0
|
foreach my $inp (@params) { |
278
|
0
|
0
|
|
|
|
0
|
if (ref $inp eq 'HASH') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
279
|
0
|
|
|
|
|
0
|
foreach my $key (keys %$inp) {$arg{$key} = $inp->{$key}} |
|
0
|
|
|
|
|
0
|
|
280
|
|
|
|
|
|
|
} elsif (ref $inp) { |
281
|
0
|
|
|
|
|
0
|
croak "Argument may not be @{[ref $inp]} reference."; |
|
0
|
|
|
|
|
0
|
|
282
|
|
|
|
|
|
|
} elsif ($argnam[$inx]) { |
283
|
0
|
|
|
|
|
0
|
$arg{$argnam[$inx]} = $inp; |
284
|
|
|
|
|
|
|
} else { |
285
|
0
|
|
|
|
|
0
|
croak "Too many positional arguments."; |
286
|
|
|
|
|
|
|
} |
287
|
0
|
|
|
|
|
0
|
$inx++; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
_import_done() |
291
|
0
|
0
|
|
|
|
0
|
or croak __PACKAGE__, |
292
|
|
|
|
|
|
|
'->import() must be called before calling ', __PACKAGE__, |
293
|
|
|
|
|
|
|
'->new()'; |
294
|
0
|
0
|
|
|
|
0
|
my $mach = $arg{host} or delete $arg{host}; |
295
|
0
|
|
0
|
|
|
0
|
my $try = $arg{variant} || $static{variant} || 'WMI,NT,PT'; |
296
|
0
|
|
|
|
|
0
|
foreach my $variant (grep {$_} split '\W+', $try) { |
|
0
|
|
|
|
|
0
|
|
297
|
0
|
|
|
|
|
0
|
my $status; |
298
|
0
|
0
|
|
|
|
0
|
$status = variant_support_status( $variant ) and do { |
299
|
0
|
|
|
|
|
0
|
push @probs, $status; |
300
|
0
|
|
|
|
|
0
|
next; |
301
|
|
|
|
|
|
|
}; |
302
|
0
|
|
|
|
|
0
|
my $self; |
303
|
0
|
0
|
|
|
|
0
|
$self = $variant_support{$variant}{make}->( \%arg ) and do { |
304
|
0
|
|
0
|
|
|
0
|
$static{variant} ||= $self->{variant} = $variant; |
305
|
|
|
|
|
|
|
}; |
306
|
0
|
|
|
|
|
0
|
return $self; |
307
|
|
|
|
|
|
|
} |
308
|
0
|
|
|
|
|
0
|
croak join '; ', @probs; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=item @values = $pi->Get (attributes ...) |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
This method returns the values of the listed attributes. If |
314
|
|
|
|
|
|
|
called in scalar context, it returns the value of the first |
315
|
|
|
|
|
|
|
attribute specified, or undef if none was. An exception is |
316
|
|
|
|
|
|
|
raised if you specify a non-existent attribute. |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
This method can also be called as a class method (that is, as |
319
|
|
|
|
|
|
|
Win32::Process::Info->Get ()) to return default attributes values. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
The relevant attribute names are: |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
B is TRUE to convert elapsed user and |
324
|
|
|
|
|
|
|
kernel times to seconds. If FALSE, they are returned in |
325
|
|
|
|
|
|
|
clunks (that is, hundreds of nanoseconds). The default is |
326
|
|
|
|
|
|
|
TRUE. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
B is the variant of the Process::Info code in use, |
329
|
|
|
|
|
|
|
and should be zero or more of 'WMI' or 'NT', separated by |
330
|
|
|
|
|
|
|
commas. 'WMI' selects the Windows Management Implementation, and |
331
|
|
|
|
|
|
|
'NT' selects the Windows NT native interface. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
B is the name of the machine connected to. This is |
334
|
|
|
|
|
|
|
not available as a class attribute. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=cut |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
sub Get { |
339
|
0
|
|
|
0
|
1
|
0
|
my ($self, @args) = @_; |
340
|
0
|
0
|
|
|
|
0
|
$self = \%static unless ref $self; |
341
|
0
|
|
|
|
|
0
|
my @vals; |
342
|
0
|
|
|
|
|
0
|
foreach my $name (@args) { |
343
|
0
|
0
|
|
|
|
0
|
croak "Error - Attribute '$name' does not exist." |
344
|
|
|
|
|
|
|
unless exists $self->{$name}; |
345
|
0
|
0
|
|
|
|
0
|
croak "Error - Attribute '$name' is private." |
346
|
|
|
|
|
|
|
if $name =~ m/^_/; |
347
|
0
|
|
|
|
|
0
|
push @vals, $self->{$name}; |
348
|
|
|
|
|
|
|
} |
349
|
0
|
0
|
|
|
|
0
|
return wantarray ? @vals : $vals[0]; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=item @values = $pi->Set (attribute => value ...) |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
This method sets the values of the listed attributes, |
355
|
|
|
|
|
|
|
returning the values of all attributes listed if called in |
356
|
|
|
|
|
|
|
list context, or of the first attribute listed if called |
357
|
|
|
|
|
|
|
in scalar context. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
This method can also be called as a class method (that is, as |
360
|
|
|
|
|
|
|
Win32::Process::Info->Set ()) to change default attribute values. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
The relevant attribute names are the same as for Get. |
363
|
|
|
|
|
|
|
However: |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
B is read-only at the instance level. That is, |
366
|
|
|
|
|
|
|
Win32::Process::Info->Set (variant => 'NT') is OK, but |
367
|
|
|
|
|
|
|
$pi->Set (variant => 'NT') will raise an exception. If |
368
|
|
|
|
|
|
|
you set B to an empty string (the default), the |
369
|
|
|
|
|
|
|
next "new" will iterate over all possibilities (or the |
370
|
|
|
|
|
|
|
contents of environment variable |
371
|
|
|
|
|
|
|
PERL_WIN32_PROCESS_INFO_VARIANT if present), and set |
372
|
|
|
|
|
|
|
B to the first one that actually works. |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
B is not available as a class attribute, and is |
375
|
|
|
|
|
|
|
read-only as an instance attribute. It is B useful for |
376
|
|
|
|
|
|
|
discovering your machine name - if you instantiated the |
377
|
|
|
|
|
|
|
object without specifying a machine name, you will get |
378
|
|
|
|
|
|
|
nothing useful back. |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=cut |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub Set { |
383
|
0
|
|
|
0
|
1
|
0
|
my ($self, @args) = @_; |
384
|
0
|
0
|
|
|
|
0
|
croak "Error - Set requires an even number of arguments." |
385
|
|
|
|
|
|
|
if @args % 2; |
386
|
0
|
0
|
|
|
|
0
|
$self = \%static unless ref $self; |
387
|
0
|
|
0
|
|
|
0
|
my $mutr = $self->{_mutator} || \%mutator; |
388
|
0
|
|
|
|
|
0
|
my @vals; |
389
|
0
|
|
|
|
|
0
|
while (@args) { |
390
|
0
|
|
|
|
|
0
|
my $name = shift @args; |
391
|
0
|
|
|
|
|
0
|
my $val = shift @args; |
392
|
0
|
0
|
|
|
|
0
|
croak "Error - Attribute '$name' does not exist." |
393
|
|
|
|
|
|
|
unless exists $self->{$name}; |
394
|
0
|
0
|
|
|
|
0
|
croak "Error - Attribute '$name' is read-only." |
395
|
|
|
|
|
|
|
unless exists $mutr->{$name}; |
396
|
0
|
|
|
|
|
0
|
$self->{$name} = $mutr->{$name}->($self, $name, $val); |
397
|
0
|
|
|
|
|
0
|
push @vals, $self->{$name}; |
398
|
|
|
|
|
|
|
} |
399
|
0
|
0
|
|
|
|
0
|
return wantarray ? @vals : $vals[0]; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=item @pids = $pi->ListPids (); |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
This method lists all known process IDs in the system. If |
405
|
|
|
|
|
|
|
called in scalar context, it returns a reference to the |
406
|
|
|
|
|
|
|
list of PIDs. If you pass in a list of pids, the return will |
407
|
|
|
|
|
|
|
be the intersection of the argument list and the actual PIDs |
408
|
|
|
|
|
|
|
in the system. |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=cut |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
sub ListPids { |
413
|
0
|
|
|
0
|
1
|
0
|
confess |
414
|
|
|
|
|
|
|
"Error - Whoever coded this forgot to override ListPids."; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=item @info = $pi->GetProcInfo (); |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
This method returns a list of anonymous hashes, each containing |
420
|
|
|
|
|
|
|
information on one process. If no arguments are passed, the |
421
|
|
|
|
|
|
|
list represents all processes in the system. You can pass a |
422
|
|
|
|
|
|
|
list of process IDs, and get out a list of the attributes of |
423
|
|
|
|
|
|
|
all such processes that actually exist. If you call this |
424
|
|
|
|
|
|
|
method in scalar context, you get a reference to the list. |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
What keys are available depends on the variant in use. |
427
|
|
|
|
|
|
|
You can hope to get at least the following keys for a |
428
|
|
|
|
|
|
|
"normal" process (i.e. not the idle process, which is PID 0, |
429
|
|
|
|
|
|
|
nor the system, which is some small indeterminate PID) to |
430
|
|
|
|
|
|
|
which you have access: |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
CreationDate |
433
|
|
|
|
|
|
|
ExecutablePath |
434
|
|
|
|
|
|
|
KernelModeTime |
435
|
|
|
|
|
|
|
MaximumWorkingSetSize |
436
|
|
|
|
|
|
|
MinimumWorkingSetSize |
437
|
|
|
|
|
|
|
Name (generally the name of the executable file) |
438
|
|
|
|
|
|
|
ProcessId |
439
|
|
|
|
|
|
|
UserModeTime |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
You may find other keys available as well, depending on which |
442
|
|
|
|
|
|
|
operating system you're using, and which variant of Process::Info |
443
|
|
|
|
|
|
|
you're using. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
This method also optionally takes as its first argument a reference |
446
|
|
|
|
|
|
|
to a hash of option values. The only supported key is: |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
no_user_info => 1 |
449
|
|
|
|
|
|
|
Do not return keys Owner and OwnerSid, even if available. |
450
|
|
|
|
|
|
|
These tend to be time-consuming, and can cause problems |
451
|
|
|
|
|
|
|
under the WMI variant. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=cut |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub GetProcInfo { |
456
|
0
|
|
|
0
|
1
|
0
|
confess |
457
|
|
|
|
|
|
|
"Programming Error - Whoever coded this forgot to override GetProcInfo."; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item Win32::Process::Info->import () |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
The purpose of this static method is to specify which variants of the |
463
|
|
|
|
|
|
|
functionality are legal to use. Possible arguments are 'NT', 'WMI', |
464
|
|
|
|
|
|
|
'PT', or some combination of these (e.g. ('NT', 'WMI')). Unrecognized |
465
|
|
|
|
|
|
|
arguments are ignored, though this may change if this class becomes a |
466
|
|
|
|
|
|
|
subclass of Exporter. If called with no arguments, it is as though it |
467
|
|
|
|
|
|
|
were called with arguments ('NT', 'WMI', 'PT'). See L, below, for |
468
|
|
|
|
|
|
|
why this mess was introduced in the first place. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
This method must be called at least once, B, or B |
471
|
|
|
|
|
|
|
variants will be legal to use. Usually it does B need to be |
472
|
|
|
|
|
|
|
explicitly called by the user, since it is called implicitly when you |
473
|
|
|
|
|
|
|
C |
474
|
|
|
|
|
|
|
you B have to call this method explicitly. |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
If this method is called more than once, the second and subsequent calls |
477
|
|
|
|
|
|
|
will have no effect on what variants are available. The reason for this |
478
|
|
|
|
|
|
|
will be made clear (I hope!) under L, below. |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
The only time a user of this module needs to do anything different |
481
|
|
|
|
|
|
|
versus version 1.006 and previous of this module is if this module is |
482
|
|
|
|
|
|
|
being loaded in such a way that this method is not implicitly called. |
483
|
|
|
|
|
|
|
This can happen two ways: |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
use Win32::Process::Info (); |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
explicitly bypasses the implicit call of this method. Don't do that. |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
require Win32::Process::Info; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
also does not call this method. If you must load this module using |
492
|
|
|
|
|
|
|
require rather than use, follow the require with |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
Win32::Process::Info->import (); |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
passing any necessary arguments. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=cut |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
{ # Begin local symbol block. |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
my $idempotent; |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
sub import { ## no critic (RequireArgUnpacking) |
505
|
1
|
|
|
1
|
|
325
|
my ($pkg, @params) = @_; |
506
|
1
|
|
|
|
|
1
|
my (@args, @vars); |
507
|
1
|
|
|
|
|
3
|
foreach (@params) { |
508
|
0
|
0
|
|
|
|
0
|
if (exists $variant_support{$_}) { |
509
|
0
|
|
|
|
|
0
|
push @vars, $_; |
510
|
|
|
|
|
|
|
} else { |
511
|
0
|
|
|
|
|
0
|
push @args, $_; |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
1
|
50
|
|
|
|
4
|
if ($idempotent++) { |
516
|
|
|
|
|
|
|
# Warning here maybe? |
517
|
|
|
|
|
|
|
} else { |
518
|
1
|
50
|
|
|
|
6
|
@vars or push @vars, keys %variant_support; |
519
|
1
|
|
|
|
|
1
|
foreach my $try (@vars) { |
520
|
3
|
50
|
|
|
|
7
|
$variant_support{$try} or next; |
521
|
3
|
|
33
|
|
|
2
|
$variant_support{$try}{unsupported} = eval { |
522
|
|
|
|
|
|
|
$variant_support{$try}{check_support}->()} || $@; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
} |
525
|
|
|
|
|
|
|
|
526
|
1
|
|
|
|
|
3
|
return; |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
# Do this if we become a subclass of Exporter |
529
|
|
|
|
|
|
|
# @_ = ( $pkg, @args ); |
530
|
|
|
|
|
|
|
# goto &Exporter::import;; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
# Return the number of times import() done. |
534
|
|
|
|
|
|
|
sub _import_done { |
535
|
3
|
|
|
3
|
|
7
|
return $idempotent; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
} # End local symbol block. |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
{ |
542
|
|
|
|
|
|
|
my $is_reactos = $^O eq 'MSWin32' && |
543
|
|
|
|
|
|
|
defined $ENV{OS} && lc $ENV{OS} eq 'reactos'; |
544
|
|
|
|
|
|
|
sub _isReactOS { |
545
|
1
|
|
|
1
|
|
2
|
return $is_reactos; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=item %subs = $pi->Subprocesses ([pid ...]) |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
This method takes as its argument a list of PIDs, and returns a hash |
553
|
|
|
|
|
|
|
indexed by PID and containing, for each PID, a reference to a list of |
554
|
|
|
|
|
|
|
all subprocesses of that process. If those processes have subprocesses |
555
|
|
|
|
|
|
|
as well, you will get the sub-sub processes, and so ad infinitum, so |
556
|
|
|
|
|
|
|
you may well get back more hash keys than you passed process IDs. Note |
557
|
|
|
|
|
|
|
that the process of finding the sub-sub processes is iterative, not |
558
|
|
|
|
|
|
|
recursive; so you don't get back a tree. |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
If no argument is passed, you get all processes in the system. |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
If called in scalar context you get a reference to the hash. |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
This method works off the ParentProcessId attribute. Not all variants |
565
|
|
|
|
|
|
|
support this. If the variant you're using doesn't support this |
566
|
|
|
|
|
|
|
attribute, you get back an empty hash. Specifically: |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
NT -> unsupported |
569
|
|
|
|
|
|
|
PT -> supported |
570
|
|
|
|
|
|
|
WMI -> supported |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
=cut |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub Subprocesses { |
575
|
0
|
|
|
0
|
1
|
0
|
my ($self, @args) = @_; |
576
|
0
|
|
|
|
|
0
|
my %prox = map {($_->{ProcessId} => $_)} |
|
0
|
|
|
|
|
0
|
|
577
|
0
|
|
|
|
|
0
|
@{$self->GetProcInfo ({no_user_info => 1})}; |
578
|
0
|
|
|
|
|
0
|
my %subs; |
579
|
0
|
|
|
|
|
0
|
my $rslt = \%subs; |
580
|
0
|
|
|
|
|
0
|
my $key_found; |
581
|
0
|
|
|
|
|
0
|
foreach my $proc (values %prox) { |
582
|
0
|
|
0
|
|
|
0
|
$subs{$proc->{ProcessId}} ||= []; |
583
|
|
|
|
|
|
|
# TRW 1.011_01 next unless $proc->{ParentProcessId}; |
584
|
0
|
0
|
|
|
|
0
|
defined (my $pop = $proc->{ParentProcessId}) or next; # TRW 1.011_01 |
585
|
0
|
|
|
|
|
0
|
$key_found++; |
586
|
|
|
|
|
|
|
# TRW 1.011_01 next unless $prox{$proc->{ParentProcessId}}; |
587
|
0
|
0
|
|
|
|
0
|
$prox{$pop} or next; # TRW 1.011_01 |
588
|
|
|
|
|
|
|
# TRW 1.012_02 $proc->{CreationDate} >= $prox{$pop}{CreationDate} or next; # TRW 1.011_01 |
589
|
0
|
0
|
0
|
|
|
0
|
(defined($proc->{CreationDate}) && |
|
|
|
0
|
|
|
|
|
590
|
|
|
|
|
|
|
defined($prox{$pop}{CreationDate}) && |
591
|
|
|
|
|
|
|
$proc->{CreationDate} >= $prox{$pop}{CreationDate}) |
592
|
|
|
|
|
|
|
or next; # TRW 1.012_02 |
593
|
|
|
|
|
|
|
# TRW 1.011_01 push @{$subs{$proc->{ParentProcessId}}}, $proc->{ProcessId}; |
594
|
0
|
|
|
|
|
0
|
push @{$subs{$pop}}, $proc->{ProcessId}; |
|
0
|
|
|
|
|
0
|
|
595
|
|
|
|
|
|
|
} |
596
|
0
|
|
|
|
|
0
|
my %listed; |
597
|
0
|
0
|
|
|
|
0
|
return %listed unless $key_found; |
598
|
0
|
0
|
|
|
|
0
|
if (@args) { |
599
|
0
|
|
|
|
|
0
|
$rslt = \%listed; |
600
|
0
|
|
|
|
|
0
|
while (@args) { |
601
|
0
|
|
|
|
|
0
|
my $pid = shift @args; |
602
|
0
|
0
|
|
|
|
0
|
next unless $subs{$pid}; # TRW 1.006 |
603
|
0
|
0
|
|
|
|
0
|
next if $listed{$pid}; |
604
|
0
|
|
|
|
|
0
|
$listed{$pid} = $subs{$pid}; |
605
|
0
|
|
|
|
|
0
|
push @args, @{$subs{$pid}}; |
|
0
|
|
|
|
|
0
|
|
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
} |
608
|
0
|
0
|
|
|
|
0
|
return wantarray ? %$rslt : $rslt; |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
=item @info = $pi->SubProcInfo (); |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
This is a convenience method which wraps GetProcInfo(). It has the same |
614
|
|
|
|
|
|
|
calling sequence, and returns generally the same data. But the data |
615
|
|
|
|
|
|
|
returned by this method will also have the {subProcesses} key, which |
616
|
|
|
|
|
|
|
will contain a reference to an array of hash references representing the |
617
|
|
|
|
|
|
|
data on subprocesses of each process. |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
Unlike the data returned from Subprocesses(), the data here are not |
620
|
|
|
|
|
|
|
flattened; so if you specify one or more process IDs as arguments, you |
621
|
|
|
|
|
|
|
will get back at most the number of process IDs you specified; fewer if |
622
|
|
|
|
|
|
|
some of the specified processes do not exist. |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
B that a given process can occur more than once in the |
625
|
|
|
|
|
|
|
output. If you call SubProcInfo without arguments, the @info array will |
626
|
|
|
|
|
|
|
contain every process in the system, even those which are also in some |
627
|
|
|
|
|
|
|
other process' {subProcesses} array. |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
Also unlike Subprocesses(), you will get an exception if you use this |
630
|
|
|
|
|
|
|
method with a variant that does not support the ParentProcessId key. |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=cut |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
sub SubProcInfo { |
635
|
0
|
|
|
0
|
1
|
0
|
my ($self, @args) = @_; |
636
|
0
|
0
|
|
|
|
0
|
my $opt = ref $args[0] eq 'HASH' ? shift @args : {}; |
637
|
0
|
|
|
|
|
0
|
my @data = $self->GetProcInfo ($opt); |
638
|
0
|
|
|
|
|
0
|
my %subs = map {$_->{ProcessId} => $_} @data; |
|
0
|
|
|
|
|
0
|
|
639
|
0
|
|
|
|
|
0
|
my $bingo; |
640
|
0
|
|
|
|
|
0
|
foreach my $proc (@data) { |
641
|
0
|
0
|
|
|
|
0
|
exists $proc->{ParentProcessId} or next; |
642
|
0
|
|
0
|
|
|
0
|
$proc->{subProcesses} ||= []; |
643
|
0
|
|
|
|
|
0
|
$bingo++; |
644
|
0
|
0
|
|
|
|
0
|
defined (my $dad = $subs{$proc->{ParentProcessId}}) or next; |
645
|
0
|
0
|
0
|
|
|
0
|
(defined $dad->{CreationDate} && defined $proc->{CreationDate}) |
646
|
|
|
|
|
|
|
or next; |
647
|
0
|
0
|
|
|
|
0
|
$dad->{CreationDate} > $proc->{CreationDate} and next; |
648
|
0
|
|
0
|
|
|
0
|
push @{$dad->{subProcesses} ||= []}, $proc; |
|
0
|
|
|
|
|
0
|
|
649
|
|
|
|
|
|
|
} |
650
|
0
|
0
|
|
|
|
0
|
$bingo or croak "Error - Variant '@{[$self->Get('variant') |
|
0
|
|
|
|
|
0
|
|
651
|
|
|
|
|
|
|
]}' does not support the ParentProcessId key"; |
652
|
0
|
0
|
|
|
|
0
|
if (@args) { |
653
|
0
|
0
|
|
|
|
0
|
return (map {exists $subs{$_} ? $subs{$_} : ()} @args); |
|
0
|
|
|
|
|
0
|
|
654
|
|
|
|
|
|
|
} else { |
655
|
0
|
|
|
|
|
0
|
return @data; |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
=item $pid = $pi->My_Pid() |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
This convenience method returns the process ID of the current process, |
662
|
|
|
|
|
|
|
in a form appropriate to the operating system and the variant in use. |
663
|
|
|
|
|
|
|
Normally, it simply returns C<$$>. But Cygwin has its own idea of what |
664
|
|
|
|
|
|
|
the process ID is, which may differ from Windows. Worse than that, under |
665
|
|
|
|
|
|
|
Cygwin the NT and WMI variants return Windows PIDs, while PT appears to |
666
|
|
|
|
|
|
|
return Cygwin PIDs. |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=cut |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
# This is defined above, trickily, as an assignment to *My_Pid, so we |
671
|
|
|
|
|
|
|
# don't have to test $^O every time. It's above because code in a BEGIN |
672
|
|
|
|
|
|
|
# block needs it. |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=item $text = Win32::Process::Info->variant_support_status($variant); |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
This static method returns the support status of the given variant. The |
677
|
|
|
|
|
|
|
return is false if the variant is supported, or an appropriate message |
678
|
|
|
|
|
|
|
if the variant is unsupported. |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
This method can also be called as a normal method, or even as a |
681
|
|
|
|
|
|
|
subroutine. |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
=cut |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
sub variant_support_status { |
686
|
3
|
|
|
3
|
1
|
1539
|
my @args = @_; |
687
|
3
|
50
|
|
|
|
8
|
my $variant = pop @args or croak "Variant not specified"; |
688
|
3
|
50
|
|
|
|
7
|
exists $variant_support{$variant} |
689
|
|
|
|
|
|
|
or croak "Variant '$variant' is unknown"; |
690
|
3
|
50
|
|
|
|
4
|
_import_done() |
691
|
|
|
|
|
|
|
or croak __PACKAGE__, |
692
|
|
|
|
|
|
|
'->import() must be called before calling ', __PACKAGE__, |
693
|
|
|
|
|
|
|
'->variant_support_status()'; |
694
|
3
|
|
|
|
|
8
|
return $variant_support{$variant}{unsupported}; |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=item print "$pi Version = @{[$pi->Version ()]}\n" |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
This method just returns the version number of the |
700
|
|
|
|
|
|
|
Win32::Process::Info object. |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
=cut |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
sub Version { |
705
|
1
|
|
|
1
|
1
|
8
|
return $Win32::Process::Info::VERSION; |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
# |
709
|
|
|
|
|
|
|
# $self->_build_hash ([hashref], key, value ...) |
710
|
|
|
|
|
|
|
# builds a process info hash out of the given keys and values. |
711
|
|
|
|
|
|
|
# The keys are assumed to be the WMI keys, and will be trans- |
712
|
|
|
|
|
|
|
# formed if needed. The values will also be transformed if |
713
|
|
|
|
|
|
|
# needed. The resulting hash entries will be placed into the |
714
|
|
|
|
|
|
|
# given hash if one is present, or into a new hash if not. |
715
|
|
|
|
|
|
|
# Either way, the hash is returned. |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub _build_hash { |
718
|
0
|
|
|
0
|
|
|
my ($self, $hash, @args) = @_; |
719
|
0
|
|
0
|
|
|
|
$hash ||= {}; |
720
|
0
|
|
|
|
|
|
while (@args) { |
721
|
0
|
|
|
|
|
|
my $key = shift @args; |
722
|
0
|
|
|
|
|
|
my $val = shift @args; |
723
|
0
|
0
|
|
|
|
|
$val = $self->{_xfrm}{$key}->($self, $val) |
724
|
|
|
|
|
|
|
if (exists $self->{_xfrm}{$key}); |
725
|
0
|
|
|
|
|
|
$hash->{$key} = $val; |
726
|
|
|
|
|
|
|
} |
727
|
0
|
|
|
|
|
|
return $hash; |
728
|
|
|
|
|
|
|
} |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
# $self->_clunks_to_desired (clunks ...) |
732
|
|
|
|
|
|
|
# converts elapsed times in clunks to elapsed times in |
733
|
|
|
|
|
|
|
# seconds, PROVIDED $self->{elapsed_in_seconds} is TRUE. |
734
|
|
|
|
|
|
|
# Otherwise it simply returns its arguments unmodified. |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
sub _clunks_to_desired { |
737
|
0
|
|
|
0
|
|
|
my $self = shift; |
738
|
0
|
0
|
|
|
|
|
@_ = map {defined $_ ? $_ / 10_000_000 : undef} @_ if $self->{elapsed_in_seconds}; |
|
0
|
0
|
|
|
|
|
|
739
|
0
|
0
|
|
|
|
|
return wantarray ? @_ : $_[0]; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
# $self->_date_to_time_t (date ...) |
743
|
|
|
|
|
|
|
# converts the input dates (assumed YYYYmmddhhMMss) to |
744
|
|
|
|
|
|
|
# Perl internal time, returning the results. The "self" |
745
|
|
|
|
|
|
|
# argument is unused. |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
sub _date_to_time_t { |
749
|
0
|
|
|
0
|
|
|
my ($self, @args) = @_; |
750
|
0
|
|
|
|
|
|
my @result; |
751
|
0
|
|
|
|
|
|
local $^W = 0; # Prevent Time::Local 1.1 from complaining. This appears |
752
|
|
|
|
|
|
|
# to be fixed in 1.11, but since Time::Local is part of |
753
|
|
|
|
|
|
|
# the ActivePerl core, there's no PPM installer for it. |
754
|
|
|
|
|
|
|
# At least, not that I can find. |
755
|
0
|
|
|
|
|
|
foreach (@args) { |
756
|
0
|
0
|
|
|
|
|
if ($_) { |
757
|
0
|
|
|
|
|
|
my ($yr, $mo, $da, $hr, $mi, $sc) = m/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; |
758
|
0
|
|
|
|
|
|
--$mo; |
759
|
0
|
|
|
|
|
|
my $val = timelocal ($sc, $mi, $hr, $da, $mo, $yr); |
760
|
0
|
|
|
|
|
|
push @result, $val; |
761
|
|
|
|
|
|
|
} |
762
|
|
|
|
|
|
|
else { |
763
|
0
|
|
|
|
|
|
push @result, undef; |
764
|
|
|
|
|
|
|
} |
765
|
|
|
|
|
|
|
} |
766
|
0
|
0
|
|
|
|
|
return @result if wantarray; |
767
|
0
|
|
|
|
|
|
return $result[0]; |
768
|
|
|
|
|
|
|
} |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
1; |
771
|
|
|
|
|
|
|
__END__ |