Skip to content

Commit 52c58fe

Browse files
committed
Update Program.cs
1 parent 0624177 commit 52c58fe

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

src/DiffEngineWord/Program.cs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics;
12
using System.Runtime.InteropServices;
23

34
static partial class Program
@@ -35,6 +36,17 @@ static int Main(string[] args)
3536
return 1;
3637
}
3738

39+
// Create a job object that kills child processes when this process exits
40+
var job = CreateJobObject(IntPtr.Zero, null);
41+
var info = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
42+
{
43+
BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
44+
{
45+
LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
46+
}
47+
};
48+
SetInformationJobObject(job, JobObjectExtendedLimitInformation, ref info, (uint)Marshal.SizeOf(info));
49+
3850
Console.CancelKeyPress += OnCancelKeyPress;
3951
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
4052
SetConsoleCtrlHandler(_consoleCtrlHandler, true);
@@ -79,16 +91,19 @@ static int Main(string[] args)
7991

8092
word.Visible = true;
8193

82-
// Get process from Word's window handle
94+
// Get process from Word's window handle and assign to job
8395
var hwnd = (IntPtr)word.ActiveWindow.Hwnd;
8496
GetWindowThreadProcessId(hwnd, out var processId);
8597
using var process = Process.GetProcessById(processId);
98+
AssignProcessToJobObject(job, process.Handle);
99+
86100
process.WaitForExit();
87101

88102
// Release COM objects
89103
Marshal.ReleaseComObject(comparedDoc);
90104
Marshal.ReleaseComObject(word);
91105
_word = null;
106+
CloseHandle(job);
92107

93108
return 0;
94109
}
@@ -125,12 +140,66 @@ static void CloseWord()
125140
_word = null;
126141
}
127142

143+
const uint JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;
144+
const int JobObjectExtendedLimitInformation = 9;
145+
146+
[StructLayout(LayoutKind.Sequential)]
147+
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
148+
{
149+
public long PerProcessUserTimeLimit;
150+
public long PerJobUserTimeLimit;
151+
public uint LimitFlags;
152+
public nuint MinimumWorkingSetSize;
153+
public nuint MaximumWorkingSetSize;
154+
public uint ActiveProcessLimit;
155+
public nuint Affinity;
156+
public uint PriorityClass;
157+
public uint SchedulingClass;
158+
}
159+
160+
[StructLayout(LayoutKind.Sequential)]
161+
struct IO_COUNTERS
162+
{
163+
public ulong ReadOperationCount;
164+
public ulong WriteOperationCount;
165+
public ulong OtherOperationCount;
166+
public ulong ReadTransferCount;
167+
public ulong WriteTransferCount;
168+
public ulong OtherTransferCount;
169+
}
170+
171+
[StructLayout(LayoutKind.Sequential)]
172+
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
173+
{
174+
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
175+
public IO_COUNTERS IoInfo;
176+
public nuint ProcessMemoryLimit;
177+
public nuint JobMemoryLimit;
178+
public nuint PeakProcessMemoryUsed;
179+
public nuint PeakJobMemoryUsed;
180+
}
181+
128182
[LibraryImport("user32.dll")]
129183
internal static partial uint GetWindowThreadProcessId(IntPtr hWnd, out int processId);
130184

131185
[LibraryImport("kernel32.dll")]
132186
[return: MarshalAs(UnmanagedType.Bool)]
133187
private static partial bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handler, [MarshalAs(UnmanagedType.Bool)] bool add);
134188

189+
[LibraryImport("kernel32.dll", EntryPoint = "CreateJobObjectW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
190+
private static partial IntPtr CreateJobObject(IntPtr lpJobAttributes, string? lpName);
191+
192+
[LibraryImport("kernel32.dll", SetLastError = true)]
193+
[return: MarshalAs(UnmanagedType.Bool)]
194+
private static partial bool SetInformationJobObject(IntPtr hJob, int jobObjectInfoClass, ref JOBOBJECT_EXTENDED_LIMIT_INFORMATION lpJobObjectInfo, uint cbJobObjectInfoLength);
195+
196+
[LibraryImport("kernel32.dll", SetLastError = true)]
197+
[return: MarshalAs(UnmanagedType.Bool)]
198+
private static partial bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
199+
200+
[LibraryImport("kernel32.dll", SetLastError = true)]
201+
[return: MarshalAs(UnmanagedType.Bool)]
202+
private static partial bool CloseHandle(IntPtr hObject);
203+
135204
delegate bool ConsoleCtrlDelegate(int ctrlType);
136205
}

0 commit comments

Comments
 (0)