WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Creating a Windows DLL with Visual Basic
Pages: 1, 2, 3

The ActiveX DLL Project Type

Let's begin by creating an ActiveX DLL project and seeing what happens if we try to call it as if it were a standard Windows DLL. When you create an ActiveX DLL project, Visual Basic automatically adds a class module (a .cls file) to it. You can rename this if you want, but don't include any code. Instead, add a code module (a .bas file) to the project, add the DLL's code, and then compile the DLL. When you run the DLL test application, the error message dialog shown in Figure 1 appears. The error message indicates that although the DLL was found, the specific called function (Increment) was not.

Figure 1
Figure 1. Error when accessing an ActiveX DLL as a Windows DLL

The most likely cause of this error is that the function is not actually exported by the DLL. We can use the DumpBin utility to examine a DLL's exports by using the syntax
Dumpbin <path and name of dll> /exports

If we run DumpBin using this syntax, we see the following output:

Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


Dump of file mathlib.dll

File Type: DLL

  Section contains the following exports for MathLib.dll

           0 characteristics
    41B9E52C time date stamp Fri Dec 10 10:04:28 2004
        0.00 version
           1 ordinal base
           4 number of functions
           4 number of names

    ordinal hint RVA      name

          1    0 0000192E DllCanUnloadNow
          2    1 00001902 DllGetClassObject
          3    2 00001918 DllRegisterServer
          4    3 000018EC DllUnregisterServer

  Summary

        1000 .data
        1000 .reloc
        1000 .rsrc
        1000 .text

Our DLL exports four functions, all of which are utility functions that support COM. Clearly we need to export DllMain and our three math functions. But how? Visual Basic does not appear to allow you to export DLL functions from ActiveX DLLs, thus effectively preventing you from using Visual Basic to create a standard Windows DLL.

This difficulty, however, is not insurmountable. When we select the File -> Make <filename>.dll menu option to create an ActiveX DLL, it appears that Visual Basic is seamlessly taking our source code and outputting an ActiveX DLL. But if we examine the subdirectory in which Visual Basic was installed, it appears that the process is not quite so seamless. Along with VB6.EXE, the Visual Basic executable that defines the Visual Basic environment, we can also find C2.EXE and LINK.EXE, which are a compiler and a linker, respectively. Their presence in this directory suggests that VB6.EXE itself does not handle the generation of a DLL file, but that at some point in the compilation process, it calls these programs.

We can find out how Visual Basic is using the compiler and linker more precisely by renaming them and creating wrapper executables named C2 and LINK that in turn call the real compiler and linker. The following is the source code for a new version of a console-mode C2.EXE that calls the "real" C2 compiler, which we've renamed C2comp.exe:


Public Sub Main()

On Error Resume Next

   Dim strCmd As String, strPath As String
   Dim oFS As New Scripting.FileSystemObject
   Dim ts As TextStream

   strCmd = Command
   
   strPath = App.Path
   
   Set ts = oFS.CreateTextFile(strPath & "\c2log.txt")
   
   ts.WriteLine "Beginning execution at " & Date & " " & Time()
   ts.WriteBlankLines 1
   ts.WriteLine "Command line parameters to c2 call:"
   ts.WriteLine "   " & strCmd
   ts.WriteBlankLines 1
   ts.WriteLine "Calling C2 compiler"
   
   Shell "c2comp.exe " & strCmd
   If Err.Number <> 0 Then
      ts.WriteLine "Error in calling C2 compiler..."
   End If
   
   ts.WriteBlankLines 1
   ts.WriteLine "Returned from c2 compiler call"
   ts.Close
   
End Sub

The process of compiling an ActiveX DLL produces the following output in our log file:


Beginning execution at 12/10/2004 12:44:22 PM

Command line parameters to c2 call:
   -il "C:\DOCUME~1\Ron\LOCALS~1\Temp\VB277103" -f "C:\VB Projects\
   MathLib\MathMod.bas" -W 3 -Gy -G5 -Gs4096 -dos -Zl -Fo"C:\
   VB Projects\MathLib\MathMod.OBJ" -QIfdiv -ML -basic

Calling C2 compiler

Returned from c2 compiler call

These are fairly standard command-line arguments to produce object files that in turn are supplied to the linker. That means that to determine how to produce a Windows DLL, we'll have to intercept the call to the linker so that we can see what arguments Visual Basic passes to it. The following code does that:


Public Sub Main()

On Error Resume Next

   Dim strCmd As String, strPath As String
   Dim oFS As New Scripting.FileSystemObject
   Dim ts As TextStream

   strCmd = Command
   
   strPath = App.Path
   
   Set ts = oFS.CreateTextFile(strPath & "\lnklog.txt")
   
   ts.WriteLine "Beginning execution at " & Date & " " & Time()
   ts.WriteBlankLines 1
   ts.WriteLine "Command line parameters to LINK call:"
   ts.WriteLine "   " & strCmd
   ts.WriteBlankLines 1
   ts.WriteLine "Calling LINK linker"
   
   Shell "linklnk.exe " & strCmd
   If Err.Number <> 0 Then
      ts.WriteLine "Error in calling linker..."
      Err.Clear
   End If
   
   ts.WriteBlankLines 1
   ts.WriteLine "Returned from linker call"
   ts.Close
   
End Sub

It requires that we rename the linker LinkLnk.exe and name our link wrapper Link.exe.

When we attempt to compile an ActiveX DLL project, our linker log file contains the following output:


Beginning execution at 12/11/2004 12:44:33 PM

Command line parameters to LINK call:
   "C:\Program Files\Microsoft Visual Studio\VB98\Class1.OBJ" 
   "C:\Program Files\Microsoft Visual Studio\VB98\Project1.OBJ" 
   "C:\Program Files\Microsoft Visual Studio\VB98\VBAEXE6.LIB" 
   /ENTRY:__vbaS 
   /OUT:"C:\Program Files\Microsoft Visual Studio\VB98\Project1.dll" 
   /BASE:0x11000000 
   /SUBSYSTEM:WINDOWS,4.0 /VERSION:1.0 
   /DLL  
   /INCREMENTAL:NO /OPT:REF /MERGE:.rdata=.text /IGNORE:4078 

Calling LINK linker

Returned from linker call

If we compare these command-line arguments with the syntax required to link the object files for a DLL using either C or C++, an omission becomes immediately apparent. Although the /DLL switch is supplied to create a standard DLL, there is no /DEF switch to define a module definition (.def) file that lists the functions exported by the DLL. (If we were programming in C or C++, we could use statements within our code to define our exports. Visual Basic doesn't support this, however, making the .def file the sole means of defining a library's exports.) Moreover, if we examine the files generated for an ActiveX DLL project by the Visual Basic environment, we'll also find that Visual Basic itself has not generated a .def file.

Pages: 1, 2, 3

Next Pagearrow