public Task StartAsync(Tool tool) { IntPtr desktopHandle = WindowsUtility.CreateDesktop(DesktopName); // embrace the madness -- it seems Windows always wants exactly one instance of "ctfmon.exe" in the new desktop var ctfmonStartInfo = new ProcessStartInfo { FileName = "ctfmon.exe", WorkingDirectory = "." }; WindowsApi.PROCESS_INFORMATION ctfmonProcess = WindowsUtility.CreateProcess(ctfmonStartInfo, DesktopName); AssociateWithJob(ctfmonProcess, false); // start the desired process var arguments = string.Join(" ", tool.Settings.GetArguments(tool)); var startInfo = new ProcessStartInfo { FileName = tool.ExecutablePath, Arguments = arguments, WorkingDirectory = tool.WorkingDirectory }; WindowsApi.PROCESS_INFORMATION targetProcess = WindowsUtility.CreateProcess(startInfo, DesktopName); AssociateWithJob(targetProcess, true); WindowsApi.CloseDesktop(desktopHandle); return(Task.FromResult((object)null)); }
private void AssociateWithJob(WindowsApi.PROCESS_INFORMATION processInformation, bool throwOnError) { if (_jobHandle == IntPtr.Zero) { lock (_jobHandleLock) { if (_jobHandle == IntPtr.Zero) { _jobHandle = WindowsApi.CreateJobObject(IntPtr.Zero, null); var basic = new WindowsApi.JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = WindowsApi.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE }; var extended = new WindowsApi.JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = basic }; int length = Marshal.SizeOf(typeof(WindowsApi.JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedPointer = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extended, extendedPointer, false); if (!WindowsApi.SetInformationJobObject(_jobHandle, WindowsApi.JOBOBJECTINFOCLASS.ExtendedLimitInformation, extendedPointer, (uint)length)) { throw new TorSharpException($"Unable to set information on the job object. Error: {WindowsUtility.GetLastErrorMessage()}."); } } } } if (processInformation.dwProcessId != 0) { lock (_processIdsLock) { _processIds.Add(processInformation.dwProcessId); } } if (!WindowsApi.AssignProcessToJobObject(_jobHandle, processInformation.hProcess) && throwOnError) { throw new TorSharpException($"Unable to assign the process to the job object. Error: {WindowsUtility.GetLastErrorMessage()}."); } }