Pregunta

Tengo una secuencia de comandos que se puede ejecutar de forma remota a través de Invoke-Command

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

Mientras que utilizo parámetros por defecto, funciona bien. Sin embargo, el guión tiene 2 [nombre] interruptor de parámetros (-debug y -CLEAR)

¿Cómo puedo pasar los parámetros de conmutación a través de la invocación de comando? He probado el -ArgumentList pero estoy teniendo errores, así que debe tener la sintaxis incorrecta o algo así. Cualquier ayuda es muy apreciada.

¿Fue útil?

Solución

-ArgumentList se basa en el uso con ScriptBlock comandos, por ejemplo:

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

Cuando se llama con un -File todavía pasa los parámetros como una matriz Splatted mudo. He presentado un solicitud de función a haber que se añaden al comando (que vote hacia arriba).

Por lo tanto, usted tiene dos opciones:

Si usted tiene un script que se veía así, en una ubicación de red accesible desde la máquina remota (nota que -Debug está implícita porque cuando se utiliza el atributo Parameter, el guión se CmdletBinding implícita, y por lo tanto, todos los parámetros comunes ):

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

sin quedar atrapado en el significado de $Clear ... si quería invocar que se puede utilizar cualquiera de las sintaxis siguiente 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

En ese, estoy duplicación de todos los parámetros que me importa en el ScriptBlock para que pueda pasar valores. Si puedo sean difíciles de código (que es lo que realmente hice), no hay necesidad de hacer eso y el uso PSBoundParameters, puedo sólo tiene que pasar los que necesito. En el segundo ejemplo a continuación voy a pasar el $ Borrar uno, sólo para demostrar cómo pasar los parámetros del conmutador:

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

La otra opción

Si el guión es en su máquina local, y no quiere cambiar los parámetros a ser posicional, o si desea especificar parámetros que son parámetros comunes (lo que no puede controlarlos) que se desea obtener el contenido de ese guión y incrustarla en su 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 realmente necesita para pasar de una variable para el nombre del script, lo que haría dependerá de si la variable se define de forma local o remota. En general, si usted tiene un $Script variable o una variable $Env:Script entorno con el nombre de un guión, puede ejecutarlo con el operador de llamada (&): &$Script o &$Env:Script

Si se trata de una variable de entorno que ya está definido en el equipo remoto, eso es todo lo que hay que hacer. Si se trata de un locales variable, entonces tendrá que pasar al bloque de secuencia de comandos remota:

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

Otros consejos

Mi solución a esto fue para escribir el bloque de script de forma dinámica 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

Paso de argumentos fue muy frustrante, tratando diversos métodos, por ejemplo, España -arguments, $using:p1, etc y esto sólo funcionó como se desee con ningún problema.

Desde que controlar el contenido y la expansión de variables de la cadena que crea el [scriptblock] (o archivo de script) de esta manera, no hay ningún problema real con el encantamiento "Invoke-Command".

(No debería ser tan difícil. :))

sospecho que es una nueva característica desde la creación de este post - pasar parámetros al bloque de script utilizando $ Uso: var. Entonces es un mater sencillo pasar parámetros proporcionan la secuencia de comandos ya está en la máquina o en una ubicación de red conocida con relación a la máquina

Tomando el ejemplo principal sería:

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

Yo necesitaba algo para guiones de llamadas con parámetros con nombre. Tenemos una política de no utilizar posicionamiento ordinal de parámetros y que requieren el nombre del parámetro.

Mi enfoque es similar a los anteriores pero se pone el contenido del archivo de script que desea llamar y envía un bloque de parámetros que contiene los parámetros y valores.

Una de las ventajas de esto es que se puede elegir opcionalmente el que los parámetros a enviar al archivo de script que permite parámetros no obligatorios con valores por defecto.

Si se asume que hay un script llamado "MyScript.ps1" en la ruta temporal que tiene el siguiente bloque de parámetros:

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

Esta es la forma en que yo llamaría este script desde otro 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

he utilizado este en un montón de escenarios y funciona muy bien. Una cosa que de vez en cuando hay que hacer es poner comillas alrededor del bloque de asignación de valores de parámetros. Este es siempre el caso cuando hay espacios en el valor.

por ejemplo. Este bloque de parámetro se utiliza para llamar a un script que copia varios módulos en la ubicación estándar utilizado por PowerShell C:\Program Files\WindowsPowerShell\Modules que contiene un carácter de espacio.

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

Espero que esto ayude!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top