使用通用参数执行远程通用 Powershell 脚本 [英] Execute a remote generic Powershell script with generic parameters

查看:40
本文介绍了使用通用参数执行远程通用 Powershell 脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆