Deploying the Hybrid Visual Basic 6.0 and Visual Basic .NET Application
Sales Support: A Hybrid Visual Basic 6.0 & Visual Basic 2005 Application, Part 4
Summary: This article—the last in a four-part series that walks through enhancing an existing Microsoft Visual Basic 6.0 application by using functionality that is expected of modern applications—focuses solely on deployment considerations. (18 printed pages)
This article series, "Sales Support: A Hybrid Visual Basic 6.0 & Visual Basic 2005 Application," walks through enhancing an existing Microsoft Visual Basic 6.0 application by using functionality that is expected of modern applications. The application enhancements were coded in Microsoft Visual Basic .NET, simply because it was more productive and better suited to develop the desired functionality.
The key message of this article series is that the existing Visual Basic 6.0 application did not need to be migrated to Visual Basic .NET. The existing application was just enhanced by using small amounts of Visual Basic .NET code. This technique should be strongly considered if you have a large existing Visual Basic 6.0 code base that you are still maintaining and enhancing.
In Part 1 of this article series, Enhancing an Application with Windows Desktop Search and Office Outlook Integration, I showed that it is not necessary to migrate a Visual Basic 6.0 application to Visual Basic 2005 in order to take advantage of .NET functionality. Instead, you can integrate Microsoft Windows Desktop Search into a Visual Basic 6.0 application by using COM objects that have been created with Visual Basic 2005.
In Part 2, Enhancing a Visual Basic 6.0 Application with MapPoint Web Service, I demonstrated how to enhance the same application to display maps for locations in an existing database by calling into Microsoft MapPoint Web Service.
In Part 3, Enhancing a Visual Basic 6.0 Application with the ReportViewer Control, I showed how to add reporting capabilities to the application.
If you have yet to read the previous articles, I strongly recommend that you read at least the first one, to familiarize yourself with the application. This article will focus solely on deployment considerations.
When planning a deployment, it's important to understand your application dependencies. In this case, the Sales Support application is a Visual Basic 6.0 program that is dependent on extensions that are written in Visual Basic .NET. The application dependencies are diagrammed in Figure 1.
Figure 1. Application dependencies
The various components of this application must be packaged as part of the deployment. The Sales Support Application is installed by using a traditional Microsoft Visual Studio 6.0 Package and Deployment wizard setup.exe file. The VBNET_Extensions DLL, which provides the functionality for all of the preceding screen shots, is packaged by using a Visual Studio 2005 setup project. The application is also dependent on Microsoft SQL Server 2005 and the Microsoft .NET Framework 2.0, which are also packaged with the Sales Support installation.
The installation is somewhat complicated because an existing Visual Basic application, the VB.NET components, the .NET Framework, and SQL Server 2005 Express Edition must all be installed. Each of these components has its own stand-alone installer. Somehow, these all must be bound together, so that the user need only run a single setup.exe file to install everything.
The way to accomplish this is to use a bootstrapper setup.exe file. A bootstrapper can install any number of prerequisite packages and then launch the setup for the main application. This allows the .NET Framework 2.0, SQL Server 2005 Express Edition, and VBNET_Extensions to be installed as prerequisites to the Sales Support application.
Figure 2. Steps in constructing the full installer
The first component that must be constructed is the installer for the VBNET_Extensions DLL. This is accomplished simply by using a Visual Studio 2005 setup project, as shown in box (1) of Figure 2.
When building a bootstrapper, the bootstrapper "understands" the concept of prerequisites. Prerequisites are components that must be installed prior to the main application. You can include built-in prerequisites, such as the .NET framework or SQL Server 2005 Express Edition. However, for the Sales Support application, the VBNET_Extensions must be installed as a prerequisite to the main Sales Support application. The Bootstrap Manifest Generator utility is used to configure the VBNET_Extensions installer, so that it can be chosen as a prerequisite, as shown in box (2) of Figure 2.
MSBuild is then used to generate the bootstrapper setup.exe, and copy all of the prerequisite installers to a deployment folder. When MSBuild completes, you have a single folder that contains the setup.exe, all of the prerequisites, and the legacy installer. This entire folder could be copied either to a network share or to a CD.
When the bootstrapper setup.exe is executed, it installs the prerequisite components in the order that is shown in Figure 2, and then it starts the installation of the installer for the Sales Support application.
That’s a lot of steps, and, depending on your familiarity with deployment, it all might have been confusing. But each step in the process is straightforward; the following sections will walk through constructing each section of the installation in more detail.
Visual Studio 2005 allows you to add a setup project to an existing solution. This type of project provides functionality that is similar to the Visual Basic 6.0 Package and Deployment wizard, and makes it relatively easy to build a deployment for a Visual Basic .NET application or DLL.
Figure 3. Adding a setup project to the VBNET_Extensions solution
When you build a deployment, the first step is to select what you want to deploy. This deployment should deploy the VBNET_Extensions DLL, which contains the forms that were shown in the earlier screen shots. This was accomplished by right-clicking the VBNET_Extensions_Install project in the Solution Explorer, and then selecting Add | Project Output. This displays the Add Project Output Group dialog box, as shown in Figure 4.
Figure 4. Add Project Output Group dialog box
The Add Project Output Group dialog box shows that the primary output of the VBNET_Extensions project should be packaged and deployed. Generally, the primary output is the application executable or, in this case, the VBNET_Extensions DLL.
After the VBNET_Extensions primary output has been added to the VBNET_Extensions_Install setup project, Visual Studio automatically detects any dependencies and targets them for deployment, too. You can see what will be installed, and where, by right-clicking on the VBNET_Extensions_Install project, and selecting View | File System. As shown in Figure 5, the Microsoft.InteropFormsTools assembly and assemblies that are needed by the ReportViewer control will be bundled with the application and deployed to the Application folder (which defaults to a folder under C:\Program Files) on the target computer.
Figure 5. Files that will be deployed to the Application folder
Often, installations must perform certain custom actions beyond just copying files to the correct folder. For example, this application must install a database file and attach that file to SQL Server 2005 Express Edition. These kinds of operations are best performed through a custom action. The easiest way to create a custom action is to add a new Class Library project to the solution. In this Class Library project, you can code any operations that must be performed as part of the installation.
To perform custom actions for the VBNET_Extensions component, a class library that is called InstallerClassLibrary is added to the solution. An InstallerClass item is added to this project. An InstallerClass is just a class that inherits the System.Configuration.Install.Installer base class. This base class allows the Windows installer to call into this class during the install, commit, rollback, and uninstall stages of an installation. You can provide code for any of these installation stages by overriding base-class methods, as shown in Listing 1.
Public Overrides Sub Install( _ ByVal stateSaver As System.Collections.IDictionary) Dim sf As New StatusForm sf.Message = "Select a server where the database should be installed." sf.ShowDialog() stateSaver.Add("DBInstance", sf.DBInstance) MyBase.Install(stateSaver) End Sub
Listing 1. Providing a custom installation action
The Install function examines the computer to determine which instances of SQL Server are installed. SQL Server 2005 Express Edition will be installed with the application, but you might have another instance of SQL Server already installed. By using a custom form, the installer will "ask" you to which instance of SQL Server you want to attach the Sales Support database.
The SQL Server database file SalesSupport83.mdf also is added to the InstallerClassLibrary project. This will allow the actual database file to be deployed along with the application.
After the custom action has been coded, it also must be deployed by the installer. This is accomplished by right-clicking the VBNET_Extensions_Install setup project and selecting Add | Project Output. This time, the InstallerClassLibrary project is chosen for the project, and Primary Output and Content Files are selected for deployment. Choosing Content Files ensures that other ancillary files are included in the deployment. The SalesSupport83.mdf database file is considered a content file, and selecting this option ensures that this file is packaged with the deployment.
Finally, the InstallerClassLibrary must be connected to the installer, so that it will be triggered during the Install stage of the installation process. This is accomplished by right-clicking the VBNET_Extensions_Install project and selecting View | Custom Actions.
From the Custom Actions window, you can trigger custom code for various stages of the installation. For this deployment, the InstallerClassLibrary must be triggered during the Install stage. This is accomplished by right-clicking Install and selecting Add Custom Action. The installer must know the location where the custom-action executable code can be found. This illustrates why the custom-action DLL must be deployed with your application. It is run on the target computer during the installation, so that it must be packaged with the deployment. In this case, it is found in the Application folder and appears as "Primary output from InstallerClassLibrary," as shown in Figure 6.
Figure 6. Hooking the database-installation custom action to the installer
The installation can now be built by right-clicking the VBNET_Extensions_Install project and selecting Build.
At this point, the pieces are in place to install the complete application. However, the installation is not integrated into a single setup.exe. The user would have to install the legacy SalesSupport83 Visual Basic application, as well as the .NET Framework 2.0 and SQL Server 2005 Express Edition. Finally, the user would have to install also the VBNET_Extensions DLL.
To integrate these components so that they are installed from a single setup, a bootstrapper is needed. The bootstrapper installs the .NET Framework 2.0, SQL Server 2005 Express Edition, and VBNET_Extensions as application prerequisites. The bootstrapper then launches the legacy SalesSupport83 setup.exe to install the main application.
Installing the .NET Framework 2.0, and SQL Server 2005 Express Edition as application prerequisites is as easy as checking a couple of check boxes. However, the VBNET_Extensions DLL is custom code, and a little work must be done for it to be installed as a prerequisite. The easiest way to accomplish this is by using Bootstrap Manifest Generator (BMG), which is available as a free product from CodePlex.
BMG allows you to take an existing application installer and turn it into a package that can be used as an application prerequisite. To turn VBNET_Extensions into a prerequisite package, BMG is started, and then Package Manifest is chosen for the new project type, as shown in Figure 7.
Figure 7. Creating a new package manifest
This step prompts you to provide information about the package that you want to build, as shown in Figure 8.
Figure 8. Entering basic information about the package
Next, the BMG must be given the location of the VBNET_Extensions installer. This is done by clicking the Add Install File toolbar icon, which appears directly above the word "Package." The MSI installer for VBNET_Extensions is then chosen, as shown in Figure 9.
Figure 9. Selecting the VBNET_Extensions installer to make a prerequisite package
When the bootstrapper setup.exe installs the prerequisites, it requires a way of knowing whether the prerequisite installed correctly or experienced an error. This information is provided to the bootstrapper by selecting the VBNET_Extensions_Install.msi, under Package, and then selecting the Exit Codes tab, as shown in Figure 10.
Figure 10. Configuring Success and Failure exit codes
Under Custom Exit Codes, an exit code of 0 is added to indicate success. If this is not added, even though the VBNET_Extensions prerequisite will install without error, the bootstrapper will always "think" that the installation failed.
The prerequisite package can now be built. This is accomplished by clicking the Build toolbar icon, which is located on the left, directly above the word "Package."
A build-output window opens, as shown in Figure 11. BMG creates the needed package directory and files under the Visual Studio 2005 installation, so that VBNET_Extensions can be installed as a prerequisite, just as the .NET Framework 2.0 or SQL Server 2005 Express Edition was.
Figure 11. Build output when creating a package
At this point, a legacy setup.exe installer exists for the main Sales Support application. The VBNET_Extensions had been packaged, so that it can be installed as an application prerequisite. Out of the box, the .NET Framework 2.0 and SQL Server 2005 Express Edition can be installed as prerequisites. So that everything is installed from a single setup.exe file, one final step is required to glue everything together: to build the setup.exe itself.
This setup.exe is known as a bootstrapper, which means that the only thing that it "knows" how to do is kick off other installers. It will launch the install for the .NET Framework 2.0, the install for SQL Server 2005 Express Edition, the install for the custom VBNET_Extensions DLL, and, finally, the legacy setup.exe for the Visual Basic 6.0 Sales Support application.
The bootstrapper is generated by running a utility that is called MSBuild. Typically, MSBuild is used to compile projects from the command line. MSBuild can compile files, and it can perform other tasks that are commonly needed for an automated build process, such as copying files. MSBuild is driven by an XML file that contains the specific build instructions. The MSBuild project file for building the bootstrapper is shown in Listing 2.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <BootstrapperFile Include="Microsoft.Net.Framework.2.0"> <ProductName>.NET Framework 2.0</ProductName> </BootstrapperFile> <BootstrapperFile Include="Microsoft.Sql.Server.Express.1.0"> <ProductName>SQL Server 2005 Express Edition</ProductName> </BootstrapperFile> <BootstrapperFile Include="VBNET_Extensions"> <ProductName>VBNET_Extensions</ProductName> </BootstrapperFile> <BootstrapperFile Include="Microsoft.Windows.Installer.3.1"> <ProductName>Windows Installer 3.1</ProductName> </BootstrapperFile> <SourceFiles Include="$(MSBuildProjectDirectory)\..\SalesSupportV8_3\Package\setup.exe; $(MSBuildProjectDirectory)\..\SalesSupportV8_3\Package\SalesSupport.cab; $(MSBuildProjectDirectory)\..\SalesSupportV8_3\Package\Setup.LST" /> </ItemGroup> <Target Name="Bootstrapper"> <Copy SourceFiles="@(SourceFiles)" DestinationFolder="$(MSBuildProjectDirectory)\Deployment\SalesSupport" /> <GenerateBootstrapper BootstrapperItems="@(BootstrapperFile)" ApplicationFile="SalesSupport\setup.exe" ApplicationName="Sales Support Installer" ComponentsLocation="Relative" Culture="en" FallbackCulture="en-US" CopyComponents="True" Validate="False" OutputPath="$(MSBuildProjectDirectory)\Deployment" /> </Target> </Project>
Listing 2. Sales Support Bootstrapper.msbuild file
The ItemGroup section contains a listing of the packages that will be installed as prerequisites. Notice that this list includes the built-in packages for the .NET Framework 2.0 and SQL Server 2005 Express Edition. Notice also that the custom VBNET_Extensions package appears in the list. This package was created in the "Turning VBNET_Extensions into a Prerequisite for SalesSupport83" section, earlier in this document.
As part of the build process, the legacy installer (built by the Visual Basic 6.0 Package and Deployment wizard) must be copied into a Deployment directory. This is accomplished by listing the installer files in the SourceFiles tag, and then referencing that list in the Copy task under the Bootstrapper target.
The GenerateBootstrapper tag contains the information that MSBuild requires to build the actual bootstrapper setup.exe. The BootstrapperItems attribute references the prerequisites that must be included. The ApplicationFile attribute specifies the legacy installer that will be executed after the prerequisites are installed. The OutputPath specifies the folder in which the bootstrapper will be built and to which the prerequisites will be copied.
The bootstrapper is built by using the MSBuild command line. To run MSBuild, open the Visual Studio command prompt, which can be found under the Start menu (under All Programs | Visual Studio 2005 | Visual Studio Tools | Visual Studio 2005 Command Prompt). MSBuild runs and generates the bootstrapper setup.exe by entering the command msbuild "Sales Support Bootstrapper.msbuild". The output is shown in Figure 12.
Figure 12. Output from building the bootstrapper
The full deployment folder is shown in Figure 13. The contents of this folder can be copied to a CD, "zipped" for download, or packaged otherwise for distribution.
Figure 13. Complete deployment folder
The entire application, including the .NET Framework 2.0, SQL Server 2005 Express Edition, and the VBNET_Extensions, are installed by just executing the setup.exe.
Packaging products for distribution is, and always has been, difficult. Applications have prerequisites, and they often require custom code to run during the installation, for example, to attach databases, migrate settings from previous versions, and so forth.
Deploying a hybrid Visual Basic 6.0 and Visual Basic .NET application adds additional complexity. The coding that you do in Visual Basic .NET likely will be compiled into a DLL that must be deployed. The application is now dependent on the .NET Framework, which should be included as a prerequisite.
I hope that this article eases the task by giving you concrete information that you can use when you deploy your own hybrid applications. In my opinion, this is still far easier than porting the entire legacy Visual Basic 6.0 application to Visual Basic .NET.
Building hybrid applications allows you to maintain your existing application investment, learn the .NET Framework and Visual Basic .NET incrementally, and incur very little risk.
About the author
Scott Swigart spends his time consulting, authoring, and speaking about converging and emerging technologies. With development experience going back over 15 years, and by staying in constant contact with future software-development technologies, Scott is able to help organizations get the most out of today's technology while they prepare to leverage the technology of tomorrow. Scott is also the author of several .NET books, a certified Microsoft trainer (MCT) and developer (MCSD), and a Microsoft MVP. Feel free to contact the Scott at email@example.com, or check out his latest musings at blog.swigartconsulting.com.