Category Archives: VB6

BookmarkSave Addin for VB6

108
Filed under VB6

EDIT: I’ve finally gotten around to publishing the source for this addin on CodePlex.

https://bookmarksavevb6.codeplex.com

EDIT 7/25/2012: I’ve just updated the addin (see the ZIP download below) to correct a problem that can occur if you have several projects loaded in a group, and have files of the same name loaded in each project, AND you set bookmarks or breakpoints in those files. In that case, the breakpoints/bookmarks can end up being restored to the wrong file when you load the group of projects. This won’t cause any problems in your code, but your bookmarks and breakpoints won’t be restored properly, and you might receive messages saying that “a breakpoint can’t be set on that line”, or something similar.  Just download the latest version, unzip it and copy the dll over your existing dll.

If first blogged about this addin back here.

Essentially, the idea is to solve a long standing pet-peeve of mine with the VB6 IDE; the fact that it doesn’t save your bookmark or breakpoint locations from one run to the next.

Ugh!

That functionality wouldn’t have taken more than about 30 minutes for someone to implement on the VB team, but, alas, no one did, and I’ve spent far more time than I should have manually restoring breakpoints ever since.

If, like me, you’ve worked in VB.net for any amount of time, and you now find yourself, from time to time, having to load up your trusty copy of VB6 to do some maintenance work, you, almost certainly also like me, sorely lament that missing functionality.

But no more!

After quite a bit of teeth-gnashing, along with some very helpful testing comments from Sam (Thank You!), I think it’s about time to correct that long-suffered oversight!

Download the Addin here:

BookmarkSave Addin ZIP

The Zip file contains one DLL. Just extract it where-ever you want, and run REGSVR32 on it (just like any other COM dll).

NOTE: You will have to have the .net framework 4.0 installed, as this addin is compiled in .net against that version of the framework. Why, you may ask? Well, frankly, VS2010 is much nicer to code in than VB6, and I was actually quite curious whether a VB6 Addin that performed a real, useful, function could be written in VB.net and act, more or less, just like an addin that had been written in VB6. Personally, with this, I think the answer is a pretty deafening “Oh Yeah!”…

DISCLAIMER: As with anything else around these parts, your mileage may vary (the normal “It works on my machine”). I’ve tested it in conjunction with a few of the addins I use (CodeSmart and MZTools, as well as the Mouse Wheel fix, and resource editor) and have had only one minor issue. If CodeSmart is loaded  as well as BookmarkSave, CodeSmart causes the VB6 IDE to crash when you unload it, but only if you ran your application in the VB6 IDE. If this scares you, don’t download or install this addin. I worked around a number of CodeSmart “peculiarities” concerning the way they happen to subclass VB IDE code windows, but so far, the source of this problem eludes me. The good news is that other than the Crash dialog, there doesn’t appear to be any other anomalies (your project saves fine, runs, etc). My suspicion is that during the Addin UNLOAD phase of the VB6 shutdown process, a pointer isn’t being released quite right.

Using the Addin

Well, it can’t get much simpler. Once you’ve registered it, load up VB6 and check the Addins Manager to make sure it’s loaded.

If it is, load up a project of your choice, set a few breakpoints and bookmarks, and close the project.

Reopen it in VB6 and you should see all your breakpoints and bookmarks wondrously reset just like they were before!

There aren’t really any settings or options to speak up.

Bookmarks are saved into an XML file called {projectname}.BM in the same folder as your project’s VBP file.

Breakpoints are saved into a {projectname}.BP file in the same place.

Naturally, you should probably not check those files into version control.

New Hotkeys

Sadly, VB6 doesn’t provide many convenient ways of navigating bookmarks and breakpoints, so this addin adds a few.

Ctrl-K – Toggle a bookmark at the current cursor location

Alt-Left or Right – Navigate to the next or previous bookmark

Alt-Up or Down – Navigate to the next or previous breakpoint

These aren’t configurable at this time.

A few interesting bits

None of this is necessary to actually use the Addin, but I’ll mention it for the curious:

First, I make use of my DLLExport utility to actually export the DLLRegisterServer and DLLUnregisterServer functions, so that the DLL can self register with COM, just like a VB6-authored DLL can. With all the other great COM support in .net, this is a really glaring omission. I wrote about that technique here.

Next, I use my “GenerateLineMap” utility to strip line number info from the PDB file and embed it into the DLL. This information is then used during error handling to annotate any stack trace with real source code line numbers, without actually including the PDB as a separate file. This is a technique I’ve worked on for quite some time, and talked about here, here, and here. Still need to get that article written up.

Authoring VB6 IDE Addins in VB.net

2
Filed under .NET, Utilities, VB6

imageOk, Ok, I know what you’re asking yourself right now.

WTF would you want to do this?

But bare with me.

Realistically speaking, VB6 has a very limited shelf life. I have plenty of VB6 apps that run just fine under Win7 (even 64 bit), but Under Win8? Who knows.

But, the truth is, there are plenty of businesses that rely on WinXP and VB6 apps today, and those businesses aren’t converting those apps to .net (or anything else) particularly quickly.

As it happens, I’m currently doing some maintenance and upgrade work on a VB6 application, and, while it IS a 10+ year old IDE, it does have it niceties and not-so-niceties.

CodeSmart, MZTools, CodeHelper, and other add-ins can certainly help, but one thing I’ve definitely missed now that I’ve worked with VS2005+ is persistent bookmarks and breakpoints.

That fact that VB6 didn’t save bookmark and breakpoint locations is a real shame.

Now, people have asked about this capability for years. I found posts going back to 2001 asking for this function, but the only utility that even came close was the open source CodeDawg project. And while I still have the source here, I can no longer even locate a link for it on the web. No matter, really, because it never did work particularly well, would miss breakpoints or bookmarks that you set sometimes, and just generally had a terribly interface.

But it was a valiant attempt!

Fast forward to today, and I’m back in VB6, working in a large and not particularly straightforward codebase, and I find myself really needing bookmarks and breakpoints that I can set and come back to the next day or whenever.

But .net provides so much simpler coding paradigms for many things now (generic collections, and direct support for subclassing anyone!) that after a few days working up a prototype add-in in VB6, I couldn’t stand it and had to see if it was possible to put something together in .net.

That’s right. A VB6 addin written in VB.net 2010!

It’s not quite finished yet, so I’ll hold off on presenting the full monty for now, but it most certainly is doable, and actually makes for a quite nice development and debugging experience.

First, fire up VS2010 and create a DLL Library project.

In the project  properties, you’ll need to make sure to check the “Make assembly COM visible”

image

Next, On the compile tab, you need to set “Register for COM Interop”

image

You’ll also need to add a reference to the VBIDE.DLL file:image

You can usually find the file under the COM tab on the Add Reference screen:

image

Finally, create a new CLASS, call it Connect, and paste this:

<ComClass("96861C1E-73A0-46E2-9993-AE66D2BC6A91", "1AEA0235-959D-4424-8231-8EBB9B9C85FE")> _
<ProgId("BookmarkSave.Connect")> _
Public Class Connect
    Implements VBIDE.IDTExtensibility

    Private _App As Application

    Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements VBIDE.IDTExtensibility.OnAddInsUpdate
        _App.OnAddInsUpdate(custom)
    End Sub

    Public Sub OnConnection(VBInst As Object, ConnectMode As VBIDE.vbext_ConnectMode, AddInInst As VBIDE.AddIn, ByRef custom As System.Array) Implements VBIDE.IDTExtensibility.OnConnection
        Try
            If _App Is Nothing Then
                _App = New Application
            End If
            _App.OnConnection(VBInst, ConnectMode, custom)
        Catch ex As Exception
            ex.Show("Unable to start addin.")
        End Try
    End Sub

    Public Sub OnDisconnection(RemoveMode As VBIDE.vbext_DisconnectMode, ByRef custom As System.Array) Implements VBIDE.IDTExtensibility.OnDisconnection
        _App.OnDisconnect(RemoveMode, custom)
    End Sub

    Public Sub OnStartupComplete(ByRef custom As System.Array) Implements VBIDE.IDTExtensibility.OnStartupComplete
        _App.OnStartupComplete(custom)
    End Sub
End Class

Now to explain a few things.

The two GUIDs you see in the first COMCLASS line, you’ll need to generate your own unique id’s for them.

Obviously, the ProgID will also need to be changed (the general convention is {addin-name.Connect}).

The Application object is my actual core addin application. I’ve intentionally kept all the addin’s code OUT of the Connect class, to keep it simple, and because this class MUST be made visible to COM so that VB6 itself can instantiate the CONNECT object (and thus kickstart your addin). Usually, the less “stuff” you have to expose to COM in a .net assembly, the better, and this represents the bare minimum.

To make debugging seamless, be sure to set the Debug Start Action to “Start External Program” and point it at your VB6.EXE file:

image

You’ll also need to make sure your addin is registered with VB6, so it will know to load it along with any other addins. You do that by creating a key like the “BookmarkSave.Connect” key below:

image

Be sure to change the “BookmarkSave.Connect” to whatever ProgID you’ve decided on.

Give it a whirl

With all that in place, you should be able to RUN your addin from VS2010, VB6 should start and your addin CONNECT object’s OnConnection method should be called.

Now it’s time to pull out my Duran Duran and SoundGarden discs and get to coding some good ol’ fashioned pseudo-OO VB6 goodness!

VB6 Menus Disabled

4
Filed under Troubleshooting, VB6

In my current job, I have to do some maintenance on some legacy VB6 code. Yeah, its archaic by .net standards, but there’s something….comforting I guess…. about VB6. I spent almost 10 years with that language, so at this point, I know it just about as good as anyone, save maybe Bruce Kenney or Matthew Curland.

At any rate, I’ve been working with it over the last few weeks and happened today to notice that the Bookmarks menu items were all disabled, even when the cursor was located somewhere where I should be able to set a bookmark. You can see the menu items in the screenshots below. Note that in these shots, then menu items are enabled properly. I didn’t think to grab clips before trying to resolve this.

image    image

At first, I thought the problem was with one of the Addins I’d been playing with (CodeSmart, MZTools, etc).

But disabling them didn’t make a difference. Of course, it’s completely possible that an addin did the damage and VB just never “fixed itself” but I have no way of knowing.

The Fix

After playing with several possibilities and even scanning through the registry, I ended up with this simple fix.

Right Click on the menu bar, select Customize, you’ll get this window.

image

For each of the items highlighted above (and the others if you suspect problems there too), click the item and click the RESET button.

That’s it!

Simple. No reboots required. You don’t even have to restart VB.