2011-12-09 26 views
25

Estoy escribiendo un script de PowerShell que ejecutará comandos en un host remoto usando Invoke-Command y su parámetro -ScriptBlock. Por ejemplo,Usando Invoke-Command -ScriptBlock en una función con argumentos

function Foo { 
    ... 
    return "foo" 
} 
$rv = Invoke-Command --Credential $c --ComputerName $fqdn -ScriptBlock ${function:Foo} 

Esto funciona bien. Lo que me gustaría hacer ahora es lo mismo, pero llame a una función con argumentos locales. Por ejemplo,

function Bar { 
    param([String] $a, [Int] $b) 
    ... 
    return "foo" 
} 
[String] $x = "abc" 
[Int] $y = 123 
$rv = Invoke-Command --Credential $c --ComputerName $fqdn -ScriptBlock ${function:Foo($x,$y)} 

Pero esto no funciona:

Invoke-Command: No se puede validar el argumento del parámetro 'ScriptBlock'. El argumento es nulo. Proporcione un argumento no nulo y pruebe el comando nuevamente.

¿Cómo puedo usar Invoke-Command con un -ScriptBlock que es una función local con argumentos?

Me doy cuenta de que puedo envolver toda la función y los parámetros en un gran bloque de código, pero esa no es una forma limpia de hacerlo, en mi opinión.

Respuesta

41

Creo que desee:

function Foo ($a,$b) { 
    $a 
    $b 
    return "foo" 
} 

$x = "abc" 
$y= 123 

Invoke-Command -Credential $c -ComputerName $fqdn -ScriptBlock ${function:Foo} -ArgumentList $x,$y 
+0

gracias hombre, funciona a la perfección! Estaba jugando con combos de param() + -Argumentos sin suerte. –

+0

me llevó varias horas encontrar esta solución ;-) Mucho mejor que exportar/importar sesiones ¡Gracias! – icnivad

+0

Creo que el formato correcto debería ser '-ScriptBlock {$ función: Foo}' (nota '$' posición) – Mourndark

7

Puede envolver las funciones en un bloque y pasar el bloque;

$a = { 
    function foo{} 
    foo($args) 
} 

$a.invoke() // Locally 

$rv = Invoke-Command --Credential $c --ComputerName $fqdn -ScriptBlock $a //remotely 

Aunque no es muy elegante.

+0

me gustaría evitar esto. –

2

Esto también funciona:

function foo 
{ 
    param([string]$hosts, [string]$commands) 
    $scriptblock = $executioncontext.invokecommand.NewScriptBlock($commands) 
    $hosts.split(",") |% { Invoke-Command -Credential $cred -ComputerName $_.trim() -Scriptblock $scriptblock } 
} 
Cuestiones relacionadas