Thursday, March 09, 2006

Console WinForms application

Today at work one of my coworkers asked me if I knew how to create a .NET WinForms application that when invoked with command line arguments would act like a console application (no window, console input/output). At first it seemed like it should not be very hard.

First attempt.
We have created a console application that when invoked with empty arguments list would show a window. Almost good, the problem was that the console window reminded open and what's worse it showed up on top of our form.

Second attempt.
We have created a Windows Application and tried to use Console.WriteLine() to write to the console. It didn't work... It looks like Console class when used in an application that is not attached to a console redirects all writes to Stream.Null. Even bigger problem was that Console.ReadLine() throws an exception because StdInput handle was invalid.

Third attempt (Win32 magic)
After two failures we tried more pragmatic approach (google is your friend ;).
First, how does Windows know that an application is a console app. The answer lies in Subsystem field of an image Portable Executable (PE) header. For most Win32 applications two values are used: WindowsGUI and WindowsCUI (console).

The difference is that for CUI apps Windows creates a new console if a process did not inherit the console from its parent. Moreover, cmd.exe waits for the console applications to exit before it shows the next line of a command prompt.

There are also a few Win32 API functions that allow you to do some cool things with consoles even in GUI applications.

BOOL AllocConsole(void);
Creates a new console.

BOOL FreeConsole(void);
Detaches the calling process from its console.

BOOL AttachConsole(DWORD dwProcessId);
Attaches the calling process to the console of the specified process. (WinXP+ only)
ATTACH_PARENT_PROCESS can be used to attach to a parent process console.

After learning the above we had three options.
1) Create a GUI application and create a console when needed using AllocConsole. This could work but... it would always create a new console. We could use AttachConsole but it is available only on WinXP and still there is no way to force cmd.exe to wait for our process to exit.

2) Create a console app and when we decide a console is not needed use FreeConsole to get rid of it. Unfortunatelly even if we call FreeConsole right at the beginning of the Main method, console window will appear for a second or so, and it does not look good.

3) Create two separate applications to support console and GUI mode. There is a clever trick you can use so they have the same name. Check out the following article:
http://msdn.microsoft.com/msdnmag/issues/04/02/CQA/#QA3

If you know a different way of creating a dual mode (Console/GUI) application, let me know.

Sunday, February 05, 2006

Precondition checks

In my code I always try to do at least basic validation of method arguments against method preconditions. What I mean here is checking for invalid null arguments, empty strings, not-negative numbers, etc. I do it for two reasons:
  1. It clearly comuniacates what assumptions were made about the arguments when coding the method.
  2. It can save some debugging time when the method doesn't do what it should only because the arguments were not what you expected them to be.
The code I used to write looked like this:

public void Foo(object item)
{
if (item == null)
throw new ArgumentNullException("item");

...
}

The code above works fine, but does it really communicate CLEARLY what my intension was. To me, every if statement makes the code less readable so to make my intensions more clear I could try to change it to:

...
// Precondition: item cannot be null
if (item == null)
throw new ArgumentNullException("item");
...

Did it get any better? Nope. I have just added a comment that says exactly the same thing as the code below it. Waste of space...
At some point I figured out that what I try to do here is exactly the same as what I do when writting unit tests. And when I write them I don't write:

if (result != 10)
Assert.Failed("Result is not equal to expected value.");

I write

Assert.AreEqual(10, result);

So this is my precondition checking code:

public void Foo(object item)
{
Precondition.ArgumentNotNull(item, "item");
...
}

The other methods I created to check for preconditions are for example:

Precondition.ArgumentNotEmpty(string value, string argumentName)
Precondition.ArgumentNotNegative(int value, string argumentName)
Precondition.ArgumentInRange(int value, int min, int max, string argumentName)
etc...

What do you think? Do you like it and think it makes some sense? Let me know :)

Monday, January 23, 2006

Did you own C64

I did. It was the best 8 bit machine you could get (don't even mention Atari ;) If you want to bring back the memories check out http://www.c64s.com. They've got number of C64 games you can run dirrectly in your browser, how cool is that? :P

Sunday, January 22, 2006

What's wrong with System.Collections.Generic

Generics are great. The first thing that you will want to use them for are collections and that's for sure. At last you can get rid of all the XXXXCollection classes that most of the time were just a wrapers around ArrayList. Yeap, generics are really great, but lets look at System.Collections.Generic namespace. Most interfaces look similar to their 1.1 equivalents, but ICollection is quite different than ICollection.
ICollection is basically IEnumerable + Count and CopyToArray, so I used to use it whenever I wanted to give a client of my code a read-only
access to a collection of items.
ICollection is different. In addition to the features of ICollection it adds Add(T), Remove(T) and Clear() methods, so it no longer represents a readonly collection of items. What about ICollection.ReadOnly property you will ask... Ok, it is there but what happens to ICollection when ReadOnly == true? Answer: a half of its methods will throw InvalidOperationException. I don't like it... If you want it to be read-only expose the interface that will clearly comunicate your intension and does not allow modifications.
Ok, if I don't like sth I look for an alternatives. So I googled around for a third party collections libraries and found PowerCollections (http://www.wintellect.com/powercollections/) and C5 collection library (http://www.itu.dk/research/c5/). While PowerCollections complements rather than replaces System.Collections.Generic namespace, C5 library can be used as a complete replacement of the standard collections library.
What I like the most about C5 is that it introduces fine grained Interfaces representing various features of a collection. To name a few:

ICollectionValue : IEnumerable - readonly collection with featues such as Count, FindAll, ToArray, etc.

IExtensible : ICollectionValue - collection that allows adding items

ICollection : IExtensible - fully flagged collection with all (and a few extra) the features of System.Collections.Genric.ICollection

I havent used C5 in any serious development (not only because it is in prelease version and the home bage haven't been modified since 2004) but I like many of the ideas implemented in it.