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.

War es hilfreich?

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!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top