Локальное или удаленное выполнение скрипта powershell с общими параметрами

В команде разработчиков я хотел бы, чтобы одни и те же тестовые сценарии выполнялись локально разработчиком или удаленно на нашей тестовой платформе.

Вот что я хотел бы использовать в качестве предпосылок для каждого сценария

# 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:\

Однако, когда я выполняю это, я получил следующую ошибку:

Invoke-Command : A positional parameter cannot be found that accepts argument '$null'.

Кажется, что @Using:RemoteParams — неправильный способ сделать это, но я здесь совсем запутался. заранее спасибо


person FoxAlfaBravo    schedule 08.10.2015    source источник


Ответы (1)


Вот мой взгляд на проблему возможности выполнять как локальное, так и удаленное выполнение с использованием именованных параметров:

$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)")

Начните с хеш-таблицы параметров, используя локальные переменные, а затем используйте это:

[Scriptblock]::Create("$command $(&{$args} @Params)")

для создания блока сценария команды со встроенными параметрами и уже развернутыми значениями. Теперь этот блок скрипта готов к локальному запуску (либо путем вызова с помощью &, либо через точечный источник), либо удаленно с использованием Invoke-Command.

$ScriptBlock
new-something -IP: 192.168.0.1 -User: Test User -Password: P@ssW0rd!

Не требуется область видимости с $Using: или -argumentlist.

Изменить: вот пример использования скрипта, а не одной команды:

$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)")

Чтобы запустить его локально:

 Invoke-Command $ScriptBlock

или просто:

 .$ScriptBlock

Чтобы запустить его удаленно:

 Invoke-Command -Scriptblock $ScriptBlock -ComputerName Server1
person mjolinor    schedule 08.10.2015
comment
Идея этого сценария состоит в том, чтобы использовать его в начале каждого тестового сценария, чтобы пользователям не приходилось писать блок сценария, повторяющий параметры сценария. Я хотел бы, чтобы он был как можно более общим, с реальным списком параметров, объявленным только один раз в блоке именованных параметров. Например, следующим шагом будет обнаружение параметров типа файла и подготовка их в блоке скрипта. - person FoxAlfaBravo; 08.10.2015
comment
Если я правильно понимаю комментарий, вы обеспокоены тем, что пользовательский скрипт встроен в пример как $command. Вы можете заполнить это так же легко, выполнив Get-Content в файле сценария и используя путь к сценарию в качестве параметра. Вы не можете использовать $using в знаке так, как вы пытались. Это должно быть указано для каждой ссылки на переменную внутри сценария, но если вы это сделаете, сценарий не будет работать локально. Это дает вам блок скрипта, который будет работать локально или удаленно, без необходимости манипулировать областями действия переменных в скрипте. - person mjolinor; 08.10.2015