0

We have a C# application that executes PowerShell scripts as an extension point, we don't have access to change this code but it is pretty much the following:

string command = @"C:\temp.ps1";
var fileName = "powershell";
var args = $"-ExecutionPolicy unrestricted . '{command}'";

var process = CreateProcess(fileName, args);
ExecuteProcess(ref process);

private Process CreateProcess(string fileName, string args)
{
    return new Process
    {
        StartInfo =
        {
            FileName = fileName,
            Arguments = args,
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            UseShellExecute = false
        }
    };
}

private int ExecuteProcess(ref Process proc)
{
    proc.Start();

    string text = string.Empty;
    string text2 = string.Empty;
    while (!proc.HasExited)
    {
        Thread.Sleep(1000);
        text += proc.StandardOutput.ReadToEnd();
        text2 += proc.StandardError.ReadToEnd();
    }
    proc.WaitForExit();
    text2 += proc.StandardError.ReadToEnd();
    text += proc.StandardOutput.ReadToEnd();

    Console.WriteLine(text);
    Console.WriteLine(text2);

    return proc.ExitCode;
}

We have a PowerShell script that gets executed from this code that has a long-running process, to keep this simple we'll just use ping.exe with a -t argument.

ping -t google.com

We want to be able to fork the ping.exe process so that the c# application can resume execution as soon as possible and that the ping.exe in this example continues on it's merry way.

I've tried to run Start-Process inside the powershell script but this still just blocks the execution of the C# application until all the processes have fully executed (so it eventually runs to completion):

Start-Process ping -ArgumentList "-t","google.com" -RedirectStandardOutput ".\out.log" -RedirectStandardError ".\err.log"

I've also tried to run Start-Job and wrap the start process in a separate job, however, this seems to start the job but never completes

Start-Job -ScriptBlock { Start-Process ping -ArgumentList "-t","google.com" -RedirectStandardOutput ".\out.log" -RedirectStandardError ".\err.log" }

Is there any way to start a new process from within PowerShell and allow the C# application to continue executing?

Kevin Smith
  • 13,746
  • 4
  • 52
  • 77
  • Why run `ping.exe` from PowerShell when you can [do it directly](https://learn.microsoft.com/en-us/dotnet/framework/network-programming/how-to-ping-a-host)? – Bill_Stewart Oct 30 '17 at 14:06
  • Ping is just an example, we fire off other processes in our PowerShell script but won't want it to block – Kevin Smith Oct 30 '17 at 14:14
  • But why are you running PowerShell at all? Just spawn the executable you want to run. – Bill_Stewart Oct 30 '17 at 14:15
  • Like I said in the question we don't have access to the C# application that is running the PowerShell code, all we have is just PowerShell scripts we can run. – Kevin Smith Oct 30 '17 at 14:16
  • `Start-Process` runs a process asynchronously. If the C# program still blocks, then it must be somehow be waiting for processes started by the PowerShell process. – Bill_Stewart Oct 30 '17 at 14:20
  • Well it's just running the PowerShell command from the PowerShell process, so wonder if that keeps track of handles inside it – Kevin Smith Oct 30 '17 at 14:24

1 Answers1

0

I've kinda found a workaround - if I pass in -Verb Open to Start-Process it seems to resume execution to the C# application straight away. The only problem is that you can't redirect the standard out or error to files.

Start-Process ping -ArgumentList "-t","google.com" -Verb Open
Kevin Smith
  • 13,746
  • 4
  • 52
  • 77