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

使用通用参数执行远程通用Powershell脚本,powershell,Powershell,我需要编写一个Powershell脚本(我们称之为“控制器脚本”),它能够调用传递通用参数的通用远程Powershell脚本。 控制器脚本接受主机名、凭据、远程脚本路径和作为哈希表的远程脚本参数作为参数 相反,远程脚本可以是接受任何字符串参数的任何脚本 为控制器脚本使用哈希表参数非常有用,因为我可以传递参数的动态字典(取决于控制器调用),同时让PS将字典“转换”为字符串参数列表,如-Param1 Value1-Param2 Value2 我从答案中得到了一些想法,这就是我所做的(“控制器”脚本)

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

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

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

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

然后我通过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
变量之间添加了一个空格,但是错误是相同的(没有点)

术语“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
。你知道吗?我做了一些尝试,但没有任何效果。

我建议在Invoke命令中使用FilePath参数,而不是scriptblock。这样PSRemoting就完成了所有的繁重工作

Invoke-Command -ComputerName $ComputerName -Credential $cred -FilePath $ScriptPath -ArgumentList $Parameters,$args
否则,您可以使用会话复制文件并运行文件

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

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

Invoke-Command -Session $Session -ScriptBlock $ScriptBlock
编辑:这可能是您所寻找的更多内容:

第一个问题似乎是您没有正确的脚本路径,或者您的用户帐户没有访问该路径的权限。这就是你看到的错误。我已经在我的系统上测试了几种不同的方法,点源应该可以工作

前面的方法扩展变量太早,无法使用splatting。这是如何让挥霍工作:

Invoke-command -ScriptBlock {$a = $args[0]; & D:\full\path\to\testscript.ps1 @a $args[1]} -ArgumentList $Parameters,$additionalArgs
确保在参数中获取哈希表而不是字符串


[哈希表]$Parameters

我终于找到了解决方案

控制器.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"
}

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

$ScriptPath
->
$脚本路径
。您需要一个空格来点源。@gms0ulman我修复了它,但出现了相同的错误(请参阅更新的问题)@gms0ulman我更新了答案,并取得了一些进展。做得很好-看起来您已经对其进行了排序,建议您接受该答案。我尝试了此解决方案,但出现了以下错误:
Invoke命令:找不到驱动器。名为“D”的驱动器不存在
我不会使用会话在远程计算机上复制文件,因为目标脚本已在目标计算机上。提示:在本地我没有
D
驱动器,而在远程目标上我有它。我认为错误是证明
-FilePath
参数和
ScriptBlock
定义试图在本地读取路径,而不是远程读取路径(这是我所需要的)。我的建议假设您也在本地读取路径,因为这将简化您的工作。是的,这样会更简单,但在我的例子中,我在不同的机器上有不同的脚本,每个可能都有不同的版本,所以我需要使用通用参数调用通用远程脚本
Invoke-command -ScriptBlock {$a = $args[0]; & D:\full\path\to\testscript.ps1 @a $args[1]} -ArgumentList $Parameters,$additionalArgs
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"
}