I want to exit the program if I see some key words apprearing in Console.Out. This is because we use a third party DLL which has a problem that when it encounters some particular exception it never exits.
The only sulotion to us seems to be monitoring the log that is populated back to console.Out. And base on the log on console.out, the host application can edecide what to do when such exception are encountered.
Someone told me that I can use trace listener... but I am not sure about that.
what do you guys think?
The Console class provides the SetOut method which can be used to write output to a custom stream. For example, you could stream to a StringBuilder and monitor changes, or write a custom stream implementation that watches for the keywords.
For example, here is a KeywordWatcherStreamWrapper class that watches for specified keyword, and raises an event for all listeners whenever the keyword is seen:
public class KeywordWatcherStreamWrapper : TextWriter
{
private TextWriter underlyingStream;
private string keyword;
public event EventHandler KeywordFound;
public KeywordWatcherStreamWrapper(TextWriter underlyingStream, string keyword)
{
this.underlyingStream = underlyingStream;
this.keyword = keyword;
}
public override Encoding Encoding
{
get { return this.underlyingStream.Encoding; }
}
public override void Write(string s)
{
this.underlyingStream.Write(s);
if (s.Contains(keyword))
if (KeywordFound != null)
KeywordFound(this, EventArgs.Empty);
}
public override void WriteLine(string s)
{
this.underlyingStream.WriteLine(s);
if (s.Contains(keyword))
if (KeywordFound != null)
KeywordFound(this, EventArgs.Empty);
}
}
Sample usage:
var kw = new KeywordWatcherStreamWrapper(Console.Out, "Hello");
kw.KeywordFound += (s, e) => { throw new Exception("Keyword found!"); };
try {
Console.SetOut(kw);
Console.WriteLine("Testing");
Console.WriteLine("Hel");
Console.WriteLine("lo");
Console.WriteLine("Hello");
Console.WriteLine("Final");
} catch (Exception ex) { Console.Write(ex.Message); }
On the second Write statement which contains the entire keyword, the event will be raised and thus the exception will be thrown. Note also that this silently wraps the underlying stream and still writes to it, so console output is still generated as normal.
Sample output:
Testing
Hel
lo
Hello
Keyword found!
if you can wrap this into an exe, maybe you can use Process.StandardOutput.
Related
My team is developing a Plugin project, in which Host application coordinates Plugins work (each Plugin has a specific function and will be executed on a seperate Thread). I'm writing Host application and define IPlugin interface; other people will develop Plugins.
The problem is: how to know when plugin completed or thrown exception. I have a solution is using event and delegate to let Plugins callback Host application, but I think this approach is not really good. Because if develop Plugin person implemented my IPlugin interface but forget writing raising event code.
In this case, the Plugin can be plug in my host application but my host application can not know when this Plugin completed or thrown exception or other communication, that's very bad.
My code likes this:
IPlugin.cs:
public delegate void OnFinishDelegate(IPlugin p, AMessageEventArgs e);
public delegate void OnExceptionDelegate(IPlugin p, AMessageEventArgs e);
public interface IPlugin
{
event OnFinishDelegate OnFinish;
event OnExceptionDelegate OnException;
void DoWork();
}
EventArgs:
public class AMessageEventArgs:EventArgs
{
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
}
Host Application:
static void Main(string[] args)
{
// ...ignore load plugin code
//
IPlugin p = new Plugin();
// register event with IPlugin
p.OnFinish += new OnFinishDelegate(OnFinishHandler);
p.OnException += new OnExceptionDelegate(OnExceptionHandler);
// let plugin do its work on a subthread
Thread t = new Thread(p.DoWork);
t.Start();
// and then main continue do other work...
}
// if plugin throw exception, in the host application will
// handle this exception...
private static void OnExceptionHandler(IPlugin p, AMessageEventArgs e)
{
// in here will process exception of plugin...
}
// if plugin completed its work, it will use OnFinish event to
// notify to host application
private static void OnFinishHandler(IPlugin p,AMessageEventArgs e)
{
// in here will process completed work event
}
And I expect Plugin code will like below:
public class Plugin:IPlugin
{
// use event to callback host application
public event OnFinishDelegate OnFinish;
public event OnExceptionDelegate OnException;
// Create an EventArgs
AMessageEventArgs e = new AMessageEventArgs();
public void DoWork()
{
try
{
// execute update data
UpdateData();
}
catch (Exception ex)
{
e.Message = ex.Message;
// if have any exception, Plugin will raise an event in host application
// but if developer forget write below three lines of code, my host application will
// out of control.
if (OnException!=null)
{
OnException(this,e);
}
}
// if have no exception, Plugin will use OnFinish event to talk to host application
// to know that this plugin completed its work
// but if developer forget write below three lines of code, my host application will
// out of control.
if (OnFinish!=null)
{
OnFinish(this,e);
}
}
How to resolve this problem?
Additional problem: Did my IPlugin interface define well? if not well, can you advise me to improve this interface.
Thanks you!
I don't think the plugins need to know they're running in separate threads. I'd just have:
interface IPlugin {
void DoWork();
}
And then the host program would deal with catching exceptions and all the threading, something like:
Thread t = new Thread(() => {
try {
plugin.DoWork();
}
catch (Exception ex) {
// handle exception or save it to handle in the main thread
}
});
t.Start();
You've correctly identified the problem with the event model in the interface - when a plugin implements the IPlugin interface, they have to define the OnException event, but there is nothing requiring them to use it.
Define your IPlugin interface with a single DoWork method, and allow the standard exception pattern to report successful completion or an error status. If the DoWork method returns normally, the plugin is finished (no need for an OnFinish event). If DoWork throws an exception, your main application can catch the exception and deal with it (no need for an OnException event).
I would recommend looking into the Task Parallel Library for executing the plugins. It provides more control than using threads directly, including exception handling.
I've just read HeadFist Design pattern and discovered a solution: Factory Method.
In my case, I should use abstract class instead interface (IPlugin). In this abstract class, I define a Operate() method that will report result(completed result or exception result) to my host application. The second method is DoWork() method that the third party programmer can writing his function and don't care about OnComplete or OnException event.
My code like below:
Abstract class:
public delegate void OnFinishDelegate(APlugin p, AMessageEventArgs e);
public delegate void OnExceptionDelegate(APlugin p, AMessageEventArgs e);
public abstract class APlugin
{
public event OnFinishDelegate OnFinish;
public event OnExceptionDelegate OnException;
AMessageEventArgs e = new AMessageEventArgs();
public void Operate()
{
try
{
// implement plugin work
// we don't care how does the third party programmer write his Plugin program
DoWork();
// if DoWork() completed , it will raise an OnFinish event
// in my host application
e.Message = "Completed";
if (OnFinish != null)
{
OnFinish(this, e);
}
}
catch(Exception ex)
{
// if DoWork() throw exception, it will raise an OnException event
// in my host application
e.Message = ex.Message;
if (OnException!=null)
{
OnException(this,e);
}
}
}
// In here, the third party programmer will override this DoWork() method
private abstract void DoWork();
}
Host applicaton code:
static void Main(string[] args)
{
// ...ignore load plugin code
//
APlugin p = new Plugin();
// register event with IPlugin
p.OnFinish += new OnFinishDelegate(OnFinishHandler);
p.OnException += new OnExceptionDelegate(OnExceptionHandler);
// let plugin do its work on a subthread
Thread t = new Thread(p.Operate);
t.Start();
// and then main continue do other work...
}
// if plugin throw exception, in the host application will
// handle this exception...
private static void OnExceptionHandler(APlugin p, AMessageEventArgs e)
{
// in here will process exception of plugin...
}
// if plugin completed its work, it will use OnFinish event to
// notify to host application
private static void OnFinishHandler(APlugin p, AMessageEventArgs e)
{
// in here will process completed work event
}
>
And Plugin code (must like below):
class Plugin:APlugin
{
public override void DoWork()
{
// in here, the third party programmer can write anything
// for example: update data in database
UpdateData();
}
private void UpdateData()
{
// do update data
}
}
I'm frequently using asserts to detect unexpected program states. I thought an assert is a conditional message box the immediately stops all threads so that (on pressing "Retry") I can inspect the current application state.
This is not the case! While the assert message is open, my wpf application continues processing events. It is absurd, as on breaking into the debugger the situation might be totally different compared to what the assert "saw" initially. You can have the case that the check for the assert to fire changes through the assert itself, you can have recursive execution of methods - with the consequence of multiple asserts or states in which the program would never come normally.
As far as I understand the assert-function, this is a problem by design. The dialog runs on the same GUI thread as the application itself and hence needs to process messages for its own purpose. But this often has the described side-effects.
So I'm searching for an assert alternative that fulfills the requirement to stop all running threads when invoked. As workaround, I sometimes use "Debugger.Break();" which has (unfortunately) no effect if started without debugger.
For illustrating the problem, please see the following code snipped that in the most simplified manner produces some phenomenons:
public partial class MainWindow : Window
{
int _count = 0;
public MainWindow()
{
InitializeComponent();
}
private void onLoaded(object sender, RoutedEventArgs e)
{
test();
}
protected override void OnLocationChanged(EventArgs e)
{
base.OnLocationChanged(e);
}
void test()
{
++_count;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
test();
}));
Trace.TraceInformation(_count.ToString());
Debug.Assert(_count != 5);
}
}
On running the code, watch the output panel of the developer studio. You will see the numbers go up to 5, then the assert fires. But while the dialog is open, the numbers are still increasing. Hence the condition of the assert changes while the assert is open!
Now check the main window –it’s still responsive. Set a breakpoint at “base.OnLocationChanged(e);“ and move the main window => you will hit the break point. But mind the callstack:
MainWindow.OnLocationChanged(System.EventArgs e)
(…)
System.dll!Microsoft.Win32.SafeNativeMethods.MessageBox(System.IntPtr
System.dll!System.Diagnostics.AssertWrapper.ShowMessageBoxAssert(stri
System.dll!System.Diagnostics.DefaultTraceListener.Fail(string message, str
System.dll!System.Diagnostics.DefaultTraceListener.Fail(string message)
System.dll!System.Diagnostics.TraceInternal.Fail(string message)
System.dll!System.Diagnostics.Debug.Assert(bool condition)
MainWindow.test()
MainWindow.test.AnonymousMethod__0()
This clearly shows that arbitrary code can be executed while the assert is open.
So I'm searching for an assert like mechanism that stopps all existing threads and runns in it's own (thread-) context.
Any ideas?
You are finding out more about how the dispatcher loop works. And yes, the MessageBox that the default trace listener uses to report the failure does not do much to stop your program. It was designed to stop the user, it is a modal dialog box that disables all user input. But does not stop anything that you do in your code. Like it calling Dispatcher.BeginInvoke().
You will need another implementation of the TraceListener.Fail() method. That's quite possible, edit your App.xaml.cs file and make it look similar to this:
using System.Diagnostics;
...
public partial class App : Application {
public App() {
if (Debugger.IsAttached) {
var def = Debug.Listeners["Default"];
Debug.Listeners.Remove(def);
Debug.Listeners.Add(new MyListener(def));
}
}
private class MyListener : TraceListener {
private TraceListener defListener;
public MyListener(TraceListener def) { defListener = def; }
public override void Write(string message) { defListener.Write(message); }
public override void WriteLine(string message) { defListener.WriteLine(message); }
public override void Fail(string message, string detailMessage) {
base.Fail(message, detailMessage);
Debugger.Break();
}
}
}
The code works by removing the DefaultTraceListener, the one that's giving you a headache, from the installed listeners. And adds a custom one, the MyListener class. Which doesn't do much, just uses the original listener to get messages displayed in the Output window. But with an override for the Fail() message, it automatically triggers a debugger break. Just what you want here.
I'm answering my own question as summary and extension of the provided information by Jon Skeet and Hans Passant:
For the case the program runs in the debugger the option with Debugger.Break() or enabling the EEMessageException is for me the way to go. Both methods immediately stop all threads.
If not debugging and the assert occurs in the GUI thread a message box running on a separate thread helps (see http://eprystupa.wordpress.com/2008/07/28/running-wpf-application-with-multiple-ui-threads/)
Here is the code putting all together (by extending the suggestion from Hans Passant)
public partial class App : Application
{
public App()
{
var def = Debug.Listeners["Default"];
Debug.Listeners.Remove(def);
Debug.Listeners.Add(new MyListener(def, Dispatcher.CurrentDispatcher));
}
private class MyListener : TraceListener
{
private TraceListener _defListener;
private Dispatcher _guiDisp;
public MyListener(TraceListener def, Dispatcher guiDisp)
{
_defListener = def;
_guiDisp = guiDisp;
}
public override void Write(string message) { _defListener.Write(message); }
public override void WriteLine(string message) { _defListener.WriteLine(message); }
public override void Fail(string message, string detailMessage)
{
base.Fail(message, detailMessage); //write message to the output panel
if (Debugger.IsAttached)
{
//if debugger is attached, just break => all threads stopped
Debugger.Break();
}
else if (Dispatcher.CurrentDispatcher == _guiDisp)
{
//running standalone and called in the GUI thread => block it
Thread anotherGuiThread = new Thread(() =>
{
//TODO: nice dlg with buttons
var assertDlg = new Window() { Width = 100, Height = 100 };
assertDlg.Show();
assertDlg.Closed += (s, e) => assertDlg.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run(); //run on its own thread
});
anotherGuiThread.SetApartmentState(ApartmentState.STA);
anotherGuiThread.Start();
anotherGuiThread.Join();
}
else
{
//running standalone and NOT called in the GUI thread => call normal assert
_defListener.Fail(message, detailMessage);
}
}
}
}
Thank for all the interest in this question. Some of you have asked for more clarity on code involved, so in order to provide a bit more info, im going to edit it to provide a bit more detail.
Relating to my previous question, I am attempting to emulate a basic console in a WPF window (text output only). It's meant to work with a program that has a lot of code running in the background running on separate threads. This code relies heavily on a while loop as well, so my plan is to keep the WPF console window on the main thread (along with any additional GUI windows that might be needed) and execute all the code on separate threads.
The window has a WriteLine method used like so:
mainConsole.WriteLine("This is a message for the user.", SomeSender);
The rest of the code is going to need to call this method regularly.
Additional info:
The window itself is comprised of a Textblock wrapped in a Scroller. The WriteLine method of the window adds the message and formatting (font, font size, and colour - dependent on who the sender of the message is) to a List of objects which contain this information, and then displays the list of these messages including their formatting) as the content of the Textblock. The method works exactly as intended so doesn't need re-writing, it just needs to be accessible.
I've tried to keep this description as concise as possible. For more information, please see my previous question.
So my question now is: Is there an efficient way to make the window's WriteLine method usable to all threads from any class, thus enabling me to use it just like Console.WriteLine()?
While you have a number of options, it sounds like, in your case, it really does make sense for anyone, anywhere, to be able to write to your console. Given that, I'd create something like this:
public class MyConsole
{
public static event Action<string> TextWritten;
public static void Write(object obj)
{
string text = (obj ?? "").ToString();
if (TextWritten != null)
TextWritten(text);
}
public static void WriteLine(object obj)
{
Write(obj + "\n");
}
}
Then have your console form subscribe to the TextWritten event and, when text is written, write that text to the console. (Make sure to marshal to the UI thread first.)
The main advantage of using and event here, as opposed to having this class directly deal with your form, is that you can trivially add additional event handlers allowing you to interact with standard input/output, to add additional logging to files, to have multiple console forms open at once, etc. This flexibility can be useful for both debugging (i.e. additional writeouts to a flat file) and in production (allowing much easier redirection through standard in/out).
It seems you are trying to write a logging service that would allow you to access the log from anywhere within your code. You mention threads, so you will have to be mindful and handle that synchronization accordingly.
I would first create an ILogger interface such as this:
public interface ILogger
{
void Log(string line);
void Log(string format, params object[] args);
}
Then a proper Logger base class:
public abstract class Logger : ILogger
{
public abstract void Log(string line);
public virtual void Log(string format, params object[] args)
{
Log(string.Format(format, args));
}
}
Of course, you will need an actual implementation:
using System.Collections.Concurrent;
using System.Threading.Tasks;
public class ConcurrentLogger : Logger, ILogger, IDisposable
{
bool isDisposed;
BlockingCollection<string> loggedLines;
Action<string> callback;
public ConcurrentLogger(Action<string> callback)
{
if (callback == null)
throw new ArgumentNullException("callback");
var queue = new ConcurrentQueue<string>();
this.loggedLines = new BlockingCollection<string>(queue);
this.callback = callback;
StartMonitoring();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
if (isDisposed) return;
if (isDisposing)
{
if (loggedLines != null)
loggedLines.CompleteAdding();
}
isDisposed = true;
}
public override void Log(string line)
{
if (!loggedLines.IsAddingCompleted)
loggedLines.Add(line);
}
protected virtual void StartMonitoring()
{
Task.Factory.StartNew(() =>
{
foreach (var line in loggedLines.GetConsumingEnumerable())
{
if (callback != null)
callback(line);
}
loggedLines.Dispose();
}, TaskCreationOptions.LongRunning);
}
}
For global access, you will need a Singleton class, so I would make this LogManagerclass:
public sealed class LogManager : ILogger
{
#region Singleton
static readonly LogManager instance = new LogManager();
public static LogManager Current { get { return instance; } }
private LogManager() { } // Disallow creating instances.
#endregion
ILogger logger;
public ILogger Logger { get { return logger; } }
public void StartLogging(ILogger logger)
{
if (logger == null)
throw new ArgumentNullException("logger");
this.logger = logger;
}
public void StopLogging(bool dispose = true)
{
var previousLogger = this.logger as IDisposable;
this.logger =null;
if (previousLogger != null && dispose)
previousLogger.Dispose();
}
public void Log(string line)
{
if (logger != null) logger.Log(line);
}
public void Log(string format, params object[] args)
{
if (logger != null) logger.Log(format, args);
}
}
With some quick initialization:
void InitializeLog()
{
var log = new ConcurrentLogger(LogToTextBox);
LogManager.Current.StartLogging(log);
}
void LogToTextBox(string line)
{
if (!CheckAccess())
{
this.Dispatcher.BeginInvoke((Action<string>)LogToTextBox,
DispatcherPriority.Background,
line);
return;
}
logTextBox.AppendText(line + Environment.NewLine);
}
Then anywhere in your code you can call: LogManager.Current.Log(...);
Create a static class that holds the WriteLine method and a Property referencing the window, control or whatever you need inside the writeline method.
Then add some code to your MainWindow constructor or loaded event to set the Reference-Property to the needed item.
Afterwards you can use Writeline from wherever you want.
BTW: This may be much cleaner using a static MainViewModel with an Instance getter, bind the DataContext of the MainWindow to this ViewModel and use the MVVM pattern. Youy would then only set some ConsoleOutput property or call an AddLine method or even Command from wherever you want and don't have to know how it is displayed by the View. You can test your app using unit tests, you can change the visual representation, ... all withou touching the logic of your application.
namespace {yourrootnamespace}
{
namespace GlobalMethods
{
static class ConsoleMethods
{
mainConsole mc;
public static WriteLine(string msg, object sender)
{
lock (this)
{
mc.WriteLine(msg, sender)
}
}
static ConsoleMethods()
{
mc = new mainConsole();
}
//more methods
}
}
And then: using {yourrootnamespace}.GlobalMethods;
Or alternatively let the methods take in a mainConsole argument which it then uses to call.
Okay, I think the title can be quite confusing... :)
My application is using CS-Script as a script interface.
In the scripts my application will be running, I want to have some sort of "Debug print" - meaning somewhere in the script the scripter can do "Debug.Print("BLAAAAH!!!");") and that would show up somewhere in my very funky output dialog.
Of course I can create my own debug-ooutput-stuff, but since I'm using C# as a scripting language and people using C# would be used to use System.Diagnostics and use Debug.Print("..."),
it would be great if I could reroute System.Diagnostics.Debug.Print("") and System.Diagnostics.Debug.WriteLine("...") to trace their output to my cool output-window.
So.
Does anybody know if it's possible to reroute C#'s System.Diagnostic.Debug print/writeline output to something I have control over ?
For that, you can create a custom TraceListener.
You should set the compile time DEBUG symbol or run the script with /dbg option
cscs /dbg <yourScript>
You will also need to create a custom TraceListener or simply use a trace viewer like the sysinternals DebugView
I use the TraceListener for this also, but here's my code snippets:
Classes:
using System.Diagnostics;
public class DebugOutputListener : TraceListener
{
public event EventHandler<DebugMessageArgs> DebugMessage;
public override void Write(string message)
{
EventHandler<DebugMessageArgs> h = DebugMessage;
if (h != null)
{
DebugArgs args = new DebugArgs
{
Message = message
};
h(this, args);
}
}
public override void WriteLine(string message)
{
Write(message + "\r\n");
}
}
public class DebugMessageArgs : EventArgs
{
public string Message
{
get;
set;
}
}
To receive debug messages, instantiate an instance of the DebugOutputListener, subscribe to the DebugMessage event handler and register the listener with the Debug.Listeners collection.
e.g.
private void InitialiseDebugListener()
{
DebugListener dl = new DebugListener();
dl.DebugMessage += new EventHandler<DebugArgs>(Console_OnDebugMessage);
Debug.Listeners.Add(dl);
}
private void Console_OnDebugMessage(object sender, DebugMessageArgs e)
{
string debugMessage = e.Message;
// Do what you want with debugMessage.
// Be aware this may not come in on the application/form thread.
}
Im new to C# and the framework Im playing with and Im trying to figure out how some code works (there is nothing wrong with the code). Its a client/server application that sends some text from the client to the server and then receives and displays the same string in a textbox.
The code below is from the client and its form. Only the stuff for receiving the string from the server is included here. I included some comments from the framework.
public class TestModuleMobile : PreCom.Core.ModuleBase, PreCom.Core.IForm
{
public delegate void ReceiveDelegate(string data);
public event ReceiveDelegate DataReceived;
public void Receive(byte[] data)
{
string text = Encoding.UTF8.GetString(data, 0, data.Length);
if (DataReceived != null)
DataReceived.Invoke(text);
}
public override bool Initialize()
{
PreCom.Application.Instance.Communication.Register(99, Receive);
// Register(uint receiverID, RecieveDelegate receiver): Called by modules to register for communication.
//
// Parameters:
// receiverID:
// Module Id
// receiver:
// The module receive function that will be called by the framework when data
// arrives to specific module. (This method should return as soon as possible
// to avoid timeouts)
_isInitialized = true;
return true;
}
}
public partial class TestModuleMobileForm : PreCom.Controls.PreComForm
{
TestModuleMobile _module;
public TestModuleMobileForm(TestModuleMobile module)
{
_module = module;
_module.DataReceived += new TestModuleMobile.ReceiveDelegate(DataReceived);
InitializeComponent();
}
void DataReceived(string data)
{
if (InvokeRequired)
{
ThreadStart myMethod = delegate { DataReceived(data); };
this.BeginInvoke(myMethod);
return;
}
listBox1.Items.Insert(0, data);
this.preComInput21.Text = "";
}
}
Questions:
1. public override bool Initialize()
The function call to Register takes a ReceiveDelegate object as a second parameter. So how can I send a function to it (Receive) when its just a function? How does this work?
2. public void Receive(byte[] data)
What happens in the if-case? How does invoke work?
3. void DataReceived(string data)
What happens in the if-case (line by line)?
There are many related posts here on Stackoverflow which you can browse through to get a better understanding of delegates. Once you have read through them, take a relook at your code and you will find it easier to understand.
Tip: Check to the right side of this web page to see all the related posts.
You need a full understading of delegates so you better start by reading these in order:
Delegates (C# Programming Guide)
Delegates Tutorial
Delegates and Events in C# / .NET