Domanda

Ho uno script che può essere eseguito in remoto tramite Invoke-Command

Invoke-Command -ComputerName (Get-Content C:\Scripts\Servers.txt) `
               -FilePath C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1

Fino a quando io uso i parametri di default, funziona benissimo. Tuttavia, lo script ha 2 denominata [Switch] parametri (-debug e -clear)

Come faccio a passare i parametri commutati tramite Invoke-Command? Ho provato il -ArgumentList ma sto ottenendo gli errori quindi devo avere il torto di sintassi o qualcosa del genere. Ogni aiuto è molto apprezzato.

È stato utile?

Soluzione

-ArgumentList si basa su l'uso con scriptblock comandi, come:

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

Quando si chiama con un -File passa ancora i parametri come una matrice Splatted muto. Ho presentato una richiesta di funzionalità di aver aggiunto che al comando (si prega di votare che fino).

Quindi, avete due opzioni:

Se si dispone di uno script che si presentava così, in un percorso di rete accessibile dalla macchina remota (si noti che -Debug è implicito perché quando uso l'attributo Parameter, lo script ottiene CmdletBinding implicitamente, e quindi, tutti i parametri comuni ):

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."

senza rimanere sospeso sul significato di $Clear ... se si voleva richiamare che si potrebbe utilizzare uno dei seguenti sintassi 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

In che uno, sto duplicare tutti i parametri a cui tengo in scriptblock in modo da poter passare i valori. Se posso hard-code loro (che è quello che ho effettivamente fatto), non c'è bisogno di farlo e l'uso PSBoundParameters, posso solo passare quelli che ho bisogno di. Nel secondo esempio di seguito ho intenzione di passare il $ Cancella uno, solo per dimostrare come passare parametri di commutazione:

icm -cn $Env:ComputerName { 
    param([bool]$Clear)
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $(Test-Path $Profile)

L'altra opzione

Se lo script è sul computer locale, e non si vuole modificare i parametri per essere posizionale, o se si desidera specificare i parametri che sono parametri comuni (in modo da non li può controllare) che si vuole ottenere il contenuto di quella sceneggiatura e incorporarlo nel vostro scriptblock :

$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:

Se avete veramente bisogno di passare una variabile per il nome dello script, cosa avresti fatto dipenderà dal fatto che la variabile è definita in locale o in remoto. In generale, se si dispone di un $Script variabile o una variabile d'ambiente $Env:Script con il nome di uno script, è possibile eseguirlo con l'operatore di chiamata (&): &$Script o &$Env:Script

Se si tratta di una variabile d'ambiente che è già definito sul computer remoto, è tutto quello che c'è da fare. Se si tratta di un variabile locale, allora si dovrà passare al blocco di script remoto:

Invoke-Command -cn $Env:ComputerName { 
    param([String]$Script, [bool]$Clear)
    &$Script "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $ScriptPath, $(Test-Path $Profile)

Altri suggerimenti

La mia soluzione a questo era quello di scrivere il blocco di script in modo dinamico con [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

passaggio di argomenti stato molto frustrante, cercando di vari metodi, per esempio,
-arguments, $using:p1, ecc e questo appena finito di lavorare, se lo desideri senza problemi.

Da quando ho controllare il contenuto e l'espansione delle variabili della stringa che crea il [scriptblock] (o file di script) in questo modo, non v'è alcun problema reale con l'incantesimo "invoke-comando".

(Non dovrebbe essere così difficile. :))

ho il sospetto la sua una nuova funzionalità dal momento che questo post è stato creato - passare parametri al blocco di script che utilizzano $ Utilizzando: var. Allora è un semplice mater passare parametri forniti lo script è già sulla macchina o in una rete nota posizione rispetto alla macchina

Prendendo l'esempio principale sarebbe:

icm -cn $Env:ComputerName { 
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear
}

Avevo bisogno di qualcosa per gli script di chiamata con parametri denominati. Abbiamo una politica di non usare il posizionamento ordinale di parametri e che richiedono il nome del parametro.

Il mio approccio è simile a quelle di cui sopra, ma ottiene il contenuto del file di script che si desidera chiamare e invia un blocco di parametri che contiene i parametri ei valori.

Uno dei vantaggi di questo è che si può opzionalmente scegliere quali parametri da inviare al file di script che consente per i parametri non obbligatori con valori di default.

presumere che vi sia uno script chiamato "MyScript.ps1" nel percorso temporaneo che ha il seguente blocco di parametri:

[CmdletBinding(PositionalBinding = $False)]
param
(
    [Parameter(Mandatory = $True)] [String] $MyNamedParameter1,
    [Parameter(Mandatory = $True)] [String] $MyNamedParameter2,
    [Parameter(Mandatory = $False)] [String] $MyNamedParameter3 = "some default value"
)

Questo è il modo che chiamerei questo script da un altro script:

$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

Ho usato questo in un sacco di scenari e funziona davvero bene. Una cosa che di tanto in tanto bisogno di fare è mettere le virgolette intorno al blocco assegnazione valore del parametro. Questo è sempre il caso quando ci sono spazi nel valore.

es. Questo blocco param viene utilizzato per chiamare uno script che copia i vari moduli nella posizione standard utilizzato da PowerShell C:\Program Files\WindowsPowerShell\Modules che contiene un carattere di spazio.

$params = @{
        SourcePath      = "$WorkingDirectory\Modules"
        DestinationPath = "'$(Join-Path -Path $([System.Environment]::GetFolderPath('ProgramFiles')) -ChildPath 'WindowsPowershell\Modules')'"
    }

Spero che questo aiuti!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top