I am using Microsoft.PowerShell.5.1.ReferenceAssemblies to run some powershell scripts.
private void RunScript(string command)
{
var runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
var builder = new StringBuilder();
var task = new Task(() => {
var pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(command);
try
{
var result = pipeline.Invoke();
foreach (var r in result)
{
builder.Append(r.ToString());
}
}
catch (Exception e)
{
builder.Append(e);
}
runspace.Close();
var consoleOutput = builder.ToString();
runspace.Dispose();
});
psScriptsRunning.Add(runspace);
task.Start();
}
I keep track of the runspaces in psScriptsRunning. So when my app is closed, I go through and close the runspaces.
public void deinit()
{
foreach(var runspace in psScriptsRunning)
{
runspace.Dispose();
}
}
This has the effect of closing the powershell scripts and any processes it has spawned. However seems like it takes a while to actually close the processes, if you have a better way to improve this, please let me know.
However, if someone kills my app from Task Manager, this code will not run. How can I kill any processes launched by the powershell scripts?
Previously before supporting powershell scripts directly via runspaces, I used to create a process and launch via powershell.exe.
I was able to make sure any processes spawned were killed by using job objects see Kill child process when parent process is killed.
Now that I am using runspaces, how can I achieve the same ?
The reason I went with runspaces instead of using powershell.exe was due to better launching times of the powershell scripts.