Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: Executing perl program from another perl program and capturing the output

by BrowserUk (Patriarch)
on Nov 25, 2014 at 03:35 UTC ( [id://1108304]=note: print w/replies, xml ) Need Help??


in reply to Executing perl program from another perl program and capturing the output

The list form of system won't help you on windows.

The simple solution is to quote your paths (just as you would at the command line). Ie.:

my $progPath = cwd(); my $perlPath = $^X; my $args = "-c abc.conf -r"; # then build the command and capture the output... my $output = `\"$perlPath\" \"$progPath/my.pl\" $args`;

S'not com'cated :)


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
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.
  • Comment on Re: Executing perl program from another perl program and capturing the output
  • Download Code

Replies are listed 'Best First'.
Re^2: Executing perl program from another perl program and capturing the output
by Loops (Curate) on Nov 25, 2014 at 04:30 UTC

    Hi BrowserUk,

    It is my recollection that others have explicitly recommended the list form of system on Windows. Could you explain why it isn't helpful, so i'll not recommend it again in error?

      ould you explain why it isn't helpful,

      Because CreateProcess() is the only way to spawn a new process on windows; and it only accepts a single string containing the runtime arguments.

      If you supply system with the list form of arguments, they just get concatenated together, before being passed as the second argument to CreateProcess().

      There is some attempt to apply intelligence to the concatenation process, but is does not handle paths with spaces (correctly):

      win32_spawnvp(int mode, const char *cmdname, const char *const *argv) { #ifdef USE_RTL_SPAWNVP return spawnvp(mode, cmdname, (char * const *)argv); #else dTHXa(NULL); int ret; void* env; char* dir; child_IO_table tbl; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInformation; DWORD create = 0; char *cmd; char *fullcmd = NULL; char *cname = (char *)cmdname; STRLEN clen = 0; if (cname) { clen = strlen(cname); /* if command name contains dquotes, must remove them */ ...

      About the dumbest thing it could do...


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

        Interesting. Thanks.

        I did see the following in the System docs:

        On Windows, only the system PROGRAM LIST syntax will reliably avoid using the shell; system LIST , even with more than one element, will fall back to the shell if the first spawn fails.

        And was thinking mistakenly that array flattening would suffice. It appears that if "USE_RTL_SPAWNVP" is defined, that horror show is avoided though yes? A quick look in the code didn't reveal if that's true or if it's even defined in the common case. But fwiw, I did see a note in the code recommending Win32::Process instead.

        Last time I checked it did handle paths with spaces correctly because all it does is add "" around the args

Re^2: Executing perl program from another perl program and capturing the output
by Anonymous Monk on Nov 25, 2014 at 03:41 UTC

    The list form of system won't help you on windows.

    If your paths don't include quotes, system can help you on windows, if you use Capture::Tiny

    use Capture::Tiny qw/ capture /; my($stdout, $stderr, $exit) = capture { system { $args[0] } @args; };;

    If you have quotes in your paths then Win32::ShellQuote comes to the rescue

      If ... if ... Capture::Tiny. If ... then Win32::ShellQuote ...

      Just unnecessary! (Ie. A waste of time and effort.)

      If the shell (cmd.exe) requires quotes ...:

      C:\test>"c:\Program Files\Direct Modeling Express 4.0\binx64\7za.exe" +a -y c:\junk.rar "c:\Program Files\Hitman Pro 3.5\*" 7-Zip (A) 4.42 Copyright (c) 1999-2006 Igor Pavlov 2006-05-14 Scanning Creating archive c:\junk.rar Compressing HitmanPro35_x64.exe Everything is Ok

      Then invoking the same command via the shell, via backticks also requires, (and will work with) quotes ... (but use / instead of \ for paths!)

      [0] Perl> $output = `\"c:/Program Files/Direct Modeling Express 4.0/bi +nx64/7za.exe\" a -y c:/junk.rar \"c:/Program Files/Hitman Pro 3.5/*\" +`;; [0] Perl> print $output;; 7-Zip (A) 4.42 Copyright (c) 1999-2006 Igor Pavlov 2006-05-14 Scanning Updating archive c:/junk.rar Compressing HitmanPro35_x64.exe Everything is Ok

      And that's *all* that is required. No ifs; no buts; learn the rules, and it just works.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

        And that's *all* that is required. No ifs; no buts; learn the rules, and it just works.

        Yeah, I stick to learning perl quoting rules, and then don't worry about cmd.exe quoting rules too much

Re^2: Executing perl program from another perl program and capturing the output
by rgren925 (Beadle) on Nov 29, 2014 at 23:12 UTC
    This was exactly what I needed. I had tried just about every combination of quotes and escaped quotes BUT this, naturally. I had tried Win32:GetShortPathName and it worked but, as this is a cross-platform tool, I prefer to avoid platform-specific code paths where possible. Thanks very much!
      I had tried Win32:GetShortPathName and it worked but, as this is a cross-platform tool, I prefer to avoid platform-specific code paths where possible.

      Indeed. I don't have to write cross-platform very often, and I have no problem using well-written modules when required.

      But unlike many others (it seems), my criteria for "when required" extends well beyond 'it exists'. If I don't need it, I don't use it(*).

      I like simple! (Which my wife would probably say, is just as well ... :)

      There are very good reasons for keeping ones dependencies to a minimum.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1108304]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2024-04-18 12:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found