vbAdvance

vbAdvance is a Visual Basic Add-In which gives access to advanced build features and many IDE convenience features.


Concepts

VB5 and VB6 are able to build true Win32 native code executables by using what is essentially the Visual C++ compiler and linker. These build tools are a part of every VB 5 and VB 6 installation* and are as full featured as those found in Visual C++. However, the Visual Basic user interface provides access to only a subset of the capabilities found in this extremely powerful build system. For example, function exports and console subsytem applications can be built using the tools that ship with VB 5 and 6, but VB does not provide you with a way to access these features. The features are not missing, you just aren't given a way to access them..

vbAdvance gives you this access. On a per-project basis, you are able to access and configure these powerful build settings, as well as a host of other IDE convenience features. The result is that a range of capabilities that were previously unavailable are now made available to VB developers.

In addition to the build system enhancements, vbAdvance also extends the VB IDE, adding convenience features like Syntax Checking and clearing the Immediate Window when you run your project. vbAdvance is a fast, efficient tool that greatly enhances VB's build capabilities, and makes the Visual Basic IDE better and easier to use.

As a Visual Basic Add-In, vbAdvance runs while you design and compile your applications. Once your app is built, vbAdvance is no longer needed. vbAdvance adds no distributable dependencies to your projects - there is nothing to distribute because vbAdvance is only needed by the VB IDE.

All vbAdvance project settings are stored as plain text in your project's VBP file, ensuring your settings migrate easily with each project, and making it easy to set up advanced build configurations with automated build tools. These settings in no way interfere with the normal workings of VB, and you can build the same project on a machine without vbAdvance installed, without incident. (Albeit also without the advanced build features offered by vbAdvance.)

Because some of the features exposed by vbAdvance were not designed into Visual Basic, special care must be exercised when using these features. You must have a solid understanding of Windows programming to take complete advantage of this tool. At the same time, many of the features will be appreciated by even novice programmers.

* Applies to Visual Basic Professional and Enterprise Editions. Visual Basic Learning edition does not permit creation of native code executables.


Features

The following features are made available through vbAdvance:

Build Features

  • Console Applications - Create true console-subsystem applications in Visual Basic that interact with the command-prompt from which they were launched.
  • Function Exports - Export functions from DLLs to build standard DLLs using Visual Basic. Function exports are required for certain application types such as Control Panel Applets and ISAPI filters. Having access to this feature allows you to build these applications using VB. You can also implement the DllInstall feature of RegSvr32.exe in your DLLs to provide command-line switch customized registration of your DLLs. Many application plug-ins require function exports, which means you can now use Visual Basic to create them instead of having to resort to another language.
  • Complete Version Number Control - Visual Basic inexplicably omits one of the fields in your application's version number resource. The version number standard is as follows:
    Major.Minor.Revision.Build
    What VB normally gives you is this:
    Major.Minor.0.Build
    In other words, the Revision field is always set to 0. To confuse matters further, what VB calls the Revision field is actually the Build field. Be confused and frustrated no longer - vbAdvance gives you full access to your application's version fields.
  • DllMain - The DllMain entrypoint is used in standard DLLs as a way to recieve startup and teardown notification. vbAdvance gives you the ability to use a DllMain entrypoint in your standard DLLs.
  • DllRegisterServer / DllUnregisterServer customization - An extension of the Function Exports feature, the ability to override and customize these two registration exports gives you full control over your DLL's registration.
  • XP Manifest Resource Compiler - This option automatically compiles in the necessary XP Manifest into your application in order to support the new XP themes. This feature eliminates the need to distribute a seperate XML file with your application and the trouble that goes along with it.
  • Terminal Server Aware Applications - Create applications that are Terminal Server Aware, giving you full control over your app's behavior when run in a Terminal Server environment.
  • App Icons - Set your application icon without the need for a Form or a Resource file. Just point to the icon file and build your project.
  • Advanced Debug File Options - Strip private information from your PDB debug files to prevent reverse-engineering of your app when distributing debug files. Compile the Symbolic Debug Information into your EXE or DLL and avoid having to distribute a seperate PDB file. Generate MAP and DBG files for your project. With vbAdvance, the full list of possible debug file generation options is made available to you.
  • Resource-Only DLLs - Build a resource-only DLL from your project's resource file with the touch of a button.
  • Dynamic Conditional Compile Arguments - Specify conditional compile argument values that differ between design time and compile time. This is particularily useful for the DbgWProc.dll constant, DEBUGWINDOWPROC, which must be set to 1 when in design mode and 0 when compiled. Another example would be an IN_IDE conditional to determine if you're running in design mode, or compiled.
  • Custom DOS Stub EXEs - VB automatically creates a DOS stub EXE for you when you build an executable. The purpose for this is to output some text to the command line when your EXE is run from the DOS environment, explaining that it is a Windows app and will not run under DOS. The Custom DOS Stub EXE feature allows you to place your own DOS stub EXE into your app, allowing you to customize the text that is displayed or even to run an actual DOS version of your application.

IDE Enhancements

  • Check Syntax - Check for syntax errors without building your binary.
  • Build Button - Very similar to the Visual C++ Build button, this builds your project immediately. No dialogs are presented after the first build of the project sets the build path.
  • Execute Button - Very similar to the Visual C++ Execute button, this launches your compiled app. A Send Command Line Args option allows you to send your project's command-line arguments to the executable.
  • Send Code Module to Text Editor - VB's code editor is decent, but not great. If it weren't for Intellisense, there'd be nothing special about VB's integrated code editor. For high-powered editing, many programmer's turn to a professional text editor. vbAdvance makes it trivial to send the current code module to your text editor. Just press the button and your editor will open with the code module you were just viewing from VB. And when you've made your changes and return to VB, vbAdvance's Detect Code Module Changes feature will detect your edits and reload the module for you.
  • Detect Code Module changes outside of IDE - This feature enables VB to detect when any code modules in your project are changed by another process. For example, if you Get Latest from SourceSafe, and one of your code modules is overwritten with a newer version, or if you edit one of the modules with a text editor, or even if you copy over a module using Windows Explorer, this feature will notify you that there was a change and offer to reload the module automatically, saving you from having to reload the entire project in order to pick up the changes.
  • Disable Build Dialogs - The first time you build your project, you are presented with a 'Save As...' style dialog to tell VB where you want to build your project and what you want it named. This makes perfect sense. What doesn't make sense is that even though you already told VB what to name the executable, VB keeps asking you the same question every time you build your project - and to make matters worse, it kindly tells you that there's already a file of that name (duh!) and do you want to overwrite it? Well, vbAdvance to the rescue! The Disable Build Dialogs feature prevents those dialogs from appearing once you've told VB where to build the project. The first time you'll be asked where to build it, and subsequent times you will not be bothered. This is the normal behavior of the vbAdvance Build button, this feature allows you to apply it when building from the File menu option.
  • Clear Immediate Window - This feature automatically clears the Immediate Window when you run your project.
  • Sizeable Dialogs in the IDE - Ever wonder why all of the standard Windows common dialogs used by the VB IDE are not sizeable? So did we, and we took care of the problem. When vbAdvance is running, all standard Open and Save dialogs are sizeable.
  • Binary Compatibility File Enhancement - An extension of the sizeable dialogs feature is found when you select your Binary Compatibility file for an ActiveX DLL project. It has become standard practice to use an extension of *.cmp for compatibility files in order to avoid confusion with the target DLL. Unfortunately, VB's Open dialog requires a few clicks to change the Selection Filter to 'All Files' in order to see any *.cmp files. vbAdvance adds the *.cmp filter entry to this Open dialog and makes it the default selection.


Untitled Document

Toolbar

The vbAdvance Toolbar displays six buttons:

  1. Advanced Options - This button brings up the Advanced Options dialog which allows you to configure your project's advanced build settings, as well as the advanced IDE settings.
  2. Send Current Code Module to Text Editor - This sends the currently viewed code module to your default text editor. This allows you to use a far more powerful code editor in concert with the VB IDE.
  3. Check Syntax - This button runs the VB compiler up to, but not including, the point where a binary is built, giving you a full syntax check of your code without the hassles of having to generate a binary.
  4. Build - This button builds your binary without the dialog boxes. This is the equivalent of selecting File->Make but without the "Make Project" and "Do you want to replace it?" dialogs that pop up.
  5. Execute - This button runs your binary, if it exists.
  6. Make Resource-Only DLL - This button builds a resource-only DLL if you have a resource file in your project.


Advanced Options

The Advanced Options dialog contains five tabs:

  • Build Options - Settings for the various build options.
  • Exports - Specify any function exports. For DLL projects only.
  • Resource-Only DLL - Settings for building a Resource-Only DLL. Not tied to a project type.
  • General - All other project settings.
  • IDE Settings - Settings that are not project-specific, but that affect the entire IDE.

All vbAdvance settings are found in this dialog. Press OK to accept your settings and close the dialog. Press Cancel to close the dialog without saving changes. You must save your project for any project-related settings to persist. Press About to see the About dialog. Pressing Help brings up this help file.


Build Options Tab

The Build Options Tab of the Advanced Options dialog contains build-specific settings:

  • Version Number - Your project's version number is set in the VB Project Properties dialog. Unfortunately, VB does not give you access to the Revision field. The field that VB calls Revision is actually the Build field of the version number. Whatever values are set in VB's Project Properties dialog will be displayed here in the greyed out boxes. The Revision field is editable, allowing you to specify the Revision number.

    The VB version fields map to the actual version fields like so:

    VB Field
             Actual Field
    Major | Major
    Minor | Minor
    - Revision
    Revision | Build

  • Build As Console Application - Check this box to build your EXE as a Console Subsystem Application, which will allow it to interact with the Command Prompt.
  • Include XP Manifest Resource - Check this to have vbAdvance automatically compile an XP Manifest into your application in order to support the new XP Themes. Note that you will also need to add a line of code to your application to initialize the Common Controls. See the following Knowledge Base article:
    http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B309366
  • Generate MAP File - To generate a MAP file for debugging purposes, select this check box. This option automatically generates line-number information.
  • Terminal Server Aware - Check this to mark your application as a Terminal Server Aware application.
  • Application Icon -Use this setting to specify an icon file (*.ico) to use as your application icon.
  • Attach Custom DOS Stub Executable - This setting allows you to change the default DOS Stub EXE which is compiled into your VB Windows app.
  • Advanced Symbolic Debug Info Settings - If you have 'Create Symbolic Debug Info' checked in your Project's Properties dialog under the Compile tab, the following debug file settings can be configured:
    1. Create a seperate PDB file (normal VB6 behavior) - This is the default and does not change anything. You will get a PDB file as always.
    2. Create a seperate PDB file with the private information removed - This setting will strip the private information from your PDB file.
    3. Create a seperate DBG file with the private information removed - This results in a DBG format file being generated rather than a PDB, and again with the private information stripped out.
    4. Compile the debug information into the EXE/DLL - This will essentially embed your PDB file into your EXE/DLL/OCX so that you do not need to ship a seperate file to take advantage of advanced debugging techniques.


Exports Tab

The Exports Tab of the Advanced Options dialog allows you to specify function exports for DLL projects:

All functions available for export in your project will be listed here. To export a function from your DLL, simply check the function in the list, and build the DLL. All Public methods located in BAS modules will be listed here and are selectable for export.

The function names must be unique - this is a limitation of the linker. It has no way to specify two exports of the same name.

The Exported Names may be renamed. The Local Names are listed from your Public BAS functions. By default, the Exported Names will match the Local Names. The Exported Name is the name with which the export will appear. The Local Name is the function that the export will resolve to.

To rename an Exported Name entry, slowly double-click on the Exported Name entry to place it in edit mode, or right-click the entry and select "Rename" to place it in edit mode, then type in the desired export name.


Resource-Only DLL Tab

The Resource DLL Tab of the Advanced Options dialog contains settings needed for building Resource-Only DLLs:

  • Resource-Only DLL Build Filename - This specifies the path and filename of the resource DLL that is built by pressing the "Make Resource-Only DLL" button on the vbAdvance toolbar.

  • Use Default - This resets the Resource-Only DLL Build Filename to the default setting.

  • Path to cvtres.exe - This setting is required and is used to define the location of the file "cvtres.exe". This EXE is required for building resource-only DLLs. Unfortunately, this file is not installed with VB. It also is not redistributable and so cannot be included in the vbAdvance installation. It is installed with Visual C++. If you have Visual C++ installed, you will see the path to the file already entered. There is nothing more you need to do. If you don't have Visual C++ installed, you can download the file from Microsoft. At the time of this writing, the file was available at this location:
    http://download.microsoft.com/download/vstudio97pro/Patch/1/WIN98/EN-US/Cvtres1.exe
    The download link is also specified in Knowledge Base article Q187280.

    If necessary, download and install cvtres.exe onto your hard drive. Once you've decided where to store the file, enter the full path to the executable into the 'Path to cvtres.exe' textbox. You only need to do this once.


General Tab

The General Tab of the Advanced Options dialog contains general project settings:

  • Send Command-Line Args... - Use this setting to tell vbAdvance to send the command-line arguments that are set in the Project Properties dialog when you click the Execute button.
  • Dynamic Conditional Compile Arguments - Enter compile-time conditional compile argument overrides here. Your existing arguments will be displayed but are not editable here.


IDE Settings Tab

The IDE Settings Tab of the Advanced Options dialog contains the advanced IDE settings:

  • Clear Immediate Window when project runs - This setting clears the Immediate Window automatically whenever you run your project in debug mode.

  • Detect when code modules are changed outside of the IDE - This setting enables VB to detect when any loaded code modules are changed by an outside process. When a change is detected, you will be notified and given the option to automatically reload the affected module(s).

  • Disable build dialogs - This setting eliminates the pair of dialogs that normally pop up when you build your project.


Console Applications Overview

Console applications are Win32 executables that are run from the Windows Command Prompt. They receive input from, and send output to, the Command Prompt. An example is the net.exe utility. Type net into the Command Prompt and you will see an informational message written to the same Command Prompt by this utility.

How does a Console application differ from any other Windows application? All 32-bit Windows applications contain a piece of information that identifies them as being of a certain sub-type. This sub-type is referred to as the subsystem, and it tells Windows how to run the application. The following subsystems are available in Win32:

  • CONSOLE - Tells Windows to launch the app within a Command Prompt.
  • WINDOWS - Tells Windows that the app will provide it's own windows.
  • NATIVE - For native mode apps, such as device drivers. Not possible with VB.
  • POSIX - For POSIX compliant applications. Not possible with VB.
  • WINDOWSCE - Tells Windows it is a Windows CE application. You use a tool like eMbedded VB, or the .Net Compact Framework to build this type of application.

Of the 5 subsystem types listed above, only the first two are of interest to VB 5 and 6 developers, and of those two, only the WINDOWS subsystem type is available when you compile your application. VB does not offer you the option of setting the subsystem - it always sets it to be WINDOWS. If you want to build a Console application, you must find a way to set the application's subsystem to CONSOLE.

You can change the subsystem of your application after your EXE has been built by using the VB linker with the following syntax:
link.exe /edit /subsystem:console appname.exe

Where appname.exe is the name of your application.

This approach works fine, but it requires the additional step after you've built your EXE, which is, at best, bothersome. It would be nice if VB would simply give you the option to build your EXE as a CONSOLE subsytem app in the first place. After all, the ability to do so is clearly built in to the VB linker, as we've demonstrated above. vbAdvance gives you this missing option. Simply check the "Build As Console Application" check box and VB will build your EXE with the subsystem already set to CONSOLE, so there is no post-build step required.

The other half of the puzzle of how to build a Console app in VB is how to interact with the Command Prompt. How do you receive input, and how do you send output? Not only did Microsoft not provide the option to build a CONSOLE subsystem application, they also did not provide any language syntax for interacting with a Command Prompt. Fortunately, they did provide a way to call Win32 API functions, and this is where we turn for the answer.

The ReadFile and WriteFile APIs have the ability to read from STDIN (the input pipe that receives text typed or otherwise input into the Command Prompt) and STDOUT (the output pipe that sends text to the Command Prompt).

The Simple and Advanced Console samples demonstrate how to use these, and more, APIs to provide anything from very simple text output capability, to full-featured Command Prompt interaction and control.

Another option is to use the Microsoft Scripting Runtime DLL (scrrun.dll). The FileSystemObject in this DLL allows you to access STDIN and STDOUT. We can't recommend this approach due to problems with the Scripting Runtime DLL, but we wanted to mention it for the sake of completeness.


Simple Console Sample

This example demonstrates how to build a Console application which simply outputs text to the Command Prompt. This demonstrates just about the bare minimum amount of code required to write to the Command Prompt.

Two API calls are used:
GetStdHandle
WriteFile

GetStdHandle is used to get a handle to STDOUT, which we then pass to WriteFile, along with the text we want sent. A single helper function is used to wrap the API calls.

Compile the project and run the "Simple Console Example.exe" from a Command Prompt. You will see the text "Hello world!" output to the screen.


Advanced Console Samples

These examples demonstrate how to build full-featured console applications in VB and are courtesy of Karl E. Peterson ( www.mvps.org/vb ). Karl's MConsole.bas module is a remarkable console-support module for VB, and contains everything you need to build full-featured, robust console applications in VB.

To see just how powerful this module is, run each of the sample applications:

ConDemo1.exe (Interactive.vbp)
Either run this from the command line or better yet from the IDE to see an example of how to build an interactive console application.

ConDemo2.exe (PipedInput.vbp)
Run this from the command line like so:

C:\Program Files\vbAdvance\Samples\Console Applications\Advanced\>dir | ConDemo2.exe
-- or --
C:\Program Files\vbAdvance\Samples\Console Applications\Advanced\>ConDemo2.exe < temp.txt

Either approach will copy whatever is piped into the app to the clipboard. This demonstrates how this console module provides support for piped input.

ConDemo3.exe (ExitCode.vbp)
Run this from the command line like so:

C:\Program Files\vbAdvance\Samples\Console Applications\Advanced\>retval ConDemo3.exe 55

This demonstrates how the console support module provides support for error return values to your console application.

Note that the DebugOutput method in these samples not only prints to the Immediate window in the IDE, but also to the system debug stream, which can be monitored with either of the following tools:
http://grantschenck.tripod.com/dbwinv2.htm
http://www.sysinternals.com/ntw2k/freeware/debugview.shtml


Exports Overview

Concepts

Generally speaking, there are two types of DLLs in Windows. There are standard DLLs and COM DLLs. A standard DLL exposes all of it's functions through exports. A COM DLL exposes it's functions through a COM typelibrary interface (along with a few helper functions which are exported).

VB allows you to call exported functions in a standard DLL (via a typelibrary or the Declare statement), but it doesn't allow you to create them yourself. VB only allows you to build COM DLLs.

There are some cases where it is desirable to build a standard DLL, such as in the case of a Control Panel Applet. A Control Panel Applet by definition must export one function that conforms to a specific name and footprint. Using VB alone, there is no way to build a Control Panel Applet. Another example would be some application plug-in architectures which require your plug-in DLL to provide exported functions. Again, using VB alone, you would not be able to build this type of plug-in.

When you have vbAdvance loaded, you gain the ability to specify function exports in your VB DLLs. Any Public methods you have in your project that are located in a BAS module can be exported in your DLL.

Exporting functions in a VB DLL is not a trivial thing to do. You should not attempt this without fully understanding what is involved. The following text and accompanying sample projects attempt to explain the pitfalls and possibilities. Done properly, standard DLLs in VB are a reality and open up a new world of possibilities with Visual Basic.

Caveats / Requirements

VB apps are completely dependent on the VB runtime. The VB runtime 'engine' requires some initialization before it can be used. When you compile your app, VB is automatically adding code to your project to ensure the runtime is initialized when your app starts. When your DLL is called, this runtime initialization code runs and then your code runs, and all is well.

However, what happens when you expose a new entrypoint into your DLL in the way of a function export? The VB compiler is not only not expecting this, it was never designed to handle the possibility in the first place. The result is that while you have a new exported function in your DLL, the VB compiler never creates the necessary runtime initialization code for that new entrypoint. If your export is called and the runtime has not been initialized, your DLL will GPF.

So how do we get the VB runtime initialized? When you build your DLL, the VB compiler requires a Public Class in your project so that it can create a Public COM object interface for the DLL. It also adds the necessary runtime initialization startup code to the DLL, so that when this Public COM object is created, the runtime initialization code will run. All we have to do to initialize the VB runtime for our project, is to create this Public COM object once, and the internal runtime initialization code will run.

Normally, you need to register a COM DLL so that an object within it can be created. However, this is not actually a requirement. You can create a COM object without the Registry and your vbAdvance installation contains a couple of support files that can be used to instantiate an object from your DLL without the need for the DLL to be registered.

The export samples that are installed with vbAdvance demonstrate how to use the included support files to ensure that the VB runtime engine is initialized before your code executes. Once this requirement is met, writing standard DLLs in VB is easily achieved.

You might be wondering how VB code can be used to initialize the runtime, when the runtime hasn't been initialized yet - kind of a chicken and egg dilemma. The answer is very carefully. There is very little code that will run without GPFs when the runtime has not yet been initialized. Do not attempt to modify the runtime initialization code unless you know exactly what you are doing, and likewise, do not attempt to run VB code without the runtime initialized without a full understanding of what will and will not work.

It's important to understand too, that the VB runtime must be initialized on every thread that your VB code will run on. Typically, there is only one thread of execution, and initializing it the one time will suffice. However, depending on the calling process, it is possible that your exports will get called on different threads. You must ensure the runtime is available on each calling thread. Also understand that VB makes heavy use of Thread Local Storage, and so data set in one thread is not necessarily going to be available on another thread. vbAdvance will allow you to create your exports. It will not ensure that you use them wisely or correctly. Use this feature with care.

If the intended caller of your DLL is another VB app, then you must understand how VB handles Strings in Declare statements. You have to realize that the String will be converted and no longer be available as a VB String. You can use a TypeLibrary to define the export in the caller instead of a Declare to get past this, but then the DLL will not unload until the calling process terminates. To get past that problem, you could use LoadLibrary / GetProcAddress and call the export dynamically, which requires some further reading that is beyond the scope of this help documentation. The VB Caller example demonstrates some of these interactions. Building a standard DLL in VB is probably more useful for non-VB callers than VB callers due to the odd way that VB does String conversion with the Declare statement.

Exported functions cannot be debugged in-process as exports. You must debug the function as you would any other function in a BAS module. Alternatively, the OutputDebugString API can be used in conjunction with a good debug message viewer such as DebugView from www.sysinternals.com.

Approaches

There are a number of different approaches you can take with the exports feature, depending on what you want to accomplish. We break them down loosely here:

  1. Standard DLL
  2. COM DLL with custom DllRegisterServer and/or DllUnregisterServer routines.
  3. Hybrid COM/Standard DLL

Approach #1, Standard DLL -

In this case, we are building a standard DLL, which will be called only via the functions it exports. An example of this is a Control Panel Applet. When building this type of DLL, it is easiest to use a DllMain function, which is made possible through vbAdvance. The DllMain function is an optional entry point into a DLL. If the function is used, it is called by the system when processes and threads are initialized and terminated, or upon calls to the LoadLibrary and FreeLibrary functions. What this means is that when your DLL is first loaded by a calling process, you will recieve notification through DllMain, and can call the runtime initialization support code that is included with vbAdvance, ensuring that your exports can be safely called with the knowledge that the VB runtime is already initialized and available to your VB code.

Approach #2, COM DLL with custom DllRegisterServer and/or DllUnregisterServer routines.

DllRegisterServer and DllUnregisterServer are two exports that are created by VB in all VB-authored DLLs. These exported functions contain the code that places all necessary entries into the Registry so that the COM objects within the DLL can be found. When you use a tool like regsvr32.exe to register and unregister your DLLs, it is actually calling these exports, which do the actual registration and unregistration. Until now, there has never been a way to run custom code from within these exports, which is a shame as there is the occasional need to do so. vbAdvance allows you to create your own DllRegisterServer and DllUnregisterServer function exports, and conveniently renames the VB-generated ones. You can then optionally write a complete implementation yourself, or simply call the renamed exports and add some of your own custom code to your exports. When you do this, it's important to realize that you cannot use a DllMain export and call the VB-generated registration exports. Using DllMain overrides the normal entrypoint for your DLL which the VB-generated registration code is dependent on. You can use DllMain if you intend to completely replace the VB-generated functionality. The sample included with the vbAdvance installation demonstrates how to do this without a DllMain export.

Approach #3, Hybrid COM/Standard DLL

In this case, you will be adding exports to a normal VB COM DLL. You will not be able to use a DllMain entrypoint. You must be certain that the VB runtime is initialized before any of the code in your exported functions is run. The easiest way to do this is to simply require that one of the COM objects in the DLL be called first. You could also provide an Init export and run the runtime initialization support code from there.

Error Handling

It's important to understand something about VB's error handling mechanism when dealing with exported functions. Do not expect VB to be able to communicate error information across the export or API boundary of your DLL. Your exports must exist in BAS modules, and VB uses an internal exception handling mechanism for propogating errors from BAS module methods up to their callers. VB rightly expects the caller of a BAS module method to be another module within the same project. Unfortunately, when you create an export, this is not the case. Do not raise errors or allow errors to be raised from your exported functions. You must trap all errors at your API boundary. It is up to you how you want to communicate error information to the caller. Just understand that the caller is not going to be able to handle the error that VB will raise.

If your caller is another VB app, you might be tempted to use the VB error handling mechanism anyway. This will fail. However, it is possible to raise an error to a VB caller with a little extra work. The reason is that as a caller, VB is prepared to handle COM HRESULT exception information. If you correctly encode your error as an HRESULT, you can raise it to a VB caller, where it will be interpreted correctly.

Further Reading

For an in-depth view into how VB works, the pitfalls and workarounds for exports, multi-threading, error handling, calling function pointers, and much more, refer to the book "Advanced Visual Basic 6" by Matthew Curland. Not only is the text content worthwhile, but the tools that are included are also well worth the purchase price. This book is highly recommended. www.powervb.com


Control Panel Applet

Control Panel Applets Overview

Control Panel Applets are standard Windows DLLs that are required to export a single function called CPlApplet. To be installed as a Control Panel, the DLL must be named with a .CPL extension and must be placed in the System/System32 folder.

The details of the CPlApplet export are explained in MSDN.

Creating Control Panel Applets Using Visual Basic

To create a Control Panel in Visual Basic, you must create a DLL project and set up the CPlApplet export so that it calls your Form when the CPL_DBLCLICK message arrives. The sample code demonstrates what is needed in this routine. There is a small amount of helper code required to successfully provide this export in VB. The problem with providing this export from VB is that the export is called by a non-VB thread. Because of this, the VB runtime engine is not yet started and all but the simplest VB code will fail. The sample code demonstrates how to initialize the VB runtimes in order to be able to display your Form.

This is the general flow of events when your Control Panel Applet is called:

1. DllMain is called, and the VB runtime engine is initialized.

2. CPlApplet is called repeatedly with a different message each time. One of these messages is CPL_INQUIRE, which tells you to return a number of resource IDs where the system can find the icon for the Control Panel, as well as the string name and description for the Control Panel. The other message of interest is CPL_DBLCLICK which tells us to display our dialog. At this point we display the Form modally.

The CPlApplet export requires that a resource file be present to provide the messages and icon that the Control Panel will display.

To set up your own Control Panel using the sample code as a template, simply change the following:

1. Change the resource file resources accordingly. The Icon with ID 101 is displayed when the Control Panels window is open. The String with ID 101 is used as a tooltip and the String with ID 102 is used as the name of the Control Panel.

2. Set up the FCPDialog form to your liking.

Note that the system caches your Control Panel information, and so you may not see a change reflected if you change an icon or string resource. You may need to log off and back on to see your changes.

Installing the sample Control Panel Applet

To install a Control Panel Applet, be sure it has a .cpl extension instead of the .dll extension, and place it into the system folder. That's all that's required. To install the sample Control Panel Applet, simply build the project. It is already set to build in your system folder. Once it's built, open the Control Panels folder. You will see a new Control Panel called "Sample VB Control Panel". Hover your mouse pointer over it to see the tooltip. Launch the Control Panel and witness that the Form opens.

Uninstalling the sample Control Panel Applet

To uninstall a Control Panel Applet applet, simply delete it from the system folder. To uninstall the Sample VB Control Panel that you just created, delete the file named "vbcpsample.cpl" from the System or System32 folder (depending on which version of Windows you have).


DllRegisterServer

The DllRegisterServer sample demonstrates overriding/customizing of DllRegisterServer and DllUnregisterServer.

To see the results of the sample code, register or unregister the DllRegisterServerSample.dll using regsvr32.exe (or equivalent tool) and witness that these exports have been customized with a standard VB message box, and that the functions return a success value.

To customize DllRegisterServer, you must create your own Public DllRegisterServer function in a BAS module and export it through vbAdvance's Advanced Options dialog. When you build your DLL, vbAdvance renames the VB-generated DllRegisterServer export "RegisterDllServer", allowing your custom export to co-exist with the default export. If you want to take advantage of the VB-generated code, you simply call the RegisterDllServer export from your own DllRegisterServer export. The sample project demonstrates this technique.

The accompanying example also demonstrates how to initialize the VB runtime without a DllMain entrypoint.

Note that VB registers your DLL every time you compile it. It does so by running the code it normally places into the DllRegisterServer export. If you are testing locally, you will need to register your DLL manually to cause your custom code to run.


Non-VB Called Export Example

Typically, a standard DLL written in VB will be written for a non-VB caller, such as in the case of a Control Panel Applet. While the Control Panel sample already demonstrates that, this sample code is provided for those that want to see the actual interaction between a non-VB EXE and a VB standard DLL.

The sample comes with an extremely simple EXE written in MS VC++. It demonstrates the basic interaction between a non-VB caller and a VB standard DLL.

Simply run the C_App.exe executable and witness that the Form from within the VB DLL is shown.


VB Called Export Example

When a VB standard DLL is going to be called by a VB EXE, there are some issues to be aware of. Things like Strings won't pass as you might expect if you are using a Declare statement. Error propagation is not obvious. DllMain can't be used. The export feature really is most useful for non-VB callers, when there is no other option, such as with certain plug-ins and things like Control Panels.

The sample code demonstrates a number of techniques for passing various data types. It uses a typelibrary instead of Declares. Step through the caller project in the IDE to see what is happening. As with all VB standard DLLs you will not be able to step through the DLL code in the IDE.


Conditional Compile Sample

The Conditional Compile sample application demonstrates the use of vbAdvance's Dynamic Conditional Compile Arguments. There is only one argument in the sample, which is IN_IDE. The value of this arg in the standard VB Project Properties dialog is 1. The value in the vbAdvance Advanced Options dialog is 0. This results in a value of 1 at design time and a value of 0 when running compiled.

To test the sample, run the project from the IDE by pressing F5 and witness that the message box states "In IDE". Next, run the compiled EXE. Witness that the message box states "Compiled".

Whatever values you have entered in the Compile Time Argument Overrides box are going to be used when the app is compiled. So you may have more or fewer arguments than you have at design time.

Also, the Syntax Check feature will use the compile-time arguments when checking syntax.


Untitled Document

XP Themes / Manifest Sample

The Windows XP user interface adds support for larger icons with greater color information. In addition, it allows for 'themes' where the overall look of all windows in the system can be changed simply by changing the visual theme. Unfortunately for Visual Basic developers, Microsoft did not bother to update VB to handle these new icons or themes. Some of the new XP icons cannot be used as a Form's icon property, which means you cannot use them as your application icon. The other problem is that the VB Resource Editor cannot handle the new XP Manifest resource type, and in order to support the new XP themes, you must distribute a seperate XML manifest file with your application. Not only is this a hassle, but there is a bug on Windows NT Server that prevents an application from starting when the application uses the seperate manifest file. (Microsoft KB article Q316625: "You Cannot Start a Program That Uses a Manifest File That Is Stored on a Windows NT 4.0 Server".

The XP Theme sample application demonstrates just how easy it is to add support for Windows XP's new look by allowing you to specify your application icon without the need to use a Form's icon property (bypassing the problem with VB Forms and XP icons) as well as automatically compiling in the necessary XP Manifest resource, so that you don't need to trouble with a seperate XML file. Simply ticking a checkbox and selecting an icon file is all that's required to add XP Themes support to your VB app.

Note that you will still need to add one line of code to your app's startup routine. In the XP Themes sample, this is found in Sub Main.

More information on XP themes can be found at these links:

Microsoft KB article Q309366:
http://support.microsoft.com/default.aspx?scid=kb;en-us;309366

vbAccelerator XP Visual Styles articles:
http://www.vbaccelerator.com/home/VB/Code/Libraries/XP_Visual_Styles/index.asp


Resource-Only DLL

The Resource-Only DLL sample demonstrates the steps needed to be able to build resource-only DLLs in VB.

To test the sample, open the "res-only dll" project and press the "Make Resource-Only DLL" button to build the DLL. Next, open and run the TestProject and witness that the resource is able to be loaded from the DLL.

Command-line builds that generate resource-only DLLs are not provided by vbAdvance. The reason for this is that VB will try to compile the project - which is not what you want. Instead, all you need to do to build a resource-only DLL from the command line is to call the linker yourself like so:

link.exe /noentry /dll /machine:i386 /out:project1.dll project1.res

For the linker to be able to build the resource DLL, the resource file in your project must be converted to a linkable file. This is accomplished by a utility EXE called "cvtres.exe". This utility is not shipped with Visual Basic, and due to the fact that it is not redistributable, is not shipped with vbAdvance. Fortunately, it is not difficult to get a copy of this utility. If you have Visual C++ installed, then you already have a copy of cvtres.exe. If you don't have Visual C++, you can download a self-extracting archive from Microsoft. At the time of this writing, the file was available at the following location:
http://download.microsoft.com/download/vstudio97pro/Patch/1/WIN98/EN-US/Cvtres1.exe
The download link is also specified in Knowledge Base article Q187280.

Once you have the cvtres.exe file installed, you need to specify the location of the file in the vbAdvance Advanced Options dialog, under the Resource DLL Tab. You need do this only once.


Installation

vbAdvance is distributed as a single self-extracting installer EXE. Double-click the EXE to launch the installation process. You will be presented with standard installation options. Once installed, the add-in will load automatically the next time you start VB. The vbAdvance Toolbar will be floating in the center of the screen and may be repositioned and docked to your liking.

To uninstall the add-in, go to the Add/Remove Programs Control Panel, select vbAdvance, and select Uninstall. Alternatively, you may launch the uninstaller from the vbAdvance Start Menu entry.

If you are upgrading from a previous version, you may simply run the installer over your existing version. You do not need to first uninstall a previous version.


Registration

As a registered user, you will receive:

  • A license to use the latest release of the software. You will receive by email a license key which will unlock the trial version, giving you unlimited use of the product.
  • Free upgrades to all future releases, which will be made available for downloading from our Internet web site.
  • Technical support via e-mail.

To purchase a license to use vbAdvance, visit our website at www.vbAdvance.com/purchase.htm.

To register your copy of the software after you have paid for it and received your registration code, open the Advanced Options dialog, click on the "About" button, then click on the "Register" button. Enter your registration info and click OK.


Notes

The vbAdvance.tlb TypeLibrary is provided for your use. You may freely use this file in your applications. However, you do not need to distribute it with your application, nor are you allowed to. This file is required by many of the sample applications.

Because vbAdvance gives you access to features of the VB compiler and linker, and because the compiler and linker are only used when compiling to native code, these features can only be realized in native code compiled projects. P-code compilations are not supported in vbAdvance.

Because vbAdvance exposes functionality that VB was not intended to expose, we cannot provide support beyond that which the product claims to accomplish. i.e. If you wish to export a function, we will only guarantee that the export exists, we will not guarantee that it will be callable under all conditions. What you do with the export is up to you. We are merely giving you the capability.

Due to the nature of some of the techniques vbAdvance must use to control the VB build environment, there may be conflicts with other add-ins that use these same techniques. Should this occur, we will evaluate the conflict to determine if a workaround exists. Note however, that there may be nothing that can be done and that vbAdvance may not be able to coexist with some add-ins. This situation should be rare.


Untitled Document

Command Line Builds

Command-line builds are fully supported in vbAdvance. To use the command-line feature of vbAdvance, simply set the Load Behavior for the add-in to "Command Line". Due to a bug in VB, you cannot set the add-in's Load Behavior to both "Load On Startup" and "Command Line". These two settings are mutually exclusive and you must pick one or the other. If both are selected, then "Load On Startup" is used and the add-in will not load on a command line build.


Links

The links on this page are by no means a complete list of online resources for VB. This is merely a short list of what we feel are some of the most valuable resources available to VB developers and to users of vbAdvance in particular.

www.powervb.com
A portion of the sample code distributed with vbAdvance is courtesy of Matthew Curland and is taken from his book "Advanced Visual Basic 6: Power Techniques for Everyday Programs". We strongly recommend this book to anyone using the export features of vbAdvance. Much of what vbAdvance allows you to do is made simpler by the use of the code, tools and techniques in this book. The Type Library Editor Add-In alone is well worth the purchase price of the book. This book is essential reading for anyone pushing the limits of VB.

www.mvps.org
This site houses perhaps the most authoritative collection of VB sample sites on the net. Some of the true VB gurus house their sites under this URL. Most of what you need to do in VB that isn't already built-in to VB has been written by one of these developers, and they've posted their code online for all to benefit from. Browse these sites and be happy.

msnews.microsoft.com
The VB newsgroups at this news server are frequented by some of the best VB developers in the business and are an incredible resource to the VB community. If you have a VB question, chances are it's already been answered here. A quick search at groups.google.com will often turn up the answer, and if not, a new post to one of the VB groups will likely yield results, often within hours of the posting.


Requirements

  • Visual Basic Professional or Enterprise Edition version 5 or 6 / Service Pack 3 or higher.
  • Any Microsoft-supported Win32 operating system (server or workstation): Windows 98, ME, NT 4.0 (SP#4 or later), 2000, XP.
  • Native code compilations only, p-code is not supported.
  • For building resource-only DLLs, a copy of cvtres.exe is necessary. This utility is not redistributable and so is not installed with vbAdvance. cvtres.exe is installed with Visual C++, and is also downloadable from Microsoft's website. At the time of this writing, the file was available at the following location:
    http://download.microsoft.com/download/vstudio97pro/Patch/1/WIN98/EN-US/Cvtres1.exe
    The download link is also specified in Knowledge Base article Q187280.


Distribution

As a Visual Basic Add-In, vbAdvance runs while you design and compile your applications. Once your app is built, vbAdvance is no longer needed. vbAdvance has no distribution requirements - there is nothing to distribute because vbAdvance is only needed by the VB IDE.

You are expressely forbidden from distributing the vbAdvance.dll DLL, the vbAdvance.tlb Type Library or any of the vbAdvance sample code as raw source code. You are allowed to use the sample source code in your own projects, provided it is only distributed in compiled form.


Untitled Document

Notes

vbAdvance exposes functionality that the developers of Visual Basic chose not to expose. Because of this, it's important to be aware of what you are doing. One of the most powerful features vbAdvance has is the ability to export functions from DLLs. DLL Exports can pose a problem if the export is called on a non-VB thread. When this is the case, there is very little code that you can run that will not GPF. You may use Windows APIs that are typelibrary defined and that do not return HRESULTs and do not have the UsesGetLastError attribute set. You may use only the very simplest VB code. If you wish to use normal VB, you must first get the VB runtime engine to initialize. To do this you must create an object from your DLL on the thread. This is acomplished with the code demonstrated in both the Control Panel applet sample and the DllRegisterServer sample. Additionally, the book "Advanced Visual Basic 6", referred to in the Links section of the help file, discusses this issue thoroughly and presents the solution in detail.

Because vbAdvance exposes functionality that VB was not intended to expose, we cannot provide support beyond that which the product claims to accomplish. i.e. If you wish to export a function, we will only guarantee that the export exists, we will not guarantee that it will be callable under all conditions. What you do with the export is up to you. We are merely giving you the capability.

Command-line builds are supported in vbAdvance. Simply set the Load Behavior for the add-in to "Command Line". Due to a bug in VB, you cannot set the add-ins Load Behavior to both "Load On Startup" and "Command Line". These two settings are mutually exclusive and you must pick one or the other. If both are selected, then "Load On Startup" is used and the add-in will not load on a command line build.


Console Application

The Console App samples demonstrate how to build a Console Subsystem application in VB.

A Console application requires two main things: 1) The necessary console APIs. 2) The app be built as a Console Subsytem application. The sample project demonstrates basic console I/O.

The console app contains only one BAS module and one method which is Sub Main. Console apps are intended for command-prompt interaction and so it is appropriate to use Sub Main as the startup for the app.

To test the sample, build the application, open a command prompt and navigate to the directory where the sample's EXE resides. Type "console app.exe" and witness that the command prompt is interactive.

The only vbAdvance setting necessary to build a Console application is found on the EXE Tab of the Advanced Options dialog. Simply check the "Build As Console Application" check box.