UnstoppableDrew has asked for the wisdom of the Perl Monks concerning the following question:

This is driving me crazy, and I'm hoping someone can offer up a good alternative.

My problem: I have a perl script that is a test harness. It starts up some clients using fork/exec and then does stuff. This much all works great. Now there is a new requirement. I need to start a matlab RMI server, which is essentially just calling java with the matlab class. The problem is there isn't a graceful way to shutdown the matlab server, you have to kill it. Perl under windows doesn't return a true pid when it forks, and it changes upon exec anyway. My solution was to use Win32::OLE and access the process info. Since it's possible there will be other java processes running I tried to find the pid's of all the java.exe processes and save them. I then fork/exec the rmi server, and look again to find the new java process. However if you have Win32::OLE in your script and fork it throws an unhandled exception. There was a bug filed against Active perl about this back in 2005, but it's clearly not fixed yet.

I tried various methods of load win32::ole, do my thing, unload it, and load it again for the second pid scrape, but its just not working.

Here's the most recent iteration of the code:

sub scrape_java_pids { use Win32::OLE; my $CLASS = "winmgmts:{impersonationLevel=impersonate}\\\\.\\Root\\c +imv2"; my $WMI = Win32::OLE->GetObject( $CLASS ) || die "Error - failed to +instantiate Win32::OLE object: $!\n"; my %jpid; foreach my $Proc ( $WMI->ExecQuery("SELECT * FROM Win32_Process WHER +E Name = 'java.exe'") ) { $jpid{ $Proc->{ProcessID} } = 1; } Symbol::delete_package("Win32::OLE"); # fork & win32::ole don't pla +y nicely. delete $INC{'Win32/OLE.pm'}; $WMI=""; return %jpid; }
There has got to be a better way to do this.

Replies are listed 'Best First'.
Re: Windows + Win32::OLE + fork = Hell
by BrowserUk (Patriarch) on Oct 03, 2007 at 18:18 UTC

    On win32, system is far simpler to use than fork followed by exec. Eg:

    my $pid = system 1, "/path/to/the/command.exe arg1 arg2";

    Note: the first parameter '1', it causes the command to be run asynchronously, and the pid returned is a real pid.

    This does have limitations. If your command involves shell characters, (io redirection etc.) then a cmd.exe session will be started and your command will be run within that which works fine except that the pid returned will be for cmd.exe and killing that will not kill the executable started from it.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Windows + Win32::OLE + fork = Hell
by UnstoppableDrew (Sexton) on Oct 03, 2007 at 16:49 UTC
    Well I basically solved my problem. I used the SysInternals pstools kit and opened a pipe from pslist. Somewhat inelegant to go to an external tool, but seems like my only choice.
Re: Windows + Win32::OLE + fork = Hell
by renodino (Curate) on Oct 03, 2007 at 16:55 UTC
    Be advised that fork() on Windows is really just spawning a thread. (I don't recall what exec() maps to, possibly nothing).

    Take a look at Win32::Process instead.


    Perl Contrarian & SQL fanboy
Re: Windows + Win32::OLE + fork = Hell
by cmv (Chaplain) on Oct 03, 2007 at 22:40 UTC
    I'm just learning about the wonders of the wmic command on windows xp machines.

    You can get process information for all processes currently running on your xp box by running the command:

    wmic process list /format:value
    A quick perl script to play with this might look like:
    use Data::Dumper; # Get proc info via wmic (not available on all versions of windows)... my @procs = split(/^\s*\cM\n/m, `wmic process list /format:value`); shift(@procs); # Remove initial blank line # Iterate through each process... foreach my $p (@procs) { $p =~ s/\cM//g; # Grrrr, rotten windows my %node = split(/[=\n]/, $p); # Hashify information print Dumper(\%node); }
      I've just discovered that killing all running windows process(es) for a particular executable is very easy with wmic:
      WMIC PROCESS where name='evil.exe' delete
      Handy little tool -- too bad it isn't written in perl...
Re: Windows + Win32::OLE + fork = Hell
by UnstoppableDrew (Sexton) on Oct 04, 2007 at 16:31 UTC
    Thanks for all the suggestions. You've given me some good ideas to try and utilize in future projects.
Re: Windows + Win32::OLE + fork = Hell
by Cop (Initiate) on Oct 03, 2007 at 18:12 UTC

    From design point of view, it is a bad idea to create process based application on a thread based OS. You are not using the strength, but the weakness of your target environment.

      Yeah, that's my *nix background showing. I haven't drunk enough Koolaid on the windows side yet. :)