使用通用参数执行远程通用Powershell脚本

时间:2018-08-20 15:29:18

标签: powershell

我需要编写一个Powershell脚本(我们称其为“控制器脚本”),该脚本能够调用传递通用参数的通用远程Powershell脚本。 控制器脚本接受主机名,凭据,远程脚本路径和远程脚本的参数作为哈希表作为参数。

相反,远程脚本可以是接受任何字符串参数的任何脚本。

使用哈希表参数作为控制器脚本非常有用,因为我可以传递参数的动态字典(取决于控制器调用),同时让PS进行将字典“转换”为字符串参数列表的工作,例如-Param1 Value1 -Param2 Value2

我从this的答案中得到了一些想法,这就是我所做的(“控制器”脚本):

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

然后我通过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

我在点和$ScriptPath定义中的ScriptBlock变量之间添加了一个空格,但是错误是相同的(没有点)。

$ScriptBlock = [Scriptblock]::Create(". $ScriptPath $(&{$args} @Parameters)")
  

术语'D:\ TestScript.ps1'不被识别为   cmdlet,函数,脚本文件或可操作程序。检查拼写   的名称,或者如果包含路径,请验证路径是否为   更正并重试。

更新2

我找到了一种无需参数即可调用远程脚本的方法。

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

我获得了不带参数的远程脚本输出。现在剩下要做的就是在远程路径$Parameters上调用脚本时远程散列表表$ScriptPath。你有什么主意吗?我做了一些试验,但没有任何效果。

2 个答案:

答案 0 :(得分:2)

我终于找到了解决方法

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"
}

正如您在这里看到的那样,我们使用$Using中的ScriptBlock变量来检索外部变量($ScriptPath$Parameters),然后我们将远程脚本称为Splatting参数哈希表。

答案 1 :(得分:0)

我建议在Invoke-Command中使用FilePath参数,而不要在脚本块中使用。这样,PSRemoting可以完成所有繁重的工作。

Invoke-Command -ComputerName $ComputerName -Credential $cred -FilePath $ScriptPath -ArgumentList $Parameters,$args

否则,您可以使用Sessions复制文件并运行文件。

$Session = New-PSSession -ComputerName $Computer -Credential $credential

Copy-Item -Path $ScriptPath -Destination $Dest -ToSession $Session

Invoke-Command -Session $Session -ScriptBlock $ScriptBlock

编辑:这可能是您正在寻找的更多内容

第一个问题似乎是您没有正确的脚本路径,或者您的用户帐户无权访问该路径。那就是您所看到的错误。我已经在我的系统上测试了几种不同的方式,并且网点搜索应该可以工作。

以前的方法太早扩展了变量,以至于无法使用展开。这是如何进行喷溅工作的方法:

Invoke-command -ScriptBlock {$a = $args[0]; & D:\full\path\to\testscript.ps1 @a $args[1]} -ArgumentList $Parameters,$additionalArgs

请确保在参数中获取哈希表而不是字符串

[HashTable] $ Parameters