问题
In a development team, I would like to have the same test scripts to be executed locally by a developper or remotely by our test platform.
Here is what I would like to use as premises for each script
# Test local/remote execution by reading C:\ directory
param(
[switch] $verbose,
[switch] $remote,
[string] $ip,
[string] $user,
[string] $password
#Add here script specific parameters
)
Write-Host "Command invokation incoming parameter count : " $psboundparameters.count
if ($remote) {
$Params = @{}
$RemoteParams = @{}
$pass = ConvertTo-SecureString -String $password -AsPlainText -Force
$Params.Credential = new-object -TypeName System.management.automation.PSCredential -argumentlist $user, $pass
$Params.ComputerName = $ip
$Params.FilePath = $MyInvocation.MyCommand.Name
$null = $psboundparameters.Remove('remote')
$null = $psboundparameters.Remove('ip')
$null = $psboundparameters.Remove('user')
$null = $psboundparameters.Remove('password')
foreach($psbp in $PSBoundParameters.GetEnumerator())
{
$RemoteParams.$($psbp.Key)=$psbp.Value
}
Write-Host $RemoteParams
Invoke-Command @Params @Using:RemoteParams
Exit
}
Write-Host "Command execution incoming parameters count : " $psboundparameters.count
# Here goes the test
Get-ChildItem C:\
However, when I execute this, I got the following error:
Invoke-Command : A positional parameter cannot be found that accepts argument '$null'.
It seems that @Using:RemoteParams is not the correct way of doing this, but I'm quite lost here. Thanks in advance
回答1:
Here's my take on the problem of being able to do both local and remote execution using named parameters:
$IP = '192.168.0.1'
$User = 'Test User'
$Password = 'P@ssW0rd!'
$params = @{
IP = $IP
User = $User
Password = $Password
}
$command = 'new-something'
$ScriptBlock = [Scriptblock]::Create("$command $(&{$args} @Params)")
Start with a hash table of parameters, using local varibles, then use this:
[Scriptblock]::Create("$command $(&{$args} @Params)")
to create a script block of the command, with the parameters inline and the values already expanded. Now that script block is ready to be run locally (either by invocation with &
or dot-sourcing), or remotely using Invoke-Command
.
$ScriptBlock
new-something -IP: 192.168.0.1 -User: Test User -Password: P@ssW0rd!
No scoping with $Using:
or -argumentlist
required.
Edit: Here's an example using a script rather than a single command:
$path = 'c:\windows'
$filter = '*.xml'
$Params =
@{
Path = $path
Filter = $filter
}
$command = @'
{
Param (
[String]$path,
[String]$Filter
)
Get-childitem -Path $path -Filter $filter
}
'@
$ScriptBlock = [Scriptblock]::Create(".$command $(&{$args} @Params)")
To run it locally:
Invoke-Command $ScriptBlock
or just:
.$ScriptBlock
To run it remotely:
Invoke-Command -Scriptblock $ScriptBlock -ComputerName Server1
来源:https://stackoverflow.com/questions/33021988/local-or-remote-execution-of-powershell-script-with-generic-parameters