Custom textwriter for Console outputstream not working in external classes - c#

I'm trying to forward the Console output to a Windows Forms TextBox control. So I attached a custom TextWriter to the Console which appends the output to the TextBox.
But I think the TextWriter or TextBox is inaccessible from within an external class. How to fix this? Check my code below:
partial class Form1 : Form
{
public StringWriter _TextWriter;
public Form1()
{
InitializeComponent();
this._TextWriter = new TextBoxStreamWriter(this.textBox1);
Console.SetOut(this._TextWriter);
Console.WriteLine("This text does appear in the TextBox, works perfect.");
Test ConsoleOutputExternalClass = new Test();
}
}
public class TextBoxStreamWriter : StringWriter
{
TextBox _output = null;
public TextBoxStreamWriter(TextBox output)
{
this._output = output;
}
public override void WriteLine(string value)
{
base.WriteLine(value);
this._output.AppendText(value.ToString());
}
public override Encoding Encoding
{
get
{
return Encoding.UTF8;
}
}
}
private class Test
{
public Test()
{
// HERE I GET AN EXCEPTION ERROR !!
Console.WriteLine("System.IO.IOException: 'The handle is invalid.'");
}
}

As I found out after experimenting, the problem had another cause than I expected. In my program I used Console.Clear() to remove all printed lines, but apparently this also destroys the link to the custom set output stream.
And this wouldn't clear the TextBox after all, I should be using TextBox.Clear().
I'm sorry for this, because my question is not to the point in this case, the problem appeared to lie somewhere else. In fact, the code in my question does work perfectly because there is no call to Console.Clear(), but I just didn't find out what really caused the problem yet.
The real question would be: how to "override" Console.Clear() in order to clear the TextBox? But this is for another topic.

Related

Stop ADK/DLL writing to console

I have an ADK provided by a hardware manufacturer for connecting to and using their hardware.
The ADK is a DLL we have referenced in our project, then called and used methods based on events. The problem is that the DLL constantly writes some text to the console. The string is always the same, We need to use the console so completely turning it off is not a viable solution.
I have attempted an implementation of the TextWriter class that ignores this string but this output from the DLL does not come into the class when I breakpoint inside it.
The TextWriter we built looked like this;
public class MyTextWriter : TextWriter
{
private TextWriter _standardOut;
public MyTextWriter(TextWriter ConsoleOut)
{
this._standardOut = ConsoleOut;
}
public override Encoding Encoding
{
get
{
return Encoding.ASCII;
}
}
public override void WriteLine(string val)
{
if(val != "Hello")
{
_standardOut.WriteLine(val);
}
}
}
Is there any other way to stop this DLL writing to the console?

Use textbox value in another cs file

I'd like to add a WinForm into my Console App:
namespace ExchangeNativeDemo.Window
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
I would like to pass textbox1 value to Program.cs, like:
var emailaddress = textbox1.value
In program.cs:
using ExchangeNativeDemo.Window;
namespace ExchangeNativeDemo
{
class Program
{
static void Main(string[] args)
{
But I got the error:
is inaccessible due to its protection level
What I missed?
When you add a TextBox (or other control) to a WinForm using Visual Studio, the control is defaulted to protected scope, meaning that the only code that can access it is the code in the WinForm itself or classes that derive from it.
There are two common options:
Just change the TextBox from protected to public. This breaks encapsulation a bit so this isn't my favorite.
Write a custom property that exposes the textbox's Text property, e.g.
class Form1
{
//.....Other stuff....
public string Text1Value
{
get { return this.textbox1.Text; }
}
}
Since you know that it is supposed to be the email address, and you want to at least try to be a little encapsulated, you might actually want to name it EmailAddressEntered or something similar.
public string EmailAddressEntered
{
get { return this.textbox1.Text; }
}
Then in your main program, create an instance of the form, display it, then read the property.
void Main()
{
//....do other stuff....
var form = new Form1();
form.ShowDialog();
var emailaddress = form.EmailAddressEntered;
}
Also note, a TextBox does not have a Value. The contents are stored in the Text property instead.
Also also note, your main function should contain a call to Application.Run or you'll find that Form1 doesn't work very well.
You need to make textbox1 public,
or add property to `Form1 that will expose its value:
public string Textbox1Text
{
get { return textbox1.Text; }
}
I believe you need to declare your var as public otherwise it is automatically private. Try and let me know.

Creating a dll but need to reference a changeable function/ void/ code

So I am creating a dll and what it does is it basically authenticates a username and password with a server and if it wrong it writes failure in an output box and if it is correct it launches another form or does whatever the person who is using the dll wants it to do. Here is the code:
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
LaunchCode.Globals.output = "SUCCESS" + Environment.NewLine;
//Success action
json = streamReader.ReadToEnd(); //---Can't get the nested JSON, read the entire response minus the 200 code.
}
Where I have "//Success action" is where the code would go for whatever the user wants the dll to do (open a form, open a message box, etc) but this being a dll the user doesn't have access to the code. So I wanted to have the dll reference a void or what ever would work, in a different form. I tried looking for example on how to do this on google but I couldn't really find anything and I really have no idea on how to accomplish this.
If you need me to clarify anything just ask and Thanks for the help in advance.
You need to use delegates. Below is an example code that uses a special delegate Action. You can use either inbuilt delegates or make your own.
public class Program
{
public void Main(string[] args)
{
Foo foo = new Foo();
foo.SomeMethod(ActionProvider.ShowMessageBox);
}
}
public static class ActionProvider
{
public static void ShowMessageBox()
{
//Write code for showing message box
Console.WriteLine("Showing message box");
}
}
// Assume this class to be in another dll
public class Foo
{
public void SomeMethod(Action callback)
{
//Do something
callback();
//Do something else
}
}

Feed listBox from different classes c#

here some beginners question after 2 hours of googling.
I have got a WindowsForm named GUI with an listbox item (it not have to be a listbox)
What I want to realize is having a box in the GUI an send from every classes in my project text to that box.
Example:
in Programm.cs I want simply write something like this GUI.WriteToLog("Hello World");
and it should appear in that box.
This GUI.WriteToLog should work in every class.
I tried to write a static function WriteToLog in the GUI class but if its static I cant use the listBox1 in that function.
public partial class GUI : Form
{
public void WriteToLog(string msg)
{
listBox1.Items.Add(msg);
}
}
Here the class that should access the box:
class FileManager
{
internal static void RenameFiles(string filePath)
{
GUI g = new GUI();
g.WriteToLog("Moving Files");
try {
File.Move(filePath, filePath + ".RDY");
}
catch (Exception e)
{
string message = e.ToString();
string caption = "Error";
MessageBox.Show(message, caption);
}
}
EDIT:
More Details what I want to do:
I have to access the ListBox from all of my classes, because it should inform about status. After some more google searches. I figured out that the best way to do this is to write an event ? I this right ? How du I do this ? Example what I want: GUI with the ListBox ... I'm in class "FileManager" Function "RenameFile" there I want write one line to the ListBox "Hey, I'm renaming files now" or I'm in Class "Communicator" in Function "SendEmail" so I want to add a line to the ListBox "Hey dude, I'm sending a fabilous email" ...
When you call the method RenameFiles you create a new instance of the class called GUI. So you're not using the same form.
You can fix your code by using dependency injection when creating your GUI class so that the FileManager has access without needing to create a new class.
By adding something like this to the FileManager and calling the setter on creation of your GUI.
private GUI gui;
public void SetGUI(GUI g)
{
this.gui = g;
}
A solution is use singleton pattern below an example:
public partial class GUI
{
private static GUI _instance;
public static GUI Instance
{
get { return _instance ?? (_instance = new GUI()); }
}
public void WriteToLog(string msg)
{
//[your code]...
}
}
class FileManager
{
internal static void RenameFiles(string filePath)
{
GUI.Instance.WriteToLog("Moving Files");
// [other code]...
}
}

access textbox from anywhere in application

How can I make a textbox in my winforms application that accepts new lines of text from anywhere in the application?
I have a main form that contains a textbox. I'd like to directly add text to the box from a method in another class.
Update
I tried this in my main form:
public void Output(String value)
{
if (txtOutput.Text.Length > 0)
{
txtOutput.AppendText(Environment.NewLine);
}
txtOutput.AppendText(value);
}
But I can't call Output from the other class. I'm new to C#, so perhaps I'm missing something obvious.
Regards, Miel.
PS Yes, I know this is bad design, but for now this seems to be the best way to do what I want. The textbox would function like a console.
You'll need to expose the Text property of the TextBox as a string property on your form. For example...
public string TextBoxText
{
get { return textBoxName.Text; }
set { textBoxName.Text = value; }
}
Edit
After reading the question edit, your problem is that you need a reference to a specific instance of the form whereever you're trying to execute that code. You can either pass around a reference (which is the better option), or you could use some smelly code and have a static property that refers to one instance of your form. Something like...
public partial class MyForm : Form
{
private static MyForm instance;
public static MyForm Instance
{
get { return instance; }
}
public MyForm() : base()
{
InitializeComponent();
// ....
instance = this;
}
}
Using this approach, you could call MyForm.Instance.Output("test");
In order to decouple a bit more you could inverse the control a bit:
// interface for exposing append method
public interface IAppend
{
void AppendText(string text);
}
// some class that can use the IAppend interface
public class SomeOtherClass
{
private IAppend _appendTarget = null;
public SomeOtherClass(IAppend appendTarget)
{
_appendTarget = appendTarget;
}
private void AppendText(string text)
{
if (_appendTarget != null)
{
_appendTarget.AppendText(text);
}
}
public void MethodThatWillWantToAppendText()
{
// do some stuff
this.AppendText("I will add this.");
}
}
// implementation of IAppend in the form
void IAppend.AppendText(string text)
{
textBox1.AppendText(text);
}
It looks like your design is a little bit corrupted. You shouldn't let buisness logic mess with GUI controls. Why don't you try a return value and assigning it on the interface side?
This is a REALLY bad way of doing it, but just to make sure all the answers are out there...
In the VS designer, each form control has an item in the Properties window named Modifiers that defaults to Private. Changing this to one of the others settings, such as Internal or Public, will let you access it from outside the form.
I must stress that this is the worst way to do it.

Categories