1. ホーム
  2. powershell

Invoke-Commandで名前付きパラメータを渡すには?

2023-09-12 17:12:29

質問

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 スクリプトブロック コマンドのようなものです。

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

で呼び出すと -File で呼び出すと、まだ馬鹿なスプラッタ配列のようにパラメータが渡されます。 私が提出した 機能要求 を提出しました (投票お願いします)。

というわけで、2つの選択肢があります。

リモートマシンからアクセス可能なネットワークの場所に、このようなスクリプトがあった場合 (ただし、このスクリプトは -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 を使う必要はなく、必要なものだけを渡せばいいのです。以下の2番目の例では、スイッチ・パラメータを渡す方法を示すために、$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)
    & $ScriptPath "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $ScriptPath, (Test-Path $Profile)