I am testing Debug DLLs with NUnit and it is very annoying that with every testrun a large amount of Debug Assertions come up.
So i have written a tool which is polling for a new Debug Assertion. the tool is iterating to all windows every x milliseconds and checks if the title is one of the collection of possible Debug Assertion window titles.
In pseudo code it looks like this:
void main()
{
var thread = new Thread(ThreadMethod);
thread.Start();
}
private void ThreadMethod()
{
while(true)
{
foreach(var title in possibleWindowTitles)
{
IntPtr windowHandle = FindWindowHandle(title);
if(windowHandle != IntPtr.Zero)
{
SetToForeground(windowHandle);
SendKeys.SendWait("%I);
}
}
}
}
The codeline SendKeys.SendWait("%I") sends the keycombination of ALT + I to the window, which is the keycombination for the "Continue" Button.
My Question is:
Is there a better option? something like:
An event when a new window comes up
A better method of closing the window (the CloseWindow method from the User32.dll hasn't worked for me -- no Exception, but nothing happens)
A better solution for the SetToForeGround() workaround
The best way would be an suppression of the Assertion -- Is that possible?
My way works, but i think my solution is very prone to errors. So i hole there is someone with a good idea
You can configure the behavior of the dialog box. This is a behavior provided by the DefaultTraceListener, which is configurable in code or via config file. The documentation for Debug.Assert mentions this.
In the config file, you can turn off the UI like this:
<configuration>
<system.diagnostics>
<assert assertuienabled="false" logfilename="c:\myFile.log" />
</system.diagnostics>
</configuration>
You can also just remove the default trace listener from the collection via the config file:
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<remove name="Default" />
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\myListener.log" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Either of these can also be done via code, with the Debug.Listeners collection.
Related
How can I define a default TraceListener, that is automatically added to all TraceSources, in a net 4.0 c# project?
Currently I have to list every named TraceSource I use in the App.config file like this:
<system.diagnostics>
<sharedListeners>
<add name="MyListener" type="MyListenerType,MyAssemblyName" />
</sharedListeners>
<sources>
<source name="Class1" switchValue="All">
<listeners><add name="MyListener"></add></listeners>
</source>
<source name="Class2" switchValue="All">
<listeners><add name="MyListener"></add></listeners>
</source>
<source name="Class3" switchValue="All">
<listeners><add name="MyListener"></add></listeners>
</source>
... repeat for a gazillion classes ...
</sources>
<system.diagnostics>
I am using a SharedListener that should receive all outputs from all TraceSources, unless otherwise specified. With the above syntax, this requires a manual entry for each TraceSource.
Whenever I introduce a new class with a new TraceSource, I have to update the App.Config. If multiple programs use that assembly, I have to update multiple App.Config. A spelling mistake while updating these entries will not produce any error, it will just silently omit all trace output from the correct source.
Is there a way I can set a default TraceListener via App.config, so that I only have to name specific TraceSources if I want to deviate from the default?
I didn't find a great solution to this, so what I did was at least centralize the creation of TraceSources. Then I can add any of the 'trace' listeners in app.config to these newly created sources:
TraceSource toReturn = new TraceSource(name, filterLevel);
//remove the default trace listener; don't 'clear' the listeners entirely, because that would undo changes made in app.config; this is a decent compromise
toReturn.Listeners.Remove("Default");
//add all global trace listeners from the app.config
toReturn.Listeners.AddRange(Trace.Listeners);
return toReturn;
Now any listeners I add to <system.diagnostics> \ <trace> \ <listeners> will be added to all trace sources I create with this code.
You could add a default listener in the machine config, but that would affect more apps than you want to affect.
This is how trace listener defined in app.config:
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="Listener" type="System.Diagnostics.TextWriterTraceListener" initializeData="Import.log" traceOutputOptions="None" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
And the simple method that calls Trace.WriteLine:
public static void WriteLine(LogLevel logLevel, string message)
{
var message = String.Format("{0}", messageText);
Trace.WriteLine(message);
}
But as a result - there is no file created and messages there. I thought that the reason could be in method that is calling outside of assembly. But that looks impossible.
Is there any additional settings that I missed? Thanks in advance.
Actually the problem was in that the static method with logging was invoking from another assembly. There are two solutions I've figured out:
Make app.config copying after build (or copy manually) to the folder with assembly which contains
that method;
Declare diagnostics section with trace options in app.config of executing assembly.
I came across this: Winforms logging framework
But, I cannot get it working.
In the app.config, I have the following:
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="yourName" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\mylogfile.txt" />
</listeners>
</trace>
</system.diagnostics
In my code, I have the following to write to the log file:
Trace.Write("test");
Trace.TraceError("There's been an error captain: {0}", e);
Trace.TraceWarning("The system broke but don't worry.");
Trace.TraceInformation("Starting up the engines.");
The file is created. But nothing is written to it. Trace is turned on in visual studio.
Not sure what is missing here.
You've turned off autoflush. Try setting autoflush to true or calling Trace.Flush at the end of your code sample.
New to c# and .net, working in visual studio 2012. I want to have the ability to display values to an output window for debug purposes. I am very familiar with the watch windows, but that does not meet my current needs.
My most recent effort I took the exact sample from the msdn website.
Debug.Listeners.Add(new TextWriterTraceListener(Console.Out));
Debug.AutoFlush = true;
Debug.Indent();
Debug.WriteLine("Entering Main");
Console.WriteLine("Hello World.");
Debug.WriteLine("Exiting Main");
Debug.Unindent();
This example can be found at http://msdn.microsoft.com/en-us/library/system.diagnostics.debug%28v=vs.71%29.aspx
I added a breakpoint on the very next line after the above code. When I hit the breakpoint I have no errors displaying and my output window has none of the anticipated content. I do have the using System.Diagnostics set.
As described in MSDN, System.Diagnostics.Debug writes their messages into all subscribed TraceListeners (http://msdn.microsoft.com/en-us/library/system.diagnostics.tracelistener.aspx). Note that you should #define TRACE or add /d:TRACE when you compile your program. You can setup your listeners in configuration file like this.
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TextWriterOutput.log" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
What's the best way to catch and log errors when developing a WCF service layer, and why?
I can think of three ways,
1) Manual try/catches around each method.
2) Leave the responsibility to the WCF engine.
3) Use a third party library such as Enterprise Library Policy Injection/Logging.
I would implement custom IErrorHandler and use log4net
[AttributeUsage (AttributeTargets.Interface)]
public class ErrorPolicyBehaviorAttribute : Attribute, IContractBehavior, IErrorHandler
{
private ILog m_logger;
#region IErrorHandler
public void ProvideFault (Exception error, MessageVersion version, ref Message fault)
{
return;
}
public bool HandleError (Exception error)
{
m_logger.Error (error.Message, error);
return true;
}
#endregion
#region IContractBehavior
public void ApplyDispatchBehavior (ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
...init logger
......Add this class to a list of dispatchRuntime.ChannelDispatcher.ErrorHandlers...
}
#endregion
}
This class also implements IContractBehavior, so you can use it as Attribute on your service contracts.
[ErrorPolicyBehavior]
public interface IYourServiceContract
{ }
log4net is quite flexible, so you can log what you need and when you need.
WCF can be configured to output traces for process milestones across all components of the applications, such as operation calls, code exceptions, warnings and other significant processing events.
The following is an app.config example to enable tracing.
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning" propagateActivity="true" >
<listeners>
<add name="xml"/>
</listeners>
</source>
<source name="myUserTraceSource" switchValue="Warning, ActivityTracing">
<listeners>
<add name="xml"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="TraceLog.svclog" />
</sharedListeners>
</system.diagnostics>
</configuration>
You can read more about WCF Tracing from MSDN: Configuring Tracing.
Microsoft provides a Service Trace Viewer Tool to read .svclog files.
Apart from tracing, you may also want to consider using log4net for in-application logging.
If you are asking for logging framework ELMAH is also a good option to consider. If you dont like to litter your code with try/catch around each method, you can try using AOP frameworks which would give you the ability to handle exceptions by marking the method with Attributes
It might be worth your while to check out log4net. There is a good tutorial here on CodeProject.
I would go with number 1. Mainly because of reduced overhead over number 3 and number 2 should just be a no-no.
Granted you still want to log to something say like a file or event manager. But I personnally would use log4net for it since it's a bit lighter than all the entlib stuff.