powershell执行外部命令不接受参数

时间:2013-09-11 15:49:28

标签: powershell

我正在执行以下代码,尝试执行7z.exe命令来解压缩文件。

$ dir包含zip文件路径的用户输入,当然可以包含空格!和$ dir \ temp2下面是我之前创建的目录。

    Get-ChildItem -path $dir -Filter *.zip | 
    ForEach-Object { 
         $zip_path = """" + $dir + "\" + $_.name + """"
         $output = " -o""$dir\temp2"""
         &7z e $zip_path $output
    }

当我执行它时,我从7z.exe

获得以下内容

7-Zip [64] 9.20版权所有(c)1999-2010 Igor Pavlov 2010-11-18

处理存档:C:\ test dir \ test.zip

没有要处理的文件

档案:0 大小:0 压缩:50219965

如果我然后将$ zip_path和$ output中的值复制到我自己的cmd行,那就可以了!

例如: 7z e“c:\ test dir \ test.zip”-o“c:\ test output”

现在,我可以重现相同的消息“没有要处理的文件”,当我在powershell中使用cli中的以下cmd执行时,我得到了这个消息。

7z e“c:\ test dir \ test.zip”o“c:\ test output”

所以,似乎powershell正在从我的-o选项中删除破折号。是的,它需要-o“C:\ test output”而不是-o“c:\ test output”和7z.exe -o参数和它的值之间没有空格。

我很难过,我做错了什么,或者我应该以不同的方式做这件事?任何建议或帮助谢谢

3 个答案:

答案 0 :(得分:3)

我永远无法使Invoke-Expression(别名=&)正常工作,所以我学会了如何使用过程对象

    $7ZExe = (Get-Command -CommandType Application  -Name 7z )
    $7ZArgs = @(
        ('-o"{0}\{1}"' -f $dir, $_.Name), 
        ('"{0}\{1}"' -f $dir, 'temp2')
    )

    [Diagnostics.ProcessStartInfo]$7Zpsi = New-Object -TypeName:System.Diagnostics.ProcessStartInfo -Property:@{
        CreateNoWindow = $false;
        UseShellExecute = $false;
        Filename = $7ZExe.Path;
        Arguments = $7ZArgs;
        WindowStyle = 'Hidden';
        RedirectStandardOutput = $true
        RedirectStandardError = $true
        WorkingDirectory = $(Get-Location).Path
    }

    $proc = [System.Diagnostics.Process]::Start($7zpsi)
    $7ZOut = $proc.StandardOutput
    $7ZErr = $proc.StandardError
    $proc.WaitForExit()

答案 1 :(得分:3)

我能够复制确切的问题,并尝试了许多组合转义-o转换和转义引号"而不是。但是,正如一个答案提到SysInternals,我使用ProcessMonitor找出它传递给7z.exe的格式。在普通命令行中工作的东西在powershell中不能以相同的方式工作。例如,如果我尝试在PowerShell中构建参数就像cmdline一样,它将失败。即-o"C:\scripts\so\new folder"不起作用。但是,如果在引号内包含-o切换,则PowerShell会传递"-oC:\scripts\so\new folder"很高兴接受的字符串7z.exe。所以我了解到7z.exe会接受两种格式,如

"C:\Program Files\7-zip\7z.exe" e "C:\scripts\so\new folder.zip" -o"C:\scripts\so\new folder"

"C:\Program Files\7-zip\7z.exe" e "C:\scripts\so\new folder.zip" "-oC:\scripts\so\new folder"

这两个例子都包含空格。

[string]$pathtoexe = "C:\Program Files\7-Zip\7z.exe"
$dir = "C:\scripts\so"
$output = "$dir\new folder"
Get-ChildItem -path $dir -Filter *.zip | % {        
    [array]$marguments = "e",$_.FullName,"-o$output";    
    & $pathtoexe $marguments 
}

PS V3中的另一种方法是转义PowerShell解析功能。您可以使用--%命令告诉powershell停止解析更多这样的命令。

$zipfile = "C:\scripts\so\newfolder.zip"
$destinationfolder = "C:\scripts\so\New Folder"
[string]$pathtoexe = "C:\Program Files\7-Zip\7z.exe"
& $pathtoexe --% e "C:\scripts\so\newfolder.zip" -o"C:\scripts\so\new folder"

使用--%语法键入命令就像在命令行中键入命令一样。我测试了这个逻辑,它将文件提取到目标文件夹。

详细了解--%支票PS> help about_parsing

此方法的问题是--%之后无法包含变量。这个问题的解决方案是将--%作为另一个字符串变量包含在内并像这样传递它。这种方法类似于最初没有工作的命令行方法。

[string]$pathtoexe = "C:\Program Files\7-Zip\7z.exe"
$dir = "C:\scripts\so"
$output = "$dir\new folder"
Get-ChildItem -path $dir -Filter *.zip | % {        
$zipfile = $_.FullName;
[string]$formated = [System.String]::Concat("e ", """$zipfile"""," -o""$output""");
[string]$stopparser = '--%';
& $pathtoexe $stopparser $formated; 
}

答案 2 :(得分:3)

使用Windows Process Explorer Sysinternals中出色的suite我能够观察到一些非常有趣的行为。我简化了你的命令行,如下所示:

dir -Path $dir -Filter *.zip | 
  select FullName | 
  % { & 7za.exe e $_ "-o$dir\tmp" }

这实际上是根据Process Explorer调用以下命令行:

C:\temp\7za.exe @{FullName="C:\temp\test.zip"} -oC:\temp\test

告诉PowerShell扩展FullName属性会将其强制退出hashmap,并将其视为7-zip可以处理的常规字符串:

dir -Path $dir -Filter *.zip | 
  select -ExpandProperty FullName | 
  % { & 7za.exe e $_ "-o$dir\tmp" }

可能还有其他问题,例如处理文件名中的空格,我真的没有考虑或考虑,但我认为值得添加一条说明PowerShell(在这种情况下为v2)并没有完全通过你可能期望的参数。