Export (0) Print
Expand All
Around the World with Visual Basic
Asynchronous Method Execution Using Delegates
Building a Progress Bar that Doesn't Progress
Calling All Operators
Create a Graphical Editor Using RichTextBox and GDI+
Creating A Breadcrumb Control
Creating a Five-Star Rating Control
Creating and Managing Secondary Threads
Data Binding Radio Buttons to a List
Deploying Assemblies
Designing With Custom Attributes
Digital Grandma
Doing Async the Easy Way
Extracting Data from .NET Assemblies
Implementing Callbacks with a Multicast Delegate
Naming and Building Assemblies in Visual Basic .NET
Programming Events of the Framework Class Libraries
Programming I/O with Streams in Visual Basic .NET
Reflection in Visual Basic .NET
Remembering User Information in Visual Basic .NET
Advanced Basics: Revisiting Operator Overloading
Scaling Up: The Very Busy Background Compiler
Synchronizing Multiple Windows Forms
Thread Synchronization
Updating the UI from a Secondary Thread
Using Inheritance in the .NET World
Using the ReaderWriterLock Class
Visual Basic: Simplify Common Tasks by Customizing the My Namespace
What's My IP Address?
Windows Forms Controls: Z-order and Copying Collections
Expand Minimize

Can I Interest You in 5000 Classes?

Visual Studio .NET 2003
 

Scott Swigart
Swigart Consulting LLC.

March 2006

Applies to:

   Microsoft Visual Basic 6
   Microsoft Visual Basic .NET 2003
   Microsoft Visual Basic 2005
   Microsoft Visual Studio 2005

Summary: In the previous article (Using the .NET Framework Class Library from Visual Basic 6), you saw how it was possible to start to unlock the functionality in the .NET framework to make it available to your Visual Basic 6 applications. This time, you will see how anything in the .NET Framework can be utilized in Visual Basic 6 by creating simple wrapper classes. This can let you quickly add powerful functionality to existing Visual Basic 6 applications, without the need to rewrite those applications in .NET. (13 printed pages)

Click here to download the code sample for this article.


Contents

Prerequisites
Accessing the Web
Regular Expressions
Putting It All Together
Conclusion
Resources

Prerequisites

To use the code for this article, you should have Visual Basic 6.0, and either Visual Studio 2005 or Visual Basic Express. Visual Basic Express is a free and relatively small download, available to all from the MSDN site.

Accessing the Web

In the previous article, you saw how you could use the .NET WebClient.Download file method to download a file from the Internet and save it to disk. However, the WebClient class has a lot more functionality that you might want to use. For example, you might want to download a file into a string so that you can work with it programmatically. The WebClient has the ability to do just that, through the OpenRead method, but you can't call this method directly from Visual Basic 6. To access the method, you need to write a trivial wrapper around the WebClient class.

To see the wrapper in action, you can download the code associated with this article, and double-click the included "Install.bat" file. If you want to create the wrapper by hand, you can perform the steps in the following walkthrough:

Walkthrough 1: Creating a wrapper for WebClient

  1. If you're using Visual Studio Express, download the code files for this article, and copy ComClass.zip to My Documents\Visual Studio 2005\Templates\ItemTemplates\Visual Basic. This installs the ComClass item template, which makes it easy to create COM objects in Visual Basic .NET. If you have Visual Studio 2005, this template is already installed.
  2. Start Visual Studio 2005 or Visual Basic Express.
  3. Select the File | New Project menu command.
  4. If you're using Visual Studio 2005, for Project Type select Visual Basic. This step is not necessary if you're using Visual Basic Express, as it automatically creates Visual Basic projects.
    1. For Templates, select Class Library.
    2. For Name enter NetFxWrapper, and click OK.
  5. In the Solution Explorer, delete Class1.vb.
  6. Select the Project | Add new item menu command.
    1. For Template select COM Class.
    2. For Name enter WebClientWrapper, and click Add.
  7. At the very top of the file, enter the following lines of code:
    Imports System.IO
    Imports System.Net
    Imports System.Runtime.InteropServices
    
    
  8. Before the "End Class" statement, enter the following function.
    Public Function DownloadFileAsString(ByVal url As String) As String
        Dim w As New WebClient()
        Dim sr As New StreamReader(w.OpenRead(url))
        Dim s As String = sr.ReadToEnd
        sr.Close()
        Return s
    End Function
    
    

    The DownloadFileAsString function uses the .NET WebClient class to open the URL and start reading the contents. The entire contents of the URL are read into a string, and the string is returned.

  9. Select the Build | Build NetFxWrapper menu command. This will compile the wrapper and register it as a COM object.

Using this from your Visual Basic 6 application is simple.

Walkthrough 2: Using the wrapper from Visual Basic 6.0

  1. Start Visual Basic 6.0.
  2. In the New Project dialog select Standard Exe, and click Open.
  3. Select the Project | References menu command.
  4. Select NetFxWrapper, and click OK.
  5. Add controls to the user interface so that it appears as follows. Let the controls keep their default names.

    Figure 1. Constructing the Visual Basic 6 user interface

  6. Set the MultiLine property of the larger text box to True.
  7. Double-click the Download button to generate the code for its event handler. Enter the following code.
    Dim w As NetFxWrapper.WebClientWrapper
    Set w = New NetFxWrapper.WebClientWrapper
    Text2 = w.DownloadFileAsString(Text1)
    
  8. Press F5 to run the application.
  9. For the URL, enter http://www.microsoft.com.
  10. Click Download. The text for the Web page should appear in the text box.

    Figure 2. Application that downloads a page using the wrapper

You can see that with just a few lines of .NET code, a significant amount of new functionality became available to Visual Basic 6.

At this point, it's worth dissecting the .NET wrapper code, and talking about what's required to register this code so that it can be referenced from Visual Basic 6. The first couple of lines of code import namespaces:

Imports System.IO
Imports System.Net
Imports System.Runtime.InteropServices

Think of these as almost being like a global With statement. If you don't import these namespaces, then you need to prefix them to every .NET class that you want to use with the full namespace. For example, with the Imports, you can declare an instance of WebClient as:

Private w As New WebClient

Without the imports, you would have to specify the fully qualified namespace that WebClient is part of, as in:

Private w As New System.Net.WebClient

The next section of code declares the wrapper class itself:

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

The first line applies an attribute to the class that will make it COM callable.

Next, a wrapper method is declared:

Public Function DownloadFileAsString(ByVal url As String) As String
    Dim w As New WebClient()
    Dim sr As New StreamReader(w.OpenRead(url))
    Dim s As String = sr.ReadToEnd
    sr.Close()
    Return s
End Function

Normally, the OpenRead method of the WebClient class is not directly callable from a Visual Basic 6 application. However, DownloadFileAsString wraps this method so that you can pass in a URL as a string, and get the page contents back as a string. Because it is taking and returning types that Visual Basic 6 can easily deal with, the DownloadFileAsString method can be called right from Visual Basic 6. The method doesn't have to do much. It just uses the WebClient class to open the URL, read the entire contents, and return the results.

At this point, the class is complete, and ready to be used from your Visual Basic 6 application. The only tasks remaining are to compile the class and register it so that it will show up in the list of Visual Basic 6 available references. A batch file is provided, called "Build And Register.bat," which accomplishes this. If you want to examine the contents of the batch file, you will see that it does a few things. First, it installs the wrapper into the global assembly cache (GAC). The GAC is a common location at which .NET DLLs can be placed so that they are easily usable by multiple applications. Next, the registry entries are created so that your .NET class appears as a regular COM object, and a type library is created for your class.

The wrapper class can now be used from Visual Basic 6, just like any COM object. From a Visual Basic 6 application, you can use the Project | References menu to add a reference to NetFxWrapper:

Figure 3. Referencing the wrapper class from Visual Basic 6

The Visual Basic 6 code to use the wrapper is now trivial:

Private Sub cmdDownload_Click()
    Dim w As wrappers.WebClientWrapper
    Set w = New wrappers.WebClientWrapper
    txtResults = w.DownloadFileAsString(txtUrl)
End Sub

You can create an instance of the WebClientWrapper, just like any other COM object, and just call the DownloadFileAsString method to download a Web page and get the results as a string.

Regular Expressions

Now that you have a string of potentially interesting information, you'll see how you can use regular expressions to search the string and extract data from it. Regular Expressions are classes that can be used to match patterns (such as phone numbers, e-mail addresses, zip codes, and so on) in strings and extract them. To access this powerful functionality, a simple wrapper has been provided for the .NET Regex class in the code download for this article.

Imports System.Text.RegularExpressions

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

    Private r As Regex

#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 = "88fbf42f-26e1-4909-9c18-4694fbbbbd80"
    Public Const InterfaceId As String = "0ae77958-9197-4642-9cdd-821091252c85"
    Public Const EventsId As String = "4b973489-094e-4c2f-8a70-5d9b29c57a33"
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub SetExpression(ByVal patternString As String)
        r = New Regex(patternString)
    End Sub

    Public Function Matches(ByVal input As String) As String()
        Dim matchList As MatchCollection

        matchList = r.Matches(input)

        Dim matchValues(matchList.Count - 1) As String
        For i As Integer = 0 To matchList.Count - 1
            matchValues(i) = matchList(i).Groups(0).Value
        Next

        Return matchValues
    End Function

End Class

There are two important methods in this class. The first method, SetExpression, is used to define the pattern that will be searched for. This is how you determine if this regular expression should extract numbers, e-mail addresses, and so on. The second method, Matches, returns an array of strings for all the extracted data. In other words, an array of e-mail addresses, zipcodes, and so on.

The "Regex Test" project, included with this article, includes this functionality to extract a number of kinds of data from a string. To use "Regex Test," simply execute the "install.bat" file in the code download for this article. You can then open the "Regex Test" project in Visual Basic 6, and run it:

Figure 4. Extracting data using a regular expression

You can see in that this application is able to use a regular expression to extract information like zip codes, phone numbers, and words beginning with a capital letter from a string. The regular expression (in this case \d{5}) looks for a pattern of five consecutive numbers to find zip codes. The code for this application uses the RegexWrapper to utilize the .NET Regex class to perform the search.

Private Sub cmdSearch_Click()
    txtResults = ""
    
    Dim r As NetFxWrapper.RegexWrapper
    Set r = New NetFxWrapper.RegexWrapper
    r.SetExpression (txtExpression)
    
    Dim s As Variant
    For Each s In r.Matches(txtData)
        txtResults = txtResults & s & vbCrLf
    Next
End Sub

Private Sub optCapWords_Click()
    txtExpression = "[A-Z]\w*"
End Sub

Private Sub optPhone_Click()
    txtExpression = "\d{3}-\d{3}-\d{4}"
End Sub

Private Sub optZipcode_Click()
    txtExpression = "\d{5}"
End Sub

You can see that the code simply sets the regular expression based on the value of txtExpression, and then calls the Matches method to get back an array of resulting matching strings.

Constructing Regular Expressions

You can spend literally years learning all the ins and outs of regular expressions, so just the basics will be covered here. In its simplest form, a regular expression can used to search for literal strings. For example, the regular expression Fred could be used to search a string for all occurrences of "Fred."

However, regular expressions are really useful when you know what the data will "look" like, but you don't have a literal string to search for. For example, a zip code is typically five numbers, but it could be practically any five numbers. For this kind of search, you could use /d{5} This means match any number (0 - 9), exactly five consecutive times. So this would match 11111, but would not match 11X111. This kind of expression could be put together to match a phone number, as /d{3}-/d{3}-/d{4}, which means, search for three numbers, followed by a dash, followed by three more numbers, followed by another dash, followed by four numbers.

Regular expressions can be made much more sophisticated to, for example, match a five or nine digit zip code, or match a phone number that follows a variety of patterns (such as (503)111-1111). There is extensive information about regular expressions online, and in a variety of books.

Putting It All Together

It's now time to use these classes to accomplish something I found personally useful. One problem that I frequently encounter is that sites will often post a set of useful slides or applications, but each slide or application will be posted as a separate file. For example, when Microsoft posted the slides from the Professional Developers Conference (PDC), they posted each PowerPoint as a separate download. I just didn't want to have to click on each one, and download it individually. Also, the Tablet PC PowerToys are all posted as separate downloads. "Wouldn't it be nice," I thought, "if I could build an application that would search the Web page and download all files of a specific type." With the WebClient and Regex classes, you have all the tools you need. WebClient can be used to download the page as a string. Regex can be used to search all links to files of a specific type, and then WebClient can be used again to perform the actual file downloads.

First, the WebClient class is used to download the page containing the links, and then a regular expression is used to extract the link href information. The results are returned as an array of strings.

Private Function GetHrefs(url As String) As String()
    '
    ' Download the source page
    '
    Dim wc As WebClientWrapper
    Set wc = New WebClientWrapper
    Dim file As String
    file = wc.DownloadFileAsString(url)

    '
    ' Use a regular expression to extract the hrefs from
    ' the page.
    '
    Dim r As RegexWrapper
    Set r = New RegexWrapper
    r.SetIgnoreCase
    r.SetExpression ("(?<=href\s*=\s*[""']).*?(?=[""'])")
    GetHrefs = r.Matches(file)
End Function

You can see that the first part of the function downloads the URL as a string. The next part of the function creates an instance of the Regex class and specifies the expression. This expression is a little complex, but given a string such as <a href='http://someurl/somefile.doc'>, this regular expression would return just the "http://someurl/somefile.doc" part. If you use this against an entire Web page, you get all the URLs of the anchor tags.

At this point, the application has what it needs to start downloading all the documents referenced on the page:

For Each url In urls
    If Right(url, 4) = ".ppt" Or Right(url, 4) = ".zip" Or _
        Right(url, 4) = ".doc" Or Right(url, 4) = ".pdf" Or _
        Right(url, 4) = ".exe" Then

        ' Get the filename from the end of the URL
        '
        Dim fileName As String
        fileName = Right(url, Len(url) - InStrRev(url, "/"))
        fileName = Replace(fileName, "%20", " ")
        
        '
        ' Download files
        '
        If Not f.FileExists(dest & "\" & fileName) Then
            txtFileList = txtFileList & "Downloading " & _
                fileName & vbCrLf
            DoEvents
                
            Dim w As WebClient
            Set w = New WebClient
            w.DownloadFile url, dest & "\" & fileName
        End If
    End If
Next

Here the application loops through all the URLs, and examines them to see if they point to a desired file type. In this case, that's any PowerPoint, Word Document, PDF, ZIP, or executable file. The application then uses the WebClient class to download the file.

Conclusion

This application would have been quite challenging to write with just Visual Basic 6. With the .NET Framework and some simple wrapper classes, the needed functionality became immediately available. WebClient and Regex are just a couple examples of the literally thousands of classes in the Framework that can speed your development. By creating simple wrapper classes, the full power of the Framework is at your disposal.

Resources

Deploying Hybrid Visual Basic 6 and Visual Basic .NET Applications

Global Assembly Cache

 

About the author

Scott Swigart spends his time consulting, authoring, and speaking about emerging and converging technologies. Scott has worked with a wide range of technologies over his career, beginning with Commodore 64 programming at the age of 12, writing hardware diagnostics for UNIX systems in C++, and building windows desktop, and Web applications. Over the years, Scott has worked with component development, XML technologies, .NET, Web service, and other languages, platforms, and paradigms. With this experience, Scott has seen how technology evolves over time, and is focused on helping organizations get the most out of the technology of today, while preparing for the technology of tomorrow. Scott is also a Microsoft MVP, and co-author of numerous books and articles. Scott can be reached at scott@swigartconsulting.com.

Show:
© 2014 Microsoft