Mastering CGI with Visual Basic: Build Powerful Web Applications

Table of Contents

Common Gateway Interface (CGI) applications have long served as a fundamental method for web servers to interact with external programs, enabling dynamic content generation. While modern web development has evolved significantly, understanding CGI principles, especially with languages like Visual Basic, offers valuable insight into the origins of interactive web applications. This article provides a comprehensive guide to developing CGI applications using Visual Basic, detailing the essential techniques and offering practical examples.

Mastering CGI with Visual Basic

At its core, a CGI application is designed to be executable by a web server, processing incoming requests and generating an HTTP response. The versatility of CGI allows it to be implemented in virtually any programming language capable of interacting with the operating system’s environment variables and standard input/output streams. Visual Basic, renowned for its robust text handling capabilities and ease of development, became an attractive choice for many web developers looking to build server-side applications during its prime.

This guide will walk through the intricacies of writing CGI applications in Visual Basic, covering critical aspects such as accessing environment variables and managing data flow through standard input (STDIN) and standard output (STDOUT). We will illustrate these techniques with a simple, yet effective, Visual Basic CGI sample, demonstrating how to construct and deploy a functional web application. By the end of this article, readers will have a clear understanding of how to leverage Visual Basic for server-side processing within the CGI framework.

Understanding Common Gateway Interface (CGI)

The Common Gateway Interface (CGI) defines a standard protocol for web servers to execute programs that generate web pages dynamically. When a user requests a URL that points to a CGI program, the web server initiates the program, passing request information to it and receiving the generated output in return. This process allows websites to offer interactive features, such as processing form data, retrieving information from databases, or personalizing content for users.

CGI acts as an intermediary, facilitating communication between the web server and the external application. The web server collects all relevant request data, including form submissions, HTTP headers, and client information, and then channels this data to the CGI program. The CGI program processes this input, performs its designated tasks, and ultimately sends an HTTP response back to the web server, which then forwards it to the client’s browser.

Historically, CGI was one of the earliest and most widely adopted methods for creating dynamic web content, predating many of the more advanced application server technologies we see today. Its language independence was a key strength, allowing developers to choose the best tool for the job, whether it was Perl, C++, or, as we explore here, Visual Basic. Understanding CGI’s fundamental role provides context for the evolution of web development and the underlying mechanisms that still influence modern web architectures.

Why Visual Basic for CGI?

Visual Basic might seem like an unconventional choice for web development to those accustomed to modern scripting languages, but its strengths made it quite appealing for CGI in its era. The language’s powerful text handling capabilities, combined with its rapid application development (RAD) environment, allowed developers to quickly prototype and deploy server-side logic. Visual Basic’s intuitive syntax and extensive library support simplified tasks that could be more complex in lower-level languages.

For many developers already proficient in Visual Basic for desktop applications, extending their skills to server-side programming via CGI was a natural progression. The ability to leverage existing knowledge and tools meant a lower barrier to entry for creating dynamic web content. This made Visual Basic a practical option for building interactive web pages, processing form submissions, and generating custom responses, even if it primarily meant compiling standalone executables rather than writing embedded scripts.

While Visual Basic’s prominence in web development eventually waned with the rise of dedicated web frameworks and server-side platforms, its role in the CGI landscape underscores its versatility. It demonstrated that robust web applications could be constructed using familiar programming paradigms, provided the developer understood the intricacies of the CGI protocol. The techniques discussed in this article highlight how Visual Basic was adapted to meet the demands of early dynamic web content creation.

Retrieving Environment Variables

A crucial aspect of any CGI application is its ability to access environment variables. These variables are set by the web server and provide the CGI program with essential information about the client request, the server configuration, and the execution environment. Details such as the request method (GET or POST), client’s IP address, requested URL, and content length for POST requests are all communicated through environment variables.

In Visual Basic, retrieving an environment variable is straightforward, thanks to the built-in Environ$ function. This function takes the name of the environment variable as a string argument and returns its corresponding value. For instance, to obtain the value of a variable named NAME, you would use the syntax:

VALUE = Environ$(NAME)

This simple yet powerful function allows a Visual Basic CGI application to dynamically adapt its behavior based on the specific context of each client request. By systematically querying these variables, the application can determine how to process input, identify the client, and tailor its response accordingly. A comprehensive understanding of the available environment variables is therefore fundamental to designing effective and responsive CGI programs.

Key CGI Environment Variables

Understanding the various environment variables available to a CGI script is critical for processing requests effectively. These variables provide the context necessary for the application to function correctly. Here’s a table summarizing some of the most common and important CGI environment variables:

Variable Name Description
AUTH_TYPE Specifies the authentication method used to validate the user.
CONTENT_LENGTH Indicates the length of the query data (in bytes or characters) if the request method is POST. This is crucial for reading data from STDIN.
CONTENT_TYPE Describes the media type of the content if the request method is POST. Common values include application/x-www-form-urlencoded or multipart/form-data.
GATEWAY_INTERFACE Defines the version of the CGI specification the server is using (e.g., CGI/1.1).
HTTP_ACCEPT Lists the media types that the client can handle. This comes from the Accept header in the HTTP request.
HTTP_REFERER The URL of the page that referred the user agent to the current page. Useful for tracking navigation paths.
HTTP_USER_AGENT Provides information about the user agent (browser) making the request, including its name and version.
PATH_INFO Extra path information given by the client. It represents a virtual path that follows the CGI script’s path but precedes the query string.
PATH_TRANSLATED The server’s virtual-to-physical mapping of PATH_INFO.
QUERY_STRING Contains the URL-encoded name-value pairs from the request URL, typically used for GET requests. Example: Name=Joe&Color=Red.
REMOTE_ADDR The IP address of the client making the request.
REMOTE_HOST The hostname of the client making the request. If the server does not perform reverse lookups, this may be identical to REMOTE_ADDR.
REMOTE_USER The authenticated username if the script requires HTTP authentication.
REQUEST_METHOD The HTTP method used for the request (e.g., GET, POST, HEAD). Essential for determining how to process incoming data.
SCRIPT_NAME The virtual path to the script being executed.
SERVER_NAME The hostname, DNS alias, or IP address of the server.
SERVER_PORT The port number to which the request was sent (e.g., 80, 443).
SERVER_PROTOCOL The name and version of the information protocol used by the request (e.g., HTTP/1.0, HTTP/1.1).
SERVER_SOFTWARE The name and version of the web server software (e.g., Apache/2.4.1, Microsoft-IIS/10.0).

By understanding and utilizing these environment variables, Visual Basic CGI applications can effectively interpret client requests and generate appropriate dynamic responses. Developers should consult MSDN documentation or server-specific guides for a complete list and detailed descriptions of all available variables.

Reading from STDIN and Writing to STDOUT

For CGI applications to interact with the client and server effectively, they must manage data flow through standard input (STDIN) and standard output (STDOUT). STDIN is where the CGI program receives data sent by the client, particularly for POST requests, while STDOUT is where the CGI program writes its HTTP response, which is then sent back to the client via the web server. Direct access to these streams is essential for building robust CGI applications.

In Visual Basic, interacting with STDIN and STDOUT requires leveraging Win32 API functions, as Visual Basic’s built-in file I/O functions are not directly suited for standard console streams in this context. Specifically, the ReadFile function is used to read data from STDIN, and the WriteFile function is used to send data to STDOUT. To use these functions, you first need to obtain handles to the STDIN and STDOUT streams, which is achieved through the GetStdHandle function.

To simplify these function calls within Visual Basic, aliasing is commonly employed, allowing the developer to refer to GetStdHandle with more descriptive names like stdin and stdout. The correct declaration of these Win32 API functions within a Visual Basic module is critical for their successful operation. These declarations specify the function signatures, required libraries (kernel32.dll), and parameter types, ensuring proper interoperability between Visual Basic and the underlying Windows API.

Win32 API Declarations for CGI

The following declarations are essential for any Visual Basic CGI application that needs to read from STDIN and write to STDOUT. These declarations expose the necessary Win32 API functions to your Visual Basic code, allowing direct manipulation of the standard input/output streams. The Alias keyword is used to provide more VB-friendly function names, making the code more readable and maintainable.

Public Declare Function stdin Lib "kernel332" Alias "GetStdHandle" _
(Optional ByVal Handletype As Long = STD_INPUT_HANDLE) As Long

Public Declare Function stdout Lib "kernel332" Alias "GetStdHandle" _
(Optional ByVal Handletype As Long = STD_OUTPUT_HANDLE) As Long

Public Declare Function ReadFile Lib "kernel332" _
(ByVal hFile As Long, ByVal lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
lpNumberOfBytesRead As Long, Optional ByVal lpOverlapped As Long = 0&) As Long

Public Declare Function WriteFile Lib "kernel332" _
(ByVal hFile As Long, ByVal lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, _
lpNumberOfBytesWritten As Long, Optional ByVal lpOverlapped As Long = 0&) As Long

These declarations must be placed in a standard module within your Visual Basic project. The Lib "kernel32" specifies the dynamic-link library where these functions reside, and ByVal ensures that arguments are passed by value, as expected by the C-style Win32 API. Pay close attention to the parameter types and their order to avoid runtime errors, as incorrect declarations can lead to unpredictable behavior or application crashes.

Furthermore, the constants required by GetStdHandle for specifying which standard handle to retrieve also need to be defined. These constants, STD_INPUT_HANDLE and STD_OUTPUT_HANDLE, are standard identifiers for the input and output streams within the Windows operating system. Defining them explicitly in your Visual Basic module enhances code clarity and ensures that the correct handles are requested from the system.

Public Const STD_INPUT_HANDLE = -10&
Public Const STD_OUTPUT_HANDLE = -11&

By having these declarations and constants in place, your Visual Basic CGI application gains the foundational capability to perform low-level input/output operations, which are indispensable for processing client requests and generating dynamic web content. For a detailed explanation of each parameter within these functions, refer to the official MSDN documentation, which provides comprehensive descriptions and usage guidelines for the Win32 API.

Sample Code: A Simple “Hello” CGI Application

To illustrate the techniques discussed, let’s examine a straightforward Visual Basic CGI application named Hello.bas. This sample demonstrates how to retrieve client input from STDIN for a POST request and then construct and send an HTML response back through STDOUT. While error trapping is intentionally omitted for brevity in this example, it is crucial for production-grade applications.

The code begins by declaring various constants for common CGI environment variables, offering both readability and compile-time validation, minimizing potential errors. It also includes the necessary Win32 API declarations for GetStdHandle (aliased as stdin and stdout), ReadFile, and WriteFile, which are fundamental for I/O operations within the CGI context. These declarations ensure that the Visual Basic application can effectively interface with the operating system’s standard streams.

The Main subroutine serves as the entry point for the CGI application. Inside Main, the application first determines the expected content length from the CONTENT_LENGTH environment variable, then allocates a buffer to read the incoming client data from STDIN. After reading the input, it parses the data (assuming a simple name=value pair) and constructs an HTTP response, including the necessary headers and the dynamic content. Finally, this complete response is written to STDOUT, completing the request-response cycle.

Hello.bas Code Example

Option Explicit

Public Const STD_INPUT_HANDLE = -10&
Public Const STD_OUTPUT_HANDLE = -11&

' CGI Environment Variable Constants
Public Const CGI_AUTH_TYPE As String = "AUTH_TYPE"
Public Const CGI_CONTENT_LENGTH As String = "CONTENT_LENGTH"
Public Const CGI_CONTENT_TYPE As String = "CONTENT_TYPE"
Public Const CGI_GATEWAY_INTERFACE As String = "GATEWAY_INTERFACE"
Public Const CGI_HTTP_ACCEPT As String = "HTTP_ACCEPT"
Public Const CGI_HTTP_REFERER As String = "HTTP_REFERER"
Public Const CGI_HTTP_USER_AGENT As String = "HTTP_USER_AGENT"
Public Const CGI_PATH_INFO As String = "PATH_INFO"
Public Const CGI_PATH_TRANSLATED As String = "PATH_TRANSLATED"
Public Const CGI_QUERY_STRING As String = "QUERY_STRING"
Public Const CGI_REMOTE_ADDR As String = "REMOTE_ADDR"
Public Const CGI_REMOTE_HOST As String = "REMOTE_HOST"
Public Const CGI_REMOTE_USER As String = "REMOTE_USER"
Public Const CGI_REQUEST_METHOD As String = "REQUEST_METHOD"
Public Const CGI_SCRIPT_NAME As String = "SCRIPT_NAME"
Public Const CGI_SERVER_NAME As String = "SERVER_NAME"
Public Const CGI_SERVER_PORT As String = "SERVER_PORT"
Public Const CGI_SERVER_PROTOCOL As String = "SERVER_PROTOCOL"
Public Const CGI_SERVER_SOFTWARE As String = "SERVER_SOFTWARE"

' Win32 API Declarations
Public Declare Function Sleep Lib "kernel32" _
(ByVal dwMilliseconds As Long) As Long

Public Declare Function stdin Lib "kernel32" Alias "GetStdHandle" _
(Optional ByVal Handletype As Long = STD_INPUT_HANDLE) As Long

Public Declare Function stdout Lib "kernel32" Alias "GetStdHandle" _
(Optional ByVal Handletype As Long = STD_OUTPUT_HANDLE) As Long

Public Declare Function ReadFile Lib "kernel32" _
(ByVal hFile As Long, ByVal lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
lpNumberOfBytesRead As Long, Optional ByVal lpOverlapped As Long = 0&) As Long

Public Declare Function WriteFile Lib "kernel32" _
(ByVal hFile As Long, ByVal lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, _
lpNumberOfBytesWritten As Long, Optional ByVal lpOverlapped As Long = 0&) As Long

Sub Main()

    Dim sReadBuffer As String
    Dim sWriteBuffer As String
    Dim lBytesRead As Long
    Dim lBytesWritten As Long
    Dim hStdIn As Long
    Dim hStdOut As Long
    Dim iPos As Integer
    Dim lContentLength As Long

    ' The Sleep function can be useful during debugging to attach a debugger.
    ' Sleep 60000 ' Uncomment to pause execution for 60 seconds

    ' Retrieve CONTENT_LENGTH environment variable to know how much data to read.
    ' Ensure the value is converted to a long for buffer allocation.
    lContentLength = CLng(Environ$(CGI_CONTENT_LENGTH))
    sReadBuffer = String$(lContentLength, 0)

    ' Get handle to STDIN
    hStdIn = stdin()

    ' Read client's input from STDIN
    If lContentLength > 0 Then
        ReadFile hStdIn, ByVal sReadBuffer, lContentLength, lBytesRead
    End If

    ' Find '=' in the name/value pair (e.g., "Name=John") and parse the buffer.
    ' This simple parsing assumes a single name=value pair.
    iPos = InStr(sReadBuffer, "=")
    If iPos > 0 Then
        sReadBuffer = Mid$(sReadBuffer, iPos + 1) ' Extract the value (e.g., "John")
    Else
        sReadBuffer = "" ' Handle cases where '=' is not found
    End If

    ' Construct the HTTP response.
    ' First, send HTTP headers: Status line and Content-Type.
    ' Then, two CRLF characters to separate headers from the body.
    ' Finally, the HTML body content.
    sWriteBuffer = "HTTP/1.0 200 OK" & vbCrLf & _
                   "Content-Type: text/html" & vbCrLf & _
                   vbCrLf & "Hello "

    ' Get handle to STDOUT
    hStdOut = stdout()

    ' Write the HTTP headers and initial part of the body to STDOUT
    ' Add 1 to length for null termination if buffer contains binary data,
    ' but for text, Len(sWriteBuffer) is usually sufficient.
    WriteFile hStdOut, ByVal sWriteBuffer, Len(sWriteBuffer), lBytesWritten

    ' Write the parsed client name to STDOUT to complete the greeting
    WriteFile hStdOut, ByVal sReadBuffer, Len(sReadBuffer), lBytesWritten

End Sub

HTML Form to Test the CGI (Test.htm)

To interact with the Hello.exe CGI application, a simple HTML form is required. This Test.htm file defines a form that uses the POST method to send data to the CGI executable. The input field named “Name” will carry the user’s entry, which the Visual Basic CGI application will then process.

<HTML>
    <HEAD>
        <TITLE>Testing VB CGI</TITLE>
    </HEAD>
    <BODY>
        <H1>Enter Your Name</H1>
        <FORM action="/cgi-bin/hello.exe" method="POST">
            <LABEL for="userName">Name:</LABEL>
            <INPUT TYPE="TEXT" ID="userName" NAME="Name" placeholder="Your Name"><BR>
            <BR>
            <INPUT TYPE="SUBMIT" VALUE="Say Hello">
        </FORM>
    </BODY>
</HTML>

When a user enters a name in the text field and clicks “Say Hello,” the browser will send a POST request to /cgi-bin/hello.exe. The form data, in the format Name=UserInput, will be sent in the request body, which the Visual Basic application will read from STDIN. The CGI application will then respond with a page displaying “Hello [UserInput]”. This example clearly illustrates the client-server interaction within the CGI framework.

Steps to Build and Deploy the CGI Hello.exe

Building and deploying a Visual Basic CGI application involves a few specific steps to ensure it functions correctly within a web server environment. Unlike standard desktop applications, CGI executables must be configured to run as server-side processes and handle requests without a graphical user interface. Follow these instructions to create your Hello.exe file and prepare it for deployment.

  1. Create a New Project: Open Visual Basic 6.0 (or a compatible version) and initiate a new project. Select “Standard EXE” as the project type.
  2. Remove Default Form: Standard EXE projects typically start with Form1. For a CGI application, no visual interface is required, so remove Form1 from your project. This prevents the application from attempting to display a GUI, which would cause it to stop responding when run as a service.
  3. Add a Module: Add a new “Module” to your project. This module will contain all your CGI application’s code, including API declarations, constants, and the Main subroutine. Name this module HELLO for consistency with the example.
  4. Set Startup Object: Go to the Project Properties (Project -> Project1 Properties…). In the “General” tab, set the “Startup Object” to Sub Main. This ensures that your Main subroutine is the first code executed when the Hello.exe is launched by the web server.
  5. Copy and Paste Code: Paste the entire Hello.bas code provided in the sample section into your newly created module. Double-check all declarations and constants for accuracy.
  6. Compile the Executable: From the Visual Basic IDE, go to File -> Make Hello.exe… Choose a destination for your executable file and click OK. This will compile your Visual Basic code into a standalone Hello.exe file, ready for deployment.

Once Hello.exe is successfully compiled, it’s ready to be deployed to your web server. Copy this executable file into the web server’s designated CGI directory, often named cgi-bin. Ensure that the cgi-bin directory on your web server is configured with Execute permissions, which is crucial for the server to be able to run your CGI application. Without these permissions, the server will not be able to launch the executable, resulting in errors.

Important Considerations for Visual Basic CGI Applications

When developing Visual Basic CGI applications, it’s imperative to keep several critical operational aspects in mind, as they differ significantly from traditional desktop applications. These considerations impact everything from how you handle data to how you debug and deploy your code, ensuring the application runs smoothly and reliably within a server environment.

  • Handling HTTP Methods (GET vs. POST): The sample code demonstrates processing an HTTP POST request, where data is sent in the request body. For GET requests, the CGI application must retrieve the QUERY_STRING environment variable. This variable contains name/value pairs appended to the URL, separated by & (e.g., Name=Joe&Color=Red). Visual Basic CGI applications are responsible for implementing all necessary parsing logic, including decoding URL-encoded characters. URL encoding converts spaces to + and special characters (like !) to their hexadecimal ASCII values (e.g., %21).

  • Limited Network Access: Because CGI applications are typically started by the web server service, they often run under a restricted user account. This means that your CGI application may not have the necessary permissions to access network shares or other sensitive resources outside of its immediate execution environment. Plan your application architecture accordingly, ensuring all required resources are locally accessible or that appropriate permissions are explicitly granted to the server’s user account.

  • No Visual Interface Elements: CGI applications operate in a headless server environment. Consequently, visual interface forms, controls, and message boxes are entirely meaningless and will not be displayed to the user. Attempting to show a message box, for instance, will cause the CGI application to hang indefinitely, as there is no interactive desktop to display it on. All interaction must occur through STDOUT (for sending responses) or through server-side logging.

  • Robust Error Handling: Given the lack of a visual interface, comprehensive error handling is paramount in Visual Basic CGI code. Default error message boxes, which might appear in desktop applications, will cause a CGI application to stop responding. Implement structured error handling (On Error GoTo or On Error Resume Next with explicit checks) to gracefully manage exceptions. Instead of displaying errors, log them to a server-side file or write custom error messages directly to the user’s browser via STDOUT.

  • Debugging Techniques: Debugging a running CGI application can be challenging since it’s executed by the web server. Visual C++ debuggers can be used to debug Visual Basic applications. To prepare your Visual Basic executable for debugging, ensure you compile it to “Native Code” and select “Create Symbolic Debug Info,” while also choosing “No Optimization.” Once the .exe is generated and running (e.g., triggered by a web request), a Visual C++ debugger can “attach” to the running CGI process, allowing you to set breakpoints and inspect variables. You can add a Sleep function call at the start of your Main subroutine to provide a window for attaching the debugger.

  • Deployment and Permissions: To test a CGI application, copy the compiled .exe file to an IIS virtual directory that has “Execute” permissions enabled. This setting allows the web server to run the executable as a program rather than serving it as a static file. Incorrect permissions are a common source of “500 Internal Server Error” messages when dealing with CGI applications.

By carefully considering these points, developers can build more reliable, maintainable, and debuggable Visual Basic CGI applications that effectively serve dynamic web content within the server environment. While CGI in Visual Basic might be less common today, these principles remain foundational to server-side development.

CGI Request-Response Flow

Understanding the basic flow of a CGI request and response is essential for developing and troubleshooting applications. A simplified diagram helps visualize this interaction:

mermaid graph TD A[Client Browser] -->|HTTP Request| B(Web Server); B -->|Invokes CGI Application (executes .exe)| C(CGI Application - VB .exe); C -->|Reads Environment Variables| D[Environment Variables (QUERY_STRING, CONTENT_LENGTH, etc.)]; C -->|Reads Request Body (POST Data) via STDIN| E[STDIN]; E --> C; C -->|Processes Data & Generates Response| F{Logic & Data Processing}; F --> C; C -->|Writes HTTP Headers & Body via STDOUT| G[STDOUT]; G --> B; B -->|Sends HTTP Response| A;

This diagram illustrates how the client browser initiates a request, which is then processed by the web server. The web server acts as a conduit, passing relevant information (environment variables, STDIN) to the CGI application. The CGI application performs its logic and sends its response (HTTP headers and body) back to the web server via STDOUT, which then forwards the final HTTP response to the client browser.

Evolution Beyond Visual Basic CGI

While Visual Basic CGI was a viable solution for early dynamic web content, the landscape of web development has evolved significantly. The limitations of CGI, such as the overhead of spawning a new process for every request, led to the development of more efficient technologies. Modern alternatives like ISAPI (Internet Server Application Programming Interface) for IIS, ASP (Active Server Pages), and later ASP.NET provided tighter integration with the web server, reducing process overhead and improving performance.

Other platforms also emerged, offering more specialized and powerful frameworks for server-side programming. These include PHP, Java Servlets and JSP, Python with frameworks like Django and Flask, and Node.js. These technologies often provide built-in features for session management, database connectivity, and templating, which CGI applications had to implement from scratch. While Visual Basic itself evolved into VB.NET, the primary focus for web development shifted towards dedicated web frameworks that offer greater scalability, security, and development efficiency.

Nevertheless, understanding the principles of CGI and its implementation in Visual Basic remains valuable. It provides a historical perspective on how web interactivity began and highlights the fundamental concepts of request processing, input/output management, and environment variables that are still foundational to modern web architectures. The challenges faced by early CGI developers often shaped the design of subsequent, more sophisticated web development platforms.


We hope this comprehensive guide has illuminated the process of building CGI applications with Visual Basic. While the technology may be considered legacy by modern standards, the underlying concepts of web request processing remain timeless.

What are your experiences with CGI development, or perhaps with using Visual Basic for server-side tasks? Share your thoughts and questions in the comments below!

Post a Comment