Reputation:
Since StandardOutput isn't reactive I need a way to observe it. I know Process class exposes an event for receiving notifications when output has been written so I used this extension method to get an IObservable for the standard output
public static class ProcessExtensions
{
public static IObservable<string> StandardOutputObservable(this Process process)
{
process.EnableRaisingEvents = true;
process.StartInfo.RedirectStandardOutput = true;
var received = Observable.FromEventPattern<DataReceivedEventHandler,DataReceivedEventArgs>(
handler => handler.Invoke,
h => process.OutputDataReceived += h,
h => process.OutputDataReceived -= h)
.TakeUntil(Observable.FromEventPattern(
h => process.Exited += h,
h => process.Exited -= h))
.Select(e => e.EventArgs.Data);
process.BeginOutputReadLine();
return received;
/* Or if cancellation is important to you...
return Observable.Create<string>(observer =>
{
var cancel = Disposable.Create(process.CancelOutputRead);
return new CompositeDisposable(
cancel,
received.Subscribe(observer));
});
*/
}
}
as found here. But when I start the process
public sealed class ProgramHelper
{
private readonly Process _program = new Process();
public IObservable<string> ObservableOutput { get; private set; }
public ProgramHelper(string programPath, string programArgs)
{
_program.StartInfo.FileName = programPath;
_program.StartInfo.Arguments = programArgs;
}
public void StartProgram()
{
ConfigService.SaveConfig(
new Config(
new Uri(@"http://some.url.com")));
_program.Start();
ObservableOutput = _program.StandardOutputObservable();
}
}
...
[TestFixture]
public class When_program_starts
{
private ProgramHelper _program;
[Test]
public void It_should_not_complain()
{
//W
Action act = () => _program.StartProgram();
//T
act.ShouldNotThrow<Exception>();
}
}
I get this error:
"StandardOut has not been redirected or the process hasn't started yet."
Thank you for your time.
EDIT: edited the ProgramHelper to
public ProgramHelper(string programPath, string programArgs)
{
_program.StartInfo.FileName = programPath;
_program.StartInfo.Arguments = programArgs;
_program.EnableRaisingEvents = true;
_program.StartInfo.UseShellExecute = false;
_program.StartInfo.RedirectStandardOutput = true;
}
but now it throws "Access is denied exception".
It seems I don't have permission to start the process programmatically; if I start the exe from console it works just fine.
Upvotes: 3
Views: 794
Reputation: 12443
You are mutating the Process.StartInfo property after the process has been started.
From the Process.StartInfo MSDN documentation:
You can change the parameters specified in the StartInfo property up to the time that you call the Start method on the process. After you start the process, changing the StartInfo values does not affect or restart the associated process.
Upvotes: 3