Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit f90aa66

Browse files
madelsondanmoseley
authored andcommitted
Process info standard input encoding (#25990)
* Add StandardInputEncoding to ProcessStartInfo * Add test coverage for ProcessStartInfo.StandardInputEncoding * Add unix support for ProcessStartInfo.StandardInputEncoding * Clean up StandardInputEncoding implementation * Incorporate feedback from #25990 for ProcessStartInfo.StandardInputEncoding feature. * ProcessStartInfo.StandardInputEncoding: skip two unsupported tests on UAP
1 parent 3d2ca8c commit f90aa66

13 files changed

+145
-4
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ public ProcessStartInfo(string fileName, string arguments) { }
170170
public bool RedirectStandardInput { get { throw null; } set { } }
171171
public bool RedirectStandardOutput { get { throw null; } set { } }
172172
public System.Text.Encoding StandardErrorEncoding { get { throw null; } set { } }
173+
public System.Text.Encoding StandardInputEncoding { get { throw null; } set { } }
173174
public System.Text.Encoding StandardOutputEncoding { get { throw null; } set { } }
174175
public string UserName { get { throw null; } set { } }
175176
public bool UseShellExecute { get { throw null; } set { } }

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,7 @@
309309
<data name="GetProcessInfoNotSupported" xml:space="preserve">
310310
<value>Retrieving information about local processes is not supported on this platform.</value>
311311
</data>
312+
<data name="StandardInputEncodingNotAllowed" xml:space="preserve">
313+
<value>StandardInputEncoding is only supported when standard input is redirected.</value>
314+
</data>
312315
</root>

src/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ private bool StartCore(ProcessStartInfo startInfo)
317317
{
318318
Debug.Assert(stdinFd >= 0);
319319
_standardInput = new StreamWriter(OpenStream(stdinFd, FileAccess.Write),
320-
s_utf8NoBom, StreamBufferSize) { AutoFlush = true };
320+
startInfo.StandardInputEncoding ?? s_utf8NoBom, StreamBufferSize) { AutoFlush = true };
321321
}
322322
if (startInfo.RedirectStandardOutput)
323323
{

src/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ private unsafe bool StartWithShellExecuteEx(ProcessStartInfo startInfo)
3434
if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
3535
throw new InvalidOperationException(SR.CantRedirectStreams);
3636

37+
if (startInfo.StandardInputEncoding != null)
38+
throw new InvalidOperationException(SR.StandardInputEncodingNotAllowed);
39+
3740
if (startInfo.StandardErrorEncoding != null)
3841
throw new InvalidOperationException(SR.StandardErrorEncodingNotAllowed);
3942

src/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ private bool StartWithCreateProcess(ProcessStartInfo startInfo)
633633

634634
if (startInfo.RedirectStandardInput)
635635
{
636-
Encoding enc = GetEncoding((int)Interop.Kernel32.GetConsoleCP());
636+
Encoding enc = startInfo.StandardInputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleCP());
637637
_standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), enc, 4096);
638638
_standardInput.AutoFlush = true;
639639
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,10 @@ public bool Start()
11561156
{
11571157
throw new InvalidOperationException(SR.FileNameMissing);
11581158
}
1159+
if (startInfo.StandardInputEncoding != null && !startInfo.RedirectStandardInput)
1160+
{
1161+
throw new InvalidOperationException(SR.StandardInputEncodingNotAllowed);
1162+
}
11591163
if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput)
11601164
{
11611165
throw new InvalidOperationException(SR.StandardOutputEncodingNotAllowed);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ public IDictionary<string, string> Environment
9595
public bool RedirectStandardOutput { get; set; }
9696
public bool RedirectStandardError { get; set; }
9797

98-
public Encoding StandardErrorEncoding { get; set; }
98+
public Encoding StandardInputEncoding { get; set; }
9999

100+
public Encoding StandardErrorEncoding { get; set; }
101+
100102
public Encoding StandardOutputEncoding { get; set; }
101103

102104
/// <devdoc>

src/System.Diagnostics.Process/tests/Configurations.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
netstandard-Unix;
77
uap-Windows_NT;
88
uapaot-Windows_NT;
9+
netcoreapp-Windows_NT;
10+
netcoreapp-Unix;
911
</BuildConfigurations>
1012
</PropertyGroup>
1113
</Project>

src/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace System.Diagnostics.Tests
1212
{
13-
public class ProcessStreamReadTests : ProcessTestBase
13+
public partial class ProcessStreamReadTests : ProcessTestBase
1414
{
1515
[Fact]
1616
public void TestSyncErrorStream()
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using Xunit;
11+
12+
namespace System.Diagnostics.Tests
13+
{
14+
public partial class ProcessStreamReadTests : ProcessTestBase
15+
{
16+
[Fact]
17+
[SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "RemotelyInvokable.ReadLineWithCustomEncodingWriteLineWithUtf8 is not supported on uap")]
18+
public void TestCustomStandardInputEncoding()
19+
{
20+
var process = CreateProcessPortable(RemotelyInvokable.ReadLineWithCustomEncodingWriteLineWithUtf8, Encoding.UTF32.WebName);
21+
process.StartInfo.RedirectStandardInput = true;
22+
process.StartInfo.StandardInputEncoding = Encoding.UTF32;
23+
process.StartInfo.RedirectStandardOutput = true;
24+
process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
25+
process.Start();
26+
27+
const string TestLine = "\U0001f627\U0001f62e\U0001f62f";
28+
process.StandardInput.WriteLine(TestLine);
29+
process.StandardInput.Close();
30+
31+
var output = process.StandardOutput.ReadLine();
32+
Assert.Equal(TestLine, output);
33+
34+
Assert.True(process.WaitForExit(WaitInMS));
35+
Assert.Equal(RemotelyInvokable.SuccessExitCode, process.ExitCode);
36+
}
37+
38+
[Fact]
39+
[SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "RemotelyInvokable.ReadLineWithCustomEncodingWriteLineWithUtf8 is not supported on uap")]
40+
public void TestMismatchedStandardInputEncoding()
41+
{
42+
var process = CreateProcessPortable(RemotelyInvokable.ReadLineWithCustomEncodingWriteLineWithUtf8, Encoding.UTF32.WebName);
43+
process.StartInfo.RedirectStandardInput = true;
44+
// incorrect: the process will be writing in UTF-32
45+
process.StartInfo.StandardInputEncoding = Encoding.ASCII;
46+
process.StartInfo.RedirectStandardOutput = true;
47+
process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
48+
process.Start();
49+
50+
const string TestLine = "\U0001f627\U0001f62e\U0001f62f";
51+
process.StandardInput.WriteLine(TestLine);
52+
process.StandardInput.Close();
53+
54+
var output = process.StandardOutput.ReadLine();
55+
Assert.NotEqual(TestLine, output);
56+
57+
Assert.True(process.WaitForExit(WaitInMS));
58+
Assert.Equal(RemotelyInvokable.SuccessExitCode, process.ExitCode);
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)