使用通用参数执行远程通用 Powershell 脚本 [英] Execute a remote generic Powershell script with generic parameters
问题描述
我需要编写一个 Powershell 脚本(我们称之为控制器脚本"),它能够调用传递通用参数的通用远程 Powershell 脚本.控制器脚本接受主机名、凭据、远程脚本路径和作为散列表的远程脚本参数作为参数.
相反,远程脚本可以是接受任何字符串参数的任何脚本.
对控制器脚本使用哈希表参数很有用,因为我可以传递参数的动态字典(取决于控制器调用),同时让 PS 执行将字典转换"为字符串参数列表的工作,例如-Param1 Value1 -Param2 Value2
.
我从这个答案中得到了一些想法,这就是我所做的(控制器"脚本):>
参数([字符串] $ComputerName,[字符串] $用户名,[字符串] $密码,[字符串] $ScriptPath,[字符串] $Parameters)$EncPassword = ConvertTo-SecureString $Password -AsPlainText -Force$cred = 新对象 System.Management.Automation.PSCredential($Username,$EncPassword)$ScriptBlock = [Scriptblock]::Create(".$ScriptPath $(&{$args} @Parameters)")Invoke-Command -ComputerName $ComputerName -Credential $cred -Scriptblock $ScriptBlock
然后我以这种方式通过 PS 提示执行它:
.\controller.ps1 -ComputerName MACHINE_NAME -Username USERNAME -Password PASSWORD -ScriptPath "D:\TestScript.ps1" -Parameters @{AParameter = "asd"}
执行失败并出现此错误:
<块引用>术语.D:\TestScript.ps1"不被识别为cmdlet、函数、脚本文件或可运行的程序.检查拼写名称,或者如果包含路径,请验证路径是否为更正并重试.
所以看起来 Scriptblock
指的是本地脚本(在控制器的机器上),而不是目标脚本所在的远程机器.
有没有办法让我使用 hashtable 参数执行远程 PS 脚本,这是所需的灵活性要求?
更新 1
我在 ScriptBlock
定义中的点和 $ScriptPath
变量之间添加了一个空格,但错误是相同的(没有点).
$ScriptBlock = [Scriptblock]::Create(".$ScriptPath $(&{$args} @Parameters)")
<块引用>
术语D:\TestScript.ps1"不被识别为cmdlet、函数、脚本文件或可运行的程序.检查拼写名称,或者如果包含路径,请验证路径是否为更正并重试.
更新 2
我找到了一种无需参数即可调用远程脚本的方法.
参数([字符串] $ComputerName,[字符串] $用户名,[字符串] $密码,[字符串] $ScriptPath,[哈希表] $Parameters)$EncPassword = ConvertTo-SecureString $Password -AsPlainText -Force$cred = 新对象 System.Management.Automation.PSCredential($Username,$EncPassword)Invoke-Command -ComputerName $computerName -Credential $cred -ScriptBlock {Invoke-Expression $args[0]} -ArgumentList $ScriptPath
我得到了没有参数的远程脚本输出.现在剩下要做的就是在远程路径 $ScriptPath
上调用脚本时远程散布哈希表 $Parameters
.你有什么主意吗?我做了一些试验,但没有任何效果.
我终于找到了解决方案
controller.ps1
参数([字符串] $ComputerName,[字符串] $用户名,[字符串] $密码,[字符串] $ScriptPath,[哈希表] $Parameters)$EncPassword = ConvertTo-SecureString $Password -AsPlainText -Force$cred = 新对象 System.Management.Automation.PSCredential($Username,$EncPassword)调用命令 -ComputerName $computerName -Credential $cred -ScriptBlock {$params = $Using:Parameters调用表达式$Using:ScriptPath @params"}
正如您在此处看到的,我们使用 ScriptBlock
中的 $Using
变量来检索外部变量($ScriptPath
和 $Parameters
),然后我们调用远程脚本散布参数哈希表.
I need to write a Powershell script (let's call it "the controller script") that is able to call a generic remote Powershell script passing generic parameters. The controller script accepts as parameters the hostname, the credentials, the remote script path and the remote script's parameters as a hashtable.
The remote script, instead, may be any script which accepts any string parameter.
Using the hashtable parameter for the controller script is useful in that I can pass a dynamic dictionary of parameters (that depends on the controller call) while making PS do the work of "transform" the dictionary to a list of string parameters like -Param1 Value1 -Param2 Value2
.
I got some ideas from this answer and this is what I did (the "controller" script):
Param(
[string] $ComputerName,
[string] $Username,
[string] $Password,
[string] $ScriptPath,
[string] $Parameters
)
$EncPassword = ConvertTo-SecureString $Password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($Username,$EncPassword)
$ScriptBlock = [Scriptblock]::Create(".$ScriptPath $(&{$args} @Parameters)")
Invoke-Command -ComputerName $ComputerName -Credential $cred -Scriptblock $ScriptBlock
Then I execute it via the PS prompt this way:
.\controller.ps1 -ComputerName MACHINE_NAME -Username USERNAME -Password PASSWORD -ScriptPath "D:\TestScript.ps1" -Parameters @{AParameter = "asd"}
The execution fails with this error:
The term '.D:\TestScript.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
So it seems that the Scriptblock
refers to a local script (on the controller's machine), not to the remote machine where the target script resides.
Is there any way to let me execute a remote PS script using the hashtable parameter, which is the desired flexibility requirement?
UPDATE 1
I added a whitespace between the dot and the $ScriptPath
variable in the ScriptBlock
definition but the error is the same (without the dot).
$ScriptBlock = [Scriptblock]::Create(". $ScriptPath $(&{$args} @Parameters)")
The term 'D:\TestScript.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
UPDATE 2
I've found a way to call the remote script without the parameters.
Param(
[string] $ComputerName,
[string] $Username,
[string] $Password,
[string] $ScriptPath,
[hashtable] $Parameters
)
$EncPassword = ConvertTo-SecureString $Password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($Username,$EncPassword )
Invoke-Command -ComputerName $computerName -Credential $cred -ScriptBlock {Invoke-Expression $args[0]} -ArgumentList $ScriptPath
I get the remote script output without parameters. Now the left thing to do is splatting the hashtable $Parameters
remotely when calling the script at the remote path $ScriptPath
. Do you have any idea? I made some trials but nothing worked.
I finally found the solution
controller.ps1
Param(
[string] $ComputerName,
[string] $Username,
[string] $Password,
[string] $ScriptPath,
[hashtable] $Parameters
)
$EncPassword = ConvertTo-SecureString $Password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($Username,$EncPassword )
Invoke-Command -ComputerName $computerName -Credential $cred -ScriptBlock {
$params = $Using:Parameters
Invoke-Expression "$Using:ScriptPath @params"
}
As you can see here we use the $Using
variable in the ScriptBlock
to retrieve the outside variables ($ScriptPath
and $Parameters
) and then we call the remote script splatting the parameters hashtable.
这篇关于使用通用参数执行远程通用 Powershell 脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!