mirror of https://github.com/winsw/winsw
Improve ProcessExtensions
parent
3c5d67e287
commit
d771e474dc
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,54 +32,61 @@ 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;
|
|
||||||
|
|
||||||
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)
|
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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue