Automatically run unit-tests when compiling in Visual Studio 2008

I’ve been getting into test-driven development lately and am absolutely loving it. However, it’s a pain to have to remember to run your tests each time you build. I’d prefer it that whenever I build my solution my tests are automatically run, and the results displayed to me.

In Visual Basic 2008, simply hit Alt-F11, and open your EnvironmentsEvents module. If you don’t have this module, simply create one, and paste the following code into it.

There is an extra feature here as well, cribbed from some smart guy. I’m building a DTF project as part of my solution which takes forever to compile, and locks Visual Studio up while it does. Therefore, I want to start compiling as soon as a project fails so I get a much faster turnaround.

Option Strict Off
Option Explicit Off

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90

Imports System.Diagnostics

Public Module EnvironmentEvents

#Region "Automatically generated code, do not modify"
'Automatically generated code, do not modify
'Event Sources Begin

      <System.ContextStaticAttribute()> Public WithEvents DTEEvents As EnvDTE.DTEEvents

      <System.ContextStaticAttribute()> Public WithEvents DocumentEvents As EnvDTE.DocumentEvents

      <System.ContextStaticAttribute()> Public WithEvents WindowEvents As EnvDTE.WindowEvents

      <System.ContextStaticAttribute()> Public WithEvents TaskListEvents As EnvDTE.TaskListEvents

      <System.ContextStaticAttribute()> Public WithEvents FindEvents As EnvDTE.FindEvents

      <System.ContextStaticAttribute()> Public WithEvents OutputWindowEvents As EnvDTE.OutputWindowEvents

      <System.ContextStaticAttribute()> Public WithEvents SelectionEvents As EnvDTE.SelectionEvents

      <System.ContextStaticAttribute()> Public WithEvents BuildEvents As EnvDTE.BuildEvents

      <System.ContextStaticAttribute()> Public WithEvents SolutionEvents As EnvDTE.SolutionEvents

      <System.ContextStaticAttribute()> Public WithEvents SolutionItemsEvents As EnvDTE.ProjectItemsEvents

      <System.ContextStaticAttribute()> Public WithEvents MiscFilesEvents As EnvDTE.ProjectItemsEvents

      <System.ContextStaticAttribute()> Public WithEvents DebuggerEvents As EnvDTE.DebuggerEvents

      <System.ContextStaticAttribute()> Public WithEvents ProjectsEvents As EnvDTE.ProjectsEvents

      <System.ContextStaticAttribute()> Public WithEvents TextDocumentKeyPressEvents As EnvDTE80.TextDocumentKeyPressEvents

      <System.ContextStaticAttribute()> Public WithEvents CodeModelEvents As EnvDTE80.CodeModelEvents

      <System.ContextStaticAttribute()> Public WithEvents DebuggerProcessEvents As EnvDTE80.DebuggerProcessEvents

      <System.ContextStaticAttribute()> Public WithEvents DebuggerExpressionEvaluationEvents As EnvDTE80.DebuggerExpressionEvaluationEvents

'Event Sources End

'End of automatically generated code

#End Region
    'The following code will run all tests following a successful solution build.
    '
    'Hooking into build events is discussed at
    'http://visualstudiohacks.com/general/customize-your-project-build-process/
    '
    'The macro code to run the tests was taken by recording a macro
    'and inspecting the generated code.

    'Flag to prevent tests running if a project fails to compile.
    Private runTests As Boolean

    Private Sub BuildEvents_OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildBegin
        runTests = True
    End Sub

    Private Sub BuildEvents_OnBuildProjConfigDone(ByVal Project As String, ByVal ProjectConfig As String, ByVal Platform As String, ByVal SolutionConfig As String, ByVal Success As Boolean) Handles BuildEvents.OnBuildProjConfigDone

        If Not Success Then
            runTests = False
            DTE.ExecuteCommand("Build.Cancel")
        End If
    End Sub

    Private Sub BuildEvents_OnBuildDone( _
        ByVal Scope As EnvDTE.vsBuildScope, _
        ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildDone

         If (Action = vsBuildAction.vsBuildActionBuild Or Action = vsBuildAction.vsBuildActionRebuildAll) And _
            Scope = vsBuildScope.vsBuildScopeSolution And _
            runTests Then

            DTE.ExecuteCommand("Test.RunAllTestsInSolution")

        End If
    End Sub
End Module

Environment.Exit – don’t use it

We all know the seven deadly sins – sloth, greed, envy, and so on. Well, today I found an eighth. I set up an automated system-test for a report generator we use at work. Basically, it will run the tool, and then interrogate the output to ensure it is correct (like a very large unit test). I wrote the test harness in the inbuilt test system in Visual Studio 2008, as I’m familiar with it.

Initially I set it up to call the “Main” method directly (it’s a console application), but quickly discovered that this wouldn’t work because the original developer had sprinkled Enviroment.Exit’s like they were fucking confetti. The effect of this was, of course, that whenever an exception was thrown, or the tool successfully completed (so, every single run, one way or the other), the test script would be killed so it would report as aborted. At this point, I looked like this:
Angry baby

The workaround I came up with in the end, as there was far too much code to re-engineer it, was to use the Process class to launch the app, and then check it’s return code. The big disadvantage here is that I can’t debug the code straight from the unit test.

I’m sure there’s some clever way to attach a debugger through code, but it would be better if it just didn’t use Environment.Exit in the first place.

Automatically deploying printers in a Windows 7/Windows Server 2003 environment

When he had a homogenous Windows XP/Windows Server 2003 environment, we were able to manage our printers by assigning them using the prnmngr.vbs script, called from a VBScript file.

However, when we introduced Windows 7 machines, the script no longer worked. The problem was that Windows now opened a dialog asking the user if they wanted to install the printer driver. As this was being run from a script, there was no user to accept the dialog, so the process silently failed.

The solution is to configuring the “Point and Print Restrictions” policy setting to “Disabled” in both User Configuration and Computer Configuration. This will allow for silent printer driver installation, and thus allow the printer to be mapped successfully. The reason we apply it to both Users and Computers is that Windows 7 ignores the User setting, while previous versions of Windows didn’t have the Computer setting.

You can simply create the relevant registry keys: http://support.microsoft.com/kb/888046. However, a better approach, if you have a Windows Server 2008 CD is to update it to

Or, you can update your ADM files. Run Windows Server 2008 AD Prep on your computers: http://support.microsoft.com/kb/888046

Once you have run AD Prep, you need to install the Windows 7 administration tools on a Windows 7 machine using http://www.microsoft.com/downloads/details.aspx?FamilyID=7d2f6ad7-656b-4313-a005-4e344e43997d&displaylang=en#filelist. Once you have done this, you can use the newer GPO settings, by using the client program on the Win7 machine.

Sorting the start menu more easily in Windows XP

Discovered something new today! The Windows XP start menu is pretty lame about keeping the Programs in order. Rearranging it by dragging the programs around is fiddly.

However, there is another way! Right-click on the start menu and select properties. Then click the “Customize” button. Finally, click the “Sort” button. Tada! You’re start menu programs are sorted in their default order.