Improve ProcessExtensions

pull/776/head
NextTurn 2020-09-14 00:00:00 +08:00 committed by Next Turn
parent 3c5d67e287
commit d771e474dc
4 changed files with 53 additions and 33 deletions

View File

@ -5,7 +5,7 @@ using static WinSW.Native.HandleApis;
namespace WinSW.Native namespace WinSW.Native
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal readonly ref struct Handle internal readonly struct Handle : IDisposable
{ {
private readonly IntPtr handle; private readonly IntPtr handle;

View File

@ -34,12 +34,20 @@ namespace WinSW.Native
int processInformationLength, int processInformationLength,
IntPtr returnLength = default); IntPtr returnLength = default);
[DllImport(Libraries.Kernel32)]
internal static extern Handle OpenProcess(ProcessAccess desiredAccess, bool inheritHandle, int processId);
[DllImport(Libraries.Advapi32, SetLastError = true)] [DllImport(Libraries.Advapi32, SetLastError = true)]
internal static extern bool OpenProcessToken( internal static extern bool OpenProcessToken(
IntPtr processHandle, IntPtr processHandle,
TokenAccessLevels desiredAccess, TokenAccessLevels desiredAccess,
out Handle tokenHandle); out Handle tokenHandle);
internal enum ProcessAccess : uint
{
QueryInformation = 0x0400,
}
internal enum PROCESSINFOCLASS internal enum PROCESSINFOCLASS
{ {
ProcessBasicInformation = 0, ProcessBasicInformation = 0,

View File

@ -20,9 +20,10 @@ namespace WinSW.Util
foreach (var child in GetChildren(process)) foreach (var child in GetChildren(process))
{ {
using (child) using (child.Process)
using (child.Handle)
{ {
StopTree(child, millisecondsTimeout); StopTree(child.Process, millisecondsTimeout);
} }
} }
} }
@ -31,30 +32,41 @@ namespace WinSW.Util
{ {
foreach (var child in GetChildren(process)) foreach (var child in GetChildren(process))
{ {
using (child) using (child.Process)
using (child.Handle)
{ {
StopTree(child, millisecondsTimeout); StopTree(child.Process, millisecondsTimeout);
} }
} }
} }
internal static unsafe List<Process> GetChildren(this Process process) // The handle is to keep a reference to the process.
internal static unsafe List<(Process Process, Handle Handle)> GetChildren(this Process process)
{ {
var startTime = process.StartTime; var startTime = process.StartTime;
int processId = process.Id; int processId = process.Id;
var children = new List<Process>(); var children = new List<(Process Process, Handle Handle)>();
foreach (var other in Process.GetProcesses()) foreach (var other in Process.GetProcesses())
{ {
var handle = OpenProcess(ProcessAccess.QueryInformation, false, other.Id);
if (handle == IntPtr.Zero)
{
goto Next;
}
try try
{ {
if (other.StartTime <= startTime) if (other.StartTime <= startTime)
{ {
goto Next; goto Next;
} }
}
var handle = other.Handle; catch (Exception e) when (e is InvalidOperationException || e is Win32Exception)
{
goto Next;
}
if (NtQueryInformationProcess( if (NtQueryInformationProcess(
handle, handle,
@ -68,17 +80,13 @@ namespace WinSW.Util
if ((int)information.InheritedFromUniqueProcessId == processId) if ((int)information.InheritedFromUniqueProcessId == processId)
{ {
Log.Debug($"Found child process '{other.Format()}'."); Log.Debug($"Found child process '{other.Format()}'.");
children.Add(other); children.Add((other, handle));
continue; continue;
} }
Next: Next:
other.Dispose(); other.Dispose();
} handle.Dispose();
catch (Exception e) when (e is InvalidOperationException || e is Win32Exception)
{
other.Dispose();
}
} }
return children; return children;
@ -94,7 +102,7 @@ namespace WinSW.Util
return null; return null;
} }
if (!(SendCtrlC(process) is bool sent)) if (SendCtrlC(process) is not bool sent)
{ {
return null; return null;
} }
@ -143,7 +151,7 @@ namespace WinSW.Util
goto Exited; goto Exited;
} }
if (!(SendCtrlC(process) is bool sent)) if (SendCtrlC(process) is not bool sent)
{ {
goto Exited; goto Exited;
} }

View File

@ -880,8 +880,12 @@ namespace WinSW
int count = children.Count; int count = children.Count;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
using var child = children[i]; var child = children[i];
Draw(child, indentation, i == count - 1); using (child.Process)
using (child.Handle)
{
Draw(child.Process, indentation, i == count - 1);
}
} }
} }
} }