PowerShell Pass Named parameters to ArgumentList
One option:
$params = @{P1 = 1P2 = 2 P3 = 3}$ScriptPath = 'D:\Test.ps1'$sb = [scriptblock]::create(".{$(get-content $ScriptPath -Raw)} $(&{$args} @params)")Invoke-Command -ComputerName server -ScriptBlock $sb
The code by mjolinor works great, but it took me several minutes to understand it.
The code makes a simple thing - generates a content of script block with built-in parameters:
&{ Param ( [string]$P3, [string]$P2, [string]$P1 ) Write-Output "P1 Value:" $P1 Write-Output "P2 Value:" $P2 Write-Output "P3 Value:" $P3} -P1 1 -P2 2 -P3 3
Then this script block is passed to Invoke-Command.
To simplify the code:
".{$(get-content $ScriptPath -Raw)} $(&{$args} @params)"$scriptContent = Get-Content $ScriptPath -Raw$formattedParams = &{ $args } @params# The `.{}` statement could be replaced with `&{}` here, because we don't need to persist variables after script call.$scriptBlockContent = ".{ $scriptContent } $formattedParams"$sb = [scriptblock]::create($scriptBlockContent)
Let's make a basic C# implementation:
void Run(){ var parameters = new Dictionary<string, string> { ["P1"] = "1", ["P2"] = "2", ["P3"] = "3" }; var scriptResult = InvokeScript("Test.ps1", "server", parameters) Console.WriteLine(scriptResult);}string InvokeScript(string filePath, string computerName, Dictionary<string, string> parameters){ var innerScriptContent = File.ReadAllText(filePath); var formattedParams = string.Join(" ", parameters.Select(p => $"-{p.Key} {p.Value}")); var scriptContent = "$sb = { &{ " + innerScriptContent + " } " + formattedParams + " }\n" + $"Invoke-Command -ComputerName {computerName} -ScriptBlock $sb"; var tempFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".ps1"); File.WriteAllText(tempFile, scriptContent); var psi = new ProcessStartInfo { FileName = "powershell", Arguments = $@"-ExecutionPolicy Bypass -File ""{tempFile}""", RedirectStandardOutput = true, UseShellExecute = false }; var process = Process.Start(psi); var responseText = process.StandardOutput.ReadToEnd(); File.Delete(tempFile); return responseText;}
The code generates a temporary script and executes it.
Example script:
$sb = { &{ Param ( [string]$P3, [string]$P2, [string]$P1 ) Write-Output "P1 Value:" $P1 Write-Output "P2 Value:" $P2 Write-Output "P3 Value:" $P3 } -P1 1 -P2 2 -P3 3}Invoke-Command -ComputerName server -ScriptBlock $sb
Here's a simple solution:
[PowerShell]::Create().AddCommand('D:\test.ps1').AddParameters(@{ P1 = 1; P2 = 2; P3 = 3 }).Invoke()
Here's output:
PS C:\Windows\system32> [PowerShell]::Create().AddCommand('D:\test.ps1').AddParameters(@{ P1 = 1; P2 = 2; P3 = 3 }).Invoke()P1 Value :1P2 Value:2P3 Value :3