public override int Event(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { switch (pEvent) { case IDebugProcessCreateEvent2 _: { pProcess.GetProcessId(out var logicalId); OnProcessCreated?.Invoke(this, logicalId); } break; case IDebugProcessDestroyEvent2 _: { pProcess.GetProcessId(out var logicalId); OnProcessRemoved?.Invoke(this, logicalId); } break; } return(VSConstants.S_OK); }
public static async Task <ProcessStats> Run(string commandline, OnProcessOutput onProcessOutput, OnProcessCreated onProcessCreated) { var pi = new PROCESS_INFORMATION(); try { CreatePipeAsyncReadSyncWrite(out NamedPipeServerStream readerOut, out NamedPipeClientStream writerOut); CreatePipeAsyncReadSyncWrite(out NamedPipeServerStream readerErr, out NamedPipeClientStream writerErr); using (readerOut) using (writerOut) using (readerErr) using (writerErr) { pi = CreateProcess(commandline, writerOut, writerErr); onProcessCreated?.Invoke(pi.dwProcessId); // // 2019-09-22 Spindi himself // this Close() is very importante. // When we do not close the writer handle here, the read from out/err will hang. // writerOut.Close(); writerErr.Close(); Task stdout = Misc.ReadLinesAsync(new StreamReader(readerOut), (line) => onProcessOutput(KINDOFOUTPUT.STDOUT, line)); Task stderr = Misc.ReadLinesAsync(new StreamReader(readerErr), (line) => onProcessOutput(KINDOFOUTPUT.STDERR, line)); await Task.WhenAll(stdout, stderr); uint exitCode = GetExitCode(pi); return(CreateProcessStats(pi, exitCode)); } } finally { if (!pi.hProcess.Equals(IntPtr.Zero)) { CloseHandle(pi.hProcess); } } }