C#: Use System.Diagnostics.Trace and DbgView within a WPF-Application


One of my favorite tools to debug MFC-Applications was the Win32-call:

::OutputDebugString( "Test\n" );

You can use it to trace information withing your application during runtime without a log-file. You only have to run the tool DbgView to monitor these log-entries ( if you want to try it out you can download DbgView here. )

Because I am currently working with C# in my job I wanted to use this tool as well for WVF-applications. And of course there is a corresponding API-method in the .NET-framework called:

Trace.WriteLine( string msg );

You can find the documentation here.

It is easy to use. Just insert your Trace-log-entries in your code. When you want to take a look into your application you can start DbgView to see, what is ongoing. Just make sure, that you have defined

#define TRACE

at the beginning of your source-file. Here is a small example:

#define TRACE

using System.Diagnosics;

class Test {
    static int main() {
        Trace.WriteLine("Hello, world!" );
        Exit(0);
    }
}

Please use only one statement per assert


Do you know the assert-macro? It is an easy tool for debugging: You can use it to
check if a pointer is a NULL-pointer or if your application is in a proper state
for processing. When this is not the case, if will stop your application,
when you are using a debug mode, in release mode normally nothing happens.
Depending on your platform this can vary a little bit. For instance the
Qt-framework prints a log-message if you have a failed assert test to stderr when
you are currently using a release build. So assert is a nice tool to check
pre-conditions for you function / method. And you will see your application crashing
when this precondition is not fulfilled. Thanks to some preprocessor-magic the
statement itself will be printed to stdout. So when you are writing something
like:

void foo( bar_t *ptr ) {
  assert( NULL != ptr );
  ...
}

and your pointer is a NULL-pointer in your application you will get some info on
your stdout like:

assert in line 222, file bla.cpp: assert( NULL != ptr );

Great, you see what is wrong and you can start to fix that bug. But sometimes you
have to check more than one parameter or state:

global_state_t MyState = init;

void foo( bar_t *ptr ) {
  assert( NULL != ptr && MyState == init );
  ...
}

Nice one, your application still breaks and you can still see, what went wrong?
Unfortunately not, you will get a message like:

assert in line 222, file bla.cpp: assert( NULL != ptr && MyState == init );

So what went wrong, you will not be able to understand this on a first look.
Because the pointer could be NULL or the state may be wrong or both of the tests
went wrong. You need to dig deeper to understand the error.
For a second developer this will get more complicated, because he will most likely
not know which error case he should check first, because he didn’t wrote the code.s
So when you have to check more than one state please use more than one assert:

global_state_t MyState = init;

void foo( bar_t *ptr ) {
  assert( NULL != ptr );
  assert( MyState == init );
  ...
}

Thanks!