PowerShell Pass Named parameters to ArgumentList PowerShell Pass Named parameters to ArgumentList powershell powershell

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