DEV Community

Masui Masanori
Masui Masanori

Posted on

Execute PowerShell scripts in C#

Intro

This time, I will try executing PowerShell scripts in C#.
There are some way to do this.

For example, I can use Process class.

PsAccessor.cs

using System.Diagnostics;

namespace AccessPowerShellSample;

public class PsAccessor
{
    public async Task<string?> ExecuteProcess()
    {
        using(var app = new Process())
        {
            app.StartInfo.FileName = "powershell.exe";
            app.StartInfo.Arguments = "echo HelloWorld!!";
            app.EnableRaisingEvents = true;
            app.StartInfo.RedirectStandardOutput = true;
            app.StartInfo.RedirectStandardError = true;
            // Must not set true to execute PowerShell command
            app.StartInfo.UseShellExecute = false;
            app.Start();
            using(var o = app.StandardOutput)
            {
                return await o.ReadToEndAsync();
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

I also can "PowerShell" class.

So I will try it in this time.

Use PowerShell class.

To use "PowerShell", I have to add some NuGet packages.

  • System.Management.Automation
  • Microsoft.PowerShell.Commands.Diagnostics
  • Microsoft.PowerShell.ConsoleHost
  • Microsoft.PowerShell.Commands.Utility
  • Microsoft.PowerShell.Commands.Management
  • Microsoft.WSMan.Management

PsAccessor.cs

using System.Management.Automation;

namespace AccessPowerShellSample;

public class PsAccessor
{
    public string? GenerateHmacSha512(string inputData, string key)
    {
        using(var ps = PowerShell.Create())
        {
            ps.AddCommand("echo");
            ps.AddArgument("Hello World!");
            var results = ps.Invoke<string>();
            return results.FirstOrDefault();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

AddScript

How about more complicated case?

For example, I will try generating a hash value by HMAC SHA-512.

hashValueGenerator.ps1

param(
    [Parameter()]
    [String] $secret_key,
    [String] $message
)
$oHMACSHA512 = New-Object System.Security.Cryptography.HMACSHA512
$oHMACSHA512.key = [Text.Encoding]::ASCII.GetBytes($secret_key)
$signature_rawout = $oHMACSHA512.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
$signature = ""
$signature_rawout | ForEach-Object { $i = [Convert]::ToString($_,16); if ($i.length -eq 1) { $i ='0' + $i }; $signature += $i }

Enter fullscreen mode Exit fullscreen mode

To execute it, I can use "Process" like below.

public async Task<string?> ExecuteProcess(string key, string message)
{
    using(var app = new Process())
    {
        app.StartInfo.FileName = "powershell.exe";
        app.StartInfo.Arguments = $"$oHMACSHA512 = New-Object System.Security.Cryptography.HMACSHA512;$oHMACSHA512.key = [Text.Encoding]::ASCII.GetBytes('{key}');$signature_rawout = $oHMACSHA512.ComputeHash([Text.Encoding]::ASCII.GetBytes('{message}'));$signature = '';$signature_rawout | ForEach-Object {{ $i = [Convert]::ToString($_,16); if ($i.length -eq 1) {{ $i ='0' + $i }}; $signature += $i }};[Convert]::ToBase64String($signature_rawout)";
        app.EnableRaisingEvents = true;
        app.StartInfo.RedirectStandardOutput = true;
        app.StartInfo.RedirectStandardError = true;
        // Must not set true to execute PowerShell command
        app.StartInfo.UseShellExecute = false;
        app.Start();
        using(var o = app.StandardOutput)
        {
            return await o.ReadToEndAsync();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Although I can get result, but it's very hard to debug.

I also can use PowerShell script files.

    public string? GenerateHmacSha512(string key, string message)
    {
        using(var ps = PowerShell.Create())
        {
            ps.AddScript(File.ReadAllText("./hashValueGenerator.ps1"));
            ps.AddParameter("secret_key", key);
            ps.AddParameter("message", message);
            var results = ps.Invoke<string>();
            return results.FirstOrDefault();
        }
    }
Enter fullscreen mode Exit fullscreen mode

I can use "AddCommand" to do this.
But I will get error because PowerShell execution policy.

Unhandled exception. System.Management.Automation.PSSecurityException: File C:\Users\example\OneDrive\Documents\workspace\AccessPowerShellSample\hashValueGenerator.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.
...
Enter fullscreen mode Exit fullscreen mode

So I think I should use "AddScript".

Resources

Top comments (0)