Browse Source

Improve ProcessExtensions

NextTurn 5 years ago
parent
commit
d771e474dc

+ 1 - 1
src/WinSW.Core/Native/Handle.cs

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

+ 8 - 0
src/WinSW.Core/Native/ProcessApis.cs

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

+ 38 - 30
src/WinSW.Core/Util/ProcessExtensions.cs

@@ -20,9 +20,10 @@ namespace WinSW.Util
 
             foreach (var child in GetChildren(process))
             {
-                using (child)
+                using (child.Process)
+                using (child.Handle)
                 {
-                    StopTree(child, millisecondsTimeout);
+                    StopTree(child.Process, millisecondsTimeout);
                 }
             }
         }
@@ -31,54 +32,61 @@ namespace WinSW.Util
         {
             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;
             int processId = process.Id;
 
-            var children = new List<Process>();
+            var children = new List<(Process Process, Handle Handle)>();
 
             foreach (var other in Process.GetProcesses())
             {
+                var handle = OpenProcess(ProcessAccess.QueryInformation, false, other.Id);
+                if (handle == IntPtr.Zero)
+                {
+                    goto Next;
+                }
+
                 try
                 {
                     if (other.StartTime <= startTime)
                     {
                         goto Next;
                     }
-
-                    var handle = other.Handle;
-
-                    if (NtQueryInformationProcess(
-                        handle,
-                        PROCESSINFOCLASS.ProcessBasicInformation,
-                        out var information,
-                        sizeof(PROCESS_BASIC_INFORMATION)) != 0)
-                    {
-                        goto Next;
-                    }
-
-                    if ((int)information.InheritedFromUniqueProcessId == processId)
-                    {
-                        Log.Debug($"Found child process '{other.Format()}'.");
-                        children.Add(other);
-                        continue;
-                    }
-
-                Next:
-                    other.Dispose();
                 }
                 catch (Exception e) when (e is InvalidOperationException || e is Win32Exception)
                 {
-                    other.Dispose();
+                    goto Next;
+                }
+
+                if (NtQueryInformationProcess(
+                    handle,
+                    PROCESSINFOCLASS.ProcessBasicInformation,
+                    out var information,
+                    sizeof(PROCESS_BASIC_INFORMATION)) != 0)
+                {
+                    goto Next;
                 }
+
+                if ((int)information.InheritedFromUniqueProcessId == processId)
+                {
+                    Log.Debug($"Found child process '{other.Format()}'.");
+                    children.Add((other, handle));
+                    continue;
+                }
+
+            Next:
+                other.Dispose();
+                handle.Dispose();
             }
 
             return children;
@@ -94,7 +102,7 @@ namespace WinSW.Util
                 return null;
             }
 
-            if (!(SendCtrlC(process) is bool sent))
+            if (SendCtrlC(process) is not bool sent)
             {
                 return null;
             }
@@ -143,7 +151,7 @@ namespace WinSW.Util
                 goto Exited;
             }
 
-            if (!(SendCtrlC(process) is bool sent))
+            if (SendCtrlC(process) is not bool sent)
             {
                 goto Exited;
             }

+ 6 - 2
src/WinSW/Program.cs

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