BCSearch, one of the larger applications I’ve made available, was written in Visual Basic 6. I use it quite frequently myself, but it has a few issues that I wanted to address today. Since I have since moved on to C#, D, Python, and other more expressive languages, going back to my old code was an interesting experience. One interesting thing about BCSearch is that it doesn’t, immediately, look like a Visual Basic 6 application.
Visual Basic 6, of course, is not really all that similar to VB.NET. Many die-hard VB6 users, such as Karl Peterson, for example, extend it as saying it is a different language. This is 100% true. But at the same time, VB.NET addresses SO many language problems with VB6, that it pretty well has to be a different language to fix them. Many of the problems VB6 developers had were deeply rooted in the architecture of the language core. An excellent
rebuttal Progress Report about these perceived differences can be read here .
There are some rather glaring problems with using Visual Basic 6 today. For one thing, it was designed and written in 1998, with a service pack released in 2003, to my recollection. This means that it’s architecture is solely stuck in 1998. The current year, as I write this, is 2012. 14 years later. Windows has gone from Windows 98 and NT4 through Windows ME, 2000, XP, Vista, and now Windows 7, with Windows 8- which promises to yet again change the UX programming model- on the horizon. Visual Basic 6 is a curiousity- a novelty. Even so, there are a myriad of tools for the dedicated to create modern applications. VBAccelerator is one such site. The creator has moved on to VB.NET and C#, but his older controls and libraries are extremely powerful. Add to this some shell type libraries that can be leveraged from VB6 as well. Visual Basic 6, however, shows it’s age nonetheless.
In particular, looking at my BCSearch program and thinking about how the various things would be implemented in C#, the C# code I imagine is far more concise and therefore easier to maintain. The Search program itself uses my “BASeCamp File System Objects” Class Library that I wrote several years ago, which attempts, and for the most part succeeds, at giving a very good object-based heirarchy for accessing Files and Directories that goes beyond the VBScript FileSystemObject and extends as low as Binary File Streams, Stream “filters” and NTFS alternate data streams. IN particular, it leverages the FileSearch and CFileSearchEx classes rather extensively, the latter of which I wrote specifically for use in a search-type application.
The code attempts to work asynchronously. Anybody with experience in VB6 is probably facepalming right now at the mere thought of trying to get threads in VB6. And I agree. The VBA and VBRUN libraries are not what I would call thread-safe or re-entrant, and some of their structures are in Thread Local Storage so basically you can fake threads, as long as you don’t use anything from the runtime, which is easier said then done. This is not how BCSearch does it, however. In order to “fake” asynchronous access The FileSearch class starts a timer, whose entry routine starts the search. What ends up happening is we have two concurrent lines of execution which yield to one another with doevents. This allows the main form to respond to User input.
Another thing that highlights the deficiencies of VB6 is it’s lack of Object-Orientation. Now, it has classes, and you can do Interface inheritance, but there is no implementation inheritance, and many of the things you take for granted in some other languages, such as constructors, indexers, and operator overloads, simply are not available. Some of these can be “faked”- for example, constructors could be faked. Let’s say we have MrPoint.cls:
Creating an instance of this class requires something like this:
Some VB users may be going “AH HA! but you can do this and make it a tad shorter:
True, but this has a bit of a performance implication. in VB6, the New keyword in a Dim statement doesn’t allocate the value immediately, but instead will add more logic so that every access of the variable has a check; the above is the equivalent of this:
Which adds a bit of extra logic and can slow down accesses in a deep loop or other intensive operation. Either way, this sort of initialization is pretty slow, isn’t it- having to create the object, then set properties. Most Languages that support classes allow for Constructors. VB6 is unsurprisingly an exception to this. You can fake it by creating a GlobalSingleUse class (By changing it’s instancing property) with a Function or Property that returns a new instance of that type. The typical name of such a member is the name of the class it creates. For example:
One could even create ‘overloads’ by using optional arguments:
The typical approach is to add the GlobalSingleUse class to a ActiveX DLL, and reference that DLL in the “main” project. Since the Instancing property is only usable in ActiveX Components anyway
In some ways this is reminiscent of Python’s method of object instantiation, which forgoes a “New” keyword. Even with these types of hacks, VB6 as a language leaves much to be desired, as does it’s IDE.
Being that it is from 1998, the IDE has actually aged quite well. In another twist, The Visual Studio version from that era no longer works on later versions of Windows at all, due to a few issues it seems to have. For those that might be scratching their head- Visual Basic 6 and earlier were in Visual Studio, but you didn’t use Visual Studio for them. That is, while things like Fortran Powerstation, Visual J++, Visual C++, and so forth used The save development environment (msdev.exe) with “changes” applied through various add-on libraries, Visual Basic was a standalone program that stood apart. In this sense it is similar to it’s adopted cousin in the Visual Studio family, FoxPro.
Thankfully, While the IDE as it is now can be a massive annoyance to work with, (particularly if you are used to things like Eclipse, MonoDevelop, or Visual Studio 2008 as I am), it has a rich extensibility framework that has been fully leveraged by various plugin and addin developers. Giving us tools such as the free MZTools6, AxTools CodeSMART, and several others, which improve the general capability of the IDE and bring it up to more modern standards.
The above is a Application I wrote some time ago in VB6 to leverage a Object-Based File Library I also wrote in VB6. At a glance, it looks nothing Like a VB6 Application. Visual Basic 6 and earlier didn’t support alpha channel bitmaps, and the toolstrip and stuff look “new”! what is this insanity? Thanks to enterprising Visual Basic “Classic” devotees, there is a wealth of information on modernizing a Visual Basic 6 Application. From hacking the VB6.EXE program to change dialog sizes to be more convenient on larger monitors, to adding manifests to it to make the IDE work with the Vista/7 Glass look (as above), so showing Alpha Icons for your form icon. Many of the tools I leverage I found on the excellent vbaccelerator.com, as Mentioned earlier.
However, while the end result looks nice, it’s filled with Gross hacks. Even within my own File Library. A Quick Overview- the File Library is similar to the MS FileSystemObject’s, but more full featured. the base object is “BCFSObject”, which methods not unlike FileSystemObject. One can enumerate directories too.
This was a sticky point. It still doesn’t work. Right now it reads all the directories and returns them. The Ideal case would be an iterator, but VB6 doesn’t support iterators. There is an IEnumVariant interface, which you can define using IDL and add as a reference, but in order to actually implement the interface, you need to literally hack your classes Virtual Dispatch Table. It’s as gross as it sounds. This is because VB6 won’t let you have functions as reserved words; the IEnumVariant interface happens to have a method called Next() which also just so happens to be the core logic of the interface. What you end up doing is remapping your virtual function call table to point to a Module level variable that quite literally takes a first argument as a Long Pointer which it manually dereferences into an Object, and all sorts of hairy gunk. Add to this that the references are often weak and merely mousing over a variable at the wrong time could very well cause the IDE to crash.
I had a working implementation, but it would randomly crash, which obviously put a crimp in it’s capabilities.
The shame is that this same code is dead easier to make in VB.NET, and dead easi-er to make in C#; with C#, just write an iterator coroutine; with VB.NET you have to do more hairy stuff and implement a specific interface, but you don’t have to muck around with Virtual Dispatch tables or anything like that. A lot of stuff you get for free in VB.NET, C#, and other later languages, you have to work on to get working in VB6. For some this can be a point of pride, but when you think about it, it doesn’t really matter if you happened to write a program in a certain language and worked around limitations to get it to work a certain way- to the user, they are all programs. So why spend hours hacking around in memory pointers with Visual Basic 6 when you can do the same thing, and much safer, with C# or VB.NET? There is no reason. Unless you want your program to run without the .NET Framework, which seems to be a common goal which seems to forget that the user doesn’t really care that you went to all that trouble to avoid a framework they probably already have installed if you happen to be missing any number of things that you would have had to reimplement from it.
1,124 total views, no views today