Calling Windows API Subs and Functions

 

The Windows API is a set of code libraries (DLL files) containing numerous functions for working with all aspects of Windows (graphics, the file system, fonts, low-level memory access, etc.). These function libraries are available to programmers coding with any Windows development system (VB, C++, Delphi, etc.).

 

While using the API is often treated as an "advanced" programming topic (and to be sure, using the API allows you to delve as deep into the depths of Windows programming as you desire), the coding to actually set up and use an API function is relatively straightforward. The basic steps are:

 

 

 

 

To find the declarations and documentation necessary to use any of the 1000+ Windows API functions available, you can consult any of the numerous API Help websites. Google is of course best for searching.

 

Sample Program

 

We will now build a simple program that demonstrates the use of API functions. We will call upon the "GetComputerName" function to access the name of your computer and display it in the console winodw.

 

Note: On Windows XP, the name of the computer can be found by right-clicking on the My Computer icon and choosing Properties, which then displays the System Properties screen shown below. The second tab, Computer Name, shows your computer name. In this case, the name of the computer is “toshiba-user” (shown circled in red below).

 

 

Following is the code for the sample console application to display the computer name:

 

Module Module1

 

    Private Declare Function GetComputerName Lib "kernel32.dll" Alias "GetComputerNameA" _

                                    (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

 

    Sub Main()

 

        Dim strBuffer As String

        Dim intCharCount As Integer

        Dim intRetVal As Integer

        Const MAX_COMPUTERNAME_LENGTH As Integer = 31

        Dim strMessage As String

 

        intCharCount = MAX_COMPUTERNAME_LENGTH

        strBuffer = New String(Chr(0), intCharCount + 1)

        intRetVal = GetComputerName(strBuffer, intCharCount)

 

        If intRetVal <> 0 Then

            strMessage = "Your computer name is: " _

                       & strBuffer.Substring(0, intCharCount)

        Else

            strMessage = "Computer name could not be determined."

        End If

 

        Console.WriteLine(strMessage)

 

        Console.WriteLine("")

        Console.WriteLine("(Press Enter to close this window.)")

        Console.ReadLine()

 

    End Sub

 

End Module

 

A screen-shot of the run is shown below:

 

 

 

We can analyze the code as follows. First, an explanation of the Declare statement. The Declare statement has the following general syntax:

 

[Public | Private] Declare Function Name Lib LibraryName [Alias AliasName] ([parameter list]) As datatype

- or -

[Public | Private] Declare Sub Name Lib LibraryName [Alias AliasName] ([parameter list])

 

As discussed above, the Public or Private keyword establishes the scope of the function as it will be used in your program.

 

As in normal VB Subs and Functions, use the Function keyword (and the corresponding As datatype clause at the end of the declaration) if the API function returns a value (in most cases, the "Function" form will be used, and the return value (datatype) will be Integer). In other cases, where the API function does not return a value, use the Sub keyword and leave off the As datatype clause.

 

Name specifies the name of the function as it will be used in the VB program. When the internal name of the function within the library (DLL file) is different, use the Alias clause to specify the actual internal name within the DLL.

 

LibraryName specifies which DLL the function can be found in.

 

AliasName specifies the actual internal name of the function within the Windows DLL file. The Alias clause needs to be used if the name used for Name is different. The Alias clause is useful when an internal name conflicts with a keyword (but can be used if you simply want to use a different name to call the function).

 

Parameter list is the comma-separated list of arguments that the function expects.

 

As datatype specifies the data type returned by the function. In most cases, this is a 32-bit integer specified in VB.NET as Integer. (Note: In previous versions of VB, the Integer data type was a 16-bit integer and the Long was a 32-bit integer. Thus, the return value for API functions was typically specified as Long when declaring APIs in the previous VB versions. In VB.NET, the Integer data type is now a 32-bit integer and the Long is a 64-bit integer, so we must use Integer data type to specify the return value for API functions.)

 

In this example, our declaration looks like this:

 

    Private Declare Function GetComputerName Lib "kernel32.dll" Alias "GetComputerNameA" _

                                    (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

 

This tells the system we are looking for the GetComputerName function located in the kernel32.dll Windows system file. (The Alias clause indicates that the actual name of the function in the dll is GetComputerNameA, however, declaring the function as above, we can refer to the function as GetComputerName in our VB code.)

 

The arguments to this particular function are lpBuffer, which is a string that will store the computer name, and nSize which is a number (integer) that will store the number of characters contained in the computer name. (Technically, the lpBuffer argument is a “null-terminated string”, which is a string in which the trailing character(s) are the null character (ASCII code 0). The characters up to but not including the first null character represents the value of the string.)

 

The As Integer specification at the end of our declaration indicates that the function will be returning a Integer value. In the case of many API functions, a 32-bit Integer value will be returned to indicate the success or failure of the call.

 

The crux of the processing occurs in these three lines. We are setting the variable intCharCount to the value of the constant MAX_COMPUTER_LENGTH, which is set to 31. The next statement pads the variable strBuffer with 32 null characters. The actual call to the API function follows, which causes the computer name to be stored in strBuffer (in our case the result will be the string “TOSHIBA-USER” followed by 20 null characters). This is because the string “TOSHIBA-USER” contains 12 characters, and since the total length of the string is 32 characters, 20 null characters will trail at the end of the string. The function will also store the value 12 in the variable intCharCount, representing the number of characters in the name that was retrieved. The result of the function (the return value) is stored in the variable intRetVal. If the result is non-zero, the function succeeded; if zero, the function failed.

 

        intCharCount = MAX_COMPUTERNAME_LENGTH

        strBuffer = New String(Chr(0), intCharCount + 1)

        intRetVal = GetComputerName(strBuffer, intCharCount)

 

The code that follows tests the return value. If the return value is non-zero, then the call was successful, and a message containing the computer’s name is stored in the variable strMessage (the Substring method is applied to the strBuffer variable to grab its 12 leftmost characters). Otherwise, we set strMessage to indicate that the function failed. In any case, the message is then displayed on the console.

 

 

        If intRetVal <> 0 Then

            strMessage = "Your computer name is: " _

                       & strBuffer.Substring(0, intCharCount)

        Else

            strMessage = "Computer name could not be determined."

        End If

 

        Console.WriteLine(strMessage)

 

 

Download the VB project code for the example above here.

 

NOTE: We can use the API functions in VB.NET using the steps covered in this article. However, it must be noted that most of the functionality of Windows API has been encapsulated in Object Oriented Classes of .NET framework and many more will be added to this list of classes and functions. Therefore, it is recommend that before using an API, we must check if the similar functionality is available in .NET classes.