Classic VB Corner

Executing Debuggables

How do you track down what's really going on inside your compiled EXEs?

Have you ever had one of those problems that only manifests itself in a compiled EXE, that you simply cannot reproduce in the Classic Visual Basic IDE? Or even worse, that only occurs on the client's machines, and not on yours at all? I'd like to show you the technique I've pretty much switched over to, entirely, because it works in both the IDE and EXE.

Almost undoubtedly, you've been using Debug.Print ever since you started using Classic VB. It's often the single most valuable debugging tool in your toolbox, as you can use it to generate a running stream of status messages without interfering in any way with the normal course of execution. But just as surely as you've used this useful tool in the past, you've also wished it wasn't limited to the IDE.

Fortunately, Win32 offers us the OutputDebugString function, which performs almost exactly the same function as Debug.Print does. This function is incredibly easy to use and can be wrapped up as an almost functionally equivalent replacement for Debug.Print as such:

Private Declare Sub OutputDebugString Lib "kernel32" _
Alias "OutputDebugStringA" (ByVal lpOutputString As String)

Public Sub DebugOutput(ByVal Data As String, _
Optional ByVal CrLf As Boolean = True)

' Output to the ether... Someone may be listening...
Debug.Print Data;
Call OutputDebugString(Data)
If CrLf Then
Debug.Print
Call OutputDebugString(vbCrLf)
End If
End Sub

One of the nice things about Debug.Print is that you can suppress the linefeed that follows your output by using a semicolon at the end of the line:
Debug.Print "Trailing semi-colon ";
Debug.Print "suppresses linefeed."

To achieve that same effect with our DebugOutput routine above, I added an optional parameter that assumes you want the CrLf output but allows you to override it. Unfortunately, there's no way for us to entirely emulate the DOS legacy Print command with it's ability to embed successive strings using semicolons and commas, so you'll need to patch up any implied concatenation. Migrating such statements from Debug.Print to DebugOutput requires this sort of tweak:

Debug.Print "The value: "; x
DebugOutput "The value: " & CStr(x)

But where does that output go when you're running an EXE? Well, here are two very handy (and free!) tools I'd like to recommend. Either can read the output from OutputDebugString. My favorite is DBWin32, written by Grant Schenck, because it supports all 32-bit Windows platforms. If you've ever downloaded the SysInternals suite, you may already have DebugView, which was written by Mark Russinovich and requires at least Windows 2000 to run. Something I never noticed until writing this column is that the two don't play nice together -- only run one at a time for best results.

Both utilities allow you to save the results to a text file, but DBWin is a bit friendlier in this regard, as it operates in an MDI manner, effectively isolating the output from each process into its own child window. DebugView does offer you the ability to filter what output it displays, though, so you can still isolate just what you want. (And, yes, this can be an issue, as Windows is full of debug code!)

Granted, you can always rig your application so it outputs all the debugging information to a text file or database. But that's a tremendous overhead to bear for what should be extremely rare circumstances. Sending this information off into the ether, though, is nearly harmless from an efficiency perspective, as it incurs virtually no overhead. And it's there when you need it. Just be sure that your debugging messages are something you're willing to allow others to see. Anyone who ever runs tools like DBWin32 or DebugView can see this output. And now, so can you!

About the Author

Karl E. Peterson wrote Q&A, Programming Techniques, and various other columns for VBPJ and VSM from 1995 onward, until Classic VB columns were dropped entirely in favor of other languages. Similarly, Karl was a Microsoft BASIC MVP from 1994 through 2005, until such community contributions were no longer deemed valuable. He is the author of VisualStudioMagazine.com's new Classic VB Corner column. You can contact him through his Web site if you'd like to suggest future topics for this column.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube