【问题标题】:How I do invoke a PowerShell Start-Process command with arguments that require quoting from a Command Prompt / batch file?如何使用需要从命令提示符/批处理文件中引用的参数调用 PowerShell Start-Process 命令?
【发布时间】:2018-06-17 21:55:29
【问题描述】:

在PowerShell 中尝试执行一个命令时出现此错误:

我正在尝试exec这个命令:

powershell.exe Start-Process -FilePath "C:\Windows\System32\attrib +h +s "%CD%"" -Verb runAs

谁能帮我弄清楚为什么会发生这种情况以及如何解决它?

【问题讨论】:

  • 您的问题标题是询问如何在 PowerShell 中执行命令,但您似乎正在通过 cmd.exe 中的 PowerShell 执行带有 cmd.exe 参数的 cmd.exe 文件! 为什么?
  • 如果这个问题和你的lastest one有关,那就没有意义了,因为你可以直接从右键上下文菜单注册表位置运行PowerShell Start-Process ...命令,你不需要cmd.exe 完全参与其中!
  • 同样在PowerShell中,你也可以在没有attrib.exe的情况下设置当前目录属性! $(Get-Item $(Get-Location)).Attributes='Hidden,System'.
  • @Compo: 是的,cmd.exe 不会在您调用通过注册表定义的文件资源管理器上下文菜单命令时隐式涉及。由于您因此无权访问环境变量,因此必须将%CD% 替换为%V,这是右键单击文件夹的完整路径的占位符。然而,关于引用,基本上与从cmd.exe 调用时的规则相同,并且引用是 OP 的主要问题。
  • @mklement0,我知道creating a context menu entry 中的过程,但这个问题仍然是关于“当前目录”的。 OP 尚未确认这两个问题是否相关。

标签: powershell batch-file syntax quoting


【解决方案1】:

有人可以帮我弄清楚为什么会这样吗?

Start-Process cmdlet 的 -FilePath 参数需要可执行文件本身的名称或路径,而不是整个命令行。

传递给通过-FilePath 指定的可执行文件的参数 必须作为数组 通过-ArgumentList 单独传递 (-Args) 参数。

从cmd.exe(批处理文件)调用时,在一个"-enclosed 参数中传递整个命令行以供PowerShell 评估在概念上更简洁:

powershell.exe -Command "Start-Process -Verb RunAs -FilePath attrib.exe -Args +h, +s, '\"%CD%\"'"

注意需要转义 %CD% 值 双重,首先为了 PowerShell 将其包含在 ' 中,然后在 \" 中:外部 ' 确保PowerShell 本身将值识别为单个参数,并且嵌入的 \" 引用确保最终目标程序 attrib.exe 也将值视为单个参数。

不幸的是,这种双重转义的需要是不必要的 - 在this GitHub issue 中讨论过。

【讨论】:

    【解决方案2】:

    不需要完全限定 attrib.exe 的路径,它可以通过 DOS 和 PoSH 环境变量本机使用。

    powershell attrib 'd:\temp\SomeFile.txt'
    # A                    D:\temp\SomeFile.txt
    
    powershell attrib +r 'd:\temp\SomeFile.txt'
    
    powershell attrib 'd:\temp\SomeFile.txt'
    # A    R               D:\temp\SomeFile.txt
    

    任何带空格的字符串都必须用引号括起来,以及参数,否则它们必须单独传递。

    Start-Process powershell -ArgumentList "-NoExit","-Command  &{ $ConsoleCommand }" -Wait
    

    在你的用例和我展示的情况下,你所做的只是调用 PoSH 来运行你可以在 DOS 中执行的 DOS 命令。那么,除了 runas 之外,为什么还要使用 PoSH?

    此外,当您按照自己尝试的方式执行命令时,正确引用以正确限定该命令的运行可能会令人困惑。这是那条线的真正问题。 传递参数必须正确完成,如果处理不当,空格会导致问题,从而导致您的错误。

    另外,为什么要从 cmd.exe 开始进行这项工作,只是为了结束向 PoSH 控制台主机运行此命令?

    只需在 PoSH 控制台主机中本地执行此操作,这本质上就是您正在执行的操作。省去额外的步骤和复杂性。

    只需启动 powershellexe,而不是 cmd.exe 并运行您的 DOS 命令。

    attrib +r 'd:\temp\SomeFile.txt'
    

    cmd.exe 可以做的事情很少,PoSH 控制台不能,PoSH(控制台主机和 ISE)可以做很多 cmd.exe 不能做的事情。 那么,为什么不直接开始并留在 PoSH 中呢?

    您可以在 PoSH 控制台主机中运行所有 DOS 命令(在 ISE 中,需要付出更多努力才能让它们正常工作),或者只使用 PoSH 等效命令。

    使用 PowerShell Cmdlet 处理文件属性 --- 'blogs.technet.microsoft.com/heyscriptingguy/2011/01/26/use-a-powershell-cmdlet-to-work-with-file-attributes'

    我知道那颗牙有点长。但是,您也可以执行以下操作,以获取属性,并使用类似但不同的 cmdlet 修改它们。

    (Get-ChildItem -Path 'D:\Temp\SomeFile.txt').Attributes
    # ReadOnly, Archive
    
    # or this
    (gci 'D:\Temp\SomeFile.txt').Attributes
    
    # or this
    (dir 'D:\Temp\SomeFile.txt').Attributes
    
    # or this
    (ls 'D:\Temp\SomeFile.txt').Attributes
    

    以上每个都做完全相同的事情。 设置属性就是这样……

    Set-ItemProperty -Path 'D:\Temp\SomeFile.txt'-Name IsReadOnly -Value $false
    
    # or
    sp 'D:\Temp\SomeFile.txt' IsReadOnly $false
    
    (ls 'D:\Temp\SomeFile.txt').Attributes
    # Archive
    

    当然可以使用 .bat 来调用 PoSH 脚本文件。但如果您只是坐在航站楼前,请根据需要选择其中一个。

    【讨论】:

    • OP 正在尝试通过 Start-Process -Verb RunAs 运行 attrib.exe elevated,这是 direct 调用无法做到的 - 无论是在 cmd.exe 还是在 PowerShell 中。 OP的具体问题是尝试将整个attrib 命令行传递给Start-Process -FilePath,而-FilePath只期望目标可执行文件(文件名/路径) , 其参数需要通过 -ArgumentList 单独传递。
    • 一些旁白:请不要将cmd.exe ("Command Prompt") 称为“DOS”——后者仅适用于过时的 MS-DOS 和 Windows 9x 操作系统。同样,虽然“PoSH”(及其大小写变体)背后有一些历史,但为了清楚起见,我建议远离它——官方名称“PowerShell”只是稍长一些。引用外部资源时请使用完整的 URL,以便它们在答案中显示为可直接点击的链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多