Launching WinForms apps from a console

This is harder than it seemed like it should be.

I wanted to have a console app with trace. I like tracing to a console. But if I’m writing a console app, the trace is going to interleave with the UI. So I thought, I’ll create a win form class and then Applicatin.Run() it, then send text to a TextBox. And I’ll get pretty trace in a window other than the main Console.

So I did that, and the application blocks on Application.Run(), meaning the form responded to clicks and key presses, but the console freezes and executes no code.

So I learned to do form.Show() plus Application.DoEvents(), which shows the form, allows the console code to run, and then lets the form UI update.

But things still seemed blocked… and they were. This time because Console.ReadKey() was blocking. So I change Console.ReadKey() to a while-Thread.Sleep(250) and I could then move both windows, and send output to both windows via my TraceListener and ordinary console commands.

Console is single threaded, so is is easy to get blocked, which blocks any Forms it might have spawned. Also, Forms really doesn’t like to be manipulated from a thread different from the thread that created the Form. So some kinds of cross window communication blew up.

So that was my experiment. I guess the alternative would be to write to a WPF window, which could potentially make very pretty trace, but I don’t know if it would be worth my time to learn WPF.

Reading System.Diagnostics from the Mono sources

I’ve been trying to use System.Diagnostics for a while. I think I see why it failed to catch on. It thinks that developers will write a lot of code for a tertiary customer– the production server admin staff. Why do I think this? A good third of the code and complexity of the namespace is related to XML configuration. A production server admin can’t recompile the code, but sometimes in some organizations they can change configuration, say a .config, .ini or registry setting. And through these means they could turn trace on and off. But that is only if the original developers wrote a lot of trace that uses a library that can be turned on and off. System.Net and System.ServiceModel both use System.Diagnostics trace. Most other framework namespaces do not– you can use Reflector or the like to search the .NET API for instances of TraceSource– you find out that there are not a lot. People were using Console.WriteLine, Respone.Write and every other technique they learned in their first Hello World program.

Making Systems.Diagnostics Palatable to Developers
* Trace needs to be production safe. Not just for threading but for performance. Write should take a lambda function instead of a string. The listeners shouldn’t have a slow default that writes to a hard to see invisible listener (the DebugString API)
* Trace should work well in environments where a real database and possibly the filesystem isn’t available. ASP.NET makes it too hard to write to console because you have to attach the console to the WebDev Server using Win32 API calls, there isn’t a built in Application[], Cache or Session listener, nor is there an OleDb, MS-Acess, or Excel listener.
* Trace should allow for all components to be customized, Listeners, Sources, Switches, Filters, and Output Formating. The last, formatting, is barely developed in the Systems.Diagnostics API. Switches and Sources have to be completely wrapped to effectively change their behavior. And you can only have 1 Filter per listener and 1 switch per source– big restriction. Another annoyance is that if you do want to extend the API, then currently you have to stick within the constriants of legacy config– so you can’t implement multiple switches per source without abandoning the legacy xml config and writing a whole new xml config section handler.
* Trace should have a fluent API. I want to be able to write in a fluent API the configuration scenarios and then use an admin page to turn these scenarios on and off. Some typical scenarios — show me the app trace, show me the sql trace, show me the data trace, show perf trace, show everything, show only the current user, show all users, show me the next 10 minutes, write it to Session and then email it to me. When I have those, I have an incentive to write trace, and then when the code goes to production, the production admin will have a chance of diagnosing what is going on.

Production Trace

Assume you work in a large organization, you write code, you really would like to see some diagnostic trace from your app in Test, Staging or Production, but a server admin owns all of them. You can’t have the event logs, remote desktop access, or ask that the web.config be edited to add or a remove a System.Diagnostics section. Just imagine.

Production trace needs to be:
- high performing, if it slows down the app, which may already be under load, not good.
- secure, since trace exposes internals, it should have some authorization restrictions
- not require change of code or config files, because large organizations often have paralyzing change management processes
- support a variety of listeners that will meet the requirements above (and if those listeners are write only, then a reader will need to be written)

System.Diagnostics -File-
- Perf- Not very performant, will likely have contention for the file.

System.Diagnostics-Console, DebugString, Windows Event Log
- You can’t see it. End of story.

ASP.NET Trace.axd and In Page
- Perf- not so good.
- Security- it’s well known, so security teams often disable it
- Config- Can sort of enable on a by page/by user basis if you use a master page or base page to check rights and maybe a query string.

Custom Session Listener
Write to session.
- Okay for single user trace. Need a page to dump the results.
- Perf probably okay, could hog memory.
- Security, pretty good, by default you can only see your own stuff.

Custom Cache Listener
- Write trace to cache
- Will have locking problems
- Won’t hog memory because of cache eviction
- Cache eviction could remove trace too fast.

HttpContext.Items listener +Base page to dump contents at end of request
- Only shows one page of trace at a time
- Probably high perf.
- Won’t show other users