September 8th, 2015 by June Blender
Last updated on September 8th, 2015

I’m not a professional tester, but I am an expert at making mistakes. I take risks. I try everything. I gravitate to “corner cases” and odd circumstances. That makes me a great amateur tester and, due to a lifetime of experience with breaking things, a pretty good debugger. But, at the Omaha PowerShell User Group meeting in August 2015, I was stumped.

What caused this bug?

David Jones, an Omaha PSUG member and talented PowerSheller, showed me the following code.

$FormGetService_Load={$textboxComputerName.Text =$env:ComputerName
}

Looks perfect. But when he ran his script, on load, the $TextboxComputerName textbox was empty.

I started by looking for misnamed items. These kinds of errors are typically caused by typos in control names. But all of the control names were accurate.

Then, I looked for any code that might overwrite the value in the textbox. But, the script had no statements that would affect the Text value on load.

I was stumped.

When the lab ended, I was very eager to see the code and talk to David. I spent a long time looking through it really thoroughly before I noticed, right at the bottom of the script, a second instance of the form load event handler. This instance had no code in it at all, but it must have been the effective event handler for the form.

$FormGetService_Load={}

Apparently, when there are multiple instances of an event handler in a GUI application, the last one takes precedence over the others.

To test my theory, I created a little form with a $LabelStatus label and a $buttonAction button.

Then, I added two event handlers to load the form and two event handlers for clicking the button. I had to use copy/paste, because PowerShell Studio tries to prevent you from doing this unintentionally. (Yes, I do this sort of thing. Doesn’t everyone?)

— The first $formTestDups_Load event sets the label text to ‘First load event’. The second one sets the label text to ‘Second load event’.

— The first $buttonAction_Click sets the button text to ‘1st click’; the second sets the button text to ‘2nd click’.

When I run my script, the label shows that the second instance of $formTestDups_Load was effective. When I click the button, no matter how many times I click, the button always says ‘2nd click’. Again, the second instance is effective.

Just to make sure, I reversed the order of the event handlers in the script.

I also added a third event handler for the button that does not set the button text. The third event handler allows me to distinguish between running all event handlers, in which case the button would display ‘1st click’ or ‘2nd click’, or running only the last event handler, in which case it would say “No action,” which is the default.

Running the script and clicking the button repeatedly verifies that the last event handler for an event is the only effective one.

Best practice: Don’t add event handlers manually

Also, if you’re in the middle of editing an event handler and make it invalid (temporarily), and then you run the script, PowerShell Studio will prompt for a missing event handler. If you know that the event handler exists, click Ignore. If you click Insert accidentally, fix the original event handler and delete the duplicate.

And, if the event handler appears to be ineffective, look for a duplicate.

To add event handlers:

For default events, double-click the control.

If the event handler for that control exists in the script, PowerShell Studio doesn’t add it again. Instead, PowerShell Studio takes you to the first line of the existing event handler in the script. (If Options/Designer/Automatically insert default events is checked, PowerShell Studio adds default events for all controls on the form — without double-clicking.)

For non-default events, right-click the control and then click Add Events.

The Add Events textbox disables events that are already added to the script, so you can accidentally add them again.

This was a great lesson for me. From now on, I’ll warn people about typing, copying, or accidentally duplicating event handlers and, when I see a result that doesn’t match the code, I’ll check for duplicates.