带有连字符参数的 Powershell Invoke-Command

标签 powershell msdeploy invoke-command

我需要能够在远程计算机上运行以下 cmd 命令。

"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:package="\\Server\Share\Package.zip" -dest:auto,computerName=Server1

Powershells Invoke-Command 看起来很有希望,但我不知道如何将参数传递给 msdeploy。

我试过了
Invoke-Command -ComputerName RemoteServer1 -ScriptBlock { "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:package="\\Server\Share\Package.zip" -dest:auto,computerName=Server1 }

但它说“你必须在'-'运算符的右侧提供一个值表达式。”。
所以我猜问题是连字符,但我不知道如何转义它们以使命令工作。

最佳答案

第一部分:处理 PowerShell 命令行细节

使用&调用外部可执行文件。语法:& "[path] command" [arguments] .

另请注意,msdeploy 支持 alternate way of specifying arguments从 PowerShell 调用时:

With a minor modification to its usual syntax, Web Deploy commands can be run from a Windows PowerShell prompt. To do this, change the colon character (:) after the verb, source, and dest arguments of the Web Deploy command to an equal sign (=). In the following example, compare the Web Deploy command with its PowerShell version.

Web Deploy command:

command: msdeploy -verb:sync -source:metakey=/lm/w3svc/1 -dest:metakey=/lm/w3svc/2 -verbose

PowerShell command:

.\msdeploy.exe -verb=sync -source=metakey=/lm/w3svc/1 -dest=metakey=/lm/w3svc/2 -verbose



请注意,参数包含在数组中:这提示 PowerShell 如何正确地将它们传递给目标应用程序。

例子:

Invoke-Command -ComputerName RemoteServer1 -ScriptBlock {&"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" @('-verb=sync', '-source=package="\\Server\Share\Package.zip"', '-dest=auto,computerName=Server1')}

第二部分:处理multi-hop authentication

从您的评论中,我看到现在 PowerShell 成功运行 msdeploy在远程服务器上,但 msdeploy无法访问远程共享:

While the command executes, now msdeploy it saying:

"More Information: Object of type 'package' and path '\Server\Share\Package.zip' cannot be created. Learn more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_EXCEPTION_WHILE_CREATING_OBJECT.

Error: The Zip package '\Server\Share\Package.zip' could not be loaded. Error: Access to the path '\Server\Share\Package.zip' is denied. Error count: 1."

Even though the user has access to the share (read/write).



这是因为您实际上尝试建立从计算机 A(客户端)到计算机 B(服务器)然后从计算机 B 的远程 session ,您尝试访问计算机 C 上共享中的文件(\\Server\Share\Package.zip)。

CredSSP example
Invoke-Command失败,因为远程 session 尝试使用计算机凭据而不是用于调用远程 session 的凭据访问文件共享。 There is a way to pass or delegate credentials from the client这样我们就可以对文件共享进行身份验证。这就是所谓的多跳身份验证,PowerShell 远程处理使用 CredSSP 实现了这一点。

要启用 CredSSP,请从提升的提示符处运行这些命令:
  • 在您的电脑上:Enable-WSManCredSSP -Role Client -DelegateComputer "TargetServer.FQ.DN"DelegateComputer参数用于指定从客户端接收委托(delegate)凭证的服务器或服务器。 DelegateComputer接受通配符 (*.FQ.DN)。您也可以指定*指定网络中的所有计算机。
  • 在目标服务器上:Enable-WSManCredSSP -Role Server

  • 现在,您应该可以运行 Invoke-Command使用 CredSSP 作为身份验证方法并传递凭据:

    Invoke-Command -ComputerName RemoteServer1 -Authentication Credssp -Credential Domain\Username -ScriptBlock {&"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" @('-verb=sync', '-source=package="\\Server\Share\Package.zip"', '-dest=auto,computerName=Server1')}
    

    第三部分:使用 Invoke-Command 传递参数

    How would I go about having the server parameterized. If I have a parameter $Server as the server name, how would I go about putting that in as a replacement for the -dest=auto,computerName=Server1 part?



    要将参数传递给脚本 block ,请使用 ArgumentList范围:

    $Servers = @('Server1', 'Server2', 'Server3')
    $Command = {
        Param($Srv)
        &"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" @('-verb=sync', '-source=package="\\Server\Share\Package.zip"', "-dest=auto,computerName=$Srv")
    }
    
    $Servers |
        ForEach-Object {
            Invoke-Command -ComputerName RemoteServer1 -Authentication Credssp -Credential Domain\Username -ScriptBlock $Command -ArgumentList $_
        }
    

    更进一步:

    Нow would I go about adding extra parameters dynamically to the command. I need to add in -skip:objectName=dirPath,absolutePath="<folder>" to the arguments in the &"C:\Program Files\..." line, for each folder in an array of strings.



    如果您要为所有服务器排除一组文件夹:

    $Servers = @('Server1', 'Server2', 'Server3')
    $SkipPaths = @('C:\folder\to\skip1', 'C:\folder\to\skip2', 'C:\folder\to\skip3')
    
    $SkipCmd = $SkipPaths | ForEach-Object {"-skip=objectName=dirPath,absolutePath=$_"}
    
    $Command = {
        Param($Srv, $Skp)
        &"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" $(@('-verb=sync', '-source=package="\\Server\Share\Package.zip"', "-dest=auto,computerName=$Srv") + $Skp)
    }
    
    $Servers |
        ForEach-Object {
            Invoke-Command -ComputerName RemoteServer1 -Authentication Credssp -Credential Domain\Username -ScriptBlock $Command -ArgumentList ($_, $SkipCmd)
        }
    

    如果每个服务器都有不同的文件夹集:

    $Servers = @{
        Server1 = @('C:\folder\to\skip_1', 'C:\folder\to\skip_2', 'C:\folder\to\skip_3')
        Server2 = @('C:\folder\to\skip_A', 'C:\folder\to\skip_B', 'C:\folder\to\skip_C')
        Server3 = @('C:\folder\to\skip_X', 'C:\folder\to\skip_Y', 'C:\folder\to\skip_Z')
    }
    
    $Command = {
        Param($Srv, $Skp)
        &"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" $(@('-verb=sync', '-source=package="\\Server\Share\Package.zip"', "-dest=auto,computerName=$Srv") + $Skp)
    }
    
    $Servers.GetEnumerator() |
        ForEach-Object {
            $SkipCmd = $_.Value | ForEach-Object {"-skip=objectName=dirPath,absolutePath=$_"}
            Invoke-Command -ComputerName RemoteServer1 -Authentication Credssp -Credential Domain\Username -ScriptBlock $Command -ArgumentList ($_.Key, $SkipCmd)
        }
    

    关于带有连字符参数的 Powershell Invoke-Command,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28573227/

    相关文章:

    r - PowerShell:在大文件中替换NUL不起作用

    c# - 通过PowerShell使我的C#应用​​程序可管理

    powershell - 从 XML 源注册计划任务

    python - virtualenv 挂断了安装 setuptools

    MsDeploy runCommand 提供程序 - 未经授权的错误

    visual-studio-2010 - VS2010 Web Publish 命令行版文件系统部署

    msdeploy 并跳过未命名为 x 的目录

    powershell - 使用 PowerShell Invoke 命令安装软件

    session - 从远程 session 获取完整的堆栈跟踪

    powershell - 使用 Powershell Invoke-Command 远程执行时出现 OutOfMemory 异常