Help with Win32::Process::Create()
I'm working on an app that periodically needs to execute outside procedures. Ideally, I want to launch the outside procedure in fire and forget mode; that is, I do not want to wait for the outside process to terminate. I ALREADY HAVE some code that does this (see below). My question is- is there a way to periodically poll the outside process to determine if it is still running? I've tried a few things already and none of them work. = the code = use strict; use warnings; use Win32::Process; # Parameters for the Win32::Process::Create function: # # Process This is an empty string that will receive #a process ID used to address the child process. #Returns a string that looks like this: #Win32::Process=SCALAR(0x235478). # # fullPath The full path to the program including the #program name and extension. Can be UNC. # # newArg The name of the program itself with an extension, #but no path. Also, command line arguments go here. # # inheritHndls Should the child process inherit the parent's file handles? # # flagsx OR'd combination of the flags listed above. # # dirx Startup directory for the child process. # my $process = ''; my $dirx = '.'; my $inheritHndls = 0; my $newArg = 'notepad.exe'; my $fullPath = c:\\windows\\system32\\$newArg; my $flagsx = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS; if (my $spawnhndl = Win32::Process::Create($process, $fullPath, $newArg, $inheritHndls, $flagsx, $dirx)) { my $pid = $process-GetProcessID(); print Child process returned PID: $pid\n; } else { my $errormsg = Win32::FormatMessage(Win32::GetLastError()); print Failed to launch process $fullPath: $errormsg\n; } ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Help with Win32::Process::Create()
On Tue, 23 Aug 2011, Barry Brevik wrote: I ALREADY HAVE some code that does this (see below). My question is- is there a way to periodically poll the outside process to determine if it is still running? I've tried a few things already and none of them work. if (defined $process) { if ($process-GetExitCode() == Win32::Process::STILL_ACTIVE()) { # process is still running ... } else { # process has terminated; PID is still valid ... # release process handle so the OS can do full cleanup # of the already terminated process $process = undef; } } Cheers, -Jan ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Help with Win32::Process::Create()
-Original Message- From: perl-win32-users-boun...@listserv.activestate.com [mailto:perl- win32-users-boun...@listserv.activestate.com] On Behalf Of Barry Brevik Sent: Tuesday, August 23, 2011 2:08 PM To: perl-win32-users@listserv.ActiveState.com Subject: Help with Win32::Process::Create() I'm working on an app that periodically needs to execute outside procedures. Ideally, I want to launch the outside procedure in fire and forget mode; that is, I do not want to wait for the outside process to terminate. I ALREADY HAVE some code that does this (see below). My question is- is there a way to periodically poll the outside process to determine if it is still running? I've tried a few things already and none of them work. = the code = use strict; use warnings; use Win32::Process; # Parameters for the Win32::Process::Create function: # # Process This is an empty string that will receive #a process ID used to address the child process. #Returns a string that looks like this: #Win32::Process=SCALAR(0x235478). # # fullPath The full path to the program including the #program name and extension. Can be UNC. # # newArg The name of the program itself with an extension, #but no path. Also, command line arguments go here. # # inheritHndls Should the child process inherit the parent's file handles? # # flagsx OR'd combination of the flags listed above. # # dirx Startup directory for the child process. # my $process = ''; my $dirx = '.'; my $inheritHndls = 0; my $newArg = 'notepad.exe'; my $fullPath = c:\\windows\\system32\\$newArg; my $flagsx = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS; if (my $spawnhndl = Win32::Process::Create($process, $fullPath, $newArg, $inheritHndls, $flagsx, $dirx)) { my $pid = $process-GetProcessID(); print Child process returned PID: $pid\n; } else { my $errormsg = Win32::FormatMessage(Win32::GetLastError()); print Failed to launch process $fullPath: $errormsg\n; } ___ Take a look at the GetExitCode method for Win32::Process. HTH, Ken ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Win32::Process::Create
Not sure why you use Win32Process (I' am sure you have your reasons), but I have scripts that launch child processes and wait for them to terminate. I just use the backticks(``) rather than a system command. The script will just hang until the child is done. For the other thing about minimizing/hiding the console window, Win32::GUI can do this: use Win32::GUI; my $perlwin = Win32::GUI::GetPerlWindow(); Win32::GUI::Show( $perlwin, 0 ); # SW_HIDE Win32::GUI::Show( $perlwin, 1 ); # SW_SHOWNORMAL Win32::GUI::Show( $perlwin, 5 ); # SW_SHOW Win32::GUI::Show( $perlwin, 6 ); # SW_MINIMIZE -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Michael Ellery Sent: Monday, April 28, 2008 3:24 PM To: 'perl-win32-users' Subject: Win32::Process::Create ..I use this function pretty regularly to spawn procs on windows, but I've often wanted to minimize the console or main window that was launched. Does anyone know how to do this? In the corresponding WIN32 API, there is a STARTUPINFO structure that allows this, but looks like it's not part of the Win32::Process API. Advice appreciated. -Mike Ellery ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Win32::Process::Create
I was/am also having this problem, but generally ignored having the window- I can say for my part I do normally use backticks for most things, but I use win32process when I want more control over the process, for instance I want it to run for a certain amount of time and then kill it. For instance a little snippet that shows a PowerPoint slide for 15 seconds Win32::Process::Create($goodfile, c:\\progra~1\\microsoft office\\powerpoint viewer\\PPTVIEW.EXE, PPTVIEW.EXE \$goodfile\ /s, 0, NORMAL_PRIORITY_CLASS, .) || die ErrorReport(); Win32::Sleep(15000); {$goodfile-Kill(0)} -- James Shuttlesworth Network Technologies Manager Ursinus College Computing Services [EMAIL PROTECTED] -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Stuart Arnold Sent: Tuesday, April 29, 2008 2:47 AM To: 'Michael Ellery'; 'perl-win32-users' Subject: RE: Win32::Process::Create Not sure why you use Win32Process (I' am sure you have your reasons), but I have scripts that launch child processes and wait for them to terminate. I just use the backticks(``) rather than a system command. The script will just hang until the child is done. For the other thing about minimizing/hiding the console window, Win32::GUI can do this: use Win32::GUI; my $perlwin = Win32::GUI::GetPerlWindow(); Win32::GUI::Show( $perlwin, 0 ); # SW_HIDE Win32::GUI::Show( $perlwin, 1 ); # SW_SHOWNORMAL Win32::GUI::Show( $perlwin, 5 ); # SW_SHOW Win32::GUI::Show( $perlwin, 6 ); # SW_MINIMIZE -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Michael Ellery Sent: Monday, April 28, 2008 3:24 PM To: 'perl-win32-users' Subject: Win32::Process::Create ..I use this function pretty regularly to spawn procs on windows, but I've often wanted to minimize the console or main window that was launched. Does anyone know how to do this? In the corresponding WIN32 API, there is a STARTUPINFO structure that allows this, but looks like it's not part of the Win32::Process API. Advice appreciated. -Mike Ellery ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Win32::Process::Create
Jan Dubois wrote: If you need to wait for your subprocesses, then you may want to use this somewhat obscure form: my $pid = system(1, $cmdline); # ... waitpid $pid, 0; (This is documented in `perldoc perlport` as a Win32 specific extension to system(), but not mentioned in `perldoc -f system`). okay - thanks to everyone for the advice. I never knew this non-blocking version of system() existed - very interesting. Based on my quick tests, it looks like this version might still use the shell (although I can't tell). For instance, I wasn't able to start a cmd.exe instance to run a batch file using system(1, ...) in my quick tests, but that might have been pilot error. I'll give Win32::GUI::Show a shot - that might be my best option for now. Thanks, Mike ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Win32::Process::Create
On Tue, 29 Apr 2008, Shuttlesworth, James wrote: I was/am also having this problem, but generally ignored having the window- I can say for my part I do normally use backticks for most things, but I use win32process when I want more control over the process, for instance I want it to run for a certain amount of time and then kill it. For instance a little snippet that shows a PowerPoint slide for 15 seconds Win32::Process::Create($goodfile, c:\\progra~1\\microsoft office\\powerpoint viewer\\PPTVIEW.EXE, PPTVIEW.EXE \$goodfile\ /s, 0, NORMAL_PRIORITY_CLASS, .) || die ErrorReport(); Win32::Sleep(15000); {$goodfile-Kill(0)} You can still do this with the system(1, ...) syntax too: my @arg = ('-le', '++$|; while () { print ++$_; sleep(1) }'); my $pid = system(1, $^X, @arg); sleep(5); kill 9, $pid; You should make sure to use the system(1, $prog, @arg) form instead of the system(1, $cmdline) version because the latter may run your $cmdline indirectly via the cmd.exe shell[1] and the $pid returned by system() will then be the pid of the cmd.exe process and not of your actual program. Killing the cmd.exe shell will not terminate the child process. With ActivePerl 820 and later you can of course use kill -9, $pid; to kill not only $pid, but also all of its child processes. This still doesn't work right if your program is a GUI application (like the PowerPoint viewer above), because it will run detached from the cmd.exe which can finish immediately after launching the GUI. Oh, one thing I should mention about system(1, ...): Perl is keeping the list of processes started this way in a table that is also used to keep track of pseudo-threads created by the fork() emulation. This table is limited to something like 64 entries, so make sure you call either waitpid() or kill() on the pids if you plan to create lots of child processes over time. The purpose of this table is that wait() will now which child processes belong to the current Perl instance. It also means you cannot have more than 64 child-processes running at the same time. If you need more, then you have to use Win32::Process. Cheers, -Jan [1] The decision to run a $commandline via cmd.exe is made at least partially based on the existence of shell metacharacters (at least '', '', '|' and '%', and possibly others) in the commandline. The other criteria is that if $commandline fails to start without the shell, then it will be retried via the shell just in case you are trying to run one of the builtin shell commands (echo, dir, etc). ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Win32::Process::Create
..I use this function pretty regularly to spawn procs on windows, but I've often wanted to minimize the console or main window that was launched. Does anyone know how to do this? In the corresponding WIN32 API, there is a STARTUPINFO structure that allows this, but looks like it's not part of the Win32::Process API. Advice appreciated. -Mike Ellery ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Win32::Process::Create
- Original Message - From: Michael Ellery [EMAIL PROTECTED] To: 'perl-win32-users' perl-win32-users@listserv.ActiveState.com Sent: Tuesday, April 29, 2008 5:24 AM Subject: Win32::Process::Create ..I use this function pretty regularly to spawn procs on windows, but I've often wanted to minimize the console or main window that was launched. Does anyone know how to do this? In the corresponding WIN32 API, there is a STARTUPINFO structure that allows this, but looks like it's not part of the Win32::Process API. Advice appreciated. Jst a couple of thoughts - I don't have time to test any of this out at the moment. What happens if you launch the script using the wperl executable instead of the perl executable ? Have you checked the various flags constants ? From the docs: -- EXPORTS The following constants are exported by default: CREATE_DEFAULT_ERROR_MODE CREATE_NEW_CONSOLE CREATE_NEW_PROCESS_GROUP CREATE_NO_WINDOW CREATE_SEPARATE_WOW_VDM CREATE_SUSPENDED CREATE_UNICODE_ENVIRONMENT DEBUG_ONLY_THIS_PROCESS DEBUG_PROCESS DETACHED_PROCESS HIGH_PRIORITY_CLASS IDLE_PRIORITY_CLASS INFINITE NORMAL_PRIORITY_CLASS REALTIME_PRIORITY_CLASS THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_ERROR_RETURN THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_IDLE THREAD_PRIORITY_LOWEST THREAD_PRIORITY_NORMAL THREAD_PRIORITY_TIME_CRITICAL The following additional constants are exported by request only: STILL_ACTIVE -- I was thinking specifically of CREATE_NO_WINDOW constant (but perhaps that does something else). Cheers, Rob ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Re: Win32::Process::Create
Sisyphus wrote: What happens if you launch the script using the wperl executable instead of the perl executable ? I don't even know what wperl is, although it does look like it's part of my current perl install (I have never heard of it before now). In any event, it's not an option for us since most of our stuff runs in the context of the perlSE.dll (ActiveScript engine). Have you checked the various flags constants ? From the docs: -- EXPORTS The following constants are exported by default: CREATE_DEFAULT_ERROR_MODE SNIP -- I was thinking specifically of CREATE_NO_WINDOW constant (but perhaps that does something else). I believe this corresponds to this process creation flag (from MSDN docs): CREATE_NO_WINDOW 0x0800 The process is a console application that is being run without a console window. Therefore, the console handle for the application is not set. This flag is ignored if the application is not a console application, or if it is used with either CREATE_NEW_CONSOLE or DETACHED_PROCESS. I'm really looking for something that works more generally (for console and non-console apps alike). In older versions of the win32 API, I'm pretty sure there was a field in the STARTUPINFO that allowed the caller to request the app be started mimimized, but the current docs don't show such an option. Perhaps my best bet it to try to call ShowWindow directly ?? ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Win32::Process::Create
On Mon, 28 Apr 2008, Michael Ellery wrote: ..I use this function pretty regularly to spawn procs on windows, but I've often wanted to minimize the console or main window that was launched. Does anyone know how to do this? In the corresponding WIN32 API, there is a STARTUPINFO structure that allows this, but looks like it's not part of the Win32::Process API. Advice appreciated. You cannot do this currently with Win32::Process, so you may want to file an enhancement request at http://rt.cpan.org/Public/Dist/Display.html?Name=Win32-Process You could achieve the functionality with the standard system() function though. Just call e.g. Win32::SetChildShowWindow(Win32::SW_SHOWMINIMIZED); or Win32::SetChildShowWindow(Win32::SW_HIDE); to run processes minimized, or even without a window at all. See `perldoc Win32` for the Win32SetChildShowWindow() docs. If you need to wait for your subprocesses, then you may want to use this somewhat obscure form: my $pid = system(1, $cmdline); # ... waitpid $pid, 0; (This is documented in `perldoc perlport` as a Win32 specific extension to system(), but not mentioned in `perldoc -f system`). Cheers, -Jan ___ Perl-Win32-Users mailing list Perl-Win32-Users@listserv.ActiveState.com To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Win32::Process::Create Sillyness!
Hello, I've checked the mailing list archive on active state and I can find no reference of my issue ever being mentioned. If it has, I apologize in advance for covering old ground. Anyway, I just found what IMHO is a deficiency with Win32::Process::Create. The 3 parameter (arguments passed to the executable) needs to have a leading space. Otherwise, as far as I can tell, the argument is ignored. For Example, here is some code that is basically copied from the document page http://aspn.activestate.com/ASPN/docs/ActivePerl/site/lib/Win32/Process. html This code will not work. It will merely open Notepad with a blank document. - use Win32::Process; use Win32; sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } Win32::Process::Create($ProcessObj, C:\\windows\\system32\\notepad.exe, c:\\helloworld.txt, 0, NORMAL_PRIORITY_CLASS, .)|| die ErrorReport(); $ProcessObj-Wait(INFINITE); - This code, on the other hand, will open the hellowworld.txt file. - use Win32::Process; use Win32; sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } Win32::Process::Create($ProcessObj, C:\\windows\\system32\\notepad.exe, c:\\helloworld.txt, #NOTE, leading space 0, NORMAL_PRIORITY_CLASS, .)|| die ErrorReport(); $ProcessObj-Wait(INFINITE); - Can someone explain to me why Win32::Process::Create behaves this way? Thank you Erik Felton ___ Perl-Win32-Users mailing list [EMAIL PROTECTED] To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
RE: Win32::Process::Create Sillyness!
For there to be a deficiency with this particular aspect of Win32::Process::Create, there would also need to be a deficiency with the underlying CreateProcess() Win32 API. The actual cause here is the omission of notepad in the $appname argument. Win32::Process::Create($obj,$appname,$cmdline,$iflags,$cflags,$curdir) Creates a new process. Args: $objcontainer for process object $appnamefull path name of executable module $cmdlinecommand line args $iflags flag: inherit calling processes handles or not $cflags flags for creation (see exported vars below) $curdir working dir of new process Returns non-zero on success, 0 on failure. ## example from Win32::Process docs Win32::Process::Create($ProcessObj, C:\\winnt\\system32\\notepad.exe, notepad temp.txt, 0, NORMAL_PRIORITY_CLASS, .)|| die ErrorReport(); -Original Message- From: Erik Felton [mailto:[EMAIL PROTECTED] Sent: Friday, October 01, 2004 12:08 PM To: perl-win32-users Subject: Win32::Process::Create Sillyness! Hello, I've checked the mailing list archive on active state and I can find no reference of my issue ever being mentioned. If it has, I apologize in advance for covering old ground. Anyway, I just found what IMHO is a deficiency with Win32::Process::Create. The 3 parameter (arguments passed to the executable) needs to have a leading space. Otherwise, as far as I can tell, the argument is ignored. For Example, here is some code that is basically copied from the document page http://aspn.activestate.com/ASPN/docs/ActivePerl/site/lib/Win32/Process. html This code will not work. It will merely open Notepad with a blank document. - use Win32::Process; use Win32; sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } Win32::Process::Create($ProcessObj, C:\\windows\\system32\\notepad.exe, c:\\helloworld.txt, 0, NORMAL_PRIORITY_CLASS, .)|| die ErrorReport(); $ProcessObj-Wait(INFINITE); - This code, on the other hand, will open the hellowworld.txt file. - use Win32::Process; use Win32; sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } Win32::Process::Create($ProcessObj, C:\\windows\\system32\\notepad.exe, c:\\helloworld.txt, #NOTE, leading space 0, NORMAL_PRIORITY_CLASS, .)|| die ErrorReport(); $ProcessObj-Wait(INFINITE); - Can someone explain to me why Win32::Process::Create behaves this way? Thank you Erik Felton ___ Perl-Win32-Users mailing list [EMAIL PROTECTED] To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs ___ Perl-Win32-Users mailing list [EMAIL PROTECTED] To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Win32::Process::Create
I have a script which runs several programs depending upon the contents of a state table ( implemented as a hash). The main script and the spawned processes write into the state table and also read from it before they perform something. Is it necessary to implement the state table as a Shared Memory and use locking of the shared memory to avoid simultaneous access by two competing processes ? I think that Shared memory is not really required as the main script and the processes it creates run in the same thread and so look at the same state table which is not possible if using fork on UNIX. On UNIX the forked child gets a copy of the variables from the parent and if both need to look at something in common ( as the state table mentioned above), the common variable needs to be implemented as shared memory. The only problem I can think of on NT is, if the processes try to access the state table simultaneously and there is a deadlock. I have tried to use Amine's MemMap module and used it's shared memory implementation on NT. It works fine and I can use the lock and unlock methods of the module to prevent simultaneous access of the shared region by two or more processes. But I need some opinion on whether such usage is an overkill, or there is another elegant way to implement it. Any views or advise is appreciated. Thanks Ashish Tiwari Integrated Decisions and Systems. [EMAIL PROTECTED] The views expressed here are mine and do not reflect the official position of my employer or the organization through which the Internet was accessed. ___ Perl-Win32-Users mailing list [EMAIL PROTECTED] To unsubscribe: http://listserv.ActiveState.com/mailman/listinfo/perl-win32-users
Re: Is UNC not supported with Win32::Process::Create?
Hi, With Win32::Process::Create...(and CREATE_NEW_CONSOLE flag) this works = u:\\mydir\\test.exe but this does not = myserver\\mydir\test.exe Best to add error catching code to the 'Win32::Process::Create' call. Something like : or die ErrorReport(); where sub ErrorReport is defined like: sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } That will show you whether you have supplied an unrecognised server name ('The network name cannot be found.'), or whether you have specified an incorrect path ('The network path was not found.'), or whether there is some other problem. Is UNC not supported with Win32::Process::Create? I believe it is supported. Hope this helps. Cheers, Rob ___ Perl-Win32-Users mailing list [EMAIL PROTECTED] http://listserv.ActiveState.com/mailman/listinfo/perl-win32-users