Thursday, April 28, 2011

Cross Thread calls on WinForms

In a multithreaded WinForm app, one of the most common exceptions you'll see is in trying to access a form, or controls on a form, from a different thread than the one it was created on. Fortunately there is an easy way to check if a control is being accessed from the thread it was created on - the InvokeRequired property.

This simply checks if the handle was created on the same thread as the caller. If this Property is set to true then you need to marshal the call to the UI across the thread. There are methods provided for this too - use Invoke and BeginInvoke to correctly marshal the call to the thread that created the Control. From MSDN, Control.Invoke "Executes the specified delegate on the thread that owns the control's underlying window handle".

Most of the code snippets you see on the web for this are out-of-date. Although they work well there are better solutions using built-in features of .NET that results in less code (woo-hoo!).

The old way is to declare a custom delegate
public delegate void UpdateFormTextChanged(string message);

Then you will see that delegate being invoked from the form. If parameters are to be passed they are done in an object array (yuck).
   
public void UpdateProgressMessage(string message)
{
if (!InvokeRequired)
{
DownloadStatusTextBox.Text = message;
}
else
{
UpdateFormTextChanged updateText = SetProductName;
Invoke(updateText, new object[] { productName });
}
}

A simpler way of doing this without the need to create custom delegates is to use Action<T> which takes one parameter and returns void. You replace T with your parameter type making it strongly typed - no objects or object arrays.
public void UpdateProgressMessage(string message)
{
if (!InvokeRequired)
{
DownloadStatusTextBox.Text = message;
}
else
{
Invoke(new Action<string>(UpdateProgressMessage), message);
}
}

For a method with no parameter and void return type you can use the Action() method (in .NET 3.5 and higher) or MethodInvoker in .NET 2.0
   
public void ShowProgressForm()
{
if (!InvokeRequired)
{
ShowDialog();
BringToFront();
}
else
{
// .net 2.0
Invoke(new MethodInvoker(ShowProgressForm));
// .net 3.5 +
Invoke(new Action(ShowProgressForm));
}
}

For more than one parameter you can use one of the many overloads of Action<T>. But wait! I don't see any available in .NET 2.0. Yeah, .NET 2.0 includes Action<T> but not Action<T1, T2> or Func<T, TResult> etc. but it does support Generics of course so you can write your own delegates to mimic these 3.5 features. For example, if you want to call a method on a form that has two parameters - for example, updating a progress bar
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
public void UpdateProgress(int total, int downloaded)
{
if (!InvokeRequired)
{
ProgressBar.Maximum = total;
ProgressBar.Value = downloaded;
}
else
{
Invoke(new Action<int, int>(UpdateProgress), new object[] {total, downloaded});
}
}

Wednesday, April 27, 2011

Swallowing Exceptions (Gulp...)

I do not agree with the mantra that you should NEVER swallow exceptions. I know some people who will fight you on the spot for suggesting otherwise but like any rule there are always exceptions. Don't get me wrong, I think it is a great rule-of-thumb and should be followed most of the time but I've come across a case recently where I swallow exceptions and I don't feel guilty about it...

  • Logging throws an exception

Sometimes you don't care if logging fails. Sometimes logging is really not that important and you absolutely do not want to interrupt the application (and the Customer) just because logging has failed. Right?
try
{
Logger.Write(message);
}
catch
{
}

So there is a real-life scenarios where I think it is okay to swallow an exception...Here is a good discussion on the topic on StackOverflow

Comparing Anonymous Types

If you have multiple anonymous types that have the same Properties, with the same type and in the same order then the compiler treats them as the same type.

For example, if I have two anonymous types declared as follows

var a = new { Name = "Peter" };
var b = new { Name = "Peter" };

The compiler sees these as the same type (the Properties are both called Name, they are both of type string and all the Properties are in the same order). Because Anonymous Types inherit from System.Object you can check if these two instances are equal using Equals(). Anonymous Type instances will be equal if their properties are equal. So the following outputs "True" because the Name properties are equal (strings that match exactly).

Console.WriteLine(a.Equals(b));

However, if I changed the case of one the Names to "peter", this would result in "False" because the two properties are no longer equal - String overrides Equals and ignores case in the checking for equality. It is also worth noting that using operators when checking for equality will not give you the result you might be expecting. You cannot have any members in an Anonymous Type other than Read-Only Properties meaning you cannot override a method from System.Object including operators. So the following code results in "False".

var a = new { IsAnon = true };
var b = new { IsAnon = true };
Console.WriteLine(a == b);

Thursday, April 21, 2011

Changing Start Mode of a Windows Service

Recently I needed to change the Start Type of a Windows Service from another application. Some PCs were infected with the Conficker worm. One of the things this worm does is shut down some Windows features that might help in discovering/removing the worm. One of the services it affects is BITS - used in downloading Windows Updates - by stopping the service and changing it's start mode to Disabled.

There is a managed option in .NET - the System.ServiceProcess.ServiceController class which exposes some useful Properties and Methods for managing a Service. However, it provides no way to change the start mode of a Service. In looking into this I came across this question on StackOverflow which suggests the best way to achieve this is through the Win32 API using P/Invoke.

The awesome wiki pinvoke.net is a great resource to get started. It has helped me many times in the past and it certainly helped me to write some of this code here.

First of all we need to make calls to functions in the advapi.dll. We need to call ChangeServiceConfig, OpenSCManager and OpenService.

ChangeServiceConfig is where we can actually make the change we want to the Start Mode. But you need to pass this a handle to a service. So we also need to call OpenService. This in turn requires a handle to a SCManager so we need to call
OpenSCManager. Here is the code - feel free to use and improve. It is a static class that provides one method ChangeStartMode

public static class ServiceHelper
{
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern Boolean ChangeServiceConfig(
        IntPtr hService,
        UInt32 nServiceType,
        UInt32 nStartType,
        UInt32 nErrorControl,
        String lpBinaryPathName,
        String lpLoadOrderGroup,
        IntPtr lpdwTagId,
        [In] char[] lpDependencies,
        String lpServiceStartName,
        String lpPassword,
        String lpDisplayName);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr OpenService(
        IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);

    [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr OpenSCManager(
        string machineName, string databaseName, uint dwAccess);

    [DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")]
    public static extern int CloseServiceHandle(IntPtr hSCObject);

    private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
    private const uint SERVICE_QUERY_CONFIG = 0x00000001;
    private const uint SERVICE_CHANGE_CONFIG = 0x00000002;
    private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;

    public static void ChangeStartMode(ServiceController svc, ServiceStartMode mode)
    {
        var scManagerHandle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
        if (scManagerHandle == IntPtr.Zero)
        {
            throw new ExternalException("Open Service Manager Error");
        }

        var serviceHandle = OpenService(
            scManagerHandle,
            svc.ServiceName,
            SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);

        if (serviceHandle == IntPtr.Zero)
        {
            throw new ExternalException("Open Service Error");
        }

        var result = ChangeServiceConfig(
            serviceHandle,
            SERVICE_NO_CHANGE,
            (uint)mode,
            SERVICE_NO_CHANGE,
            null,
            null,
            IntPtr.Zero,
            null,
            null,
            null,
            null);

       if (result == false)
       {
           int nError = Marshal.GetLastWin32Error();
           var win32Exception = new Win32Exception(nError);
           throw new ExternalException("Could not change service start type: "
               + win32Exception.Message);
       }

       CloseServiceHandle(serviceHandle);
       CloseServiceHandle(scManagerHandle);
   }

To use this just provide an instance of ServiceController and a ServiceStartMode.

var svc = new ServiceController("BITS");
ServiceHelper.ChangeStartMode(svc, ServiceStartMode.Automatic);

// You can then Start the service if necessary. 
if (svc.Status != ServiceControllerStatus.Running)
{
   svc.Start();
}

// And of course you should close the service when no longer needed
svc.Close();
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.aspx

Wednesday, April 13, 2011

I love moq

Moq (pronounced "Mock-you" or just "Mock") is the only mocking library for .NET developed from scratch to take full advantage of .NET 3.5 (i.e. Linq expression trees) and C# 3.0 features (i.e. lambda expressions) that make it the most productive, type-safe and refactoring-friendly mocking library available.

Mocking frameworks allow you to mock out interfaces and then wield magical powers over them by having methods return whatever values you want, start firing events and even raise exceptions. All so you can focus on testing your code without the pain of setting up the implementation of the Interface to do all the various things it needs to do for you to properly exercise your code.

Set up a Property to return a certain value
_mockModel.Setup(m => m.Description).Returns("Description");

Fire an event from the mock with certain event args
_mockModel.Raise(m => m.DownloadStarted += null, EventArgs.Empty);

Raise an exception with certain arguments
_mockModel.Setup(m => m.ResumePendingDownload()).Throws(new InvalidOperationException("error"));

Verify (like NUnit's Assert) that a method was called on the mock with certain parameters
_mockView.Verify(v => v.ShowDownloadProgressView("Progress"));

Slightly more advanced setups can also be achieved with ridiculous ease.

Verify that a method was called on the mock but you don't know the exact parameters at design-time? You can use the It.IsAny<T> feature when you know the type expected.

_mockView.Verify(v => v.ShowDownloadProgressView(It.IsAny<string>());

Verify how many times a method is called
_mockView.Verify(v => v.ShowDownloadProgressView(It.IsAny<string>()), Times.Exactly(1));

Pretty cool...

Wednesday, April 6, 2011

Bug fixing TDD-style

So some code I wrote resulted in a bug. This is a natural part of software development of course. I'm reminded of that famous programming quote

"If debugging is the process of removing software bugs, then programming must be the process of putting them in."

The standard suggests we introduce a bug every 10 lines of code we write and I knew a programmer who could actually introduce a bug without writing anything ;)

So, how will I address this bug? Well, here is an oh-so-simple process that I follow.

1. Write a failing Unit Test that proves the bug
2. Fix the bug
3. Watch the test pass and smile

By writing the failing unit test first that recreates the bug, you are improving the unit test suite. You are also preventing that bug from happening again - you are closing the loop on it.