@@ -15,24 +15,24 @@ internal sealed class ProcessRunner
1515 {
1616 private readonly IProcess _process ;
1717 private readonly TimeSpan _timeout ;
18- private readonly TaskCompletionSource < string > _tcs ;
18+ private readonly TaskCompletionSource < bool > _processExitedComplectionSource ;
1919 private readonly CancellationToken _cancellationToken ;
2020 private readonly CancellationTokenSource _timeoutCts ;
2121 private CancellationTokenRegistration _ctRegistration ;
2222 private readonly StringBuilder _stdOutBuilder ;
2323 private readonly StringBuilder _stdErrBuilder ;
24- private readonly TaskCompletionSource < bool > _stdOutCompletionSource ;
25- private readonly TaskCompletionSource < bool > _stdErrCompletionSource ;
24+ private readonly TaskCompletionSource < string > _stdOutCompletionSource ;
25+ private readonly TaskCompletionSource < string > _stdErrCompletionSource ;
2626
2727 public ProcessRunner ( IProcess process , TimeSpan timeout , CancellationToken cancellationToken )
2828 {
2929 _process = process ;
3030 _timeout = timeout ;
31- _tcs = new TaskCompletionSource < string > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
31+ _processExitedComplectionSource = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
3232 _stdOutBuilder = new StringBuilder ( ) ;
3333 _stdErrBuilder = new StringBuilder ( ) ;
34- _stdOutCompletionSource = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
35- _stdErrCompletionSource = new TaskCompletionSource < bool > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
34+ _stdOutCompletionSource = new TaskCompletionSource < string > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
35+ _stdErrCompletionSource = new TaskCompletionSource < string > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
3636
3737 if ( timeout . TotalMilliseconds >= 0 )
3838 {
@@ -49,25 +49,40 @@ public async Task<string> RunAsync()
4949 {
5050 StartProcess ( ) ;
5151
52- await _stdOutCompletionSource . Task . ConfigureAwait ( false ) ;
53- await _stdErrCompletionSource . Task . ConfigureAwait ( false ) ;
54-
55- return await _tcs . Task . ConfigureAwait ( false ) ;
52+ try
53+ {
54+ await _processExitedComplectionSource . Task . ConfigureAwait ( false ) ;
55+ var output = await _stdOutCompletionSource . Task . ConfigureAwait ( false ) ;
56+ await _stdErrCompletionSource . Task . ConfigureAwait ( false ) ;
57+ return output ;
58+ }
59+ finally
60+ {
61+ DisposeProcess ( ) ;
62+ }
5663 }
5764
5865 public string Run ( )
5966 {
6067 StartProcess ( ) ;
6168#pragma warning disable AZC0102 // Do not use GetAwaiter().GetResult().
62- _stdOutCompletionSource . Task . GetAwaiter ( ) . GetResult ( ) ;
63- _stdErrCompletionSource . Task . GetAwaiter ( ) . GetResult ( ) ;
64- return _tcs . Task . GetAwaiter ( ) . GetResult ( ) ;
69+ try
70+ {
71+ _processExitedComplectionSource . Task . GetAwaiter ( ) . GetResult ( ) ;
72+ var output = _stdOutCompletionSource . Task . GetAwaiter ( ) . GetResult ( ) ;
73+ _stdErrCompletionSource . Task . GetAwaiter ( ) . GetResult ( ) ;
74+ return output ;
75+ }
76+ finally
77+ {
78+ DisposeProcess ( ) ;
79+ }
6580#pragma warning restore AZC0102 // Do not use GetAwaiter().GetResult().
6681 }
6782
6883 private void StartProcess ( )
6984 {
70- if ( TrySetCanceled ( ) || _tcs . Task . IsCompleted )
85+ if ( TrySetCanceled ( ) || _processExitedComplectionSource . Task . IsCompleted )
7186 {
7287 return ;
7388 }
@@ -91,18 +106,26 @@ private void HandleExit()
91106 {
92107 if ( _process . ExitCode == 0 )
93108 {
94- TrySetResult ( _stdOutBuilder . ToString ( ) ) ;
109+ _processExitedComplectionSource . TrySetResult ( true ) ;
95110 }
96111 else
97112 {
98- TrySetException ( new InvalidOperationException ( _stdErrBuilder . ToString ( ) ) ) ;
113+ _processExitedComplectionSource . TrySetResult ( false ) ;
99114 }
100115 }
101116 private void HandleStdErrDataReceived ( object sender , DataReceivedEventArgsWrapper e )
102117 {
103118 if ( e . Data is null )
104119 {
105- _stdErrCompletionSource . TrySetResult ( true ) ;
120+ var result = _stdErrBuilder . ToString ( ) ;
121+ if ( result . Length == 0 )
122+ {
123+ _stdErrCompletionSource . TrySetResult ( result ) ;
124+ }
125+ else
126+ {
127+ _stdErrCompletionSource . TrySetException ( new InvalidOperationException ( result ) ) ;
128+ }
106129 }
107130 else
108131 {
@@ -114,7 +137,7 @@ private void HandleStdOutDataReceived(object sender, DataReceivedEventArgsWrappe
114137 {
115138 if ( e . Data is null )
116139 {
117- _stdOutCompletionSource . TrySetResult ( true ) ;
140+ _stdOutCompletionSource . TrySetResult ( _stdOutBuilder . ToString ( ) ) ;
118141 }
119142 else
120143 {
@@ -124,7 +147,7 @@ private void HandleStdOutDataReceived(object sender, DataReceivedEventArgsWrappe
124147
125148 private void HandleCancel ( )
126149 {
127- if ( _tcs . Task . IsCompleted )
150+ if ( _processExitedComplectionSource . Task . IsCompleted )
128151 {
129152 return ;
130153 }
@@ -137,41 +160,27 @@ private void HandleCancel()
137160 }
138161 catch ( Exception ex )
139162 {
140- TrySetException ( ex ) ;
163+ _processExitedComplectionSource . TrySetException ( ex ) ;
141164 return ;
142165 }
143166 }
144167
145168 TrySetCanceled ( ) ;
146169 }
147170
148- private void TrySetResult ( string result )
149- {
150- DisposeProcess ( ) ;
151- _tcs . TrySetResult ( result ) ;
152- }
153-
154171 private bool TrySetCanceled ( )
155172 {
156173 if ( _cancellationToken . IsCancellationRequested )
157174 {
158175 DisposeProcess ( ) ;
159176 _stdOutCompletionSource . TrySetCanceled ( _cancellationToken ) ;
160177 _stdErrCompletionSource . TrySetCanceled ( _cancellationToken ) ;
161- _tcs . TrySetCanceled ( _cancellationToken ) ;
178+ _processExitedComplectionSource . TrySetCanceled ( _cancellationToken ) ;
162179 }
163180
164181 return _cancellationToken . IsCancellationRequested ;
165182 }
166183
167- private void TrySetException ( Exception exception )
168- {
169- DisposeProcess ( ) ;
170- _stdOutCompletionSource . TrySetResult ( false ) ;
171- _stdErrCompletionSource . TrySetResult ( false ) ;
172- _tcs . TrySetException ( exception ) ;
173- }
174-
175184 private void DisposeProcess ( )
176185 {
177186 _process . OutputDataReceived -= HandleStdOutDataReceived ;
0 commit comments