Why is my exception being swallowed in my Form’s Load handler?

So, you’ve got a WinForms app and you expect an exception to be thrown within your Form’s Load handler. Maybe you even deliberately throw one yourself. But when you start debugging, the execution of your Load handler terminates at the point where the exception was thrown, but no exception is reported and your application keeps running!

This issue was baffling me for several hours today when a colleague of mine pointed me to a helpful post at StackOverflow that explains the problem.

If these conditions are met:

  1. You are running on a 64-bit version of Windows (whether your application is built for 32-bit or 64-bit doesn’t matter; only the bit depth of the OS)
  2. You are building a WinForms app
  3. You are debugging the application with Visual Studio (using default options for Exception catching)
  4. Your main form has a Load event handler
  5. During the execution of your Load handler, an exception occurs

Then:

The exception will be silently swallowed by the system and, while your handler will not continue execution, your application will continue running.If you wrap your handler code in a try/catch block, you can still explicitly catch any thrown exceptions. But if you don’t, you’ll never know anything went wrong.

Note that all of the conditions must be met. If, for instance, you run the application without debugging, then an unhandled exception still be correctly thrown.

According to this Microsoft Connect post, this has been a known issue with 64-bit Windows since 2008:

This is a known issue on 64-bit OS platform. The reason is that the 64bit OS core does not allow user mode exception through kernal mode stacks. The exception is swallowed by OS sliently. That happens in FormLoad handler, because it is called in an OS callback. 32bits OS doesn't do this, so it doesn't repro there.

Paul Betts sheds more technical light on what’s going on, although I believe his post addresses the swallowing of such exceptions even without debugging, something that is supposed to have been resolved for Windows 7 SP1.

Workarounds

If you need the debugger to break during your load method, there are a few things you can do:

Break whenever a CLR Exception is thrown

You can optionally tell Visual Studio to break whenever a CLR exception is thrown, even if it normally would have later been caught (via Debug… Exceptions… or Ctrl+Alt+E).

image

The downside to this approach is that you may see a lot of “noise” about thrown exceptions that are eventually handled (although in some circumstances this is an invaluable tool to discover exceptions that are being thrown that shouldn’t be).

You can catch exceptions in the other categories as well, but typically it’s the CLR exceptions you’ll be interested in.

Use the Application.ThreadException Handler as a Breakpoint

You can attach a handler to the Application.ThreadException event before running your app, and you can set a breakpoint within it to inspect the original exception that was thrown.

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.ThreadException += (o, args) =>
                {
                    var x = args.Exception; //Set breakpoint here to inspect args.Exception
                };

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

The downside to this approach is that you can get into this handler for all sorts of other things as well. But if you’re just trying to see what’s being thrown during startup, this will do it.

Use a 32-bit Version of Windows

Yeah, it’s drastic, but if you’ve got VMs or other machines available, you can always debug on a 32-bit version of Windows.


Rake for .NET in 5 Minutes

There’s no question—when it comes to writing build scripts, I’ll take rake over just about anything. Especially anything that requires defining a script using declarative markup (I’m looking at you, MSBuild and NAnt).

If you want to build .NET projects with Rake, here’s the fastest way to get started with Ruby and Rake on a Windows machine (you can skip to the end for an even shorter list).

Install Ruby 1.9

Visit http://rubyinstaller.org/downloads/ 

image

Download the latest Ruby 1.9 installer:

image

Run the installer.

I recommend checking the option to add Ruby executables to your PATH.

image

Install DevKit

Ruby libraries are called gems. They can be installed and uninstalled from your system as easily as adding and removing an app from an iPhone. Usually.

Some gems come with source code in a language other than Ruby, such as C or C++, and they assume that they’ll be installed on a Unix or Linux style machine system where tools like make, gcc, and sh are present. Naturally, these gems don’t install so well on Windows. DevKit fixes that.

Download the DevKit self-extracting archive from the same page you downloaded the Ruby installer: http://rubyinstaller.org/downloads/

image

Run the DevKit executable.

When the dialog asks where to extract to, change the folder to C:\DevKit (just consider this the DevKit installation directory).

image

Open a command prompt and do the following:

cd \DevKit

ruby dk.rb init

ruby dk.rb install

Then, to make sure it installed correctly, do:

gem install rdiscount --platform=ruby

If all is well, you should see the following line while rdiscount is being installed:

Temporarily enhancing PATH to include DevKit...

Update the Gem System

At the command prompt:

gem update --system

This will update the gem system to the latest available version.

Install Gems

faster_require

gem install faster_require

This little gem speeds up the performance of the ruby “require” statement on Windows. In some cases, quite a lot. I always include it on any Windows machine I use.

rake

gem install rake

This is what we’re after, after all.

albacore

gem install albacore

Albacore is a gem with a set of rake tasks that help with building .NET projects, including a task for executing msbuild which you can use to easily build a Visual Studio .sln file.

Done!

That’s it. You’re ready to start building your .NET projects with rake on Windows.

Recap: The Short List

Here’s the shorter list:

  • Download and install the latest Ruby from http://rubyinstaller.org/downloads. Include Ruby executables in PATH.
  • Download DevKit from http://rubyinstaller.org/downloads. Extract to C:\DevKit
  • Install DevKit
    • cd \DevKit
    • ruby dk.rb init
    • ruby dk.rb install
  • Verify DevKit install
    • gem install rdiscount --platform=ruby
    • Should see: Temporarily enhancing PATH to include DevKit...
  • Update gem system
    • gem update --system
  • Install gems
    • gem install faster_require
    • gem install rake
    • gem install albacore

Bad Programmers Will Doom Your Company

In technology, once you have bad programmers, you’re doomed. I can’t think of an instance where a company has sunk into technical mediocrity and recovered. Good programmers want to work with other good programmers. So once the quality of programmers at your company starts to drop, you enter a death spiral from which there is no recovery.

- Paul Graham, What Happened to Yahoo


How to Open the Classic Logon Screen from XP’s Welcome Screen

So, there’s this wonderful “feature” for Windows XP that, when you logoff, the password boxes on the Welcome screen don’t actually accept keyboard input (this was affecting me with a clean install of XP with SP3, 32-bit).

Did you know there’s a backdoor to bypass the Welcome screen and use the Classic logon dialog instead?

Just press Ctrl+Alt+Delete twice, and you’re in business:

logon


How to Check that Windows XP is Activated

In the process of installing a bunch of VMs for our test lab, I couldn’t remember if I’d activated the XP machines or not. Normally you go to Start… All Programs… Accessories… System Tools… Activate Windows, but Activate Windows wasn’t there--which I now know means that activation has (likely) already happened.

But if a missing Activate Windows program icon isn’t enough to convince you that, indeed, your copy of XP is activated, here’s how you can really check:

There is an executable that lives in C:\Windows\system32\oobe called msoobe.exe (I believe OOBE is for “out-of-box experience”). You need to run that with the /a option (I’m guessing for “activate”). When you do, the activation program will start let you know if you’re already activated.

The easiest way to do this is via Start… Run…, typing this into the box:

oobe/msoobe /a

Run

If activated, you should see this:

Activated


Create a Hotkey to Enable or Disable Your Second Monitor

I’ve been doing some multi-touch testing with MultiTouchVista, a poor man’s multi-touch simulator. It lets you use multiple mice to simulate multiple touch points. Unfortunately, it doesn’t play well with multiple monitors (Whatever coordinate data exists for the touch points gets “squished” into the space of a single, primary monitor. So if you have 2 screens side by side and you “tap” at the midpoint of your desktop that falls on the edge of each screen, the actual tap will be applied to the midpoint of the first monitor.)

No problem. I’ll disable my second monitor.

Which is fine.

Until I need to do some real work.

No problem. I’ll just enable my second monitor.

Let’s see… one click, two clicks, three clicks… no, wrong drop down, grr… four clicks, five clicks…

This is ridiculous! I need a hotkey!

Toggle Your Second Monitor with AutoHotKey

This information is already out on the internet, but I couldn’t find it all in once place. So here goes.

If you use autohotkey, there’s an easy way to define hotkeys to turn any of your monitors on and off.

UPDATE: This has only worked for me with the original, non-unicode, “basic” version of AutoHotKey. If you’re using the new AutoHotKey_L, chances are this script won’t do anything for you.

First, you’ll need a couple of monitor management functions (which are separately buried in a old 2006 forum post, and provided courtesey of Lexikos). Don’t be intimidated by how long these are. Just shove them into a separate file, like MonitorManagement.ahk:

; EnumDisplayDevices(Index [, ByRef Name, ByRef StateFlags ] )
;
; Index:        One-based index of device to get info for.
; DeviceName:   [out] The name of the device.
; StateFlags:   [out] Any reasonable combination of the following flags:
;   0x00000001      DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
;   0x00000004      DISPLAY_DEVICE_PRIMARY_DEVICE
;   0x00000008      DISPLAY_DEVICE_MIRRORING_DRIVER
; DeviceKey:    [out] Path to the device's registry key relative to HKEY_LOCAL_MACHINE.
;
; Returns true if the display device exists, otherwise false.
;
/* Example 1 (requires EnableDisplayDevice()):
    SecondaryDevice =
    count = 0
    Loop {
        if ! EnumDisplayDevices(A_Index, DeviceName, StateFlags)
            break
        if !(StateFlags & 8) ; not a pseudo-device
            if (++count = 2) ; second device
                break
    }
    if DeviceName
        EnableDisplayDevice(DeviceName, -1) ; toggle
*/
/* Example 2:
    Loop {
        if ! EnumDisplayDevices(A_Index, DeviceName, StateFlags)
            break
        if (StateFlags & 4)
            text .= DeviceName " is the primary display device.`n"
        else if (StateFlags & 1)
            text .= "The desktop extends onto " DeviceName ".`n"
        if (StateFlags & 8)
            text .= DeviceName " is a pseudo-device.`n"
    }
    MsgBox %text%
*/
EnumDisplayDevices(Index, ByRef DeviceName, ByRef StateFlags="", ByRef DeviceKey="")
{
    ; DISPLAY_DEVICE DisplayDevice
    VarSetCapacity(DisplayDevice, 424)
    ; lpDisplayDevice.cb := sizeof(DISPLAY_DEVICE)
    NumPut(424, DisplayDevice, 0)
   
    VarSetCapacity(DeviceName, 32, 0)
    VarSetCapacity(DeviceKey, 128, 0)
    ; For consistency, clear StateFlags in case of failure.
    StateFlags = 0
   
    if ! DllCall("EnumDisplayDevices"
        , "UInt", 0
        , "UInt", Index-1
        , "UInt", &DisplayDevice
        , "UInt", 0)
        return false
   
    StateFlags := NumGet(DisplayDevice, 164)
    DllCall("lstrcpynA", "Str", DeviceName, "UInt", &DisplayDevice+4,   "int", 32)
    DllCall("lstrcpynA", "Str", DeviceKey,  "UInt", &DisplayDevice+296, "int", 128)
    if (SubStr(DeviceKey,1,18)="\Registry\Machine\")
        DeviceKey := SubStr(DeviceKey,19)
    return true
}

; Enables, disables or toggles a display device.
;
; DeviceName:   The name of the device, e.g. \\.\DISPLAY1
; Action:       The action to take.
;                    0   Disable
;                    1   Enable
;                   -1   Toggle (may not be reliable if NoReset=true)
; NoReset:      If true, settings will be saved to the registry, but not applied.
;
; The following can be used to apply settings saved in the registry:
;   DllCall("ChangeDisplaySettings", "uint", 0, "uint", 1)
;
; Return values:
;    DISP_CHANGE_SUCCESSFUL       0
;    DISP_CHANGE_RESTART          1
;    DISP_CHANGE_FAILED          -1
;    DISP_CHANGE_BADMODE         -2
;    DISP_CHANGE_NOTUPDATED      -3
;    DISP_CHANGE_BADFLAGS        -4
;    DISP_CHANGE_BADPARAM        -5
;
; Examples:
;   ; disable display 2
;     EnableDisplayDevice("\\.\DISPLAY2", 0)
;     Sleep, 10000
;
;   ; simultaneously enable display 2 and disable display 1
;     EnableDisplayDevice("\\.\DISPLAY2", 1, true)
;     EnableDisplayDevice("\\.\DISPLAY1", 0)
;     Sleep, 10000
;
;   ; ensure both are enabled
;     EnableDisplayDevice("\\.\DISPLAY2", 1, true)
;     EnableDisplayDevice("\\.\DISPLAY1")
;
; Note: DeviceNames may vary. Rather than hard-coding the device name,
;       EnumDisplayDevices() should be used to enumerate the devices.
;
EnableDisplayDevice(DeviceName, Action=1, NoReset=false)
{
    if (Action = -1)
    {   ; Determine if the display should be enabled or disabled.
        Loop {
            if ! EnumDisplayDevices(A_Index, this_name, this_state)
                break
            if (this_name = DeviceName) {
                Action := !(this_state & 1) ; DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
                break
            }
        }
        ; If Action is still -1, an invalid DeviceName was specified.
        ; The script will attempt to enable the display device, but
        ; ChangeDisplaySettingsEx() will most likely return error -5.
    }

    VarSetCapacity(devmode, 156, 0)
    NumPut(156, devmode, 36, "UShort")

    ; Set DEVMODE.dmFields to indicate which fields are valid.
    if (Action) ; Enable
        NumPut(0x000020, devmode, 40)   ; position={0,0}
    else        ; Disable
        NumPut(0x180020, devmode, 40)   ; width=0, height=0, position={0,0}

    ; Since CDS_NORESET is specified here, if NoReset=true, the user must
    ; manually call ChangeDisplaySettings(NULL,1) or restart the computer.
    err := DllCall("ChangeDisplaySettingsEx", "str", DeviceName
        , "uint", &devmode, "uint", 0, "uint", 0x10000001, "uint", 0)
   
    ; ChangeDisplaySettings() is called here for two reasons:
    ;   - A restart is otherwise required to enable a secondary display device.
    ;       See:
http://support.microsoft.com/kb/308216
    ;   - Disabling display devices with just ChangeDisplaySettingsEx()
    ;     tends to leave them turned on.
    if (!err && !NoReset)
        err := DllCall("ChangeDisplaySettings", "uint", 0, "uint", 1)
   
    return err
}

Now that you have that in a separate file, you can include it in your main ahk script and easily create a hotkey to toggle your second monitor (or your first or third or fourth). I’m currently using Ctrl–Backtick to toggle my second monitor. Here’s how:

#Include MonitorManagement.ahk
^`::EnableDisplayDevice("\\.\DISPLAY2", -1) ;toggle second monitor

Modify to your liking.


White button Click() not working? Set your build to x86.

After about an hour of not being able to figure out why white wasn’t clicking on my buttons correctly, I finally stumbled across this discussion that answered my question.

If you’re on an x64 based system and you can’t get white to click, set your project to build for x86.