我需要编写一个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
。你有什么主意吗?我做了一些试验,但没有任何效果。
答案 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