0

私は C# を学んでいて、単純な WinForms アプリケーションを作成しています。それは単純な OpenVPN クライアントを開始することです。

    void button_Connect_Click(object sender, EventArgs e)
    {
        var proc = new Process();
        proc.StartInfo.FileName = "CMD.exe";
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.WorkingDirectory = @"C:\Program Files (x86)\OpenVPN\bin";
        proc.StartInfo.Arguments = "/c openvpn.exe --config config.ovpn --auto-proxy";

        // set up output redirection
        proc.StartInfo.RedirectStandardOutput = true;
        proc.StartInfo.RedirectStandardError = true;
        // Input
        proc.StartInfo.RedirectStandardInput = true;

        // Other
        proc.EnableRaisingEvents = true;
        proc.StartInfo.CreateNoWindow = false;
        // see below for output handler
        proc.ErrorDataReceived += proc_DataReceived;
        proc.OutputDataReceived += proc_DataReceived;

        proc.Start();

        StreamWriter myStreamWriter = proc.StandardInput;
        proc.BeginErrorReadLine();
        proc.BeginOutputReadLine();

        proc.WaitForExit();
    }

    void proc_DataReceived(object sender, DataReceivedEventArgs e)
    {
        // output will be in string e.Data
        if (e.Data != null)
        {
            string Data = e.Data.ToString();
            if (Data.Contains("Enter Auth Username"))
            {
                myStreamWriter("myusername");
            }
            //MessageBox.Show(Data);
        }
    }

現在実行しているのは、CMD のすべての出力を私のプログラムに送信することです。このプログラムは、出力に応じてコマンドを実行します。

私の現在の問題は、ストリームに書き込む必要があることです。で使用myStreamWriterしますproc_DataReceivedが、同じコンテキストではないため機能しません。

次のエラーが表示されます: The name 'myStreamWriter' does not exist in the current context、これは明らかにそのスコープには存在しません。

どうすればこれを機能させることができますか? プロパティを取得/設定しますか? 私が言ったように、私はC#にまったく慣れていないので、助けていただければ幸いです。

4

3 に答える 3

2

フォームに次のフィールドを追加します。

public class Form1Whatevver: Form {
    private StreamWriter myStreamWriter;
}

次に、コードで:

proc.Start();

this.myStreamWriter = proc.StandardInput;

proc.BeginErrorReadLine();
proc.BeginOutputReadLine();

これで、myStreamWriter が利用できるようになりますproc_DataReceived()

void proc_DataReceived(object sender, DataReceivedEventArgs e)
    {
        // output will be in string e.Data
        if (e.Data != null)
        {
            string Data = e.Data.ToString();
            if (Data.Contains("Enter Auth Username"))
            {
                if (myStreamWriter != null) // Just in case
                {
                    myStreamWriter("myusername");
                }
            }
            //MessageBox.Show(Data);
        }
    }
于 2012-12-14T14:47:49.440 に答える
1

あなたが話している概念は、コンテキストではなくスコープです。


myStreamWriterからアクセスできるようにコードを変更する方法はいくつかありますproc_DataReceived

おそらく最も簡単なのは、影響を与えたいオブジェクトをパラメーターとして関数に渡すことです。これは、将来のマルチスレッド化と関数型スタイルへの推進の観点から、多くの場合、優れたアプローチです。

    void proc_DataReceived(
        object sender, 
        DataReceivedEventArgs e,
        StreamWriter writer)
    {
        ...
        writer("myusername");
        ...
    }

ただしproc_DataReceived、これは明らかにイベント ハンドラーであり、おそらく関数のシグネチャを変更したくないでしょう。


クラス レベルでプライベート メンバー変数として宣言するmyStreamWriterと、クラス内のどこからでもアクセスできるようになります。はthisオプションですが、適切な形式です。

class YourForm : Form
{
    private StreamWriter myStreamWriter;

    void button_Connect_Click(...
    {
        ...
        this.myStreamWriter = proc.StandardInput;
        ...
    }

    void proc_DataRecieved(...
    {
        ...
        this.myStreamWriter("myusername");
        ...

    }
}

StreamWriterクラス/フォームの外部からアクセスする場合を除き、プロパティの実装は必要ありません。

于 2012-12-14T14:43:33.977 に答える
1

myStreamWriter単純なクイックフィックスは、クラス内 (つまり、メソッドのスコープ外) でフィールドとして定義し、スコープの 1 つからインスタンス化することです。

private StreamWriter _myStreamWriter;

void button_Connect_Click(object sender, EventArgs e)
{
    // Do some stuff

    _myStreamWriter = proc.StandardInput;

    // Do some stuff
}

これを行うと、クラス内のどこでも使用できるようになります。

于 2012-12-14T14:55:22.537 に答える