从 PowerShell 执行外部命令不接受参数

问题描述:

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

I am executing the following code attempting to execute the 7z.exe command to unzip files.

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

$dir contains the user input of the path to the zip file which can contain spaces of course! And $dir\temp2 below is a directory that I previously created.

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

当我执行它时,我从 7z.exe 得到以下内容:

When I execute it I get the following from 7z.exe:

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18

Processing archive: C:\test dir\test.zip


No files to process

Files: 0
Size:       0
Compressed: 50219965

如果我然后从 $zip_path 和 $output 复制值以形成我自己的 cmd 行,它工作

If I then copy the value from $zip_path and $output to form my own cmd line it works!

例如:

7z e "c:\test dir\test.zip" -o"c:\test output"

现在,我可以通过在 cli 中使用以下 cmd 在 PowerShell 中执行时得到相同的消息没有要处理的文件".

Now, I can reproduce the same message "no files to process" I get when I execute within PowerShell by using the following cmd in cli.

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

因此,PowerShell 似乎正在从我的 -o 选项中删除破折号字符.并且,它需要是 -o"C:\test output" 而不是 -o "c:\test output" 7z.exe 在 -o 参数和它的值之间没有空格.

So, it seems that PowerShell is removing the dash char from my -o option. And yes, it needs to be -o"C:\test output" and not -o "c:\test output" with 7z.exe there is no space between the -o parameter and its value.

我被难住了.我是不是做错了什么,还是应该换一种方式?

I am stumped. Am I doing something wrong or should I be doing this a different way?

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

I can never get Invoke-Expression (alias = &) to work right either, so I learned how to use a process object

    $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()