Wie kann ich benannte Parameter mit Invoke-Command übergeben?
-
26-09-2019 - |
Frage
ich ein Skript, dass ich remote über Invoke-Command ausführen
Invoke-Command -ComputerName (Get-Content C:\Scripts\Servers.txt) `
-FilePath C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1
Solange ich Standardparameter verwenden, es funktioniert gut. Allerdings hat das Skript 2 namens [Schalter] Parameter (-Debug und -Clear)
Wie kann ich passieren die geschalteten Parameter über die Invoke-Command? Ich habe die -ArgumentList versucht, aber ich bin immer Fehler, damit ich die Syntax falsch oder etwas haben muss. Jede Hilfe wird sehr geschätzt.
Lösung
-ArgumentList
basiert auf der Verwendung mit script Befehle, 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 einem -File
nennen es geht immer noch um die Parameter wie ein stummer splatted Array. Ich habe eine Feature-Anfrage, dass mit dem Befehl hinzugefügt haben (bitte, dass abstimmen).
Also, haben Sie zwei Möglichkeiten:
Wenn Sie ein Skript, das so aussah, in einem Ort im Netzwerk zugänglich von der entfernten Maschine (beachten Sie, dass -Debug
wird angedeutet, denn wenn ich das Parameter
Attribut verwenden, wird das Skript CmdletBinding implizit bekommt und somit alle gängigen Parameter ):
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 über die Bedeutung der $Clear
aufgehängt ... wenn Sie aufrufen wollten, dass Sie eine der folgenden Invoke-Command
Syntaxen verwenden:
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 einen, ich duplizieren alle Parameter Ich kümmere mich um in der script , damit ich Werte passieren kann. Wenn ich kann hart Code sie (das ist, was ich tat, tatsächlich), gibt es keine Notwendigkeit, das zu tun, und die Verwendung PSBoundParameters
, kann ich nur die, die gebe ich zu müssen. Im zweiten Beispiel unten werde ich den $ Klar ein, passiert, nur um zu zeigen, wie Switch-Parameter zu übergeben:
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 das Skript auf dem lokalen Computer, und Sie wollen nicht, um die Parameter ändern Positions zu sein, oder Sie mögen Parameter angeben, die gemeinsamen Parameter sind (so dass Sie sie nicht kontrollieren können), werden Sie wollen bekommen der Inhalt dieses Skript und betten es in Ihrem script :
$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 in einer Variablen für die Skriptnamen übergeben müssen, was würden Sie tun, hängt davon ab, ob die Variable lokal definiert ist, oder aus der Ferne. Im Allgemeinen, wenn Sie eine Variable $Script
oder eine Umgebungsvariable $Env:Script
mit dem Namen eines Skripts haben, können Sie es mit dem Call Operator (&) ausführen: &$Script
oder &$Env:Script
Wenn es eine Umgebungsvariable ist, die bereits auf dem Remote-Computer definiert sind, das ist alles dort ist zu ihm. Wenn es ein Lokal ist Variable, dann werden Sie es an den Remote-Skriptblock geben müssen:
Invoke-Command -cn $Env:ComputerName {
param([String]$Script, [bool]$Clear)
&$Script "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $ScriptPath, $(Test-Path $Profile)
Andere Tipps
Meine Lösung dieses Problems war das Skript Block dynamisch mit [scriptblock]:Create
zu schreiben:
# 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 sehr waren frustrierend, verschiedene Methoden versucht, zum Beispiel
-arguments
, $using:p1
usw. und dies gerade arbeitete als ohne Probleme gewünscht wird.
Da ich den Inhalt und variable Erweiterung des Strings steuern, welche die [scriptblock]
erstellt (oder Script-Datei) auf diese Weise gibt es kein wirkliches Problem mit der „Invoke-Command“ Beschwörung.
(Es sollte nicht so schwer sein. :))
Ich vermute, es ist ein neues Feature, da dieser Beitrag erstellt wurde - übergeben Sie Parameter an dem Skript Block mit $ Verwendung: var. Dann ist es ein einfacher mater passieren Parameter zur Verfügung gestellt das Skript ist bereits an der Maschine oder in einem bekannten Netzwerk-Position in Bezug auf die Maschine
das Haupt Am Beispiel wäre es:
icm -cn $Env:ComputerName {
C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear
}
Ich brauchte etwas, um den Anruf Skripte mit benannten Parametern. Wir haben eine Politik der nicht Ordnungs Positionierung von Parametern und erfordern die Parameternamen.
Mein Ansatz ist ähnlich wie die, die oben aber bekommt den Inhalt der Skriptdatei, die Sie anrufen möchten, und sendet einen Parameterblock die Parameter und Werte enthalten.
Einer der Vorteile ist, dass Sie gegebenenfalls, welche Parameter zu senden, um die Skriptdatei so dass für nicht-obligatorischen Parameter mit Standardeinstellungen wählen können.
Es Angenommen ist ein Skript „MyScript.ps1“ im temporären Pfad genannt, die den folgenden Parameterblock hat:
[CmdletBinding(PositionalBinding = $False)]
param
(
[Parameter(Mandatory = $True)] [String] $MyNamedParameter1,
[Parameter(Mandatory = $True)] [String] $MyNamedParameter2,
[Parameter(Mandatory = $False)] [String] $MyNamedParameter3 = "some default value"
)
Dies ist, wie ich dieses Skript von einem anderen Skript aufrufen würde:
$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 man gelegentlich tun müssen, ist in Anführungszeichen setzen den Parameterwert Zuordnungsblock. Dies ist immer dann der Fall, wenn es Räume im Wert.
z. Dieser param Block wird verwendet, ein Skript aufrufen, dass Kopien verschiedene Module in die Standardposition von Powershell C:\Program Files\WindowsPowerShell\Modules
verwendet, die ein Leerzeichen enthält.
$params = @{
SourcePath = "$WorkingDirectory\Modules"
DestinationPath = "'$(Join-Path -Path $([System.Environment]::GetFolderPath('ProgramFiles')) -ChildPath 'WindowsPowershell\Modules')'"
}
Hope, das hilft!