Category Archives: Troubleshooting

Getting Rid of the Bogus Warnings in MSBuild Projects

2
Filed under MSBuild, Troubleshooting

If you’ve ever loaded up an MSBuild project in VS, you have likely seen some warning messages in the Error List window, essentially saying that either the first item in a custom ItemGroup is invalid or the first Property in a custom PropertyGroup is invalid.

The problem is that the MSBuild designers wanted to provide a schema to you’d get some nice intellisense functions when editing a proj file, but, they had to allow for custom properties and items because, well, that’s what MSBuild is all about, after all!

So, those custom elements by definition, can’t be included in the generic schema and, bingo, validation warnings.

The warnings don’t actually harm anything and MSBuild effectively ignores them, so one solution is to do just that. Ignore all those new warnings in your Errors window. That’s even what MS recommends <sigh>

For me, though, ANYTHING in that errors window is a red flag.

Getting that Nice, Clean Errors Window

After digging around, it turns out there’s essentially 2 options to get rid of those warnings.

  1. Edit the Microsoft.Build.xsd file and include ALL the custom Property and Item names you might be using
  2. Or tell VS to not validate the proj file against any schema.

I can’t imagine bothering to try to keep that xsd file up to date constantly as I change proj files, so that option was out.

Fortunately, telling VS not to validate the project file is relatively easy, and pretty easy to undo as well.

First, open the proj file in Visual Studio (if it’s an actual VBPROJ or CSPROJ file, you’ll need to unload the project first, then right click on it again and select Edit Project).

Click in the project editing window, then in the Properties box, Click on the Ellipse button to change the schemas property.

image

You should see this (though, the red Xs will be green checks):

image

When you get the dialog showing all the schemas against which the file is validated, select each one and choose “Do not use this schema”

image

Click ok and repeat for any other PROJ files you need to handle this way.

When done, you should no longer see any validation warnings in the error window.

Unfortunately, this also means that the proj file won’t be pre-validated at all anymore and you won’t get any intellisense anymore. But, really, once you’ve got your proj file setup, you shouldn’t be needing to edit it much.

And if you really need to, just reverse the above process to turn the schema validation back on.

Preventing Mic Feedback in Vista

2
Filed under Media, Troubleshooting, Vista

image (No not that kind of volume!)

Seems like such a simple thing. If I’m on Skype or in general trying to use a mic in Vista, the sounds from the mic end up projecting out the speakers.

No big deal until the volumes get loud enough that you get a feedback loop. Then, look out! Dogs and cats (and wife and children) will run screaming from the house!

I’d dealt with this problem for far too long (Skype was almost unusable) but couldn’t find anything on the web addressing the issue, at least not for Vista.

So I started poking around.

After far too much searching, I finally came across the secret room in Vista where the souls at Microsoft have stashed the hidden switch.

First, right click the speaker icon in the system tray (at the bottom right of the screen), and select Playback Devices:

image

On the next dialog, select Speakers and click properties:

image

On the next dialog, select the Levels tab

image

And make sure that little speaker icon under Input Monitor is DISABLED (like it is in the above screenshot).

If not, just click it to disable it.

This will prevent the mic input from being echoed out through the speakers, and thus prevent any kind of feedback.

Sure, it’s simple now. <g>

MSBuild Properties Don’t Always Evaluate Properly

8
Filed under MSBuild, Troubleshooting

image In my travails with MSBuild lately (the latest 3.5 version), I recently ran into some rather puzzling behavior. Essentially, it boils down to this.

If you set a property value via a PropertyGroup element within a target, and then use CallTarget to call another target, the property values you set won’t be visible to conditions on that called target.

If, on the other hand, you set those same property values from a PropertyGroup within a different target that your main target refers to via the DependsOnTargets attribute, then those properties will be visible to conditions on the called target.

Yeah, you read that right <g>

Here’s a test MSProj project file that illustrates the problem.

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
    <!-- Define various properties to use during the build here -->
    <PropertyGroup>
      <TestValue>false</TestValue>
    </PropertyGroup>

    
    <!-- A DependsOnTargets target -->
    <Target Name="DetermineTestValue">
        <PropertyGroup>
            <TestValue>true</TestValue>
        </PropertyGroup>
        <Message Text="TestValue=$(TestValue)" />
    </Target>

    
    <!-- The test condition fails here and this target is skipped -->
    <Target Name="DoTheBuildSkips" 
            Condition="'$(TestValue)' == 'true'">
      <Message Text="Did the Build (skipped)" />
    </Target>

    
    <!-- The test condition DOES NOT fail here and this target is executed -->
    <Target Name="DoTheBuildWorks" 
            Condition="'$(TestValue)' == 'true'">
      <Message Text="Did the Build (works)" />
    </Target>


    <!-- Root Target just Executes two different test targets -->
    <Target Name="Build" DependsOnTargets="PropertyIsNotSeenProperly;PropertyWorks" />
    
    <!-- First test target, set the TestValue to true and use calltarget, this fails -->
    <Target Name="PropertyIsNotSeenProperly">
        <PropertyGroup>
            <TestValue>true</TestValue>
        </PropertyGroup>
        <!-- the TestValue is true at this point but false when evaluated from DoTheBuildSkips -->
        <Message Text="TestValue (place1)=$(TestValue)" />
        <CallTarget Targets="DoTheBuildSkips" />
    </Target>    

    <!-- Second test target, set the TestValue to true from the DependsOnTarget
         and the "DoTheBuildWorks" target is executed because the condition is true -->
    <Target Name="PropertyWorks" DependsOnTargets="DetermineTestValue">
        <!-- the TestValue is set to true from within DetermineTestValue and is ALSO true
             when evaluated from DoTheBuildWorks -->
        <CallTarget Targets="DoTheBuildWorks" />
    </Target>    

</Project>

Just drop it into a folder and run MSBuild. Be sure to use the /v:diag command line switch so you see the full output.

I piped the results to a file and (with some bits trimmed out) this is the result:

Microsoft (R) Build Engine Version 3.5.30729.1
[Microsoft .NET Framework, Version 2.0.50727.3074]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 7/23/2009 4:25:13 PM.
Project "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj" on node 0 (default targets).
Initial Properties:
ALLUSERSPROFILE = C:\ProgramData
...Many env vars cut out here
TestValue = false

Building with tools version "3.5".
Target "PropertyIsNotSeenProperly: (TargetId:4)" in file "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj" from project "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj":
Using "Message" task from assembly "Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "Message" (TaskId:0)
  TestValue (place1)=true (TaskId:0)
Done executing task "Message". (TaskId:0)
Using "CallTarget" task from assembly "Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "CallTarget" (TaskId:1)
Target "DoTheBuildSkips" skipped, due to false condition; ('$(TestValue)' == 'true') was evaluated as ('false' == 'true').
Done executing task "CallTarget". (TaskId:1)
Done building target "PropertyIsNotSeenProperly" in project "Test.proj".: (TargetId:4)
Target "DetermineTestValue: (TargetId:0)" in file "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj" from project "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj":
Task "Message" (TaskId:2)
  TestValue=true (TaskId:2)
Done executing task "Message". (TaskId:2)
Done building target "DetermineTestValue" in project "Test.proj".: (TargetId:0)
Target "PropertyWorks: (TargetId:5)" in file "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj" from project "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj":
Task "CallTarget" (TaskId:3)
Target "DoTheBuildWorks: (TargetId:2)" in file "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj" from project "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj":
Task "Message" (TaskId:4)
  Did the Build (works) (TaskId:4)
Done executing task "Message". (TaskId:4)
Done building target "DoTheBuildWorks" in project "Test.proj".: (TargetId:2)
Done executing task "CallTarget". (TaskId:3)
Done building target "PropertyWorks" in project "Test.proj".: (TargetId:5)
Done Building Project "O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj" (default targets).

Project Performance Summary:
      107 ms  O:\Dev\Darin\Articles\MSBuild Property Failure\Test.proj   1 calls

Target Performance Summary:
        0 ms  Build                                      1 calls
        5 ms  DoTheBuildWorks                            1 calls
        5 ms  DetermineTestValue                         1 calls
       11 ms  PropertyWorks                              1 calls
       21 ms  PropertyIsNotSeenProperly                  1 calls

Task Performance Summary:
       12 ms  Message                                    3 calls
       13 ms  CallTarget                                 2 calls

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.11

(I’ve highlighted the key lines)

This file essentially has a Build target that is just used to kick off two other targets, that are the actual tests.

The first, PropertyIsNotSeenProperly illustrates the problem. The second, PropertyWorks, works just fine.

Notice that the TestValue property starts out false, but in both cases, it does appear to get set to true.

However, at the point that the condition for the DoTheBuildSkips target is evaluated, the value of TestValue must be false, which should be impossible.

I’ve read that the CallTarget is a bit of a deprecated method anyway, so maybe this is all just a problem of old code that hasn’t been properly updated along with the rest of MSBuild.

But, I’ve found that using CallTarget on occasion can simplify some aspects of debugging larger MSBuild scripts, so that’s why I’ve used it. Further, for me anyway, it makes the script a lot easier to read when the steps that it entails are laid out in a list, one CallTarget after another, instead of one target being dependent on another, which depends on another, etc, etc.

Something to be aware of.

.NET Interoperability with COM Office Apps, a Hidden Gotcha

0
Filed under .NET, ActiveX, Office, Troubleshooting, VB Feng Shui

image I’ve been working with .NET and Office interoperability for some time now, and, other than a few minor hiccups here and there, things have generally been very smooth.

But a colleague recently ran into a problem that required a good deal of hunting to resolve. Long story short, even though .NET interoperability with Office objects is virtually foolproof, releasing your references has some hidden dangers lurking amongst the weeds.

As a general rule, it’s safe to let the .NET garbage collector (GC) do it’s thing while your application is running.

BUT, when you’re app shuts down, you need to take a few extra steps to make sure everything’s cleaned up before quitting.

The details are laid on in this article on MSDN. It’s from 2005, but, from what I can tell, it’s just as applicable now as it was then.

Essentially, the trick boils down to this:

When you’re preparing to shut your application down, you need to make SURE you’ve released all your references to any Office objects. This means setting all your various references to Nothing, or, more typically, letting the GC do its thing.

Unfortunately, the GC doesn’t necessarily do its thing during a shutdown, so you have to force the issue. And that requires code essentially like this:

WordApp.Quit() 
WordApp = Nothing 
GC.Collect() 
GC.WaitForPendingFinalizers() 
GC.Collect() 
GC.WaitForPendingFinalizers() 

The article noted above doesn’t really go into why it’s necessary to call Collect and WaitForPendingFinalizers twice, but it does appear to be required. I’m guessing it’s due to the way the Finalizer sweeps object references; it could be possible for it to release objects in a certain order, causing it to skip some objects. But that’s just a guess.

And as a final note, if your .NET code uses any COM interoperability, it might be a good idea to do some final cleanup along these lines as well.

When Videos Only Play Audio

0
Filed under Arcade, Media, Troubleshooting

image I recently was doing some work with some videos. Things were working just fine at one point, but then I installed the latest version of JRiver Media Center (version 13).

Whammo. My videos wouldn’t play anymore. Well, actually, they’d play audio, but the video was just black.

I thought it was the particular app I was using, so I tried Media Center, and Microsoft’s Media Player. Same result.

From past experiences, I figured something had hosed a codec (codecs are utility libraries installed on your machine that code and decode video and audio files, each format has it’s own codec).

But, where to start looking?

So, I did some googling and found a great page that lists all the various FOURCC codes for codecs:

http://www.fourcc.org/fcccodec.htm

From that, I found a little app you run against a specific AVI to determine what codec it uses, called GSPOT:

http://www.headbands.com/gspot/v26x/index.htm

Running that against the AVI in question yielded the XVID codec.

Alternatively, just view the AVI in a hex editor and look at the header in the file:

image

You should be able to pick out the four character CC code fairly readily.

Then, from the table at FOURCC, I went to the xvid codec page:
http://www.xvidmovies.com/codec/
Downloaded and installed. Presto! Videos with audio and video again!

It’s just that simple 🙂

Cisco VPN Headaches, The (new and improved) Solution

7
Filed under Cisco, Troubleshooting, Vista

image I wrote about my headaches with the Cisco VPN client some time ago.

I thought I’d resolved those problems, but as is the case with most things computer, I had not.

At least part of the problem, as I discovered some time ago, is that the 5.0.0 version of the Cisco VPN client didn’t properly deal with network interfaces coming and going, so in cases where that happened, the client would often end up trying to connect to the VPN host via the wrong network adapter.

How would network adapters come and go, you might ask? After all, they’re physical cards in the machine.

But not so! If you run VMWare or Microsoft’s Virtual PC, those apps create “virtualized” network adapters that come online as you start the program (and in some cases when you start each individual virtual machine) and can go offline just as frequently.

The solution (or so I thought) was to do a hard reset of Cisco’s VPN service. That worked, mostly. But it still wasn’t 100% complete. I still sometimes had trouble connecting that would, in the end, require a reboot.

Fast-forward to yesterday, when I couldn’t get connected even after several  reboots, and I decided enough was enough.

Sure enough, some Google searches revealed that there is NOW a new version of the Cisco Client, the latest I was able to find is 5.0.4.0300.

One point to note is that this is all under Vista 32. From what I understand, XP has none of these issues.

Anyway, after a lengthy and pretty painful install, this new version appears to completely fix the problem. No Service resets required at all.

The Install

The biggest problem is the actual installation of the new version.

First make sure you write down all the connection details from your existing VPN connections. Once you’ve got the new version installed, you’ll have to reset all those details back to what they were. This includes the host name (or ip address), passwords, username, etc).

Uninstall the old Cisco VPN client. For me, this took several reboots as the uninstall appeared to hang several times. Eventually, it did uninstall itself, though.

At this point you can try to install the new version, but I received a message that the “Deterministic Network Enhancer” wouldn’t install properly.

I had to manually uninstall the “Deterministic Network Enhancer” from my network connection properties dialog before Cisco would complete a successful install.

To do that, click on the Windows button (the old “Start” button), select Control Panel, and Network and Sharing Center”.

Find you network adapter listed and click View Status.

image

On the resulting screen, click Properties

image

and on the next screen, click the Deterministic Network Enhancer and uninstall it.

image

Then, you should be able to install the latest Cisco VPN Client and not have any more connection problems.

Google to find the latest version.

Cisco VPN Client and Vista 32

3
Filed under Troubleshooting

image I’ve been running the Cisco VPN Client (version 5.0.0.360) for quite some time now and have consistently had another one of those “annoying but not enough to bother doing something about it” issues the entire time.

Basically, it can often be difficult to establish a connection. Once a connection is made, it stays up quite nicely (as long as there’s a little bit of activity over it). But establishing the connection in the first place can really be an exercise in patience sometimes, often taking 10 minutes or more of repeated connection attempts before succeeding. It seemed to me to have something to do with a timeout, but I had no idea what to tune or even where to look.

I finally decided to go poking around for a possible solution this morning.

First stop was Google, looking to see if there was a new version out. There is, but only with relatively minor changes, it would appear.

But the “changes and release notes” page did have some possibly pertinent material on it.

In particular, this caught my eye:

Vista Window Auto-Tuning Feature Might Cause Network Timeout Problems

Vista introduces a new feature called “Receive Window Auto-Tuning” that continually adjusts the receive windows size, based upon the changing network conditions.

Some people reported that auto-tuning causes network timeout problems with some applications and routers.

To turn off this Auto-Tuning, just open an administrative access command prompt and enter:

netsh interface tcp set global autotuninglevel=disabled

Try it out. If it doesn’t help, you can turn auto-tuning back on by entering enabled in the above command.

At least so far for me, with it off, I’ve been able to connect immediately, every time now. A far cry from before.

*UPDATE*

There’s a little more to it than just the autotuning level, it turns out. Apparently, VMWare’s networking support can really mess with the Cisco VPN service. From what I can gather so far, Cisco’s service does not like network interfaces disappearing and reappearing. It doesn’t track them internally properly. So, even if you exit VMWare to start your Cisco VPN session, the Cisco service might still be confused.

The easiest solution is to simply restart the Cisco VPN Service (called CVPND). You can do it manually through the Services control panel, or use a batch file to restart it even more easily (check here for a nice clean little batch file that handles all the nuances of restarting a service).

Finally, it’s not just VMWare that can mess with the Cisco VPN service. Apparently, ANY application which causes network interfaces to be created or removed could cause similar problems.

New Debugging Option For InstallShield 2009

7
Filed under Installations, Troubleshooting

The new InstallShield supports a very handy command line argument for debugging the handling of prerequisites.

Often times, you’ll have a prerequisite for your install that, for whatever reason, fails to run. When that happens, if you’ve properly set the launch conditions for your install to detect the installation of your prerequisites, your install will fail based on that launch condition.

This is a good thing, but it still begs the question; why did my prerequisite fail to install?

In my case, I had a preq for the .NET Framework 3.5. But my installation failed to run the prerequisite, so it failed at the launch condition because the 3.5 framework was not on the machine.

However, I had no idea why it didn’t run the .NET installer.

Even turning on Verbose MSI Logging, didn’t help, because IS runs prerequisites BEFORE the Windows Installer kicks in, so the verbose log won’t include anything about what happens when the preqs are run.

With the new InstallShield 2009, though, your SETUP.EXE supports a new switch, /DEBUGLOG.

Use it like this:

MySetup.exe /DEBUGLOG”Path and file to debuglog”

note there’s NO SPACE between DEBUGLOG and the “.

so you might use:

MySetup.exe /DEBUGLOG”c:\debug.log”

Doing so revealed that the bootstrapper was, indeed, attempting to run the .NET Framework installer, but that it was failing. Unfortunately, It did not indicate the reason for the failure. Here’s the pertinent snippet from the log:

1-23-2009[01:10:15 PM]: Extracting ‘Microsoft .NET Framework 3.5 SP1.prq’ to C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\{D4907620-651C-4FA9-9B3F-FCE2FCADB41A}\Microsoft .NET Framework 3.5 SP1.prq
1-23-2009[01:10:15 PM]: PrereqEngine: condition,2,2,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5,SP,,1 — Successful
1-23-2009[01:10:15 PM]: PrereqEngine: operatingsystemcondition,5,1,2, — Failed!,
1-23-2009[01:10:15 PM]: PrereqEngine: operatingsystemcondition,5,2, — Failed!,
1-23-2009[01:10:15 PM]: PrereqEngine: operatingsystemcondition,5,2, — Failed!,
1-23-2009[01:10:15 PM]: PrereqEngine: operatingsystemcondition,6, — Failed!,
1-23-2009[01:10:15 PM]: PrereqEngine: operatingsystemcondition,6, — Failed!,
1-23-2009[01:10:15 PM]: PrereqEngine: operatingsystemcondition,6, — Failed!,
1-23-2009[01:10:15 PM]: PrereqEngine: file,AD29C3DEC8FB0CFDAFE8548371B0EE6D,<ISProductFolder>\SetupPrerequisites\Microsoft .net\3.5 SP1\Full\Helper.exe,http://saturn.installshield.com/devstudio/setuprequirements/Microsoft .net/3.5/Helper.exe,,, — Successful,
1-23-2009[01:10:15 PM]: PrereqEngine: file,,<ISProductFolder>\SetupPrerequisites\Microsoft .net\3.5 SP1\Full\dotnetfx35.exe,http://download.microsoft.com/download/2/0/e/20e90413-712f-438c-988e-fdaa79a8ac3d/dotnetfx35.exe,,, — Successful,
1-23-2009[01:10:15 PM]: PrereqEngine: execute,Helper.exe,/p dotnetfx35.exe /l 1033 /v “/q /norestart”,/p dotnetfx35.exe /l 1033 /v “/q /norestart”,1641,3010,, — Successful
1-23-2009[01:10:15 PM]: PrereqEngine: Id,{074EE22F-2485-4FED-83D1-AAC36C3D9ED0},http://saturn.installshield.com/is/prerequisites/microsoft .net framework 3.5 sp1.prq, — Successful
1-23-2009[01:10:15 PM]: PrereqEngine: behavior,Optional,,Reboot,2,Failure,
1-23-2009[01:10:15 PM]: PrereqEngine: Lua,
1-23-2009[01:10:15 PM]: PrereqEngine: Hidden,1
1-23-2009[01:10:15 PM]: PrereqEngine: MsiProgress,
1-23-2009[01:10:15 PM]: Skipping prerequisite ‘Microsoft .NET Framework 3.5 SP1.prq’ because it was installed before the reboot

Since things seemed to point to the .NET Installer, I ran it manually. Lo and behold, it failed because I didn’t have SP2 installed on this virtual machine.

Duh!

But that DEBUGLOG switch definitely helped point the way.

WinIPAC controller software isn’t quite right

7
Filed under Arcade, Hardware, Troubleshooting

image Here’s an example of the “When software doesn’t work right, it can cost loads and load of time” type bug.

I’m using an Ultimarc WinIPAC controller board for a project I’m working on. This is an awesome little controller board that looks like a USB keyboard, and supports mapping of up to 56 switch inputs to any normal keyboard key. It also has LED outputs for driving LED’s or other applicable circuits.

Anyway, the IPAC comes with a simple keyboard mapper/programmer that you use to layout your buttons, then assign which key to which button and finally to upload the mapping to the IPAC (It saves the mapping in non-volatile ram on the board, which is even more fantastic).

Anyway, I’d mapped a particular key to the ENTER key, as shown here.

image

But when I was testing all my mappings out, it didn’t work. Actually, it’d flash sometimes but not consistently. Every other key worked flawlessly.

I spent the better part of 3 hours trying to debug what the heck was happening, swapping wires, using a test meter to verify connections, switch operation, etc.

I even pulled the latest version of their website, but still no joy.

In the end, I discovered that it’s the WinIPAC software  that doesn’t quite handle ENTER keypresses properly. I opened up NOTEPAD and just started pressing buttons and all of them, including the switch I had mapped to ENTER, worked perfectly.

<sigh>

<UPDATE> I emailed with Andy at Ultimarc (these guys get back to you quickly! Very nice support). Anyway, his comment was that the WinIPAC software isn’t intended as a test application, only for programming.

I pointed out that if that’s the case, there really ought to be a warning somewhere to that effect, especially if you map keys whose actions can’t be displayed properly in the application. My rationale was, well, it DOES properly display keyboard status for virtually all the mappable keys so why wouldn’t any normal person assume it could be used as a test app? But, in the end, it’s easy enough to use notepad for those tested, IF you know enough to realize you need to!

Line Numbers and VB.NET

7
Filed under .NET, Troubleshooting, VB Feng Shui

Line numbers have been around ever since the dawn of time in BASIC.

Remember this classic:

10 Print “Hello”

20 Goto 10

But what many people may not know is that line numbers still exist in VB.Net!

Yep, that’s right, you can write the above routine, as I show it, in VB.NET.

Well, with one exception. Line numbers in .NET are treated as full on labels, and labels must be followed by a colon. So you’d have this in .NET:

10: Print “Hello”

20: Goto 10

Now, before I start getting hate mail about GOTO’s and such, let me say that I’m only a fan of a GOTO in a few very controlled circumstances.

But GOTO’s are the point here. Way back in the Visual Basic (Pre .NET days), line numbers combined with the ERL function made for a surprisingly effective field debugging tool. If you line numbered your code before compiling, and used ERL appropriately during your error handling, you’d be able to precisely pinpoint the offending line of code very quickly and painlessly.

I’ve used that approach for years, and even wrote an article in VB Programmers journal at one point about a very extensive generic error handling facility.

Recently, I decided to look into updating that facility for VB.NET, and unfortunately have good and bad things to report.

First the good.

  • As I said before, VB.NET still supports line numbers and the ERL statement, as well as all the old favorites ON ERROR RESUME NEXT, ON ERROR GOTO, RESUME, and RESUME NEXT.
  • You can easily compile VB.NET projects from the command line, making it relatively trivial to create a simple batch file to line number your code, compile it, then clean up the line numbered version.
  • VB.NET supports a much more sophisticated StackTrace/StackFrame functionallity that would seem, at first glance to obviate the need for ERL entirely.

but now the bad…

  • The StackTrace/StackFrame functionality works fantastically, as long as you’re willing to ship the program debugging database (PDB files) that are generated when you compile your project.
  • Worse still, you can’t use the old style ON ERROR GOTO, in the same method as the new style TRY CATCH FINALLY exception handling.

image

  • And finally, the ultimate bit of nastiness. While trapping an error with the old style ON ERROR GOTO will generate a standard exception (See the Err.GetException method), trapping an exception with structured exception handling (also known as SEH, or TRY CATCH), does not affect the ERR object at all, specifically, throwing an error in a TRY block will not set the ERL value, even if the code is line numbered.

image

So what’s the end result of all this?

Basically, do not even bother with ON ERROR GOTO style error handling in VB.Net. Even though it would appear to be supported, and even though retrieving the line number of the failing code isn’t possible without shipping your PDB, the fact that line numbers aren’t reported in code using SEH makes them pretty much useless. SEH is quite useful in many situations, so you wouldn’t want to not use it solely because of this.

But that doesn’t address two very real issues.

  1. Line numbers in stack traces are an incredibly useful debugging tool
  2. You don’t want to distribute your PDBs just to get line numbered stack traces if at all possible.

More to ponder…