-ArgumentList
basiert auf der Verwendung mit Scriptblock- Befehlen wie:
Invoke-Command -Cn (gc Servers.txt) {param($Debug=$False, $Clear=$False) C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 } -ArgumentList $False,$True
Wenn Sie es mit a aufrufen, werden -File
die Parameter immer noch wie ein dummes, bespritztes Array übergeben. Ich habe eine Feature-Anfrage eingereicht , um diese zum Befehl hinzuzufügen (bitte stimmen Sie ab).
Sie haben also zwei Möglichkeiten:
Wenn Sie ein Skript haben, das so aussieht , an einem Netzwerkspeicherort, auf den vom Remotecomputer aus zugegriffen werden kann (dies -Debug
ist impliziert, da Parameter
das Skript bei Verwendung des Attributs implizit CmdletBinding und damit alle allgemeinen Parameter erhält):
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."
Ohne sich auf die Bedeutung von $Clear
... einzulassen, wenn Sie aufrufen möchten, dass Sie eine der folgenden Invoke-Command
Syntaxen verwenden können:
icm -cn (gc Servers.txt) {
param($one,$two,$Debug=$False,$Clear=$False)
C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 @PSBoundParameters
} -ArgumentList "uno", "dos", $false, $true
In diesem Fall dupliziere ich ALLE Parameter, die mir im Skriptblock wichtig sind, damit ich Werte übergeben kann. Wenn ich sie hart codieren kann (was ich tatsächlich getan habe), muss ich das nicht tun und verwenden PSBoundParameters
, ich kann nur die übergeben, die ich brauche. Im zweiten Beispiel unten werde ich das $ Clear übergeben, um zu demonstrieren, wie Switch-Parameter übergeben werden:
icm -cn $Env:ComputerName {
param([bool]$Clear)
C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $(Test-Path $Profile)
Die andere Option
Wenn sich das Skript auf Ihrem lokalen Computer befindet und Sie die Parameter nicht so ändern möchten, dass sie positionell sind, oder wenn Sie Parameter angeben möchten, die allgemeine Parameter sind (damit Sie sie nicht steuern können), möchten Sie den Inhalt von erhalten das Skript und binden Sie es in Ihren Skriptblock ein :
$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
PostScript:
Wenn Sie wirklich eine Variable für den Skriptnamen übergeben müssen, hängt es davon ab, ob die Variable lokal oder remote definiert ist. Wenn Sie eine Variable $Script
oder eine Umgebungsvariable $Env:Script
mit dem Namen eines Skripts haben, können Sie diese im Allgemeinen mit dem Aufrufoperator (&) ausführen: &$Script
oder&$Env:Script
Wenn es sich um eine Umgebungsvariable handelt, die bereits auf dem Remotecomputer definiert ist, ist dies alles, was dazu gehört. Wenn es sich um eine lokale Variable handelt, müssen Sie sie an den Remote-Skriptblock übergeben:
Invoke-Command -cn $Env:ComputerName {
param([String]$Script, [bool]$Clear)
& $ScriptPath "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $ScriptPath, (Test-Path $Profile)
Meine Lösung bestand darin, den Skriptblock dynamisch zu schreiben mit
[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
Passing Argumente waren sehr frustrierend, verschiedene Methoden versucht, zum Beispiel
-arguments
,$using:p1
etc. und dies gerade arbeitet als ohne Probleme erwünscht.Da ich den Inhalt und die Variablenerweiterung der Zeichenfolge steuere, die die
[scriptblock]
(oder Skriptdatei) auf diese Weise erstellt, gibt es kein wirkliches Problem mit der Beschwörung "invoke-command".(Es sollte nicht so schwer sein. :))
quelle
Ich vermute, es ist eine neue Funktion, seit dieser Beitrag erstellt wurde - übergeben Sie Parameter mit $ Using: var an den Skriptblock. Dann ist es einfach, Parameter zu übergeben, vorausgesetzt, das Skript befindet sich bereits auf dem Computer oder an einem bekannten Netzwerkstandort relativ zum Computer
Am Hauptbeispiel wäre es:
icm -cn $Env:ComputerName { C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear }
quelle
Ich brauchte etwas, um Skripte mit benannten Parametern aufzurufen. Wir haben die Richtlinie, keine ordinale Positionierung von Parametern zu verwenden und den Parameternamen zu verlangen.
Mein Ansatz ähnelt dem oben beschriebenen, ruft jedoch den Inhalt der Skriptdatei ab, die Sie aufrufen möchten, und sendet einen Parameterblock mit den Parametern und Werten.
Einer der Vorteile davon ist, dass Sie optional auswählen können, welche Parameter an die Skriptdatei gesendet werden sollen, wobei nicht obligatorische Parameter mit Standardwerten berücksichtigt werden.
Angenommen, der temporäre Pfad enthält ein Skript namens "MyScript.ps1" mit dem folgenden Parameterblock:
[CmdletBinding(PositionalBinding = $False)] param ( [Parameter(Mandatory = $True)] [String] $MyNamedParameter1, [Parameter(Mandatory = $True)] [String] $MyNamedParameter2, [Parameter(Mandatory = $False)] [String] $MyNamedParameter3 = "some default value" )
So würde ich dieses Skript von einem anderen Skript aus aufrufen:
$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
Ich habe dies in vielen Szenarien verwendet und es funktioniert wirklich gut. Eine Sache, die Sie gelegentlich tun müssen, ist, den Parameterwertzuweisungsblock in Anführungszeichen zu setzen. Dies ist immer dann der Fall, wenn der Wert Leerzeichen enthält.
Beispiel: Dieser Parameterblock wird verwendet, um ein Skript aufzurufen, das verschiedene Module an den von PowerShell verwendeten Standardspeicherort kopiert,
C:\Program Files\WindowsPowerShell\Modules
der ein Leerzeichen enthält.$params = @{ SourcePath = "$WorkingDirectory\Modules" DestinationPath = "'$(Join-Path -Path $([System.Environment]::GetFolderPath('ProgramFiles')) -ChildPath 'WindowsPowershell\Modules')'" }
Hoffe das hilft!
quelle