Re: Executing perl program from another perl program and capturing the output
by BrowserUk (Patriarch) on Nov 25, 2014 at 03:35 UTC
|
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.
| [reply] [d/l] |
|
| [reply] |
|
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.
| [reply] [d/l] |
|
|
|
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 | [reply] [d/l] |
|
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.
| [reply] [d/l] [select] |
|
|
|
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!
| [reply] |
|
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.
| [reply] |
Re: Executing perl program from another perl program and capturing the output
by Loops (Curate) on Nov 25, 2014 at 02:58 UTC
|
Hi there,
You don't want to use 8.3 names. You just need to pass each individual parameter to system as a list, instead of together in a string. That way the parameters are already divided up and not further split on space characters. Unfortunately system does not capture its output, but Capture::Tiny is to the rescue in that regard:
use Capture::Tiny ':all';
my @cmd = (
'C:\program files\myprog\space invaders.exe',
'parameter 1',
'parameter 2 with spaces'
);
my ($stdout, $stderr, $exit) = capture { system @cmd };
print "The return status was $exit\n";
print "The output was $stdout\n";
| [reply] [d/l] |
|
| [reply] |
|
Well, I'll have to take your word for that. If true, then Perl does not deserve to be used on Windows. Telling people to use 8.3 filenames at this stage of the game is a sad admission of defeat and a poor implementation.
| [reply] |
|
Re: Executing perl program from another perl program and capturing the output
by BillKSmith (Monsignor) on Nov 25, 2014 at 03:03 UTC
|
The 'brute force' solution to problems with long windows names is, as your suggest, to use their short alias. You can learn the short name of a file (or directory) by using the /X option of the dir command.
There are other options, but I usually prefer this.
| [reply] |
|
by using the /X option of the dir command. :) Seeing how the OPs issue is not howing how to call the shell and stuff, using the shell to discover shortname is going to be hard :) Win32::GetShortPathName otoh is much easier
| [reply] |
Re: Executing perl program from another perl program and capturing the output
by Anonymous Monk on Nov 25, 2014 at 02:57 UTC
|
| [reply] |