Simply put, rather than:
Invoke-Command $sb -ArgumentList $arg1, $arg2
I would like to be able to do:
Invoke-Command $sb -Parameters @{NamedArg = $value1; Switch = $true}
(note that currently it's _impossible_ to call a scriptblock with a [switch] parameter as they cannot be passed positionally; this would serve to resolve that, effectively, while permitting more complex functions)
This would enable a function to do something _very_ amusing, like so:
Invoke-Command -ComputerName testPC -Scriptblock $MyInvocation.MyCommand.ScriptBlock -Parameters $PSBoundParameters
Not that that's really my use case, just thought it was fun! I'm mostly interested in giving Invoke-Command more robust function calling capability so we can call local functions in a remote session more easily, a la:
Invoke-Command -ScriptBlock ${function:Test-Function} -Parameters $Params -ComputerName RemotePC
Something like this might already be possible with splatting:
% $Params=@{"LiteralPath" = "C:\"; "Hidden" = $true;}; invoke-command -ScriptBlock { Get-ChildItem @Params }
C:\
d--hs- 2/13/2017 10:23 PM $RECYCLE.BIN
d--h-- 2/3/2019 3:23 PM $WINDOWS.~BT
d--hs- 2/4/2019 5:07 PM Config.Msi
d--hsl 8/25/2016 8:17 PM Documents and Settings
d--h-- 11/17/2018 6:36 PM ProgramData
d--h-- 9/18/2018 5:32 PM Recovery
d--hs- 9/22/2017 5:53 PM System Volume Information
-a-hs- 2/4/2019 4:54 PM 6840606720 hiberfil.sys
-a-hs- 2/4/2019 4:54 PM 2550136832 pagefile.sys
-a-hs- 2/4/2019 4:54 PM 16777216 swapfile.sys
Your last example might be possible by pasting the body of the function into a new function on the other end and splatting args against the _new_ remote function. I tried to get that working, but in the limited time I allocated to prototyping I couldn't.
Yes @DHowett this can be done, but the syntax for doing so is _decidedly_ more irritating to use!
Example:
$Parameters = @{Param1 = $Value; Switch = $true}
Invoke-Command -ComputerName RemotePC -ScriptBlock {
New-Item Function:\TempFunc -Value ${using:function:my-function} > $null
TempFunc @using:Parameters
}
Being how relatively easy this is to accomplish in any case, Invoke-Command should just support it out of the box in my opinion.
@iSazonov yeah, I've been following along with that one.
This is less about splatting itself and more about how Invoke-Command doesn't support passing parameters to its script block by name, only by position with -ArgumentList.
The RFC targets "Splatting in method invocations" too. If it doesn't resolve your request we need to enhance the RFC I believe.
That portion of the RFC is designed to be used specifically with .NET methods. For example:
[System.IO.File]::ReadAllBytes@@{Path = 'C:\test.txt' }
The fact that Invoke-Command as a Cmdlet itself only supports passing positional arguments to the script block parameter when it invokes is a separate issue.
I am having this issue too and splatting is not the issue... Not accepting named arguments is the issue.
Hey Guys, This is a real issue with scripts as it is easy to get the order of parameters wrong and write bad scripts. The ideal solution, to me, would look like this
$args = @{
P1 = 1
P3 = 3
P2 = 2
}
Invoke-Command -ScriptBlock{
param($P1, $P2, $P3)
Write-Host "$P1 $P2 $P3"
} -ArgumentList @args -Session $somesession
if you have a script with lots of parameters you want to call on another session, you are in for ugly brittle code ;-)
also maybe
Invoke-Command -FilePath d:\scripts\someFile.ps1 -ArgumentList @args -Session $somesession
Most helpful comment
I am having this issue too and splatting is not the issue... Not accepting named arguments is the issue.