Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

.NET

An Automation Object for Dynamic DLL Calls


Jeff Stong has been developing DOS, Windows, and Windows NT based applications for 10 years. Jeff can be contacted at [email protected].

You can access external DLLs from Visual Basic by using the Declare statement to declare the name of the function you want to call and the DLL that it resides in. VBScript, however, doesn't support the Declare statement. This article presents an OLE automation object that lets VBScript (or any other environment that can access automation objects) dynamically declare and access functions in external DLLs.

Using the DynamicWrapper Object

The name of the automation object I created is DynamicWrapper, and you can declare it just like any other object in VBScript:


Dim UserWrap As Object
Set UserWrap = CreateObject("DynamicWrapper")

Initially, the only method the DynamicWrapper object supports is Register(). You invoke the Register() method to describe an external DLL function before calling it. DynamicWrapper is an unusual automation object in that it dynamically adds new methods at runtime. The basic idea is that you first invoke DynamicWrapper.Register() to declare some DLL function named (for example) "SomeFunc", and the DynamicWrapper object suddenly supports a method called SomeFunc() that you can invoke to access the external DLL function. You can register and then invoke any number of external functions with a single DynamicWrapper object.

You have to call Register() to tell the DynamicWrapper object all the details about the external DLL function you want to call, including the name, calling convention, number and type of parameters, and type of return value. The following syntax is used to register a procedure:


[result = ] object.Register <dllname>, <procname> [,<tag>,...]

For example, the standard Win32 function MessageBox() resides in the DLL user32.dll and has the following C prototype:


int MessageBox(HWND hWnd, LPCTSTR lpText,
    LPCTSTR lpCaption, UINT uType);

To register this function, you would call Register() like this:


UserWrap.Register "user32.dll", "MessageBoxA", _
    "i=hssu", "f=s", "r=l"

The first two parameters are obviously the name of the DLL and the name of the function to call. If you're not certain that the DLL resides in a directory in the current command search path, then you should use a fully qualified pathname. Also note that the function named here is "MessageBoxA" and not "MessageBox". Win32 (and some third-party DLLs as well) often supports both an ANSI and a Unicode version of the same function, so there is no actual user32.dll export called "MessageBox", but there is a "MessageBoxA" and a "MessageBoxW". You must know the exact details of the external DLL function you want to call in order to invoke it correctly. Using a command like dumpbin /EXPORTS target.dll can be helpful in verifying the exported name of a DLL function.

After the function name comes three optional tag parameters that describe the function's calling convention, input parameters, and return type. You can list these optional parameters in any order, but they must be separated by commas.

The tag that describes the input parameters of the function takes the following form:


i=<flag>*<flag>*

where <flag> is one of the flags shown in Table 1, and each flag describes (in order) the type of a parameter that the function takes. The function MessageBoxA() takes a window handle, two strings, and an unsigned integer, which can be described with the string "i=hssu".

[Click image to view at full size]
Table 1: Parameter type flags.

A function's calling sequence is the specification for exactly how it expects parameters to be pushed on the stack and returned, who is responsible for adjusting the stack pointer, and so on. Most exported DLL functions use a common calling sequence, but there are important exceptions, and DynamicWrapper can handle most of them. The syntax for the optional argument that details a function's calling sequence is:


f=<flag><flag>*

where <flag> is one of the flags shown in Table 2. If you omit this optional argument, Register() uses "f=ms" as the default. Some flags are mutually exclusive as noted in Table 2. The default is correct for most DLL functions.

[Click image to view at full size]
Table 2: Calling sequence flags.

Finally, if the function you want to call returns a value, you must specify the type with an argument of the form:


r=<flag>

where <flag> is one of the characters described in Table 1. If the function returns no value, simply omit this parameter when you call Register().

After you call Register() to declare the function, you can then call it using the syntax:


Object.<procname>[parameters]

Using the previous example, you would invoke MessageBoxA() (the ANSI version of MessageBox()) like this:


UserWrap.MessageBoxA Null, "Hello World", "VBScript", 3


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.