Monday, January 31, 2011

Don’t believe everything that Reflector tells you

Every .NET developer loves Reflector, since it gives us a chance to see inside assemblies that we don’t have the source for. And I’ve even read bloggers showing off the code that has been reverse engineered by it as evidence of poor coding practices at some organisation or another (“look, these guys use gotos!”). But though Reflector is a brilliant tool, its reverse engineering skills are not perfect. See this fairly innocent looking switch statement from some code I’m working on 

          case "gateway":
            SetValue(component, "@type", "decision", true);
            string xml = component.InnerXml;
            xml = xml.Replace("gateway", "decision");
            component.InnerXml = xml;

          case "deliverable":
          case "dataObject":
            SetValue(component, "@type", "document", true);

          case "annotation":
            SetValue(component, "@type", "note", true);

And this is what Reflector shows from the compiled assembly

        if (CS$4$0001 != null)
            if (!(CS$4$0001 == "gateway"))
                if ((CS$4$0001 == "deliverable") || (CS$4$0001 == "dataObject"))
                    goto Label_00B0;
                if (CS$4$0001 == "annotation")
                    goto Label_00C5;
                this.SetValue(component, "@type", "decision", true);
                string xml = component.InnerXml.Replace("gateway", "decision");
                component.InnerXml = xml;
        goto Label_00DA;
        this.SetValue(component, "@type", "document", true);
        goto Label_00DA;
        this.SetValue(component, "@type", "note", true);

Which I think proves my point…

Thursday, January 13, 2011

Better debugging of .NET services

For a long while I’ve been debugging a .NET service using the recommended approach. Whilst this works, it’s kind of painful. the steps are something like this

  1. Build the service
  2. Realise the service was already running. Stop it from the Services Control Panel applet.
  3. Build the service again
  4. Start the service from the Services Control Panel applet.
  5. Attach to the process from Visual Studio
  6. Realise the service has already executed the piece of code I wanted to debug.
  7. Goto step 1.

There had to be a better way. And a bit of Googling brought up this approach. But I didn’t really understand how it worked. I guess I’d assumed the error shown in Visual Studio when you try to debug a service was actually coming from Visual Studio, but I now realise the error is coming from .NET. So by having a different piece of code run when in debug mode, the service is treated like any old application.

My solution is slightly different so I can also test the service starting and stopping. My service implementation has StartService and StopService public methods, which are called from OnStart and OnStop. And my Main method looks like this.

    static void Main()
      #if (!DEBUG)
      ServiceBase[] ServicesToRun;
      ServicesToRun = new ServiceBase[] 
                new MyService() 
      WorkflowService service = new MyService();