I am very bad and beginner with the PowerShell. What I need is to with the request that I receive run a powershell script. My request and response that I need looks like this:
public class MyRequest
{
public string Script { get; set; } // PowerShell script content
public string Policy { get; set; } // e.g. "Bypass", "RemoteSigned"
public string Scope { get; set; } // e.g. "Process", "CurrentUser"
public bool RunAsAdmin { get; set; } // true = elevated
public int TimeoutInSeconds { get; set; } // timeout duration
}
public class PowerShellResult
{
public int ExitCode { get; set; }
public string Output { get; set; }
public string Error { get; set; }
}
I am using CliWrap library. Now my problem is that I need to run the script as an admin if it is set in the request. I tried everything, even ChatGPT at the end.
When I set the run as no admin, it runs, but when set to as admin, the console is empty. This is my sample code.
using CliWrap;
using CliWrap.Buffered;
using System.Text;
var runner = new PowerShellRunner();
var result = await runner.RunAsync(new MyRequest
{
Script = "Write-Output 'Hello from PowerShell'",
Policy = "Restricted",
Scope = "Process",
RunAsAdmin = true,
TimeoutInSeconds = 30
});
Console.WriteLine($"PowerShell script execution completed with code: {result.ExitCode}.");
Console.WriteLine($"Errors: {result.Error}.");
Console.WriteLine($"Output: {result.Output}.");
Console.ReadKey();
public class MyRequest
{
public string Script { get; set; } // PowerShell script content
public string Policy { get; set; } // e.g. "Bypass", "RemoteSigned"
public string Scope { get; set; } // e.g. "Process", "CurrentUser"
public bool RunAsAdmin { get; set; } // true = elevated
public int TimeoutInSeconds { get; set; } // timeout duration
}
public class PowerShellResult
{
public int ExitCode { get; set; }
public string Output { get; set; }
public string Error { get; set; }
}
public class PowerShellRunner
{
public async Task<PowerShellResult> RunAsync(MyRequest request)
{
var errors = new StringBuilder();
var output = new StringBuilder();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(request.TimeoutInSeconds));
try
{
if (request.RunAsAdmin)
{
// Launch elevated PowerShell
string elevateArgs =
$"-NoProfile -ExecutionPolicy {request.Policy} '{request.Script}'";
string elevateCommand =
$"Start-Process powershell -Verb RunAs -ArgumentList \"{elevateArgs}\"";
Console.WriteLine($"Command: {elevateCommand}");
var result = await Cli.Wrap("powershell")
.WithArguments(a => a.Add("-NoProfile").Add("-Command").Add(elevateCommand))
.WithValidation(CommandResultValidation.None)
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(output))
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(errors))
.ExecuteBufferedAsync(cts.Token);
return new PowerShellResult
{
ExitCode = result.ExitCode,
Output = output.ToString(),
Error = errors.ToString()
};
}
else
{
// Normal PowerShell run
var result = await Cli.Wrap("powershell")
.WithArguments(a => a
.Add("-NoProfile")
.Add("-ExecutionPolicy").Add(request.Policy)
.Add(request.Script))
.WithValidation(CommandResultValidation.None)
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(output))
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(errors))
.ExecuteBufferedAsync(cts.Token);
return new PowerShellResult
{
ExitCode = result.ExitCode,
Output = output.ToString(),
Error = errors.ToString()
};
}
}
}
}
thnx
Start-Processnever allows you to capture the launched process' output streams directly: you need to use-RedirectStandardOutputand/or-RedirectStandardErrorin order to capture output in files. However, doing so is incompatible with elevation (-Verb RunAs), and the simplest alternative is to make the launched, elevated process itself write its output to file(s), which is also what AleksaRistic's answers suggests. See this answer for background information.