Children processes created in ASP.NET Core Process gets killed on exit

Edit

Solution not working for notepad.exe - I will try to see if there is any optionn based on Simon's answer as yo why this behaviour happens

Old answer (to be removed)

I have to wash my hands now for writing this code, but I think you can work around this limitation if that is what you need in your context. I advise against running external processes, especially from the "web server". It's asking for trouble. Replacing the process by some malicious person, credential escalation, unexpected behaviour because of syntax changes just to name a few.

Anyway this might work for you (interposing cmd.exe in between, to try to break the child-parent relationship):

var process = new Process
{
  StartInfo = new ProcessStartInfo 
      { 
         FileName ="cmd.exe",  
         Arguments = "/c calc.exe", 
         WindowStyle =  ProcessWindowStyle.Hidden
      }
};

process.Start();

As I said in my comment, there is a Job Object which is created by ASP.NET core in the out-of-process scenario. The relevant source code portion is here:

https://github.com/aspnet/AspNetCore/blob/master/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/serverprocess.cpp#L89

HRESULT
SERVER_PROCESS::SetupJobObject(VOID)
{
    HRESULT                                 hr = S_OK;
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION    jobInfo = { 0 };

    if (m_hJobObject == NULL)
    {
      ....
            jobInfo.BasicLimitInformation.LimitFlags =
                JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            if (!SetInformationJobObject(m_hJobObject,
                JobObjectExtendedLimitInformation,
                &jobInfo,
                sizeof jobInfo))
            {
                hr = HRESULT_FROM_WIN32(GetLastError());
            }
        }
    }

    return hr;
}

As per documentation, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE:

Causes all processes associated with the job to terminate when the last handle to the job is closed.

If you dig the source further, it does not seem to be optional.

Now, you can actually see this by yourself, if you reproduce your steps. Use Process Explorer, and navigate to your dotnet.exe process, this is what it will display:

enter image description here

  • note 1: in fact calc.exe stays alive (at least in my Windows 10 installation because it's now a WinRT app, so it will not end up as child of dotnet.exe), that's why I used notepad.exe
  • note 2: iisexpress.exe also creates a job object, but it's configured as breakaway ok, which means it won't kill child processes.
  • note 3: if you run from Visual Studio (not my screenshot), you may see an intermediary VSIISExeLauncher.exe process between iisexpress.exe and dotnet.exe. This one also creates a Job Object with 'kill on close' to add to the confusion...