April 2006 - Posts

Performing builds using Visual Studio 2005 Team Foundation Server on a regular basis seems to be attractive, isn't it? Starting a build simply comes down to an invocation of the online build server included with the product. Quite some people have been writing clients to invoke the webservice. However, TFS comes with a (command-line) tool called tfsbuild.exe that performs this job for you. Thanks to this, scheduling a build is pretty straightforward to do using Scheduled Tasks in Windows. The following script works like a charm if your build types don't have spaces in it:

@echo off

if "%1" == "" goto Help
if /i "%1" == "-h" goto Help

set server=%1
set project=%2
set buildType=%3

set schedule=%4
set startTime=%5
set startDate=%6

set schName=%2_%3

set tfsCommand="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\TfsBuild.exe start %server% %project% %buildType%"

set user=%userdomain%\%username%
echo %tfsCommand%

schtasks /create /sc %schedule% /tn %schName% /tr %tfsCommand% /st %startTime% /sd %startDate% /ru %user% /rp *
Goto Done

:Help
@echo Usage: schbuild TeamfoundationServer TeamProject BuildType Schedule StartTime StartDate
@echo.
@echo     TeamfoundationServer   The Team Foundation server.
@echo.
@echo     TeamProject            Team project name.
@echo.
@echo     BuildType              Build Type name.
@echo.
@echo     Schedule               Specifies the schedule frequency.
@echo                            Valid schedule types: MINUTE, HOURLY,
@echo                            DAILY, WEEKLY, MONTHLY, ONCE.
@echo.
@echo     StartTime              Time to start the build in HH:MM:SS
@echo                            (24 hour format)
@echo.
@echo     StartDate              Specifies the first date on which the
@echo                            task runs. The format is mm/dd/yyyy.

:Done

If the BuildType includes a space however, you'd have to type something like:

schbuild.bat buildmachine123 OurProject "Server Core Engine" DAILY 03:10:00 04/01/2006

In such a case you can either add the task manually or re-write the script.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Gerd - the EMEA Events Manager for TechEd and IT Forum - is blogging about the TechEd 2006 organisation which is on schedule. The website will be live and registration will open in May. And last but not least, Bill Gates will deliver a keynote on Friday morning. Check it out on Gerd's blog at http://blogs.msdn.com/gerdde.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Last week, Microsoft released the RC1 of "VS2005 Web Application Project" (abbreviated WAP) which is a new project type, providing an alternative to the Web site project model already available in Visual Studio 2005, especially to assist in migrating VS2003.NET projects to the new web application approach taken in VS2005. Download it here: Visual Studio 2005 Web Application Projects (RC1). More information will become available on http://webproject.scottgu.com/ as well.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

According to Netcraft, Microsoft gained about 4.71 percent web server market share. I'm happy to see this evolution: IIS and ASP.NET are really great pieces of technology and a lot has been proven on the field of security and reliability in the last couple of years (Code Red was a big security turn-over in IIS' history). On to a big IIS7 release...


Source: NetcraftDel.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Check out Paul Flessner's update on SQL Server 2005 on http://www.microsoft.com/sql/letter.mspx. The SVP for data technologies (including SQL Server) announced a new edition of SQL Server, called SQL Server Everywhere Edition, which will be a lightweight database engine that can be embedded in applications and is due to be released by the end of this calendar year. Another announcement is SQL Server AwaysOn Technologies to ensure higher uptimes using database mirroring, failover clustering, database snapshots, and enhanced online operations.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Today Microsoft announced that Virtual Server 2005 R2 is now available as a free download. This also will apply to the forthcoming service pack 1 of Virtual Server 2005 R2.

I guess no additional comment is required. Because virtualization technology becomes more and more important to realize the DSI story, Microsoft decided to make Virtual Server 2005 R2 available for free, also providing support for non-Microsoft operating systems through add-ins. More information can be found in the official Market Bulletin too.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Just saw a little piece of code where one has been messing up those two concepts of readonly variables and constants. So, what's the difference? Let's take a look.

Readonly variables

Take a look at the following piece of code:

public class ReadOnly
{
   private readonly int r = 1; //variable initialization upon declaration is possible for readonly variables

   public ReadOnly()
   {
      r = 2; //assignment to a readonly variable is possible in the constructor
   }

   public int R
   {
      get { return r; }
      set { r = value; } //this line won't compile because r is declared a readonly
   }
}

Basically, readonly variables act as normal variables except for the places where they can be assigned to, which are limited to the place where the declaration is done and in the constructor. Assignment to a readonly variable is prohibited everywhere else. Internally, everywhere you refer to the readonly variable, a runtime call will be done to get the value (e.g. for a field, a ldfld instruction will be used to get the value at runtime). You can see this in - of course - ildasm:

.method public hidebysig specialname instance int32 get_R() cil managed
{
   // Code size 12 (0xc)
   .maxstack 1
   .locals init (int32 V_0)
   IL_0000: nop
   IL_0001: ldarg.0
   IL_0002: ldfld int32 ReadOnly::r
   IL_0007: stloc.0
   IL_0008: br.s IL_000a
   IL_000a: ldloc.0
   IL_000b: ret
} // end of method ReadOnly::get_R

The other code might look at bit strange but basically the system gets the reference to the ReadOnly instance, then retrieves the value of the r variable (private member) and stores it in a local which is then ready to be returned to the caller. It would be a good excercise to try to optimise this code (have fun!). Of course elimination of nop won't give you any credits :-). Now take a look at the following piece of code, without a property:

public class ReadOnly
{
   public readonly int R = 12345;
}

Compile this to a library using csc.exe /t:library readonly.cs. Now create the following file:

using System;

class ReadOnlyTest
{
   public static void Main()
   {
      ReadOnly ro = new ReadOnly();
      Console.WriteLine(ro.R);
   }
}

And compile it with csc.exe /r:readonly.dll readonlytest.cs. Execution of the create executable assembly will print 12345 of course. No magic involved over here. The IL looks like this:

IL_0001: newobj instance void [ReadOnly]ReadOnly::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldfld int32 [ReadOnly]ReadOnly::R
IL_000d: call void [mscorlib]System.Console::WriteLine(int32)

The field is reffered to in the ldfld call again. Go back to ReadOnly.cs and change the code as follows:

public class ReadOnly
{
   public readonly int R = 54321;
}

Recompile ReadOnly.cs using csc.exe /t:library readonly.cs but don't recompile ReadOnlyTest.cs. When calling ReadOnlyTest.exe now, the system will print 54321, the value which was changed in the class library assembly.

You might wonder how read only variables differ from "normal" variables at runtime. Start by looking at the IL of the ReadOnly.dll file where you'll see the following declaration of our readonly variable:

.field public initonly int32 R

The initonly over here makes the difference with other declaration of (non-readonly) variables. Now, where is the value initialised? The answer is that code is injected in the constructor, before the call to the supertype constructor ("base"):

.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
   // Code size 19 (0x13)
   .maxstack 8
   IL_0000: ldarg.0
   IL_0001: ldc.i4 0x3039
   IL_0006: stfld int32 ReadOnly::R
   IL_000b: ldarg.0
   IL_000c: call instance void [mscorlib]System.Object::.ctor()
   IL_0011: nop
   IL_0012: ret
} // end of method ReadOnly::.ctor

Another question you might have is whether the runtime enforces the read-only character of a variable while executing the application? You can find the answer by doing the following:

  1. Execute ildasm.exe /out:readonlytest.il readonlytest.exe
  2. Open readonlytest.il with notepad, find the Main method code and replace it with:

      .method public static void Main()
      {
        .entrypoint
        .locals init (class [ReadOnly]ReadOnly V_0)
        newobj     instance void [ReadOnly]ReadOnly::.ctor()
        stloc.0
        ldloc.0
        ldc.i4     0x1234
        stfld      int32 [ReadOnly]ReadOnly::R
        ret
      }

  3. Assemble this modified piece of code using ilasm.exe readonlytest.il.
  4. Execute readonlytest.exe which should work smoothly.

From the previous demo you can see that runtime did not enforce the read-only character of the field. It's up to compilers to make sure read-only fields are not assigned to. By the way, doing the things I did in the previous demo results in non-verifiable code.

Constants

A heavy statement upfront: constants are totally different from read-only variables. Going a little further, constants simply don't exist at runtime. But first of all some correct terminology. In C# we're talking about a constant whileas in terms of the CLI we're talking about literals. I'll use both mutually but those terms point to the same thing: a constant-being literal value. Consider the following:

public class Constant
{
   public const int C = 12345;
}

and save it to constant.cs. Compile it with csc.exe /t:library constant.cs resulting in a constant.dll file. Opening this file using ildasm reveals the following declaration:

.field public static literal int32 C = int32(0x00003039)

Other than with read-only variables, you won't find any code in the constructor to initialize the value of C. All there is, is the static literal with assignment kind of thing from the previous line. Also notice that - although the C# definition doesn't mention static - the IL code contains the static keyword. Let's create a consumer class now:

using System;

class ConstantTest
{
   public static void Main()
   {
      Console.WriteLine(Constant.C);
   }
}

Compile it with csc.exe /r:constant.dll constanttest.cs and run it with constanttest.exe. The system will display 12345 on the screen. Now delete the constant.dll file using erase constant.dll and re-run constanttest.exe. The application will still run. Try doing the same with our readonly.dll file and re-run readonlytest.exe. The system will crash with the following:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'ReadOnly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'ReadOnly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
   at ReadOnlyTest.Main()

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

The piece in green actually shows how the CLR now (v2.0) reports how to turn "Fusion" on (see my blog post on To NGen or not to NGen for more information on Fusion).

From this experiment, you can deduce that constants don't really exist at runtime. Instead, the compiler copies the exact value of the constant to every place where the constant is used. To get this value, the compiler looks at the metadata of the referred file (in this case constant.dll's literal field C). The result in our constanttest.exe file is this:

.method public hidebysig static void Main() cil managed
{
   .entrypoint
   // Code size 13 (0xd)
   .maxstack 8
   IL_0000: nop
   IL_0001: ldc.i4 0x3039
   IL_0006: call void [mscorlib]System.Console::WriteLine(int32)
   IL_000b: nop
   IL_000c: ret
} // end of method ConstantTest::Main

As you can see, the constant's value is copied to the place where the constant was referred to. Thus, changing the value in constant.cs and recompiling constant.cs to constant.dll doesn't change the behavior of constanttest.exe. Even more, constanttest.exe doesn't require constant.dll at all while running the application. The assembly's manifest even doesn't contain an import of constant.dll:

.assembly extern mscorlib
{
   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
   .ver 2:0:0:0
}

However, the manifest of readonlytest.exe does contain a reference to readonly.dll:

.assembly extern mscorlib
{
   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
   .ver 2:0:0:0
}
.assembly extern ReadOnly
{
   .ver 0:0:0:0
}

Conclusion

Now the big warning. Don't use constants if you expect the value to change ever. Things such as a national tax percentage are not constant values. Mathematical stuff such as pi or e are constant till the next Einstein is born (and even then, they will survive :-)).

Some other useful notes:

  1. The metadata associated with a constant is also used for reflection. So, using reflection you can get the value of a constant live from the original assembly file but of course this implies a performance penalty.
  2. Whenever you're in doubt, prefer a read-only variable over a constant. Constants are really just an easy way to do copy-paste and to reduce maintenance when it would change (although changes are not propagated to other assemblies till recompilation is peformed).
  3. Constants are a maintenance hell when they are exposed outside an assembly. The highest level of visibility of a constant value should be friend (C#'s internal) to reduce constant propagation to the types defined in the assembly itself.
  4. To limit the propagation of a constant outside an assembly, you can also wrap the value in a public readonly property:

    private const int C = 12345;

    public int C { get { return C; } }


    which will only result in a literal copy of the constant in the get_C method body.
  5. Constants are always declared as static. This means that you can't use the following in C# (from our example):

    int c = new Constant().C;

    Only the following will work:

    int c = Constant.C;

Have fun and don't get caught by this any longer.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

What is it?

The principle of exceptions is a pretty easy-to-understand way to report exceptional situations to the consumer of a piece of code. Instead of using (artificial) HRESULT return values like this was the case in the (COM) past, exception handling is an object-oriented way to cope with exceptional situations. Basically, an exception object is an instance of some class (some == any class) which is thrown to when something exceptional goes wrong, for example a file I/O operation problem when a file is locked. The use of object types that inherit from System.Exception is actually not a direct requirement of the CLR (or the Virtual Execution System or VES). Essentially, exceptions are thrown when the current piece of code can't deal with the problematic situation and wants the caller to handle it further on. In order to handle such exceptions, a block of code must be protected which results in a so-called "protected block".

Throwing exceptions

We'll start by taking a look at throwing exceptions. If - on a certain point of the execution - you come to a point that you can't deal with yourself, you'll have to report this situation to the caller by throwing an exception. The first thing to do, is to decide which exception object to throw. You can use an existing exception (for example System.IO.IOException) or define an exception type yourself by inheriting from System.Exception (which is recommended when creating your own frameworks). Although the Common Language Infrastructure (CLI) allows any type of object to be used as an exception, the Common Language Specification (which aims to define a specification to allow for cross-language interoperability) dictates that every exception object is of type System.Exception (or a subtype). In order to define such a custom exception type, follow the next recommended rules:

  • Do not inherit directly from System.Exception but from System.ApplicationException;
  • Use Exception as the suffix of every exception class;
  • Provide at least the following three constructors:

    ...Exception() : base() {}
    ...Exception(string message) : base(message) {}
    ...Exception(string message, Exception innerException) : base(message, innerException) {}
     
  • Localize message strings and make sure the description message is correct from a linguistic point of view;
  • Chain exceptions using InnerException;
  • Prefer exceptions over error codes;
  • Do not throw exceptions as part of the normal control flow, only use it in exceptional situations (in a "normal program execution" no exceptions should occur);
  • Provide additional valuable information about the exception by defining extra properties wherever appropriate.

The throw statement takes the object on top of the stack and throws it as an exception. A typical piece of IL looks as follows:

newobj instance void MyException::.ctor()
throw

When an exception is thrown, a stack trace is created to trace back the origin of the exception.

Protected blocks

Catching exceptions is done by declaring a protected block (a.k.a. a try block or a guarded block) as we told before. Things brings us to the assiociated handlers:

  • a fault handler is called whenever an exception occurs but is not called as part of the normal control flow;
  • a type-filtered handler handles exceptions of a specified type (or subtype of the specified type) and is only called when such an exception was thrown, again it's not called as part of the normal control flow;
  • a user-filtered handler decides whether to handle an exception or not based on custom logic; if the test passes the handler will cope with the exception, otherwise the exception survives;
  • a finally handler is executed under any circumstance, regardless whether an exception occurs or not and can be used to close critical resources such as files or handles.

A protected region is a set of IL instructions marked as a try block which can have one or more handlers associated with it. Whenever an exception occurs within that try block, the CLR comes into play and takes over the execution flow to start executing the handler that was selected to deal with the exception (if any). If no handler was found, the exception is propagated up the call stack. Also notice I said "whenever an exception occurs", which does not necessarily mean that an exception was thrown by the called code. Rather, the runtime can also throw an exception under exceptional circumstances. Examples include a DivideByZeroException, a StackOverflowException, an OutOfMemoryException, a NullReferenceException, a MissingMethodException, etc.

Try and catch

Let's take a look at the underlying IL support to define protected blocks:

.try
{
   // code block
}

There's also an alternative which will be covered further on, but first we'll take a closer look at handler blocks. Basically, a handler block is nothing more than a block of IL code but used in the context of exception handling. One such a block is of course the well-known catch block which performs type-filtered exception handling:

.try
{
   // code block
}
catch MyException
{
   // exception handler code block
}

Actually this looks pretty much like C#, just because the sample is stripped down quite a bit. For example, we omitted the code to leave the try block and catch block when the blocks reach their end. This is required and looks as follows:

.try
{
   // code block
   leave afterTryCatchBlock
}
catch MyException
{
   // exception handler code block
   leave afterTryCatchBlock
}
afterTryCatchBlock: ...

Let's try to create a first example purely by using IL code. Open a Visual Studio 2005 Command Prompt, open Notepad and create a file called demo1.il. Copy the following into it:

.assembly Demo1
{
}

.class Demo1 extends [mscorlib]System.Object
{
   .method public static void Main()
   {
      .entrypoint
      .try
      {
         call void Demo1::Do2()
         leave.s exitTryCatchBlock
      }
      catch MyException
      {
         leave.s exitTryCatchBlock
      }
      exitTryCatchBlock: ret
   }

   .method private static void Do2()
   {
      newobj instance void MyException::.ctor()
      throw
   }

   .method public instance void .ctor()
   {
      ldarg.0
      call instance void [mscorlib]System.Object::.ctor()
      ret
   }
}

.class MyException extends [mscorlib]System.ApplicationException
{
   .method public instance void .ctor()
   {
      ldarg.0
      call instance void [mscorlib]System.Exception::.ctor()
      ret
   }
}

Next, assemble the IL code using ilasm.exe by calling ilasm.exe demo1.il. This will create an executable demo1.exe which can be executed. Let's make it a bit more fancy and put something on the screen about the exception (demo2.il):

.assembly Demo2
{
}

.class Demo2 extends [mscorlib]System.Object
{
   .method public static void Main()
   {
      .entrypoint
      .try
      {
         call void Demo2::Do2()
         leave.s exitTryCatchBlock
      }
      catch MyException
      {
         call instance string [mscorlib]System.Exception::get_Message()
         call void [mscorlib]System.Console::WriteLine(string)
         leave.s exitTryCatchBlock
      }
      exitTryCatchBlock: ret
   }

   .method private static void Do2()
   {
      ldstr "Test"
      newobj instance void MyException::.ctor(string)
      throw
   }

   .method public instance void .ctor()
   {
      ldarg.0
      call instance void [mscorlib]System.Object::.ctor()
      ret
   }
}

.class MyException extends [mscorlib]System.ApplicationException
{
   .method public instance void .ctor(string)
   {
      ldarg.0
      ldarg.1
      call instance void [mscorlib]System.Exception::.ctor(string)
      ret
   }
}

I mentioned there's also an alternative to declare a protected block and to cope with a handler. Instead of using the curly brace syntax, you can also put the whole .try ... catch "statement" on one single line referring to the various blocks, as follows (demo3.il):

.assembly Demo3
{
}

.class Demo3 extends [mscorlib]System.Object
{
   .method public static void Main()
   {
      .entrypoint
      IL_0001: call void Demo3::Do3()
      IL_0002: leave.s IL_0006
      IL_0003: call instance string [mscorlib]System.Exception::get_Message()
      IL_0004: call void [mscorlib]System.Console::WriteLine(string)
      IL_0005: leave.s IL_0006
      IL_0006: ret
      .try IL_0001 to IL_0002 catch MyException handler IL_0003 to IL_0005
   }

   .method private static void Do3()
   {
      ldstr "Test"
      newobj instance void MyException::.ctor(string)
      throw
   }

   .method public instance void .ctor()
   {
      ldarg.0
      call instance void [mscorlib]System.Object::.ctor()
      ret
   }
}

.class MyException extends [mscorlib]System.ApplicationException
{
   .method public instance void .ctor(string)
   {
      ldarg.0
      ldarg.1
      call instance void [mscorlib]System.Exception::.ctor(string)
      ret
   }
}

Defining multiple catch blocks is of course not a problem too. Assume a piece of code can throw a MyFirstException and a MySecondException exception both deriving from System.ApplicationException directly, then you could write the following guard:

.try
{
   // do something
   leave.s exitTryCatchBlock
}
catch MyFirstException
{
   // catch it somehow
   leave.s exitTryCatchBlock
}
catch MySecondException
{
   // catch it somehow
   leave.s exitTryCatchBlock
}
exitTryCatchBlock: // continue after the block

Of course the alternative one-line syntax can be used too. For multiple catch blocks and using more friendly-named labels, this looks pretty cute:

.try BeginTry1 to EndTry1
  catch MyException
    handler BeginMyExceptionHandler to EndMyExceptionHandler
  catch MySecondException
    handler BeginMySecondExceptionHandler to EndMySecondExceptionHandler

<Warning>

Take a look at the following piece of code:

.try
{
   // do something which throws MyException
   leave.s exitTryCatchBlock
}
catch [mscorlib]System.Exception
{
   ldstr "First"
   call void [mscorlib]System.Console::WriteLine(string)
   leave.s exitTryCatchBlock
}
catch MyException
{
   ldstr "Second"
   call void [mscorlib]System.Console::WriteLine(string)
   leave.s exitTryCatchBlock
}
exitTryCatchBlock: // continue after the block

This piece of code will always print "First" on the screen because the System.Exception catch block is investigated prior to investigating the MyException catch block. Essentially, once you have a block catch A { .. } all further catch blocks that specify a type that derives from A are unreachable. In contrast, the following piece of code will print "Second":

.try
{
   // do something which throws MyException
   leave.s exitTryCatchBlock
}
catch MyException
{
   ldstr "Second"
   call void [mscorlib]System.Console::WriteLine(string)
   leave.s exitTryCatchBlock
}
catch [mscorlib]System.Exception
{
   ldstr "First"
   call void [mscorlib]System.Console::WriteLine(string)
   leave.s exitTryCatchBlock
}
exitTryCatchBlock: // continue after the block

Notice that the Visual Basic compiler and the C# compiler will generate a warning and an error respectively if a catch block is unreachable (different behavior depending on the language compiler):

warning BC42029: 'Catch' block never reached, because 'MyException' inherits from 'System.Exception'.
error CS0160: A previous catch clause already catches all exceptions of this or of a super type ('System.Exception')

</Warning>

Catch it all

Sometimes you just want to catch every possible exception that occurs in a guarded block (for example in the entrypoint of the application to terminate the application in a friendly fashion in case of an unforeseen non anticipated exception). This is done using a catch-all block which is in fact just a higher-level language construct. An example in C# is the following:

try
{
   // do something
}
catch
{
   // catch all exceptions
}

In Visual Basic this looks like:

Try
   ' do something
Catch
   ' catch all exceptions
End Try

As the matter in fact, both pieces of code produce different IL. This is the C# way of working:

.try
{
   IL_0002: call void Ex::Do()
   IL_0009: leave.s IL_0016
} // end .try
catch [mscorlib]System.Object
{
   IL_000b: pop
   IL_000d: call void Ex::Clean()
   IL_0014: leave.s IL_0016
} // end handler

In Visual Basic you'll get something slightly different:

.try
{
   IL_0000: call void Ex::Do()
   IL_0005: leave.s IL_0018
} // end .try
catch [mscorlib]System.Exception
{
   IL_0007: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError(class [mscorlib]System.Exception)
   IL_000c: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
   IL_0011: call void Ex::Clean()
   IL_0016: leave.s IL_0018
} // end handler

<Remark>
Wondering what the SetProjectError and ClearProjectError stuff is used for in Visual Basic? The answer is to support backward compatibility with On Error syntax.
</Remark>

The piece of code we're looking at right now is the piece which contains the catch clause. As you can see, C# follows the CLI convention by using System.Object as the root for exceptions whileas Visual Basic follows the CLS. However, this does not mean you can do something like

throw new MyClassNotDerivingFromException();

in C# which would result in the following compiler error:

error CS0155: The type caught or thrown must be derived from System.Exception

In most cases however, you'll code a catch-all using System.Exception in the "catch clause signature", at least when you want to do something with the exception object such as getting the Message property value:

try
{
   // do something
}
catch (Exception ex)
{
   // catch all exceptions
}

In Visual Basic this looks like:

Try
   ' do something
Catch ex As Exception
   ' catch all exceptions
End Try

Notice C# also allows you to write this:

try
{
   // do something
}
catch (Exception)
{
   // catch all exceptions
}

Finally handlers

As mentioned before, a finally handler is called under any circumstance no matter whether an exception has occurred or not. In a higher-level language this might look as follows:

try
{
   Do();
}
catch (MyException ex)
{
   Console.WriteLine("Catch");
}
finally
{
   Console.WriteLine("Finally");
}

First of all, you can omit the catch block if you don't need it. In such a case, the IL code is rather predictable (you can infer it from the following piece of code). However the sample above has a combined catch and finally block, which gets translated into two nested .try blocks:

 .try
{
   .try
   {
      call void Demo5::Do()
      leave.s exitSecondTry
   }
   catch MyException
   {
      ldstr "Catch"
      call void [mscorlib]System.Console::WriteLine(string)
      leave.s exitFirstTry
   }
   exitFirstTry: leave.s exitSecondTry
}
finally
{
   ldstr "Finally"
   call void [mscorlib]System.Console::WriteLine(string)
   endfinally
}
exitSecondTry: ret

Executing this piece of code will always print "Finally" on the screen. Whether "Catch" is printed on the screen depends on the guarded block's behavior (i.e. whether the call to Do() throws a MyException). Notice the mandatory endfinally instruction at the bottom of the finally block. I guess you're mature enough now to find out how to ilasm this piece of code inside a valid .il file. Again a shorthand syntax can be used looking like this:

.try IL_abc to IL_def finally handler IL_ghi to IL_jkl

Another place where the finally clause is used (implicitly) is the IDisposable pattern in combination with the using block syntax in C# and (since .NET 2.0) also in Visual Basic. Assume the following piece of C# code:

using (new Ex())
{
   //do something
}

on a class defined as

class Ex : IDisposable
{
   public void Dispose() {}
}

which translates into the following piece of IL (cut needless pieces):

IL_0001: newobj instance void Ex::.ctor()
IL_0006: stloc.1
.try
{
   IL_0009: leave.s IL_001b
} // end .try
finally
{
   IL_000b: ldloc.1
   IL_000c: ldnull
   IL_000d: ceq
   IL_000f: stloc.2
   IL_0010: ldloc.2
   IL_0011: brtrue.s IL_001a
   IL_0013: ldloc.1
   IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose()
   IL_001a: endfinally
} // end handler
IL_001b: nop

Basically the code matches to the following:

Ex ex = new Ex();
try
{
   //do something
}
finally
{
   if (ex != null)
      ex.Dispose();
}

Fault handlers

You just saw that finally handlers are called regardless of the result of the guarded block. A fault handler is slightly different in a sense that the fault block is only called when an exception has occurred after which the exception keeps propagating up the stack (unless the whole thing is embedded in yet another guard block that catches the exception of course). An example will make things more clear:

.method public static void Main()
{
   .entrypoint
   .try
   {
      call void Demo6::Do2()
      leave.s exitTry
   }
   fault
   {
      ldstr "Fault"
      call void [mscorlib]System.Console::WriteLine(string)
      endfault
   }
   exitTry: ret
}

Again Do2() is the bad guy throwing a MyException exception. The application will crash but "Fault" will be printed on the screen. Actually the fault handler has had the chance to do some work but leaving the exception alone. However, this feature is (as far as I know) not exposed through the well-known .NET languages such as C# and Visual Basic (well, honestely, I know about a case in which the C++ compiler takes advantage of a fault-block to "fake" deterministic finalization when you have declared a finalizer using the !ClassName() syntax). You can get a similar behavior by combining a catch and (re)throw. As a little side-note I want to mention that endfault is just an alias for endfinally and both translate to the same opcode.

User-filtered handlers

The last type of handler supported by the CLR is the so-called user-filtered handler, or shortly "filters". In my opinion filters are a great piece of technology but unfortunately it's only available to Visual Basic developers (thus not for C# developers) which is a pitty because C# would - again in my opinion - benefit from this, altough it's possible (as I'll show below) to accomplish the same in C# with some other piece of code (although there is some difference in performance). But let's get start by taking a look at a little example in Visual Basic that uses filters:

Imports System

Module When1 'When is a keyword, so we need to use When1 for our method name because the lack of context-sensitivity in the compiler
   Public Sub Main()
      TestWithFilter()
      TestWithoutFilter()
   End Sub

   Public Sub TestWithFilter()
      Try
         Do2
      Catch ex As MyException When ex.Code = 1
        
'Catch it
      End Try
   End Sub

   Public Sub TestWithoutFilter()
      Try
         Do2
      Catch ex As MyException
         If ex.Code = 1 Then
            'Catch it
         Else
            Throw
         End If
      End Try
   End Sub

   Private Sub Do2 'Do is a keyword, so we need to use Do2 for our method name because the lack of context-sensitivity in the compiler
      Throw New MyException(1)
   End Sub
End Module

Class MyException
Inherits Exception
   Public Code As Integer
   Public Sub New(code as Integer)
      MyBase.New()
      Me.Code = code
   End Sub
End Class

Both the TestWithFilter and TestWithoutFilter have the same behavior. However, the first one uses user-defined filters whileas the other one uses procedural code to determine whether the exception should be caught and rethrows the exception (Check out my blog post about "To throw or to rethrow?" too for more advanced information on rethrowing exception.) if that's not the case. So, how does this piece of magic filtering look like in terms of IL-code? A quick peek:

.method public static void TestWithFilter() cil managed
{
   // Code size 49 (0x31)
   .maxstack 3
   .locals init (class MyException V_0)
   IL_0000: call void When1::Do2()
   IL_0005: leave.s IL_0030
   IL_0007: isinst MyException
   IL_000c: dup
   IL_000d: brtrue.s IL_0013
   IL_000f: pop
   IL_0010: ldc.i4.0
   IL_0011: br.s IL_0026
   IL_0013: dup
   IL_0014: stloc.0
   IL_0015: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError(class [mscorlib]System.Exception)
   IL_001a: ldloc.0
   IL_001b: ldfld int32 MyException::Code
   IL_0020: ldc.i4.1
   IL_0021: ceq
   IL_0023: ldc.i4.0
   IL_0024: cgt.un
   IL_0026: endfilter

   IL_0028: pop
   IL_0029: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
   IL_002e: leave.s IL_0030
   IL_0030: ret
   .try IL_0000 to IL_0007 filter IL_0007 handler IL_0028 to IL_0030
} // end of method When1::TestWithFilter

The last line is the most important one, containing the (short-hand syntax'd) try block declaration, including the filter. Here is how it works:

  1. Line IL_0000 to IL_0007 are executed under the vigilant try block looking for exceptions to occur. Actually, in ... to ... regions you have to exclude the last referred line, so in reality lines IL_0000 to IL_0005 are guarded.
  2. The .try block has one handler associated, being a user-defined filter defined on line IL_0007 and running till the endfilter statement is encountered. The filter leaves a value on the stack indicating whether the filter test passes (EXCEPTION_EXECUTE_HANDLER) or not. Basically, a 1 value is used to indicate the filter passes whileas 0 indicates a failure (EXCEPTION_CONTINUE_SEARCH). Actually this approach is borrowed from SEH in Windows (see Platform SDK for more information, look for Structured Exception Handling).
  3. And last but not least, the associated handler logic can be found in lines IL_0028 to IL_002e (again, exclude the last referred line).

Doing the same in C# requires you to take the TestWithoutFilter-like approach:

   void TestWithoutFilter()
   {
      try
      {
         Do2();
      }
      catch (MyException ex)
      {
         if (ex.Code == 1)
            // Catch it
         else
            throw;
      }
   }

This approach has one drawback however: performance. Let's take a look at a complete (self-written) lightweight IL-sample of filtering:

.assembly Demo7
{
}

.class public Demo7 extends [mscorlib]System.Object
{
   .method public static void WithFilter()
   {
      IL_0000: call void Demo7::Do2()
      IL_0001: leave.s IL_0020
      IL_0002: dup                           // _ ex ex
      IL_0003: isinst MyException            // _ ex (ex is MyException)
      IL_0004: brtrue.s IL_0008              // _ ex
      IL_0005: pop                           // _
      IL_0006: ldc.i4.0                      // _ 0
      IL_0007: br.s IL_000b                  // _ 0
      IL_0008: ldfld int32 MyException::Code // _ ex.Code
      IL_0009: ldc.i4.1                      // _ ex.Code 1
      IL_000a: ceq                           // _ (ex.Code == 1)
      IL_000b: endfilter
      IL_0010: nop //ldstr "You have been caught"
      IL_0011: nop //call void [mscorlib]System.Console::WriteLine(string)
      IL_0012: leave.s IL_0020
      IL_0020: ret
      .try IL_0000 to IL_0002 filter IL_0002 handler IL_0010 to IL_0020
   }

   .method public static void WithoutFilter()
   {
      IL_0000: call void Demo7::Do2()
      IL_0001: leave.s IL_0020
      IL_0002: ldfld int32 MyException::Code // _ ex.Code
      IL_0003: ldc.i4.1                      // _ ex.Code 1
      IL_0004: ceq                           // _ (ex.Code == 1)
      IL_0005: brtrue.s IL_0010              // _
      IL_0006: rethrow
      IL_0010: nop //ldstr "You have been caught"
      IL_0011: nop //call void [mscorlib]System.Console::WriteLine(string)

      IL_0012: leave.s IL_0020
      IL_0020: ret
      .try IL_0000 to IL_0002 catch MyException handler IL_0002 to IL_0020
   }

   .method private static void Do2()
   {
      ldc.i4.1
      newobj instance void MyException::.ctor(int32)
      throw
   }

   .method public instance void .ctor()
   {
      ldarg.0
      call instance void [mscorlib]System.Object::.ctor()
      ret
   }
}

.class MyException extends [mscorlib]System.ApplicationException
{
   .field public int32 Code

   .method public instance void .ctor(int32)
   {
      ldarg.0
      call instance void [mscorlib]System.Exception::.ctor()
      ldarg.0
      ldarg.1
      stfld int32 MyException::Code
      ret
   }
}

This piece of sample code shows a basic filter without the Visual Basic plumbing (see WithFilter) as well as the equivalent with a catch-rethrow approach (see WithoutFilter). The fuchsia-colored piece of comment code is actually the stack transition graph which I'm adding for self-support while writing raw IL-code. Assemble the demo file using ilasm.exe /DLL demo7.il which generates a demo7.dll file. Notice that - for performance testing - I've disabled statements IL_0010 and IL_0011 by means of a nop statement. It's also important to mark the Demo7 class as public in order to be able to use it further on.

Because it's still possible to write code with C#, let's actually use our generated assembly from within C# to call the functionality and to perform some performance measurement. Create a file called Demo7Test.cs and add the following code:

using System;
using System.Diagnostics;

class Demo7Test
{
   public static void Main()
   {
      Stopwatch watch = new Stopwatch();
      watch.Start();
      for (int i = 0; i < 10000; i++)
         Demo7.WithoutFilter();
      watch.Stop();
      Console.WriteLine("Unfiltered: {0}", watch.Elapsed);

      watch.Start();
      for (int i = 0; i < 10000; i++)
         Demo7.WithFilter();
      watch.Stop();
      Console.WriteLine("Filtered: {0}", watch.Elapsed);
   }
}

Compile this piece of code using csc.exe /r:Demo7.dll Demo7Test.cs which will produce a .exe file consuming our .dll file (which we have written completely in IL). The result on my machine looks as follows:

Unfiltered: 00:00:00.3097402
Filtered: 00:00:00.5927644

From this, we could conclude filtering is slower than unfiltered exception handling with custom logic to find out whether the caught exception can be handled successfully based on certain criteria. However, we didn't test the rethrow path in this sample so everything will depend on the distribution of passes and failures in the filtering logic. Notice that although the When-clause of Visual Basic is part of the Catch syntax line, it doesn't get translated to a catch handler at all. Instead Catch ex As MyException When ex.Code = 1 gets translated to a filter that performs type-checking as its first check (isinst MyException). If I find some extra time ever, I'll continue to trace the bottleneck in the filtered piece of code in order to report more thorough investigations.

Conclusion

Exception management in .NET is far more complex than you might think at first glance. Also, not all .NET languages expose all of the exception management richness of the CLR platform underneath. One notable example is the lack of filters in C# whileas the VB guys have included this kind of support on the product (to boost developer's productivity should be the official explanation).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Yesterday, I've been to the Visual Basic 2005 On Tour event in Brussels. About 200 attendees were there to learn about the latest version of Visual Basic and how to port their existing applications from the old Visual Basic 6 ages to the new platform. Although there was not so much new stuff in for me, I had some pretty interesting discussions about Visual Basic versus C# and did a podcast with the Visual Basic 2005 product team members together with David Boschmans. I'll post the link to this podcast later on over here on my blog. Stay tuned!

Now on to the interesting discussion in the speaker room about language features in various .NET languages. For example, C# introduced operator overloading from day one whileas Visual Basic .NET lagged behind on that field. The same holds for the using construct to work with IDisposable objects. Today, VB2005 fixes those shortcomings and that's just great. Actually, there are also places where C# is missing features which are available in Visual Basic. One notable example of this observation is the lack of support for exception filters in C#. And that's (together with a lot of other exception management stuff) the subject of my next (large-n-geeky) blog post over here.Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Some years ago I created a WOL client for Visual Basic 6 using WinSock stuff which was a pretty nice project that wasn't so straightforward to do. Today, I'm creating a little lightweight management tool to apply configuration changes to computers in a network over night, even when the machines are asleep. Shutting down a machine after maintenance is pretty simple to do using the ExitWindowsEx API, but waking a machine up requires some WOL functionality. So I decided to recreate the application (which I couldn't find anymore in my messy non-existing archive ;-)) in managed code (.NET Framework 2.0). More information about WOL can be found on Wikipedia.

Here's the code:

using System;
using
System.Net;
using
System.Net.Sockets;

namespace
WakeOnLan
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] mac = new byte[] {0x00, 0x0F, 0x1F, 0x20, 0x2D, 0x35};
            WakeUp(mac);
        }

        /// <summary>
        /// Sends a Wake-On-Lan packet to the specified MAC address.
        /// </summary>
        /// <param name="mac">Physical MAC address to send WOL packet to.</param>
        private static void WakeUp(byte[] mac)
        {
            //
            // WOL packet is sent over UDP 255.255.255.0:40000.
            //
            UdpClient client = new UdpClient();
            client.Connect(IPAddress.Broadcast, 40000);

            //
            // WOL packet contains a 6-bytes trailer and 16 times a 6-bytes sequence containing the MAC address.
            //
            byte[] packet = new byte[17 * 6];

            //
            // Trailer of 6 times 0xFF.
            //
            for (int i = 0; i < 6; i++)
                packet[i] = 0xFF;

            //
            // Body of magic packet contains 16 times the MAC address.
            //
            for (int i = 1; i <= 16; i++)
                for (int j = 0; j < 6; j++)
                    packet[i * 6 + j] = mac[j];

            //
            // Submit WOL packet.
            //
            client.Send(packet, packet.Length);
        }
    }
}
Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts « Previous page - Next page »