简体   繁体   中英

Local or remote execution of powershell script with generic parameters

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM