I feel like I'm missing something that should be obvious, but I just can't figure out how to do this.
I have a ps1 script that has a function defined in it. It calls the function and then tries using it remotely:
function foo
{
Param([string]$x)
Write-Output $x
}
foo "Hi!"
Invoke-Command -ScriptBlock { foo "Bye!" } -ComputerName someserver.example.com -Credential someuser@example.com
This short example script prints "Hi!" and then crashes saying "The term 'foo' is not recognized as the name of a cmdlet, function, script file, or operable program."
I understand that the function is not defined on the remote server because it is not in the ScriptBlock. I could redefine it there, but I'd rather not. I'd like to define the function once and use it either locally or remotely. Is there a good way to do this?
You need to pass the function itself (not a call to the function in the
ScriptBlock
).I had the same need just last week and found this SO discussion
So your code will become:
Note that by using this method, you can only pass parameters into your function positionally; you can't make use of named parameters as you could when running the function locally.
Although that's an old question I would like to add my solution.
Funny enough the param list of the scriptblock within function test, does not take an argument of type [scriptblock] and therefor needs conversion.
Another posibility is passing a hashtable to our scriptblock containing all the methods that you would like to have available in the remote session:
You can pass the definition of the function as a parameter, and then redefine the function on the remote server by creating a scriptblock and then dot-sourcing it:
This eliminates the need to have a duplicate copy of your function. You can also pass more than one function this way, if you're so inclined:
You can also put the function(s) as well as the script in a file (foo.ps1) and pass that to Invoke-Command using the FilePath parameter:
The file will be copied to the remote computers and executed.