When you need to create input forms, HTML Applications (HTAs) can be a near-perfect solution, as I explain in "Hooked on HTAs," August 2005, InstantDoc ID 46795. With just a little practice, you can create HTAs like the one I'm going to show you. This fully functional sample form, which I've named User Quota Utility, lets you set and display disk quotas on local and remote Windows Server 2003 and Windows XP computers. Even if you don't use quotas, this form is a useful example of how to develop administrative utilities by using an HTA and VBScript. If you use Windows 2003 or XP but haven't enabled quotas, you can do so (by using the Properties dialog box) on a local disk so that you can try out this sample HTA. In that situation, don't select the Deny disk space to users exceeding quota limit check box. If you select that check box, you might accidentally deny a user the ability to write to disk if the quota is exceeded. (For information about using quotas, see the Microsoft article "Managing Disk Quotas in Windows Server 2003 and Windows XP" at

The HTA at a Glance
Figure 1 shows User Quota Utility: an input screen that consists of four input fields, one drop-down box, two buttons, and two text boxes. Let's take a look at these components and at how the utility works.

The input boxes. The first input box lets the user enter a list of user IDs for the user accounts that require quota changes. In the second input box, the user enters the name of the server or computer on which the quotas reside. (If this field is left blank, the utility defaults to the local machine.) If the specified user IDs are domain accounts or accounts on another computer, the user needs to enter the domain or computer name in the third input box. (If this field is left blank, the utility again defaults to the local system.)

In the fourth input box, the user enters the quota size, in bytes. As you can see in Figure 1, I've hard-coded in a default of 5368709120, or 5GB, but you can easily modify that number. In the event that you prefer to give users a choice of entering this data in bytes, megabytes, or gigabytes, I created a second HTA (UserQuotaUtility2.hta) that provides all three options, as Figure 2 shows.

The drop-down box. The drop-down box, located directly after the second text box, lets the user select the drive letter of the computer on which the quotas reside. The drop-down box in this sample HTA uses a pretty lengthy list of drive letters. I've set the default value to the C: drive.

The buttons. When the user clicks the first button, labeled Run Modify User Quotas, User Quota Utility attempts to set the specified quota on the chosen systems. This action is associated with the RunMod subroutine in the HTA's VBScript section, which Listing 1 shows.

The second button, labeled Run Quota Query, lists quota information for a specific server and drive. This action is associated with the RunQuery subroutine in the HTA's VBScript section. The application doesn't filter user IDs when running this subroutine; instead, it lists all user quota settings for the specified computer and drive. Even when the user has listed user IDs in the first input box, clicking the Run Quota Query button will return information about all accounts on the specified system, not just the listed accounts.

The text boxes. The first text box, labeled Status Box, displays the status (i.e., successful or unsuccessful) of the most recent action. The second text box, labeled Application Information, is a summary of the application, including some instruction. These two boxes are the same types of text boxes that the utility uses for input but are declared ReadOnly, which prevents users from entering text. (You can programmatically change the contents of these text areas by assigning a different value to the fieldnames.value code in the HTA script.)

Inside the HTA
The HTA starts with the basic HTA application settings (see "Hooked on HTAs" for details about the available settings). The entire HTA is too long to print, but you can download the file (UserQuotaUtility.hta) from the Windows Scripting Solutions Web site. (Go to, enter 47101 in the InstantDoc ID text box, then click the hotlink; the .zip file also includes UserQuotaUtility2.hta.) To view the script, open the HTA file in Notepad.

After the application settings, the HTA includes the VBScript section, which Listing 1 shows. This section contains three subroutines: Window_Onload, RunMod, and RunQuery.

Window_Onload. The Window_Onload subroutine executes automatically when the application is launched. First, the subroutine uses self.Focus() to launch the application window in front of any other open windows. The subroutine then sizes the application window and sets the default quota size (qlimit.value).

RunMod. The RunMod subroutine, which is associated with the Run Modify User Quotas button, contains the code for modifying user quotas. Aside from clearing the Status field value (using the statement statval.value = ""), the code checks for the presence of a carriage return or line feed at the end of the User ID input field. A carriage return or line feed is necessary to acquire the final ID, so if one isn't present, the code adds one. RunMod uses the Split function with the vbcrlf delimiter to build an array of user IDs, which the HTA later uses to set the quotas.

The script then assigns the values from the HTA input screen to variables, which are used throughout the script. The script uses GetObject to retrieve an instance of a class. The script uses the Win32_DiskQuota class for both the RunMod and RunQuery subroutines and uses the Win32_ComputerSystem class to retrieve the local computer name when the user leaves the domain input field blank.

The meat and potatoes of the RunMod subroutine takes place at callout A in Listing 1. Here, the subroutine cycles through the user IDs. For each ID, the subroutine retrieves a specific user quota, sets the limit, and commits it by using the objQuota.Put_ method.

RunQuery. The RunQuery subroutine, which is associated with the Run Query Quota button, starts out by setting variables for input values. RunQuery then sets the wbemFlagForwardOnly and wbemFlagReturnImmediately constants. The wbemFlagForwardOnly constant causes the script to return a forward-only enumerator; such enumerators are generally much faster and use less memory than conventional enumerators. The wbemFlagReturnImmediately constant causes the call to return immediately.

Next, the RunQuery subroutine makes a Windows Management Instrumentation (WMI) connection to the server or computer that the user specified; if that field was left blank, the script connects to the local computer. The subroutine then uses a WMI Query Language (WQL) query to grab the existing quota data, as the code at callout B shows. In this query, the script specifies both the wbemFlagForwardOnly and wbemFlagReturnImmediately constants. (If you want to shorten a line of code, you can combine the constants' values and specify a decimal value of 48. An example of this shortened version appears in the code at callout A.)

In the WQL query, the WQL parameter is optional. The code at callout B uses it, but if you choose not to include it, you'll need to have two commas with nothing between them, as the Set colItems statement in callout A shows. I recommend that you specify WQL because its presence clarifies that this is a Select statement for WMI use.

After RunQuery grabs the existing quota data, it displays any returned data in a Microsoft Excel spreadsheet. Note that because no count property is available for the Win32_DiskQuota class, the subroutine puts the Excel initialization inside the For Next loop and sets up a do_once flag. If a count property were available, the subroutine could simply check for a value greater than 0, then avoid the Excel initialization and For Next loop if there were no return results from the query.

Completing the code. The HTA's VBScript section also contains a function called ConvStatus, which callout C shows. This function converts the quota status from the numerals of 0, 1, or 2 to the values of OK, Warning, or Exceeded, respectively. Note that the code checks for errors at key spots throughout the VBScript section. The code uses err.description to capture system-generated errors, then stores errors in the status variable and later displays them in the HTA's Status Box. After the VBScript section, the HTA includes code for the input window.

Create Your Own HTAs
You can view and edit the HTA file—for example, to change the quota limit—by using Notepad. If you plan to develop your own HTA interfaces and you're a pro at writing HTML, you're all set; for the most part, you can create your input screen in Notepad and simply rename it with an .hta extension. However, if you aren't familiar with HTML, I suggest you use a Web development application such as Microsoft Office FrontPage 2003. Such applications make learning HTML a lot easier, and you can have a working application up and running in a fraction of the time it might otherwise take.