80

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 を試しましたが、エラーが発生するため、構文が間違っているか何かが必要です。どんな助けでも大歓迎です。

4

5 に答える 5

100

-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)
于 2010-11-19T14:39:38.907 に答える
7

これに対する私の解決策は、次のようにスクリプト ブロックを動的に記述することでした[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" の呪文に実際の問題はありません。

(それほど難しいことではないはずです。:))

于 2016-05-23T20:01:54.457 に答える