Devator
Devator

Reputation: 3904

c# coding convention public/private contexts

I'm learning C# and I'm creating a simple WinForms application, and what it does is starting a simple OpenVPN client:

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

What it does now, is send all the output of the CMD to my program, which run commands depending on the output.

My current issue is, I need to write to the stream. I use myStreamWriter in proc_DataReceived, however it's not in the same context so it doesn't work.

I get the following error: The name 'myStreamWriter' does not exist in the current context, which is obviously non existent in that scope.

How do I make this work? Get/set properties? Like I said I'm quite new to C# so any help is appreciated.

Upvotes: 0

Views: 334

Answers (3)

Jodrell
Jodrell

Reputation: 35706

The concept you are talking about is Scope not context.


The are several ways you could alter your code so that you can access myStreamWriter from proc_DataReceived.

Arguably the simplest, is to pass the object you wish to effect as a parameter to the function. This is often a good approach in the perspective of future multi-threading and a drive towards a functional style.

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

However proc_DataReceived is obviously an event handler and you probably don't want to change the signature of the function.


If you declare myStreamWriter as a Private Member Variable at the class level you will be able to access from anywhere within the class. The this is optional but good form.

class YourForm : Form
{
    private StreamWriter myStreamWriter;

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

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

    }
}

A property implementation is not necessary unless you want to access the StreamWriter from outside the class/form.

Upvotes: 1

Kjartan
Kjartan

Reputation: 19091

The simple quick-fix is to define myStreamWriter as a field in the class (i.e. outside the scopes of your methods), then instantiate it from within one of the scopes:

private StreamWriter _myStreamWriter;

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

    _myStreamWriter = proc.StandardInput;

    // Do some stuff
}

Having done that should let you use it wherever you want within the class.

Upvotes: 1

Jason Evans
Jason Evans

Reputation: 29186

In your form, add this field:

public class Form1Whatevver: Form {
    private StreamWriter myStreamWriter;
}

Then in your code:

proc.Start();

this.myStreamWriter = proc.StandardInput;

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

Now, myStreamWriter will be available to 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);
        }
    }

Upvotes: 2

Related Questions