----- 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 Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs