Question

J'ai un script que je peux exécuter à distance via Invoke-Command

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

Tant que j'utiliser les paramètres par défaut, il fonctionne très bien. Cependant, le script a 2 nommé [commutateur] paramètres (debug et -CLEAR)

Comment puis-je passer les paramètres via le commutées Invoke-Command? Je l'ai essayé le -ArgumentList mais je reçois des erreurs, donc je dois avoir la mauvaise ou quelque chose syntaxe. Toute aide est grandement appréciée.

Était-ce utile?

La solution

-ArgumentList est basé sur l'utilisation avec scriptblock commandes, comme:

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

Lorsque vous appelez avec un -File passe toujours les paramètres comme un tableau splatted muet. J'ai envoyé un demande de fonctionnalité d'avoir ce ajouté à la commande (s'il vous plaît voter que vers le haut).

Alors, vous avez deux options:

Si vous avez un script qui ressemblait à ceci, dans un emplacement réseau accessible à partir de la machine distante (notez que -Debug est implicite parce que quand j'utilise l'attribut Parameter, le script obtient CmdletBinding implicitement, et donc, tous les paramètres communs ):

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

Sans enferrons sur le sens de $Clear ... si vous vouliez invoquer que vous pouvez utiliser soit des syntaxes Invoke-Command suivant:

icm -cn (gc Servers.txt) { 
    param($one,$two,$Debug=$False,$Clear=$False)
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 @PSBoundParameters
} -ArgumentList "uno", "dos", $false, $true

Dans celui-là, je dupliquer tous les paramètres auxquels je tiens dans le scriptblock pour que je puisse transmettre des valeurs. Si je peux coder en dur les (qui est ce que j'ai effectivement fait), il n'y a pas besoin de le faire et l'utilisation PSBoundParameters, je peux passer ceux que je dois. Dans le deuxième exemple ci-dessous, je vais passer le $ Effacer un, juste pour montrer comment passer des paramètres de commutation:

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

L'autre option

Si le script est sur votre machine locale, et vous ne voulez pas changer les paramètres à la position, ou si vous souhaitez spécifier des paramètres qui sont des paramètres communs (vous ne pouvez pas les contrôler) vous voulez obtenir le contenu de ce script et l'intégrer dans votre 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:

Si vous avez vraiment besoin de passer dans une variable pour le nom du script, ce que vous feriez dépendra de si la variable est définie localement ou à distance. En général, si vous avez un $Script variable ou un $Env:Script variable d'environnement avec le nom d'un script, vous pouvez l'exécuter avec l'opérateur d'appel (&): &$Script ou &$Env:Script

S'il est une variable d'environnement qui est déjà défini sur l'ordinateur distant, qui est tout ce qu'il ya à faire. Si c'est un locale variable, vous devrez passer au bloc de script distant:

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

Autres conseils

Ma solution à c'était d'écrire le bloc de script dynamique avec [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 arguments a été très frustrant, en essayant différentes méthodes, par exemple,
-arguments, $using:p1, etc., et cela juste travaillé comme désiré sans problème.

Depuis je contrôle le contenu et l'expansion variable de la chaîne qui crée le [scriptblock] (ou fichier script) de cette façon, il n'y a pas de problème réel avec le incantatoire « Invoke-commande ».

(Il ne devrait pas être difficile. :))

Je soupçonne que sa nouvelle fonction depuis ce poste a été créé - passer des paramètres au bloc de script à l'aide de $ via: var. Puis son simple mater pour passer des paramètres à condition que le script est déjà sur la machine ou dans un emplacement réseau connu par rapport à la machine

En prenant l'exemple principal serait:

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

Je besoin de quelque chose aux scripts d'appel avec des paramètres nommés. Nous avons une politique de ne pas utiliser le positionnement ordinale des paramètres et nécessitant le nom du paramètre.

Mon approche est similaire à celles ci-dessus, mais obtient le contenu du fichier de script que vous voulez appeler et envoie un bloc de paramètres contenant les paramètres et les valeurs.

L'un des avantages de ceci est que vous pouvez choisir en option les paramètres à envoyer au fichier script permettant des paramètres non obligatoires avec les valeurs par défaut.

En supposant qu'il ya un script appelé « MyScript.ps1 » dans le chemin temporaire qui a le bloc de paramètres suivant:

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

Voici comment je qualifierais ce script à partir d'un autre 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

J'ai utilisé cela dans beaucoup de scénarios et il fonctionne très bien. Une chose que vous avez besoin de temps en temps à faire est de mettre des guillemets autour de la valeur du paramètre bloc d'affectation. Ceci est toujours le cas quand il y a des espaces dans la valeur.

par exemple. Ce bloc de PARAM est utilisé pour appeler un script qui copie différents modules dans l'emplacement standard utilisé par PowerShell C:\Program Files\WindowsPowerShell\Modules qui contient un espace.

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

Hope this helps!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top