public static ProcessInTheJob CreateProcessInTheJob( string desktopName, string appPath, string cmdLine, IntPtr jobHandle) { var newJobHandle = IntPtr.Zero; if (jobHandle == IntPtr.Zero) { newJobHandle = jobHandle = WinApi.CreateJobObject(IntPtr.Zero, null); // TODO set limits etc } const uint NORMAL_PRIORITY_CLASS = 0x0020; const uint CREATE_SUSPENDED = 0x00000004; var sInfo = new WinApi.STARTUPINFO(); sInfo.cb = Marshal.SizeOf(sInfo); sInfo.lpDesktop = desktopName; var pSec = new WinApi.SECURITY_ATTRIBUTES(); var tSec = new WinApi.SECURITY_ATTRIBUTES(); pSec.nLength = Marshal.SizeOf(pSec); tSec.nLength = Marshal.SizeOf(tSec); string commandLine = ""; if (!string.IsNullOrEmpty(appPath) && !string.IsNullOrEmpty(cmdLine)) { commandLine = $"{appPath} {cmdLine}"; } else if (!string.IsNullOrEmpty(cmdLine)) { commandLine = cmdLine; } var retValue = WinApi.CreateProcess(appPath, commandLine, ref pSec, ref tSec, false, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED, IntPtr.Zero, null, ref sInfo, out var pInfo); WriteLine("Process ID (PID): " + pInfo.dwProcessId); WriteLine("Process Handle : " + pInfo.hProcess); var r = WinApi.AssignProcessToJobObject(jobHandle, pInfo.hProcess); if (!r) { if (newJobHandle != IntPtr.Zero) { WinApi.CloseHandle(newJobHandle); } return(new ProcessInTheJob(ProcessInTheJob.Status.COULD_NOT_ASSIGN_JOB, IntPtr.Zero, pInfo)); } // Ensure that killing one process kills the others var extendedInfo = new WinApi.JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = { LimitFlags = (short)WinApi.LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE } }; int length = Marshal.SizeOf(typeof(WinApi.JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!WinApi.SetInformationJobObject(jobHandle, WinApi.JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } Marshal.FreeHGlobal(extendedInfoPtr); WinApi.ResumeThread(pInfo.hThread); return(new ProcessInTheJob(ProcessInTheJob.Status.JOB_ASSIGNED, jobHandle, pInfo)); }
public static void CloseDesktop(IntPtr handle) { WinApi.CloseDesktop(handle); }