【问题标题】:c# coding convention public/private contexts时间:2019-04-10 标签:c#coding convention public/private contexts
【发布时间】:2012-12-14 14:26:43
【问题描述】:

我正在学习 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 的所有输出发送到我的程序,该程序根据输出运行命令。

我当前的问题是,我需要写入流。我在proc_DataReceived 中使用myStreamWriter,但是它不在同一个上下文中,所以它不起作用。

我收到以下错误:The name 'myStreamWriter' does not exist in the current context,该范围内显然不存在。

我该如何进行这项工作?获取/设置属性?就像我说的那样,我对 C# 很陌生,因此感谢您提供任何帮助。

【问题讨论】:

  • 我认为您正在寻找“范围”而不是“上下文”这个词;)。
  • 你为什么要开始cmd.exe 而不仅仅是openvpn.exe
  • @tomfanning 因为我需要写入 cmd 进程。刚打开openvpn.exe时不起作用。
  • @Devator “不起作用”是什么意思?它会抛出空引用错误吗?
  • @Devator,那是因为您已将 UseShellExecute 设置为 false

标签: c# winforms conventions


【解决方案1】:

在您的表单中,添加此字段:

public class Form1Whatevver: Form {
    private StreamWriter myStreamWriter;
}

然后在你的代码中:

proc.Start();

this.myStreamWriter = proc.StandardInput;

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

现在,proc_DataReceived() 可以使用 myStreamWriter

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

【讨论】:

    【解决方案2】:

    简单的快速修复方法是将myStreamWriter 定义为类中的一个字段(即在您的方法范围之外),然后在其中一个范围内实例化它:

    private StreamWriter _myStreamWriter;
    
    void button_Connect_Click(object sender, EventArgs e)
    {
        // Do some stuff
    
        _myStreamWriter = proc.StandardInput;
    
        // Do some stuff
    }
    

    完成后,您应该可以在课堂上的任何地方使用它。

    【讨论】:

      【解决方案3】:

      你所说的概念是Scope 不是上下文。


      您可以通过多种方式更改您的代码,以便您可以从proc_DataReceived 访问myStreamWriter

      可以说最简单的方法是将您希望实现的对象作为参数传递给函数。从未来多线程的角度来看,这通常是一种很好的方法,也是一种功能风格的驱动力。

          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,否则不需要属性实现。

      【讨论】:

      • 对不起,这不是我需要的答案。我添加了我的错误:The name 'myStreamWriter' does not exist in the current context。抱歉含糊其辞。
      • -1 这不是答案,已经有评论。
      • @Devator 我已经分几个阶段写了我的答案,这样更合意吗?
      • @juharr 我已经写完我的答案了。
      猜你喜欢
      • 2016-04-19
      • 2022-01-16
      • 2018-07-04
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 2013-05-26
      • 2015-02-10
      • 2013-06-03
      相关资源
      最近更新 更多