I have a need to run PowerShell scripts from C# application. I like using method AddScript for this. And it works quite nice. However, it does not seem to work as expected when I added parameters to script with method AddParameters.
Here is test payload (PowerShell):
param ([string]$Arg1, [string]$Arg2, [switch]$ArgParamless)
$filename = "payload_with_params.txt"
$filepath = $env:temp
$fullpath = Join-Path -Path $filepath -ChildPath $filename
$dt = Get-Date -Format "yyyy.MM.dd HH:mm:ss"
$val = $dt ' ' $Arg1 ' ' $Arg2 ' ' $ArgParamless
Add-Content -Path $fullpath -Value "$val"
It works just fine if I push it from PS like this:
.\payload_with_params.ps1 -Arg1 "Bla 1" -Arg2 "Bla 2" -ArgParamless
Result:
2023.01.19 16:58:10 Bla 1 Bla 2 True
The C# code (oversimplified):
string command = File.ReadAllText(pathToPS1);
List<CommandParameter> paramList = new List<CommandParameter>();
paramList.Add(new CommandParameter("Arg1", "Bla 1"));
paramList.Add(new CommandParameter("Arg2", "Bla 2"));
paramList.Add(new CommandParameter("ArgParamless"));
using (PowerShell ps = PowerShell.Create())
{
//Adding script file content to object
ps.AddScript(command);
if (paramList != null)
{
if (paramList.Count > 0)
{
//Adding Params to object;
ps.AddParameters(paramList);
}
}
//Launching
ps.Invoke();
}
And the result:
2023.01.19 16:54:00 System.Management.Automation.Runspaces.CommandParameter System.Management.Automation.Runspaces.CommandParameter False
So.. it's not working as I expected. How should I supply parameters to script?
CodePudding user response:
For [switch]
parameters, you'll want to bind a bool
- PowerShell will interpret true
as "Present" and false
as "Absent":
paramList.Add(new CommandParameter("ArgParamless", true));
CodePudding user response:
Well, it turns out AddParameter(CommandParameter) approach doesn't work.
This approach is working:
string command = File.ReadAllText(pathToPS1);
using (PowerShell ps = PowerShell.Create())
{
//Adding script file content to object
ps.AddScript(command);
if (paramList != null)
{
if (paramList.Count > 0)
{
//Adding Params to object;
ps.AddArgument("-Arg1 XXXXXX");
}
}
//Launching
ps.Invoke();
}
On PowerShell end this arguments can be extracted for usage from $args array:
$arglist = $args -join " "
Even better approach using hashtable:
string command = File.ReadAllText(pathToPS1);
using (PowerShell ps = PowerShell.Create())
{
//Adding script file content to object
ps.AddScript(command);
if (paramList != null)
{
if (paramList.Count > 0)
{
//Adding Params to object;
var hashtable = new Hashtable {
{ "Arg1", "XXXXXX" },
{ "Arg2", "YYYYYY" },
{ "ArgParamless", true }
};
ps.AddArgument(hashtable);
}
}
//Launching
ps.Invoke();
}
And that's what you do on PS side to use it:
function Wrapper-Test ([string]$Arg1, [string]$Arg2, [switch]$ArgParamless) {
$Result = $Args1 ' ' $Args2 ' ' $ArgParamless
return $Result
}
$MyArgs = "";
$MyArg = $args[0]
$MyArgs = Wrapper-Test @MyArg;
$filename = "payload_with_params.txt"
$filepath = $env:temp
$fullpath = Join-Path -Path $filepath -ChildPath $filename
$dt = Get-Date -Format "yyyy.MM.dd HH:mm:ss"
$arglist = $args -join " "
$val = $dt " " $MyArgs
Add-Content -Path $fullpath -Value "$val"