我需要能够在远程计算机上运行以下 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
)。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/