----- Original Message -----
From: "Rod Butcher"
> Also, perl itself always crashes after exactly 13 calls to Process32Next
> (probably on the 14th call). Plenty of RAM available, it has not
> returned code 18 to indicate no more processes (anyway, there are +- 50
> running).
Be aware that it's not Process32Next() that will return 18, but
GetLastError() - or $^E, which is essentially the same as GetLastError().
The MS docs say that GetLastError/$^E will return 18 if "no processes exist
or the snapshot does not contain process information". In that case I would
think that Process32Next() would have returned FALSE.
You may already know it , and it may have no bearing on your problem anyway,
but I thought I should clear it up just in case ... :-)
I'm also a little puzzled as to why we're doing:
$PE32 = pack 'LLLLLLLLLZ', $hProcessSnap, 0, 0, 0, 0, 0, 0, 0, 0, ' ' x 259
. "\0";
I gather that packs the PROCESSENTRY32 struct, but the first parameter
should be sizeof(PROCESSENTRY32), not $hProcessSnap.
Since sizeof(PROCESSENTRY32) == 296, shouldn't that line of code be replaced
by:
$PE32 = pack 'LLLLLLLLLZ', 296, 0, 0, 0, 0, 0, 0, 0, 0, ' ' x 259 . "\0";
I second Bill's suggestion that you provide a complete script so that we can
all be "on the same page".
Below my sig is a sample C script that I found in my MSDN docs. Not sure if
it helps.
It passes TH32CS_SNAPPROCESS (== 2) as the first argument to
CreateToolhelp32Snapshot(). So I tried the same in a perl script - which
seems to avoid the segfault you reported (which I also got with
TH32CS_SNAPTHREAD), but it only prints out the first letter of the
executable's name - ie 'p' for 'perl.exe', 'n' for 'notepad.exe', etc. A bit
more work needed on the packing/unpacking, methinks.
For the record, here's the perl script I was running - using Win32::API and
passing TH32CS_SNAPPROCESS :
####################################
use Win32::API;
use warnings;
use Data::Dumper;
Win32::API->Import('kernel32',
'HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)')
or die "import CreateToolhelp32Snapshot: $!($^E)";
use constant TH32CS_SNAPPROCESS => 0x2;
my $hProcessSnap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
die "CreateToolhelp32Snapshot: $!($^E)" if $hProcessSnap == -1;
print Data::Dumper->Dump([$hProcessSnap], [qw($hProcessSnap)]);
$PE32 = pack 'LLLLLLLLLZ', 296, 0, 0, 0, 0, 0, 0, 0, 0, ' ' x 259 . "\0";
Win32::API->Import('kernel32', 'Process32First', 'IP', 'I') or
die "import Process32First: $!($^E)";
Win32::API->Import('kernel32', 'Process32Next', 'IP', 'I') or
die "import Process32Next: $!($^E)";
my $ret = Process32First ($hProcessSnap, $PE32) or
die "Process32First: $! $(^E)";
my @PE32 = unpack 'LLLLLLLLLZ', $PE32;
print Data::Dumper->Dump([EMAIL PROTECTED], [qw([EMAIL PROTECTED])]);
my $i = 0;
while($ret) {
$PE32 = pack 'LLLLLLLLLZ', 296, 0, 0, 0, 0, 0, 0, 0, 0, ' ' x 259 .
"\0";
$ret = Process32Next ($hProcessSnap, $PE32) or
die "Process32Next: $! $(^E)";
my @PE32 = unpack 'LLLLLLLLLZ', $PE32;
print Data::Dumper->Dump([EMAIL PROTECTED], [qw([EMAIL PROTECTED])]);
}
__END__
####################################
I've also written a perl script using Inline::C.(It seems to get the
"szExeFile" part correct - and, for the rest, produces essentially the same
as the above Win32::API script.) For the record, here it is:
####################################
use warnings;
use constant INVALID_HANDLE_VALUE => 4294967295;
use constant TH32CS_INHERIT => 2147483648;
use constant TH32CS_SNAPALL => 15;
use constant TH32CS_SNAPHEAPLIST => 1;
use constant TH32CS_SNAPMODULE => 8;
use constant TH32CS_SNAPPROCESS => 2;
use constant TH32CS_SNAPTHREAD => 4;
use constant ERROR_NO_MORE_FILES => 18;
use Inline C => Config =>
BUILD_NOISY => 1, # So we see any compiler warnings
LIBS => '-lkernel32';
use Inline C => <<'EOC';
#include <windows.h>
#include <tlhelp32.h>
void print_constants() {
printf("%u\n%u\n%u\n%u\n%u\n%u\n%u\n%u\n",
INVALID_HANDLE_VALUE, TH32CS_INHERIT,
TH32CS_SNAPALL, TH32CS_SNAPHEAPLIST,
TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS,
TH32CS_SNAPTHREAD, ERROR_NO_MORE_FILES);
}
void print_sizeof_struct() {
printf("%u\n", sizeof(PROCESSENTRY32));
}
SV * wrap_CreateToolhelp32Snapshot(SV * flags, SV * pid) {
HANDLE WINAPI hnd;
hnd = CreateToolhelp32Snapshot((unsigned long) SvUV(flags), (unsigned
long)SvUV(pid));
if(hnd == INVALID_HANDLE_VALUE)
croak("CreateToolhelp32Snapshot() returned an INVALID_HANDLE_VALUE");
return newSVuv((unsigned long)hnd);
}
SV * wrap_Process32Next(SV * handle) {
PROCESSENTRY32 x;
BOOL WINAPI ret;
x.dwSize = sizeof(PROCESSENTRY32);
ret = Process32Next((HANDLE)SvUV(handle), &x);
if(ret) {
printf("%u\n%u\n%u\n%u\n%u\n%u\n%u\n%u\n%u\n%s\n",
x.dwSize, x.cntUsage, x.th32ProcessID, x.th32DefaultHeapID,
x.th32ModuleID, x.cntThreads, x.th32ParentProcessID,
x.pcPriClassBase, x.dwFlags, x.szExeFile);
}
return newSVuv((unsigned long) ret);
}
void wrap_CloseHandle(SV * handle) {
CloseHandle((HANDLE) SvUV(handle));
}
EOC
#print_constants(); # prints out the values of the various constants.
#print_sizeof_struct(); # prints out sizeof(PROCESSENTRY32)
$hnd = wrap_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
print $hnd, "\n";
while (1){
if(!wrap_Process32Next($hnd)) {
wrap_CloseHandle($hnd);
last;
}
};
__END__
####################################
I'm a friggen idiot when it comes to Windows .... please make allowances for
that.
Cheers,
Rob
The C script from the MSDN docs:
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
BOOL GetProcessList ()
{
HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
PROCESSENTRY32 pe32 = {0};
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);
// Fill in the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes, and for each process,
// display information.
if (Process32First(hProcessSnap, &pe32))
{
DWORD dwPriorityClass;
BOOL bGotModule = FALSE;
MODULEENTRY32 me32 = {0};
do
{
bGotModule = GetProcessModule(pe32.th32ProcessID,
pe32.th32ModuleID, &me32, sizeof(MODULEENTRY32));
if (bGotModule)
{
HANDLE hProcess;
// Get the actual priority class.
hProcess = OpenProcess (PROCESS_ALL_ACCESS,
FALSE, pe32.th32ProcessID);
dwPriorityClass = GetPriorityClass (hProcess);
CloseHandle (hProcess);
// Print the process's information.
printf( "\nPriority Class Base\t%d\n",
pe32.pcPriClassBase);
printf( "PID\t\t\t%d\n", pe32.th32ProcessID);
printf( "Thread Count\t\t%d\n", pe32.cntThreads);
printf( "Module Name\t\t%s\n", me32.szModule);
printf( "Full Path\t\t%s\n\n", me32.szExePath);
}
}
while (Process32Next(hProcessSnap, &pe32));
bRet = TRUE;
}
else
bRet = FALSE; // could not walk the list of processes
// Do not forget to clean up the snapshot object.
CloseHandle (hProcessSnap);
return (bRet);
}
_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs