3

StandardOutputはリアクティブではないので、それを観察する方法が必要です。Processクラスは、出力が書き込まれたときに通知を受信するためのイベントを公開することを知っているので、この拡張メソッドを使用して、標準出力のIObservableを取得しました

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));
            });
         */
    }
}

ここにあるように。しかし、私がプロセスを開始すると

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>();
    }
}

このエラーが発生します:

「StandardOutがリダイレクトされていないか、プロセスがまだ開始されていません。」

お時間をいただきありがとうございます。

編集:ProgramHelperを編集して

    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;
    }

しかし今は「アクセスは例外を拒否されました」をスローします。

プログラムでプロセスを開始する権限がないようです。コンソールからexeを起動すると、問題なく動作します。

4

1 に答える 1

3

プロセスが開始された後、Process.StartInfoプロパティを変更しています。

Process.StartInfo MSDNドキュメントから:

プロセスでStartメソッドを呼び出すまで、StartInfoプロパティで指定されたパラメーターを変更できます。プロセスを開始した後、StartInfo値を変更しても、関連するプロセスに影響を与えたり、再起動したりすることはありません。

于 2012-08-20T15:27:45.327 に答える