@@ -35,6 +35,11 @@ public static class Command
3535 /// returns <see langword="true"/> when it has handled the exit code and default exit code handling should be suppressed, and
3636 /// returns <see langword="false"/> otherwise.
3737 /// </param>
38+ /// <param name="cancellationIgnoresProcessTree">
39+ /// Whether to ignore the process tree when cancelling the command.
40+ /// If set to <c>true</c>, when the command is cancelled, any child processes created by the command
41+ /// are left running after the command is cancelled.
42+ /// </param>
3843 /// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the command to exit.</param>
3944 /// <exception cref="ExitCodeException">The command exited with non-zero exit code.</exception>
4045 /// <remarks>
@@ -50,6 +55,7 @@ public static void Run(
5055 Action < IDictionary < string , string ? > > ? configureEnvironment = null ,
5156 bool createNoWindow = false ,
5257 Func < int , bool > ? handleExitCode = null ,
58+ bool cancellationIgnoresProcessTree = false ,
5359 CancellationToken cancellationToken = default ) =>
5460 ProcessStartInfo
5561 . Create (
@@ -60,7 +66,7 @@ public static void Run(
6066 false ,
6167 configureEnvironment ?? defaultAction ,
6268 createNoWindow )
63- . Run ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationToken ) ;
69+ . Run ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationIgnoresProcessTree , cancellationToken ) ;
6470
6571 /// <summary>
6672 /// Runs a command without redirecting standard output (stdout) and standard error (stderr) and without writing to standard input (stdin).
@@ -81,6 +87,11 @@ public static void Run(
8187 /// returns <see langword="true"/> when it has handled the exit code and default exit code handling should be suppressed, and
8288 /// returns <see langword="false"/> otherwise.
8389 /// </param>
90+ /// <param name="cancellationIgnoresProcessTree">
91+ /// Whether to ignore the process tree when cancelling the command.
92+ /// If set to <c>true</c>, when the command is cancelled, any child processes created by the command
93+ /// are left running after the command is cancelled.
94+ /// </param>
8495 /// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the command to exit.</param>
8596 /// <exception cref="ExitCodeException">The command exited with non-zero exit code.</exception>
8697 public static void Run (
@@ -92,6 +103,7 @@ public static void Run(
92103 Action < IDictionary < string , string ? > > ? configureEnvironment = null ,
93104 bool createNoWindow = false ,
94105 Func < int , bool > ? handleExitCode = null ,
106+ bool cancellationIgnoresProcessTree = false ,
95107 CancellationToken cancellationToken = default ) =>
96108 ProcessStartInfo
97109 . Create (
@@ -102,19 +114,20 @@ public static void Run(
102114 false ,
103115 configureEnvironment ?? defaultAction ,
104116 createNoWindow )
105- . Run ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationToken ) ;
117+ . Run ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationIgnoresProcessTree , cancellationToken ) ;
106118
107119 private static void Run (
108120 this System . Diagnostics . ProcessStartInfo startInfo ,
109121 bool noEcho ,
110122 string echoPrefix ,
111123 Func < int , bool > ? handleExitCode ,
124+ bool cancellationIgnoresProcessTree ,
112125 CancellationToken cancellationToken )
113126 {
114127 using var process = new Process ( ) ;
115128 process . StartInfo = startInfo ;
116129
117- process . Run ( noEcho , echoPrefix , cancellationToken ) ;
130+ process . Run ( noEcho , echoPrefix , cancellationIgnoresProcessTree , cancellationToken ) ;
118131
119132 if ( ! ( handleExitCode ? . Invoke ( process . ExitCode ) ?? false ) && process . ExitCode != 0 )
120133 {
@@ -138,6 +151,11 @@ private static void Run(
138151 /// returns <see langword="true"/> when it has handled the exit code and default exit code handling should be suppressed, and
139152 /// returns <see langword="false"/> otherwise.
140153 /// </param>
154+ /// <param name="cancellationIgnoresProcessTree">
155+ /// Whether to ignore the process tree when cancelling the command.
156+ /// If set to <c>true</c>, when the command is cancelled, any child processes created by the command
157+ /// are left running after the command is cancelled.
158+ /// </param>
141159 /// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the command to exit.</param>
142160 /// <returns>A <see cref="Task"/> that represents the asynchronous running of the command.</returns>
143161 /// <exception cref="ExitCodeReadException">The command exited with non-zero exit code.</exception>
@@ -154,6 +172,7 @@ public static async Task RunAsync(
154172 Action < IDictionary < string , string ? > > ? configureEnvironment = null ,
155173 bool createNoWindow = false ,
156174 Func < int , bool > ? handleExitCode = null ,
175+ bool cancellationIgnoresProcessTree = false ,
157176 CancellationToken cancellationToken = default ) =>
158177 await ProcessStartInfo
159178 . Create (
@@ -164,7 +183,7 @@ await ProcessStartInfo
164183 false ,
165184 configureEnvironment ?? defaultAction ,
166185 createNoWindow )
167- . RunAsync ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationToken )
186+ . RunAsync ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationIgnoresProcessTree , cancellationToken )
168187 . ConfigureAwait ( false ) ;
169188
170189 /// <summary>
@@ -186,6 +205,11 @@ await ProcessStartInfo
186205 /// returns <see langword="true"/> when it has handled the exit code and default exit code handling should be suppressed, and
187206 /// returns <see langword="false"/> otherwise.
188207 /// </param>
208+ /// <param name="cancellationIgnoresProcessTree">
209+ /// Whether to ignore the process tree when cancelling the command.
210+ /// If set to <c>true</c>, when the command is cancelled, any child processes created by the command
211+ /// are left running after the command is cancelled.
212+ /// </param>
189213 /// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the command to exit.</param>
190214 /// <returns>A <see cref="Task"/> that represents the asynchronous running of the command.</returns>
191215 /// <exception cref="ExitCodeReadException">The command exited with non-zero exit code.</exception>
@@ -198,6 +222,7 @@ public static async Task RunAsync(
198222 Action < IDictionary < string , string ? > > ? configureEnvironment = null ,
199223 bool createNoWindow = false ,
200224 Func < int , bool > ? handleExitCode = null ,
225+ bool cancellationIgnoresProcessTree = false ,
201226 CancellationToken cancellationToken = default ) =>
202227 await ProcessStartInfo
203228 . Create (
@@ -208,20 +233,21 @@ await ProcessStartInfo
208233 false ,
209234 configureEnvironment ?? defaultAction ,
210235 createNoWindow )
211- . RunAsync ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationToken )
236+ . RunAsync ( noEcho , echoPrefix ?? defaultEchoPrefix , handleExitCode , cancellationIgnoresProcessTree , cancellationToken )
212237 . ConfigureAwait ( false ) ;
213238
214239 private static async Task RunAsync (
215240 this System . Diagnostics . ProcessStartInfo startInfo ,
216241 bool noEcho ,
217242 string echoPrefix ,
218243 Func < int , bool > ? handleExitCode ,
244+ bool cancellationIgnoresProcessTree ,
219245 CancellationToken cancellationToken )
220246 {
221247 using var process = new Process ( ) ;
222248 process . StartInfo = startInfo ;
223249
224- await process . RunAsync ( noEcho , echoPrefix , cancellationToken ) . ConfigureAwait ( false ) ;
250+ await process . RunAsync ( noEcho , echoPrefix , cancellationIgnoresProcessTree , cancellationToken ) . ConfigureAwait ( false ) ;
225251
226252 if ( ! ( handleExitCode ? . Invoke ( process . ExitCode ) ?? false ) && process . ExitCode != 0 )
227253 {
@@ -243,6 +269,11 @@ private static async Task RunAsync(
243269 /// returns <see langword="false"/> otherwise.
244270 /// </param>
245271 /// <param name="standardInput">The contents of standard input (stdin).</param>
272+ /// <param name="cancellationIgnoresProcessTree">
273+ /// Whether to ignore the process tree when cancelling the command.
274+ /// If set to <c>true</c>, when the command is cancelled, any child processes created by the command
275+ /// are left running after the command is cancelled.
276+ /// </param>
246277 /// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the command to exit.</param>
247278 /// <returns>
248279 /// A <see cref="Task{TResult}"/> representing the asynchronous running of the command and reading of standard output (stdout) and standard error (stderr).
@@ -259,6 +290,7 @@ private static async Task RunAsync(
259290 Encoding ? encoding = null ,
260291 Func < int , bool > ? handleExitCode = null ,
261292 string ? standardInput = null ,
293+ bool cancellationIgnoresProcessTree = false ,
262294 CancellationToken cancellationToken = default ) =>
263295 await ProcessStartInfo
264296 . Create (
@@ -273,6 +305,7 @@ await ProcessStartInfo
273305 . ReadAsync (
274306 handleExitCode ,
275307 standardInput ,
308+ cancellationIgnoresProcessTree ,
276309 cancellationToken )
277310 . ConfigureAwait ( false ) ;
278311
@@ -293,6 +326,11 @@ await ProcessStartInfo
293326 /// returns <see langword="false"/> otherwise.
294327 /// </param>
295328 /// <param name="standardInput">The contents of standard input (stdin).</param>
329+ /// <param name="cancellationIgnoresProcessTree">
330+ /// Whether to ignore the process tree when cancelling the command.
331+ /// If set to <c>true</c>, when the command is cancelled, any child processes created by the command
332+ /// are left running after the command is cancelled.
333+ /// </param>
296334 /// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the command to exit.</param>
297335 /// <returns>
298336 /// A <see cref="Task{TResult}"/> representing the asynchronous running of the command and reading of standard output (stdout) and standard error (stderr).
@@ -309,6 +347,7 @@ await ProcessStartInfo
309347 Encoding ? encoding = null ,
310348 Func < int , bool > ? handleExitCode = null ,
311349 string ? standardInput = null ,
350+ bool cancellationIgnoresProcessTree = false ,
312351 CancellationToken cancellationToken = default ) =>
313352 await ProcessStartInfo
314353 . Create (
@@ -323,19 +362,21 @@ await ProcessStartInfo
323362 . ReadAsync (
324363 handleExitCode ,
325364 standardInput ,
365+ cancellationIgnoresProcessTree ,
326366 cancellationToken )
327367 . ConfigureAwait ( false ) ;
328368
329369 private static async Task < ( string StandardOutput , string StandardError ) > ReadAsync (
330370 this System . Diagnostics . ProcessStartInfo startInfo ,
331371 Func < int , bool > ? handleExitCode ,
332372 string ? standardInput ,
373+ bool cancellationIgnoresProcessTree ,
333374 CancellationToken cancellationToken )
334375 {
335376 using var process = new Process ( ) ;
336377 process . StartInfo = startInfo ;
337378
338- var runProcess = process . RunAsync ( true , "" , cancellationToken ) ;
379+ var runProcess = process . RunAsync ( true , "" , cancellationIgnoresProcessTree , cancellationToken ) ;
339380
340381 Task < string > readOutput ;
341382 Task < string > readError ;
0 commit comments