Custom Runspaces

Create Custom Runspace

Create new C# Console App project

using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a runspace with an interactive session
            Runspace rs = RunspaceFactory.CreateRunspace();
            rs.Open();

            // Create a new PowerShell instance and assign it to the runspace
            PowerShell ps = PowerShell.Create();
            ps.Runspace = rs;

            // This command will output the current session state to a file (as per your original example)
            string cmd = "$ExecutionContext.SessionState.LanguageMode | Out-File -FilePath C:\\Windows\\Tasks\\test.txt";

            // Add the command to the PowerShell pipeline
            ps.AddScript(cmd);
            var output = ps.Invoke();

            // Output the results of the invoked script
            foreach (var result in output)
            {
                Console.WriteLine(result);
            }

            // Inform user about interactive mode
            Console.WriteLine("Session started interactively. Type 'exit' to quit.");
            Console.WriteLine("You can now interact with the PowerShell session.");

            while (true)
            {
                string input = Console.ReadLine();

                if (input.ToLower() == "exit")
                    break;

                // Clear previous errors
                ps.Streams.Error.Clear();

                // Add the input script to PowerShell session
                ps.AddScript(input);
                var commandOutput = ps.Invoke();

                // Print output
                Console.WriteLine("Command: " + input);
                foreach (var result in commandOutput)
                {
                    Console.WriteLine("Output: " + result);
                }

                // Print errors, if any
                if (ps.Streams.Error.Count > 0)
                {
                    Console.WriteLine("Errors:");
                    foreach (var error in ps.Streams.Error)
                    {
                        Console.WriteLine(error.ToString());
                    }
                }
            }

            // Close the runspace when done
            rs.Close();
        }
    }
}

Right click 'References' folder -> add new reference -> browse -> C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35 -> select System.Management.Automation.dll

Use case

This executable will launch an interactive PowerShell session in the current session. Keep in mind it is a bit janky and SOME scripts might not work correctly/as expected.

Keep in mind this requires you to bypass C# executables Applocker rules

Last updated