Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles

Our security experts present 10 vulnerable pieces of code. Your mission is to find the holes (a.k.a. bad security practices) in the code.

Michael Howard and Bryan Sullivan

MSDN Magazine November 2008

...

Read more!

Silverlight is powerful enough to let you easily build an image magnification feature for you web site with very little code, most of which is XAML. Find out how.

Jeff Prosise

MSDN Magazine November 2008

...

Read more!

Choosing the right design pattern for your ASP.NET Web application can help you achieve the separation of concerns between your presentation layer and the layers beneath it.

Dino Esposito

MSDN Magazine December 2008

...

Read more!

This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

David Callahan

MSDN Magazine October 2008

...

Read more!

The CLR team takes a look inside the System.Globalization namespace to explain how to handle data formats for proper localization and globalization.

Melitta Andersen

MSDN Magazine November 2008

...

Read more!

Also by this Author

Build a Visual Basic add-in that lets you copy C# code and paste it into Visual Studio as Visual Basic using the code converter of your choice. Scott Swigart shows you how.

Scott Swigart

MSDN Magazine February 2006

...

Read more!

Popular Articles

James Avery does it again with his popular list of developer tools. This time he covers the best Visual Studio add-ins available today that you can download for free.

James Avery

MSDN Magazine December 2005

...

Read more!

C# allows developers to embed XML comments into their source files-a useful facility, especially when more than one programmer is working on the same code. The C# parser can expand these XML tags to provide additional information and export them to an external document for further processing. This article shows how to use XML comments and explains the relevant tags. The author demonstrates how to set up your project to export your XML comments into convenient documentation for the benefit of other developers. He also shows how to use comments ...

Read more!

Here is an ASP.NET AJAX data-driven Web application that takes the best features from server- and client-side programming to deliver an efficient, user-friendly experience.

Bertrand Le Roy

MSDN Magazine October 2008

...

Read more!

A Sidebar gadget is a powerful little too that's surprisingly easy to create. Get in on the fun with Donavon West.

Donavon West

MSDN Magazine August 2007

...

Read more!

Chris Tavares explains how the ASP.NET MVC Framework's Model View Controller pattern helps you build flexible, easily tested Web applications.

Chris Tavares

MSDN Magazine March 2008

...

Read more!

Our Blog

Windows Presentation Foundation (WPF) adds functionality to the Microsoft .NET Framework so that you actually can reliably keep bound controls synchronized with their data sources.

In the December 2008 issue of MSDN Magazine, Ken Getz demonstrates how to use the ObservableCollection class provided by WPF to keep bound controls in ...

Read more!

Choosing the best alternative is a common task in software development and testing. A group of beta users may need to choose the best user interface from a set of prototypes. Or imagine the members of an open source project voting for a policy.

In the November 2008 issue of MSDN Magazine, Dr. James McCaffrey describes five of the ...

Read more!

Earlier this year MSDN Magazine embarked on a collaborative project with Behind the Code, an interview program airing on MSDN Channel 9. In this program, Robert Hess interviews prominent developers at Microsoft, and those developers also write a column for { End Bracket } in MSDN Magazine. In the newest interview, Richard Ward talks about working on the core infrastructure components of future versions of Windows, as well as ...

Read more!

Because Windows Workflow Foundation (WF) is based on a runtime that manages the execution of workflows and activities, testing must, in almost all cases, involve the use of the runtime – and this can introduce some interesting challenges.

In the November 2008 issue of MSDN Magazine, Matt Milner presents some techniques for unit testing ...

Read more!

Windows Workflow Foundation (WF) imposes some restrictions on the developer authoring programs that target it. But in return WF offers a powerful, flexible, and extensible set of runtime services such as support for long-running code.

In the December 2008 issue of MSDN Magazine, Josh Lane provides some best practices to consider ...

Read more!

Wrap It Up
Call Into The .NET Framework From Existing Visual Basic 6.0 Apps
Scott Swigart

This article discusses:
  • Considerations for upgrading existing code
  • Setting up a wrapper in Visual Studio
  • A sample network connectivity wrapper
  • Using the FTP features of the .NET Framework
This article uses the following technologies:
Visual Basic 6.0, Visual Basic 2005 Express, .NET Framework
Code download available at: VBFusion05.exe (150 KB)
Browse the Code Online
M any developers believe that if they are writing code in Visual Basic® 6.0, the vast world of the Microsoft® .NET Framework is off limits to them. But in this article, I’ll prove that isn’t true. I’ll show how you can easily leverage anything in the .NET Framework 2.0 from existing Visual Basic 6.0 applications through a technique known as Visual Basic Fusion. Make no mistake, I’m advocating nothing less than leaving some of your applications in Visual Basic 6.0. However, there’s no reason that the door to the .NET Framework class library must remain locked just because you choose not to upgrade to Visual Basic 2005.
So why not just upgrade? Tremendous resources are at your disposal if you choose to upgrade a Visual Basic 6.0 application to Visual Basic 2005. Visual Studio® provides a migration assistant that will automatically rewrite much of your Visual Basic 6.0 code. Microsoft has published a Visual Basic 6.0 to Visual Basic 2005 Migration Guide that includes an assessment tool to help determine the time and cost to upgrade your application. The Web is chock full of articles, how-tos, tips, and tricks on specific upgrading issues. There are even a few books on the topic. With so many resources available, some may question why any code should remain in Visual Basic 6.0. Why not just upgrade all of it?
In truth, upgrading code from Visual Basic 6.0 to Visual Basic 2005 can be a labor-intensive process, and the success of this endeavor hinges largely on two factors: code quality and developer experience with Visual Basic 2005 and the .NET Framework. Applications that are well architected and highly modular are easier to upgrade than applications that have become messy over time.
In the world of Visual Basic 6.0, many applications have been in production for years. Maybe these applications have needed feature enhancements on accelerated schedules. Maybe they have been programmed by numerous developers, some of whom did not have the time or patience to fully understand the code they were modifying. For whatever reason, programmers are often under pressure to get a project working and then move on. As a result, the code can get pretty convoluted over time. Sufficiently messy code is generally better off being rewritten rather than upgraded, and rewriting isn’t cheap or easy.
As for developer experience, upgrading a complex and mission-critical Visual Basic 6.0 application is a dreadful way to come up to speed on Visual Basic 2005. It’s important to have good experience with .NET before attempting to upgrade anything. There are several reasons for this. If you feed a Visual Basic 6.0 application down the chute of the migration wizard and turn the crank, what pops out the other side is a Visual Basic 2005 application that will not simply compile and run. The migration wizard will fling comments throughout the code marking locations where it was not able to automatically migrate. To fix the application and get it running, you need a solid understanding of Visual Basic 2005 and the .NET Framework. The code changes required range from simple and tedious to rewrites of entire application subsystems. So clearly, upgrading isn’t always easy.
With upgrading described as such a dismal prospect, you might wonder why anyone ever does it. Well, moving a code base to Visual Basic 2005 isn’t trivial, but it is ultimately the best way to get friction-free access to the full .NET Framework. I also find it much more productive to develop with the vast .NET Framework class libraries and with the superb productivity features provided by Visual Studio 2005. Visual Studio 2005 honestly makes Visual Studio 6.0 feel like something with a hand crank on the front. When it comes to upgrading, you’re going to have to make an application-by-application decision. Is it worth the effort? Is it feasible to do right now?

The Cheap and Easy Approach
Another option is to leave the application in Visual Basic 6.0 and just call into the .NET Framework as needed. Right in the box, the .NET Framework includes classes to ping IP addresses, detect changes to network connectivity, transmit files with FTP, access COM ports, play sounds, get operating system information such as physical memory and screen resolution, get user and domain information, read and write to the event log, access performance counters, start and stop services, and access the registry. The list goes on and on. The word "comprehensive" readily springs to mind when describing the .NET Framework 2.0 class library. By using the .NET Framework 2.0, you can likely eliminate dependencies on certain third-party controls and remove many Win32® API calls. Calling into the .NET Framework from Visual Basic 6.0 is easy and low risk. It’s also a good way to come up to speed on Visual Basic 2005 programming.
To call into the .NET Framework, as outlined in this article, you’ll need either Visual Studio 2005 or Visual Basic Express. Visual Basic Express includes all the toolbox controls, IntelliSense®, debugger, and many of the project items. It’s quite sufficient if you want to kick the tires and take Visual Basic 2005 for a spin. Plus, Visual Basic Express isn’t a trial version that stops working at some future date. Instead, it’s a pared down Visual Studio, designed to be used until the applications you’re building outgrow its capabilities.
You should also download the code associated with this article, particularly if you are using Visual Basic Express. Copy the included ComClass.zip file to your \My Documents\Visual Studio 2005\Templates\ItemTemplates\Visual Basic folder. As you’ll soon see, this project item is critical when calling into the .NET Framework from Visual Basic 6.0, and it’s not included with Visual Basic Express by default.

Calling the .NET Framework
Visual Basic 6.0 is great at calling into COM objects. However, the classes in the .NET Framework are not COM objects and are not directly callable from Visual Basic 6.0. Instead, the .NET Framework classes must be called through a wrapper. The wrappers are built using the COM Class item, and they behave like any other COM objects. The wrappers are callable from Visual Basic 6.0, Visual Basic Scripting Edition (VBScript), Visual Basic for Applications (VBA), or any other COM-compatible environment. The wrapper internals are constructed in Visual Basic 2005 and can call seamlessly into the .NET Framework (see Figure 1).
Figure 1 .NET Wrappers for Visual Basic 6.0 
The construction of wrappers is a downright trivial task. These following steps will walk you through creating a COM callable wrapper for the Ping functionality in the .NET Framework 2.0.
  1. Start either Visual Studio 2005 or Visual Basic Express.
  2. Create a new Class Library project named FX20Wrapper.
  3. Select the Project menu, and then select Add New Item.
  4. Select the COM Class item template. For the name, enter NetworkWrapper, and click Add.
  5. Add the following function to the NetworkWrapper class:
    Public Function Ping(ByVal hostNameOrAddress As String, _
            Optional ByVal timeout As Integer = -1)
        If timeout >= 0 Then
            Return My.Computer.Network.Ping(hostNameOrAddress, timeout)
        Else
            Return My.Computer.Network.Ping(hostNameOrAddress)
        End If
    End Function
That’s it! With just a few lines of code, you’ve created a COM object that will let you ping every IPv4 address in the known universe. This function lets you ping by host name or IP address. You can also specify an optional timeout value. Imagine the possibilities. The only remaining step is to use the Build menu to compile the Visual Basic Express project. The IDE compiles your project and emits a DLL, which Visual Studio registers as a COM object.
Next, you can construct a Visual Basic 6.0 project that uses this wrapper.
  1. Start Visual Basic 6.0 and create a new Standard EXE project.
  2. Create a user interface like the one shown in Figure 2.
  3. On the Project menu, select References to add a reference to FX20Wrapper. Notice that your .NET project shows up just like any other COM object.
  4. In the click event of the Ping button, add the following code:
    Private Sub Command1_Click()
        Dim network As FX20Wrapper.NetworkWrapper
        Set network = New FX20Wrapper.NetworkWrapper
        Text2 = Text2 & "Pinging " & Text1 & "..."
        DoEvents
        If network.ping(Text1) Then
            Text2 = Text2 & "Responded" & vbCrLf
        Else
            Text2 = Text2 & "Did not respond" & vbCrLf
        End If
    End Sub
  5. 5.Run the application, enter an IP address, and click the Ping button. You should see a result like that shown in Figure 2.
Figure 2 Ping Test 

Now You Have It; Now You Don’t
Applications are increasingly expected to handle unexpected changes in network connectivity. Laptops unplug. Users travel from one wireless oasis to another. The operating system notifies the user every time the network comes and goes. Wouldn’t it be nice if the operation system also notified your application? With Visual Basic 2005, it does. The My.Computer.Network object fires an event whenever the network connectivity status changes. The code in Figure 3 shows how to enhance your NetworkWrapper class to provide this notification.
Public Event NetworkAvailabilityChanged(ByVal IsAvailable As Boolean)

Public Sub New()
    AddHandler My.Computer.Network.NetworkAvailabilityChanged, _
        AddressOf My_NetworkAvailabilityChanged
End Sub

Public ReadOnly Property IsAvailable() As Boolean
    Get
        Return My.Computer.Network.IsAvailable
    End Get
End Property

Private Sub My_NetworkAvailabilityChanged(ByVal sender As Object, _
      ByVal e As Microsoft.VisualBasic.Devices.NetworkAvailableEventArgs)
    RaiseEvent NetworkAvailabilityChanged(e.IsNetworkAvailable)
End Sub
Notice that in the New subroutine (the constructor for the NetworkWrapper object), My.Computer.Network exposes a Net-workAvailabilityChanged event. This event is not directly COM-consumable. Instead, this event is hooked to a subroutine inside of the wrapper called My_NetworkAvailabilityChanged. From this routine, an event will be fired that is COM-consumable. This routine fires its own NetworkAvailabilityChanged event, which you can see contains a simple Boolean value to indicate the network status.
From the Visual Basic 6.0 side, this event is no harder to consume than a Button_Click event. The code for the Visual Basic 6.0 application is shown in Figure 4. With a tiny amount of code, your Visual Basic 6.0 applications can suddenly become network-aware. In an actual application that implements this wrapper, when the network is not available, the status bar might indicate its status as "Offline" and the ability to access network resources could be disabled.
Dim WithEvents network As FX20Wrapper.NetworkWrapper

Private Sub network_NetworkAvailabilityChanged( _
        ByVal IsAvailable As Boolean)
    ShowAvailable IsAvailable
End Sub

Private Sub Form_Load()
    Set network = New FX20Wrapper.NetworkWrapper
    ShowAvailable network.IsAvailable
End Sub

Private Sub ShowAvailable(IsAvailable As Boolean)
    cmdUploadData.Enabled = IsAvailable
    StatusBar1.SimpleText = IIf(IsAvailable, "Online", "Offline")
End Sub

Something Old and Something New
The original RFC for FTP was published in 1973, and FTP remains one of the most popular protocols for transmitting files over the Internet. Microsoft has provided programmatic support for FTP in the past through the Microsoft Internet Transfer Control and the WinInet API. However, there has not been native support for FTP as part of the .NET Framework until recently. The .NET Framework 2.0 adds support for FTP through the WebClient, FtpWebRequest, and FtpWebResponse classes. Through these classes, you can perform a variety of FTP operations. The specific operations and the FTP commands that they map to are described by the WebRequestMethods.Ftp members, shown in Figure 5.

Name Description
AppendFile Represents the FTP APPE protocol method that is used to append a file to an existing file on an FTP server.
DeleteFile Represents the FTP DELE protocol method that is used to delete a file on an FTP server.
DownloadFile Represents the FTP RETR protocol method that is used to download a file from an FTP server.
GetFileSize Represents the FTP SIZE protocol method that is used to retrieve the size of a file on an FTP server.
ListDirectory Represents the FTP NLIST protocol method that gets a short listing of the files on an FTP server.
ListDirectoryDetails Represents the FTP LIST protocol method that gets a detailed listing of the files on an FTP server.
MakeDirectory Represents the FTP MKD protocol method creates a directory on an FTP server.
PrintWorkingDirectory Represents the FTP PWD protocol method that prints the name of the current working directory.
RemoveDirectory Represents the FTP RMD protocol method that removes a directory.
Rename Represents the FTP RENAME protocol method that renames a directory.
UploadFile Represents the FTP STOR protocol method that uploads a file to an FTP server.
UploadFileWithUniqueName Represents the FTP STOU protocol method that uploads a file with a unique name to an FTP server.
The time required to download a file can vary greatly and is affected by file size and network bandwidth. To accommodate this, the FTP classes support both synchronous and asynchronous operations. Synchronous operations are the simplest to program, with a download requiring only a couple lines of Visual Basic 2005 code:
Dim w As New WebClient
w.DownloadFile(address, fileName)
However, synchronous applications block (freeze) the application until the download operation has completed. While this behavior might be fine for command-line or batch operations, users rarely appreciate the experience of an application turning to stone without providing any indication of when it will reanimate. The FTP asynchronous operations perform the downloading on a separate thread and fire events notifying of the progress and download completion. Figure 6 shows a wrapper for the FTP classes that provides both synchronous and asynchronous operations.
Imports System.Net

<ComClass(FTPWrapper.ClassId, FTPWrapper.InterfaceId, _
    FTPWrapper.EventsId)> 
Public Class FTPWrapper

#Region "COM GUIDs"
‘ These GUIDs provide the COM identity for this class 
‘ and its COM interfaces. If you change them, existing 
‘ clients will no longer be able to access the class.
Public Const ClassId As String = "a9afe450-c10e-47cd-a004-f42dc975caaf"
Public Const InterfaceId As String = _
    "ec30e4cf-877c-4947-a093-715c2002aea0"
Public Const EventsId As String = "ddffd280-bff9-40dd-9238-215232b90b11"
#End Region

Dim WithEvents w As New WebClient
Dim totalBytes As Integer

Public Event DownloadProgressChanged( _
    ByVal bytesDownloaded As Integer, _
    ByVal totalBytes As Integer)

Public Event DownloadFileCompleted()

Public Sub New()
    MyBase.New()
End Sub

Public ReadOnly Property IsBusy() As Boolean
    Get
        Return w.IsBusy
    End Get
End Property

Public Sub DownloadFile(ByVal address As String, ByVal fileName As String)
    w.DownloadFile(address, fileName)
End Sub

Public Sub DownloadFileAsync( _
    ByVal address As String, _
    ByVal fileName As String)

    If w.IsBusy Then
        Throw New ApplicationException( _
          "FTPWrapper has not completed the previous operation. " & _
          "One operation must complete before another can be initiated.")
    Else
        Dim f As FtpWebRequest = _
            CType(WebRequest.Create(address), FtpWebRequest)
        f.Method = WebRequestMethods.Ftp.GetFileSize
        Using response As FtpWebResponse = _
                CType(f.GetResponse(), FtpWebResponse)
            totalBytes = response.ContentLength
        End Using 
        w.DownloadFileAsync(New System.Uri(address), "c:\readme.txt")
    End If
End Sub

Private Sub w_DownloadFileCompleted(ByVal sender As Object, _
      ByVal e As System.ComponentModel.AsyncCompletedEventArgs) _
      Handles w.DownloadFileCompleted
    RaiseEvent DownloadFileCompleted()
End Sub

Private Sub w_DownloadProgressChanged(ByVal sender As Object, _
      ByVal e As System.Net.DownloadProgressChangedEventArgs) _
      Handles w.DownloadProgressChanged
    RaiseEvent DownloadProgressChanged(e.BytesReceived, totalBytes)
End Sub

End Class
The FTPWrapper class builds on concepts illustrated thus far. First, this class is built using the ComClass project item template. This ensures that FTPWrapper will contain the necessary GUIDs for registration as a COM object. An instance of WebClient is dimensioned WithEvents at the class level. This allows all methods within the class to access this single instance, and it allows the FTPWrapper class to handle the WebClient DownloadProgressChanged and DownloadFileCompleted events.
The DownloadFile subroutine contains a single line of code and performs a synchronous download of a specific file. As described previously, calling this subroutine turns your application to stone while the file downloads.
DownloadFileAsync is a more versatile and interesting way to download a file. This subroutine begins by ensuring that there isn’t another asynchronous operation in progress. If there is, the subroutine throws an exception, which is the Visual Basic 2005 approximation of Err.Raise. Next, DownloadFileAsync uses the FtpWebRequest class to execute a SIZE FTP command, which returns the size in bytes of the requested file. The file size is needed in order to accurately display download progress. Finally, the WebClient DownloadFileAsync function is called. This function, which initiates the file download process in the background, also begins the regular firing of the DownloadProgressChanged event.
The WebClient DownloadProgressChanged event is not directly COM consumable, so this event is also wrapped. The handler for DownloadProgressChanged fires a new event, which passes simple integer arguments for bytes downloaded and total file size. This event is easily consumable by Visual Basic 6.0. Likewise, the DownloadFileCompleted event is wrapped and made consumable for Visual Basic 6.0.
The primary goal of creating wrappers is to make .NET Framework classes appear as typical COM objects, with easily usable properties, methods, and events. The FTPWrapper achieves this goal, and Figure 7 shows the Visual Basic 6.0 code needed to download a file using FTP.
Dim WithEvents ftp As FX20Wrapper.FTPWrapper

Private Sub btnDownload_Click()
    lblProgress.Visible = True
    prgProgress.Visible = True
    Command1.Enabled = False
    ftp.DownloadFileAsync txtAddress.Text, txtFileName.Text
End Sub

Private Sub Form_Load()
    Set ftp = New FX20Wrapper.FTPWrapper
End Sub

Private Sub ftp_DownloadFileCompleted()
    lblProgress.Visible = False
    prgProgress.Visible = False
    Command1.Enabled = True
End Sub

Private Sub ftp_DownloadProgressChanged(ByVal bytesDownloaded As Long, _
        ByVal totalBytes As Long)
    prgProgress.Max = totalBytes
    prgProgress.Value = bytesDownloaded
End Sub
Starting a download is as simple as dimensioning the FTPWrapper class and calling the DownloadFile or DownloadFileAsync subroutine. If you call DownloadFileAsync, then the FTPWrapper will fire DownloadProgressChanged events as the download proceeds and a DownloadFileCompleted event when the download is completed. The DownloadProgressChanged event receives the number of bytes downloaded so far and the total file size. This information is all that’s needed to provide a progress indication of the download. Figure 8 shows the Visual Basic 6.0 FTP client while a download is in progress.
Figure 8 FTP Client Implemented in Visual Basic 6.0 
The code download for this article contains the wrapper class and sample applications shown in this article. To try out the samples, just download the code and execute the included install.bat file. This registers the wrapper class as a COM object. Then you can run any of the Visual Basic 6.0 samples.

Conclusion
Visual Basic 6.0 has become the new COBOL. This statement is made without malice toward either language. COBOL was enormously successful because it established itself as the language to use when writing mission critical mainframe applications. As the world went thick-client and GUI, Visual Basic assumed the mantle, showing itself to be arguably the best language for many business scenarios.
I can think of no mainstream business programming language that has truly gone extinct. Just as millions of lines of COBOL exist, and will for the foreseeable future, we will also be dealing with Visual Basic 6.0 for years to come. In fact, Microsoft has committed to shipping the Visual Basic 6.0 runtime on Windows Vista™, and running the Visual Basic 6.0 compatibility suite on Windows Vista to make a concerted effort to ensure that Visual Basic 6.0 applications just keep working.
But what is to be done with all this legacy code? Surely, it isn’t feasible to rewrite every line of it in Visual Basic 2005. Even if much of this code will eventually be migrated, it may not be possible to take that time and risk with a given application right now. Constraints dictate that many applications will continue their life on the Visual Basic 6.0 runtime. These applications need not ignore the .NET Framework and the productivity benefits that it brings.
You have seen how one tiny aspect of the .NET Framework, a few network classes, can be wrapped and exposed as COM objects, making their use from Visual Basic 6.0 trivial. Literally any portion of the .NET Framework can be wrapped and exposed in this way. Think of the .NET Framework as a gift from Microsoft of thousands upon thousands of classes. To use them, you need only supply the gift wrapping.

Scott Swigart spends his time consulting, writing, and speaking about converging and emerging technologies. Scott is the author of several books on .NET, a certified Microsoft trainer (MCT) and developer (MCSD), and a Microsoft MVP. You can contact Scott at scott@swigartconsulting.com.

Page view tracker