protected virtual void Dispose(bool disposing) { if (disposed) { return; } // Free the attribute list if (StartupInfo.lpAttributeList != IntPtr.Zero) { ProcessApi.DeleteProcThreadAttributeList(StartupInfo.lpAttributeList); Marshal.FreeHGlobal(StartupInfo.lpAttributeList); } // Close process and thread handles if (ProcessInfo.hProcess != IntPtr.Zero) { ConsoleApi.CloseHandle(ProcessInfo.hProcess); } if (ProcessInfo.hThread != IntPtr.Zero) { ConsoleApi.CloseHandle(ProcessInfo.hThread); } disposed = true; }
private static StartInfoExtended ConfigureProcessThread(IntPtr hPC, IntPtr attributes) { // this method implements the behavior described in https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#preparing-for-creation-of-the-child-process var lpSize = IntPtr.Zero; var success = ProcessApi.InitializeProcThreadAttributeList( lpAttributeList: IntPtr.Zero, dwAttributeCount: 1, dwFlags: 0, lpSize: ref lpSize ); if (success || lpSize == IntPtr.Zero) // we're not expecting `success` here, we just want to get the calculated lpSize { throw InteropException.CreateWithInnerHResultException("Could not calculate the number of bytes for the attribute list."); } var startupInfo = new StartInfoExtended(); startupInfo.StartupInfo.cb = Marshal.SizeOf <StartInfoExtended>(); startupInfo.lpAttributeList = Marshal.AllocHGlobal(lpSize); success = ProcessApi.InitializeProcThreadAttributeList( lpAttributeList: startupInfo.lpAttributeList, dwAttributeCount: 1, dwFlags: 0, lpSize: ref lpSize ); if (!success) { throw InteropException.CreateWithInnerHResultException("Could not set up attribute list."); } success = ProcessApi.UpdateProcThreadAttribute( lpAttributeList: startupInfo.lpAttributeList, dwFlags: 0, attribute: attributes, lpValue: hPC, cbSize: (IntPtr)IntPtr.Size, lpPreviousValue: IntPtr.Zero, lpReturnSize: IntPtr.Zero ); if (!success) { throw InteropException.CreateWithInnerHResultException("Could not set pseudoconsole thread attribute."); } return(startupInfo); }