Subject: | Process command line arguments on Win32 is broken |
Suppose next command:
"E:\деп лой\7zip\7z.exe" a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN "E:\tmp\русс кая"
Proc::Background::Win32 using Win32 CreateProcess function.
Excerpt from https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx:
CreateProcess function
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space–delimited token in the lpCommandLine string. If you are using a long file name that contains a space, *use quoted strings* to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous.
lpApplicationName should not quoted with ".
In Win32.pm we have:
-- Win32.pm --
# Create the process.
if (Win32::Process::Create($os_obj,
$args[0],
"@args",
0,
NORMAL_PRIORITY_CLASS,
'.')) {
-- Win32.pm --
Variant #1:
my $cmd = '"E:\деп лой\7zip\7z.exe"';
my $args = 'a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN "E:\a b\001.7z" "E:\tmp\русс кая"';
my $proc3 = Proc::Background->new({}, $cmd, $args);
fails with 'cannot find absolute location of "E:\деп лой\7zip\7z.exe"'
In Win32.pm:
$args[0] = "E:\деп лой\7zip\7z.exe" - but should not be qouted;
@args = "E:\деп лой\7zip\7z.exe"" a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN \"E:\a b\001.7z\" \"E:\tmp\русс кая\"" - quotes are escaped, but in in Windows cmd or perl this not work;
Variant #2:
my $cmd = 'E:\деп лой\7zip\7z.exe';
my $args = 'a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN "E:\a b\001.7z" "E:\tmp\русс кая"';
my $proc3 = Proc::Background->new({}, $cmd, $args);
fails with 'cannot find absolute location of "E:\деп лой\7zip\7z.exe"'
In Win32.pm:
$args[0] = E:\деп лой\7zip\7z.exe - OK;
@args = E:\деп лой\7zip\7z.exe" a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN \"E:\a b\001.7z\" \"E:\tmp\русс кая\"" - quotes are escaped again, 7z.exe started but with wrong arguments:
7-Zip [32] 16.04 : Copyright (c) 1999-2016 Igor Pavlov : 2016-10-04
Command Line Error:
Unsupported command:
a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN \E:\a
Working variant for Win32:
- quotes must not be escaped;
- lpApplicationName ($args[0]) must not be quoted;
- lpCommandLine should specify the executable module in quots as first part of string;
As a result:
In Win32.pm:
comment all @args escaping if Win32 platform;
+ my $command = substr($args[0],1,length($args[0])-2);
- $args[0] = Proc::Background::_resolve_path($args[0]) or return;
- $args[0] = Win32::GetShortPathName($args[0]);
...
if (Win32::Process::Create($os_obj,
$command,
"@args",
...
In script:
my $cmd = '"E:\деп лой\7zip\7z.exe"';
my $args = 'a -r -ms=on -mx3 -myx0 -m2=LZMA2 -sccWIN -scsWIN "E:\a b\001.7z" "E:\tmp\русс кая"';
my $proc3 = Proc::Background->new({}, $cmd, $args);
More information here:
Everyone quotes command line arguments the wrong way
https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
So the situation is worse than I expected.