Reputation: 3904
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
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
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
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