program tip

Invoke-Command로 명명 된 매개 변수를 어떻게 전달합니까?

radiobox 2020. 10. 30. 07:54
반응형

Invoke-Command로 명명 된 매개 변수를 어떻게 전달합니까?


Invoke-Command를 통해 원격으로 실행할 수있는 스크립트가 있습니다.

Invoke-Command -ComputerName (Get-Content C:\Scripts\Servers.txt) `
               -FilePath C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1

기본 매개 변수를 사용하는 한 정상적으로 작동합니다. 그러나 스크립트에는 2 개의 명명 된 [switch] 매개 변수 (-Debug 및 -Clear)가 있습니다.

Invoke-Command를 통해 전환 된 매개 변수를 어떻게 전달할 수 있습니까? -ArgumentList 시도했지만 오류가 발생하여 구문이 잘못되었거나 뭔가 있어야합니다. 어떤 도움이라도 대단히 감사합니다.


-ArgumentList다음 과 같은 scriptblock 명령 사용을 기반으로합니다 .

Invoke-Command -Cn (gc Servers.txt) {param($Debug=$False, $Clear=$False) C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 } -ArgumentList $False,$True

를 사용하여 호출하면 -File멍청한 splatted 배열과 같은 매개 변수를 여전히 전달합니다. 명령에 추가 할 기능 요청제출했습니다 (투표 해주십시오).

따라서 두 가지 옵션이 있습니다.

원격 컴퓨터에서 액세스 할 수있는 네트워크 위치에 다음과 같은 스크립트가있는 -Debug경우 (내가 Parameter속성을 사용할 때 스크립트가 암시 적으로 CmdletBinding을 가져 오므로 모든 공통 매개 변수를 가져 오기 때문에 암시 적입니다) :

param(
   [Parameter(Position=0)]
   $one
,
   [Parameter(Position=1)]
   $two
,
   [Parameter()]
   [Switch]$Clear
)

"The test is for '$one' and '$two' ... and we $(if($DebugPreference -ne 'SilentlyContinue'){"will"}else{"won't"}) run in debug mode, and we $(if($Clear){"will"}else{"won't"}) clear the logs after."

$Clear... 의 의미에 얽매이지 않고 호출하려면 다음 Invoke-Command구문 중 하나를 사용할 수 있습니다 .

icm -cn (gc Servers.txt) { 
    param($one,$two,$Debug=$False,$Clear=$False)
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 @PSBoundParameters
} -ArgumentList "uno", "dos", $false, $true

그 중 하나에서는 스크립트 블록 에서 관심있는 모든 매개 변수를 복제하여 값을 전달할 수 있습니다. 하드 코딩 할 수 있다면 (실제로 수행 한 작업입니다) 그렇게하고 사용할 필요가 없습니다. 필요한 PSBoundParameters것만 전달할 수 있습니다. 아래 두 번째 예제에서는 스위치 매개 변수를 전달하는 방법을 보여주기 위해 $ Clear 하나를 전달하겠습니다.

icm -cn $Env:ComputerName { 
    param([bool]$Clear)
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $(Test-Path $Profile)

다른 옵션

스크립트가 로컬 컴퓨터에 있고 매개 변수를 위치로 변경하지 않으려는 경우 또는 공통 매개 변수 인 매개 변수를 지정하려는 경우 (따라서 제어 할 수 없음) 내용을 가져 오려고합니다. 해당 스크립트를 스크립트 블록에 포함합니다 .

$script = [scriptblock]::create( @"
param(`$one,`$two,`$Debug=`$False,`$Clear=`$False)
&{ $(Get-Content C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -delimiter ([char]0)) } @PSBoundParameters
"@ )

Invoke-Command -Script $script -Args "uno", "dos", $false, $true

추신:

실제로 스크립트 이름에 대한 변수를 전달해야하는 경우 수행 할 작업은 변수가 로컬로 정의되었는지 원격으로 정의되었는지에 따라 달라집니다. 당신이 변수가있는 경우 일반적으로, $Script또는 환경 변수 $Env:Script스크립트의 이름을, 당신은 호출 연산자 (&)와 함께 실행할 수 있습니다 &$Script또는&$Env:Script

원격 컴퓨터에 이미 정의 된 환경 변수라면 그게 전부입니다. 그것은 만약 지역 변수, 당신은 원격 스크립트 블록에 전달해야합니다 :

Invoke-Command -cn $Env:ComputerName { 
    param([String]$Script, [bool]$Clear)
    &$Script "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $ScriptPath, $(Test-Path $Profile)

이에 대한 내 해결책은 다음과 같이 스크립트 블록을 동적으로 작성하는 것입니다 [scriptblock]:Create.

# Or build a complex local script with MARKERS here, and do substitutions
# I was sending install scripts to the remote along with MSI packages
# ...for things like Backup and AV protection etc.

$p1 = "good stuff"; $p2 = "better stuff"; $p3 = "best stuff"; $etc = "!"
$script = [scriptblock]::Create("MyScriptOnRemoteServer.ps1 $p1 $p2 $etc")
#strings get interpolated/expanded while a direct scriptblock does not

# the $parms are now expanded in the script block itself
# ...so just call it:
$result = invoke-command $computer -script $script

전달 인자는 매우 예를 들어, 다양한 방법을 시도하고, 좌절 된
-arguments, $using:p1, 등을 아무런 문제없이 원하는대로 이것은 단지했다.

[scriptblock]이 방법으로 (또는 스크립트 파일) 을 생성하는 문자열의 내용과 변수 확장을 제어하기 때문에 "invoke-command"주문에 실제 문제가 없습니다.

(그렇게 어렵지 않아야합니다. :))


I suspect its a new feature since this post was created - pass parameters to the script block using $Using:var. Then its a simple mater to pass parameters provided the script is already on the machine or in a known network location relative to the machine

주요 예를 들면 다음과 같습니다.

icm -cn $Env:ComputerName { 
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear
}

명명 된 매개 변수를 사용하여 스크립트를 호출하려면 무언가가 필요했습니다. 매개 변수의 서수 위치 지정을 사용하지 않고 매개 변수 이름을 요구하는 정책이 있습니다.

My approach is similar to the ones above but gets the content of the script file that you want to call and sends a parameter block containing the parameters and values.

One of the advantages of this is that you can optionally choose which parameters to send to the script file allowing for non-mandatory parameters with defaults.

Assuming there is a script called "MyScript.ps1" in the temporary path that has the following parameter block:

[CmdletBinding(PositionalBinding = $False)]
param
(
    [Parameter(Mandatory = $True)] [String] $MyNamedParameter1,
    [Parameter(Mandatory = $True)] [String] $MyNamedParameter2,
    [Parameter(Mandatory = $False)] [String] $MyNamedParameter3 = "some default value"
)

This is how I would call this script from another script:

$params = @{
    MyNamedParameter1 = $SomeValue
    MyNamedParameter2 = $SomeOtherValue
}

If ($SomeCondition)
{
    $params['MyNamedParameter3'] = $YetAnotherValue
}

$pathToScript = Join-Path -Path $env:Temp -ChildPath MyScript.ps1

$sb = [scriptblock]::create(".{$(Get-Content -Path $pathToScript -Raw)} $(&{
        $args
} @params)")
Invoke-Command -ScriptBlock $sb

I have used this in lots of scenarios and it works really well. One thing that you occasionally need to do is put quotes around the parameter value assignment block. This is always the case when there are spaces in the value.

e.g. This param block is used to call a script that copies various modules into the standard location used by PowerShell C:\Program Files\WindowsPowerShell\Modules which contains a space character.

$params = @{
        SourcePath      = "$WorkingDirectory\Modules"
        DestinationPath = "'$(Join-Path -Path $([System.Environment]::GetFolderPath('ProgramFiles')) -ChildPath 'WindowsPowershell\Modules')'"
    }

Hope this helps!

참고URL : https://stackoverflow.com/questions/4225748/how-do-i-pass-named-parameters-with-invoke-command

반응형