Skip to content

Commit 7920b52

Browse files
Copilotadamsitnik
andcommitted
Rename StandardInput/Output/Error to StandardInputHandle/OutputHandle/ErrorHandle, fix docs, add handle validation
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/7c3e65ca-2e62-4821-b8d2-0bc9bde12049
1 parent 95247af commit 7920b52

File tree

5 files changed

+88
-66
lines changed

5 files changed

+88
-66
lines changed

src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ public ProcessStartInfo(string fileName, System.Collections.Generic.IEnumerable<
253253
public bool RedirectStandardInput { get { throw null; } set { } }
254254
public bool RedirectStandardOutput { get { throw null; } set { } }
255255
public System.Text.Encoding? StandardErrorEncoding { get { throw null; } set { } }
256-
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardError { get { throw null; } set { } }
257-
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardInput { get { throw null; } set { } }
258-
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardOutput { get { throw null; } set { } }
256+
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardErrorHandle { get { throw null; } set { } }
257+
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardInputHandle { get { throw null; } set { } }
258+
public Microsoft.Win32.SafeHandles.SafeFileHandle? StandardOutputHandle { get { throw null; } set { } }
259259
public bool LeaveHandlesOpen { get { throw null; } set { } }
260260
public System.Text.Encoding? StandardInputEncoding { get { throw null; } set { } }
261261
public System.Text.Encoding? StandardOutputEncoding { get { throw null; } set { } }

src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,11 @@
210210
<data name="CantRedirectStreams" xml:space="preserve">
211211
<value>The Process object must have the UseShellExecute property set to false in order to redirect IO streams.</value>
212212
</data>
213+
<data name="Arg_InvalidHandle" xml:space="preserve">
214+
<value>Invalid handle.</value>
215+
</data>
213216
<data name="CantSetHandleAndRedirect" xml:space="preserve">
214-
<value>The StandardInput, StandardOutput, and StandardError handle properties cannot be used together with RedirectStandardInput, RedirectStandardOutput, and RedirectStandardError.</value>
217+
<value>The StandardInputHandle, StandardOutputHandle, and StandardErrorHandle properties cannot be used together with RedirectStandardInput, RedirectStandardOutput, and RedirectStandardError.</value>
215218
</data>
216219
<data name="DirectoryNotValidAsInput" xml:space="preserve">
217220
<value>The FileName property should not be a directory unless UseShellExecute is set.</value>

src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,26 +1280,30 @@ public bool Start()
12801280
}
12811281

12821282
bool anyRedirection = startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError;
1283-
bool anyHandle = startInfo.StandardInput is not null || startInfo.StandardOutput is not null || startInfo.StandardError is not null;
1283+
bool anyHandle = startInfo.StandardInputHandle is not null || startInfo.StandardOutputHandle is not null || startInfo.StandardErrorHandle is not null;
12841284
if (startInfo.UseShellExecute && (anyRedirection || anyHandle))
12851285
{
12861286
throw new InvalidOperationException(SR.CantRedirectStreams);
12871287
}
12881288

12891289
if (anyHandle)
12901290
{
1291-
if (startInfo.StandardInput is not null && startInfo.RedirectStandardInput)
1291+
if (startInfo.StandardInputHandle is not null && startInfo.RedirectStandardInput)
12921292
{
12931293
throw new InvalidOperationException(SR.CantSetHandleAndRedirect);
12941294
}
1295-
if (startInfo.StandardOutput is not null && startInfo.RedirectStandardOutput)
1295+
if (startInfo.StandardOutputHandle is not null && startInfo.RedirectStandardOutput)
12961296
{
12971297
throw new InvalidOperationException(SR.CantSetHandleAndRedirect);
12981298
}
1299-
if (startInfo.StandardError is not null && startInfo.RedirectStandardError)
1299+
if (startInfo.StandardErrorHandle is not null && startInfo.RedirectStandardError)
13001300
{
13011301
throw new InvalidOperationException(SR.CantSetHandleAndRedirect);
13021302
}
1303+
1304+
ValidateHandle(startInfo.StandardInputHandle, nameof(startInfo.StandardInputHandle));
1305+
ValidateHandle(startInfo.StandardOutputHandle, nameof(startInfo.StandardOutputHandle));
1306+
ValidateHandle(startInfo.StandardErrorHandle, nameof(startInfo.StandardErrorHandle));
13031307
}
13041308

13051309
//Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
@@ -1334,9 +1338,9 @@ public bool Start()
13341338

13351339
try
13361340
{
1337-
if (startInfo.StandardInput is not null)
1341+
if (startInfo.StandardInputHandle is not null)
13381342
{
1339-
childInputPipeHandle = startInfo.StandardInput;
1343+
childInputPipeHandle = startInfo.StandardInputHandle;
13401344
}
13411345
else if (startInfo.RedirectStandardInput)
13421346
{
@@ -1347,9 +1351,9 @@ public bool Start()
13471351
childInputPipeHandle = Console.OpenStandardInputHandle();
13481352
}
13491353

1350-
if (startInfo.StandardOutput is not null)
1354+
if (startInfo.StandardOutputHandle is not null)
13511355
{
1352-
childOutputPipeHandle = startInfo.StandardOutput;
1356+
childOutputPipeHandle = startInfo.StandardOutputHandle;
13531357
}
13541358
else if (startInfo.RedirectStandardOutput)
13551359
{
@@ -1360,9 +1364,9 @@ public bool Start()
13601364
childOutputPipeHandle = Console.OpenStandardOutputHandle();
13611365
}
13621366

1363-
if (startInfo.StandardError is not null)
1367+
if (startInfo.StandardErrorHandle is not null)
13641368
{
1365-
childErrorPipeHandle = startInfo.StandardError;
1369+
childErrorPipeHandle = startInfo.StandardErrorHandle;
13661370
}
13671371
else if (startInfo.RedirectStandardError)
13681372
{
@@ -1401,17 +1405,17 @@ public bool Start()
14011405
// process will not receive EOF when the child process closes its handles.
14021406
// It's OK to do it for handles returned by Console.OpenStandard*Handle APIs,
14031407
// because these handles are not owned and won't be closed by Dispose.
1404-
// When LeaveHandlesOpen is true, we must NOT close handles that were passed in
1405-
// by the caller via StartInfo.StandardInput/Output/Error.
1406-
if (startInfo.StandardInput is null || !startInfo.LeaveHandlesOpen)
1408+
// When LeaveHandlesOpen is true, we must NOT dispose handles that were passed in
1409+
// by the caller via StartInfo.StandardInputHandle/OutputHandle/ErrorHandle.
1410+
if (startInfo.StandardInputHandle is null || !startInfo.LeaveHandlesOpen)
14071411
{
14081412
childInputPipeHandle?.Dispose();
14091413
}
1410-
if (startInfo.StandardOutput is null || !startInfo.LeaveHandlesOpen)
1414+
if (startInfo.StandardOutputHandle is null || !startInfo.LeaveHandlesOpen)
14111415
{
14121416
childOutputPipeHandle?.Dispose();
14131417
}
1414-
if (startInfo.StandardError is null || !startInfo.LeaveHandlesOpen)
1418+
if (startInfo.StandardErrorHandle is null || !startInfo.LeaveHandlesOpen)
14151419
{
14161420
childErrorPipeHandle?.Dispose();
14171421
}
@@ -1439,6 +1443,18 @@ public bool Start()
14391443
return true;
14401444
}
14411445

1446+
private static void ValidateHandle(SafeFileHandle? handle, string paramName)
1447+
{
1448+
if (handle is not null)
1449+
{
1450+
ObjectDisposedException.ThrowIf(handle.IsClosed, paramName);
1451+
if (handle.IsInvalid)
1452+
{
1453+
throw new ArgumentException(SR.Arg_InvalidHandle, paramName);
1454+
}
1455+
}
1456+
}
1457+
14421458
/// <devdoc>
14431459
/// <para>
14441460
/// Starts a process resource by specifying the name of a

src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,15 @@ public string Arguments
124124
/// </summary>
125125
/// <remarks>
126126
/// <para>
127-
/// The handle does not need to be inheritable; the runtime will make it inheritable as needed.
127+
/// The handle does not need to be inheritable; the runtime will duplicate it as inheritable.
128128
/// Use <see cref="SafeFileHandle.CreateAnonymousPipe"/> to create a pair of connected pipe handles,
129129
/// <see cref="IO.File.OpenHandle"/> to open a file handle,
130-
/// <see cref="IO.File.OpenNullHandle"/> to discard input,
131-
/// or <see cref="Console.OpenStandardInputHandle"/> to inherit the parent's standard input.
130+
/// <see cref="IO.File.OpenNullHandle"/> to provide an empty input,
131+
/// or <see cref="Console.OpenStandardInputHandle"/> to inherit the parent's standard input
132+
/// (the default behavior when this property is <see langword="null"/>).
132133
/// </para>
133134
/// <para>
134-
/// By default, <see cref="Process.Start()"/> will close this handle after starting the child process.
135+
/// By default, <see cref="Process.Start()"/> will dispose this handle after starting the child process.
135136
/// Set <see cref="LeaveHandlesOpen"/> to <see langword="true"/> to keep the handle open.
136137
/// </para>
137138
/// <para>
@@ -140,22 +141,23 @@ public string Arguments
140141
/// </para>
141142
/// </remarks>
142143
/// <value>A <see cref="SafeFileHandle"/> to use as the standard input handle of the child process, or <see langword="null"/> to use the default behavior.</value>
143-
public SafeFileHandle? StandardInput { get; set; }
144+
public SafeFileHandle? StandardInputHandle { get; set; }
144145

145146
/// <summary>
146147
/// Gets or sets a <see cref="SafeFileHandle"/> that will be used as the standard output of the child process.
147148
/// When set, the handle is passed directly to the child process and <see cref="RedirectStandardOutput"/> must be <see langword="false"/>.
148149
/// </summary>
149150
/// <remarks>
150151
/// <para>
151-
/// The handle does not need to be inheritable; the runtime will make it inheritable as needed.
152+
/// The handle does not need to be inheritable; the runtime will duplicate it as inheritable.
152153
/// Use <see cref="SafeFileHandle.CreateAnonymousPipe"/> to create a pair of connected pipe handles,
153154
/// <see cref="IO.File.OpenHandle"/> to open a file handle,
154155
/// <see cref="IO.File.OpenNullHandle"/> to discard output,
155-
/// or <see cref="Console.OpenStandardOutputHandle"/> to inherit the parent's standard output.
156+
/// or <see cref="Console.OpenStandardOutputHandle"/> to inherit the parent's standard output
157+
/// (the default behavior when this property is <see langword="null"/>).
156158
/// </para>
157159
/// <para>
158-
/// By default, <see cref="Process.Start()"/> will close this handle after starting the child process.
160+
/// By default, <see cref="Process.Start()"/> will dispose this handle after starting the child process.
159161
/// Set <see cref="LeaveHandlesOpen"/> to <see langword="true"/> to keep the handle open.
160162
/// </para>
161163
/// <para>
@@ -164,22 +166,23 @@ public string Arguments
164166
/// </para>
165167
/// </remarks>
166168
/// <value>A <see cref="SafeFileHandle"/> to use as the standard output handle of the child process, or <see langword="null"/> to use the default behavior.</value>
167-
public SafeFileHandle? StandardOutput { get; set; }
169+
public SafeFileHandle? StandardOutputHandle { get; set; }
168170

169171
/// <summary>
170172
/// Gets or sets a <see cref="SafeFileHandle"/> that will be used as the standard error of the child process.
171173
/// When set, the handle is passed directly to the child process and <see cref="RedirectStandardError"/> must be <see langword="false"/>.
172174
/// </summary>
173175
/// <remarks>
174176
/// <para>
175-
/// The handle does not need to be inheritable; the runtime will make it inheritable as needed.
177+
/// The handle does not need to be inheritable; the runtime will duplicate it as inheritable.
176178
/// Use <see cref="SafeFileHandle.CreateAnonymousPipe"/> to create a pair of connected pipe handles,
177179
/// <see cref="IO.File.OpenHandle"/> to open a file handle,
178180
/// <see cref="IO.File.OpenNullHandle"/> to discard error output,
179-
/// or <see cref="Console.OpenStandardErrorHandle"/> to inherit the parent's standard error.
181+
/// or <see cref="Console.OpenStandardErrorHandle"/> to inherit the parent's standard error
182+
/// (the default behavior when this property is <see langword="null"/>).
180183
/// </para>
181184
/// <para>
182-
/// By default, <see cref="Process.Start()"/> will close this handle after starting the child process.
185+
/// By default, <see cref="Process.Start()"/> will dispose this handle after starting the child process.
183186
/// Set <see cref="LeaveHandlesOpen"/> to <see langword="true"/> to keep the handle open.
184187
/// </para>
185188
/// <para>
@@ -188,17 +191,17 @@ public string Arguments
188191
/// </para>
189192
/// </remarks>
190193
/// <value>A <see cref="SafeFileHandle"/> to use as the standard error handle of the child process, or <see langword="null"/> to use the default behavior.</value>
191-
public SafeFileHandle? StandardError { get; set; }
194+
public SafeFileHandle? StandardErrorHandle { get; set; }
192195

193196
/// <summary>
194-
/// Gets or sets a value indicating whether the <see cref="StandardInput"/>, <see cref="StandardOutput"/>,
195-
/// and <see cref="StandardError"/> handles should be left open after the process is started.
197+
/// Gets or sets a value indicating whether the <see cref="StandardInputHandle"/>, <see cref="StandardOutputHandle"/>,
198+
/// and <see cref="StandardErrorHandle"/> handles should be left open after the process is started.
196199
/// </summary>
197200
/// <remarks>
198-
/// When <see langword="false"/> (the default), the handles are closed by <see cref="Process.Start()"/>
199-
/// after starting the child process. When <see langword="true"/>, the caller is responsible for closing the handles.
201+
/// When <see langword="false"/> (the default), the handles are disposed by <see cref="Process.Start()"/>
202+
/// after starting the child process. When <see langword="true"/>, the caller is responsible for disposing the handles.
200203
/// </remarks>
201-
/// <value><see langword="true"/> to leave the handles open; <see langword="false"/> to close them after the process starts. The default is <see langword="false"/>.</value>
204+
/// <value><see langword="true"/> to leave the handles open; <see langword="false"/> to dispose them after the process starts. The default is <see langword="false"/>.</value>
202205
public bool LeaveHandlesOpen { get; set; }
203206

204207
public Encoding? StandardInputEncoding { get; set; }

0 commit comments

Comments
 (0)