Executive Summary:

If you use Microsoft Internet Explorer's (IE's) Favorites feature, you might be interested in a mini-app called HotLinks. You can use this miniature HTML Application (HTA) to display all your favorite Internet links in a compact, organized window on your desktop so that you can quickly get to any of your favorite places. HotLinks runs on Windows Vista, Windows XP, and other Windows OSs. You can also easily convert HotLinks to a Vista Sidebar gadget.

I have to admit, I really like my mini-apps. Their compact size lets me keep several of my favorite applications open and always available—yet out of the way—on my desktop. Although the effect isn’t quite the same as what you get with the new Vista Sidebar feature, I can mimic the sidebar effect, even on a Windows XP machine. So, you ask, what exactly is a mini-app?

In the September Scripting Pro VIP article “System Inventory Mini-App” (, I introduced a miniature HTML Application (HTA), or mini-app, called SysInfo. But don’t let the mini-app descriptor mislead you! By no means is SysInfo’s functionality diminutive or limited. Users enter a computer name and click a button, and gather an enormous amount of system information about local or remote computers.

The main reason I termed SysInfo a mini-app comes from a physical characteristic: The application window is tiny—only 180 pixels wide and 185 pixels high, a bit smaller than a 2” by 2” square. Furthermore, the mini-app runs on both Vista and pre-Vista OSs, and you can easily convert it to a Vista Sidebar gadget (a Vista mini-program that provides easy access to frequently used tools and information) right away or at a later date. (For information about how to convert SysInfo to a gadget, see “Go Go Gadgets,”

So with that background in mind, I’ll introduce you to a new mini-app: HotLinks. This mini-app displays all your favorite Internet links in a compact, organized window on your desktop so that you can quickly get to any of your favorite places. HotLinks runs on both Vista and pre-Vista OSs, and like the system inventory mini-app, you can easily convert HotLinks to a Vista Sidebar gadget.

Lots of Links in a Downsized Space
Look at Figure 1 to view a sample screenshot of HotLinks in action. Unvisited links are blue in color, visited links are purple, and the white link indicates that the mouse is hovering over it, an action that also triggers the display of a tooltip description of the link. In addition, notice the scroll bars for scrolling up, down, left, and right through the list.

Rest assured that the majority of the code for HotLinks is VBScript, but to provide some of the features, you need to know a little HTML. If you’re not familiar with HTML and think you might like to design your own application with similar features, pick up a book about HTML, or at least find some good online references.

When I started writing mini-apps, I didn’t have time to learn much HTML—just enough to get together a plain but decent-looking graphical interface. I’m not ashamed to admit that I always kept a reusable template handy for new HTA scripts and researched new HTML code only as needed. That said, the times, they are a changin’ … and the days of simple input boxes are pretty much gone. Users expect graphical apps that are functional, easy to use, and have visual appeal. HTML and HTA are powerful tools that we systems administrators have at our disposal, so let mini-app development provide the reason to add HTML to your arsenal.

HotLinks’ HTML Code
Let’s start with a few basics about HTML and HTA documents. All HTML and HTA documents follow the general layout that you see in Figure 2. Three key pairs of document tags define the structure: the opening and closing tags, the opening and closing tags, and the opening and closing tags. The and pair encompass the entire HTML document and enable your browser to determine the beginning and end of the document. The and pair delineate the heading section, which contains information about the page, such as its title, the HTA declaration if you’re developing an HTA, a script section where all of your scripting code resides, and a styles section. The and pair enclose all the content that is to be rendered (or presented) when the application is run. In the case of HotLinks, that would be all of your favorite hyperlinks.

Listing 1 and Listing 2 present the bulk of the HTML code used in HotLinks. Listing 1 shows the HTML code that precedes the VBScript section, Listing 2 shows the HTML code that follows the script section, and Listing 3 shows the script section itself. In Listing 1, you see the opening and tags, followed by the code for the page’s title and the section.

The rest of the code in Listing 1 comprises the style section for the application. The topic of styles is quite involved and will come up again and again as you work with HTML and HTAs. I’ll drill down into the details about styles in a future article, but for now, let me just say that the style type for HotLinks is defined as an internal cascading style sheet.

At callout A, you see the following line of HTML code

 tag, which signals the end of the style section, and the opening tag for the script section. We’ll skip the script section for now until we finish discussing the HTML side of the application. 

Listing 2 shows the ending of the script and heading sections and the beginning of the body section, which is enclosed by the and tags. As you can see, there’s only one line of HTML code between the body tags

You might find this fact confusing because you know that HotLinks will display a list of Internet links. This line of HTML code sets up what is called a division element. By using a division element, you essentially set up an area that you can fill later simply by referring to the division’s ID. Here the ID is “HotLinkArea”. The style property within the division statement sets the width to 245 pixels, which controls the width of the hypertext links within the application window. If the complete text of the hyperlink is wider than 245 pixels, the hyperlink text will wrap onto the next display line. (Try adjusting the pixel width in the application to see how it affects the hyperlink presentation.) You’ll see exactly how to load the list of favorite links into the division element when we look at the VBScript section of the application.

The final statement in Listing 2 is the closing tag. This tag tells the browser that it’s reached the end of the HTML document.

Deep Dive into the VBScript Code
Now let’s move on to the inner workings of the application and how to gather all of the links from the Favorites folder. Listing 3 displays the VBScript code, enclosed within the HTML tags. The opening script tag simply identifies the type of script that follows as VBScript.

The first line of VBScript code declares a public variable, LinkList. LinkList is a reference to a temporary database that will store two essential elements for each link in your Favorites folder. Because a Favorites link is a shortcut, LinkList stores the corresponding TargetPath and TargetName for the link. The TargetPath is the link’s URL or Uniform Resource Identifier (URI), and the TargetName is whatever you named the link when you added it to your Favorites list. The script first stores within the database the two values for every link, then later populates a variable called strHTML with a combination of HTML code and the contents of the database. Because the temporary database gets populated outside the main routine, you need to declare LinkList public.

At callout A, you see the Window_Onload subroutine. By virtue of its name, this subroutine runs automatically whenever you launch the application and does three things:

  1. It sets the application window size.
  2. It calls another subroutine named HotLinks.
  3. It sets up a timer.

The line of code that sets up the timer

iTimer = _

means at an interval of every 300,000 milliseconds (i.e., 300 seconds or 5 minutes), run the ReloadIt function, which appears immediately after callout A. All that ReloadIt does is reload the application window to refresh the list of Favorites that HotLinks displays. If you add new links to your Favorites list, they will show up when the window reloads. You can set the reload time to any value you like , keeping in mind that you need to enter the time in milliseconds (multiply seconds by 1000). If you find that you don’t like the application window refreshing so often, simply crank up the milliseconds. If you don’t want it updating at all, just comment out the iTimer line of code or delete it altogether.

The main processing of the HotLinks application is done in the last two sections of code: the HotLinks subroutine, which begins at callout B, and the DoLinks function, which starts at callout E. We’ll first examine the HotLinks subroutine.

Inside the HotLinks Subroutine
The HotLinks subroutine begins by initializing the HotLinkArea.InnerHTML variable to an empty string, as the third line in ca llout B shows. This variable will eventually contain all of the necessary HTML code to render the Favorites list in a compact, organized window. The next several lines of code set up what is called a disconnected recordset. Disconnected recordsets are pretty cool: They’re virtual databases that reside in memory only. Because these virtual databases aren’t connected to any existing databases, they’re termed disconnected. The following line of code creates a database in memory:

Set LinkList = _

A disconnected recordset is a subset of ActiveX Data Objects (ADO), which I’m sure you surmised from the code. The next two lines of code

LinkList.Fields.Append _
LinkList.Fields.Append _

append two fields to this database: TargetPath and TargetName. The two values following the field names represent a data type and a field width. The value 201 indicates a long string, and 256 indicates a variable-length field size. By definition, any field width greater than 255 for this type of field will be treated as variable-length, meaning that the field can store more or fewer than 256 characters. (For more information about the possible data types for fields, go to the DataTypeEnum Web page at For more information about field widths, go to the Append Method (ADO) Web page at To open the virtual database, you simply call the Open method with this line of code:


With a database ready to hold the elements of the Favorites links, the next thing to do is to set up two different types of shell objects, as callout C shows. I set up the Windows Script Host's (WSH's) WshShell (WScript.Shell) object and the Windows Shell (Shell.Application) object. The WScript.Shell.SpecialFolders property retrieves the path to the Favorites folder in this line of code:

Favorites = _

The Shell.Application object gets the namespace of the Favorites folder in this line of code:

Set objFolder = _

The Favorites variable will contain a value similar to C:\Users\username\Favorites on a Vista machine and C:\Documents and Settings\username\Favorites on an XP machine.

The Shell.Namespace method returns a folder object of the Favorites folder that you can step through by calling the Items method

Set colFavs = objFolder.Items

where colFavs represents the collection of items in the Favorites folder. Now that the collection exists, I set up a For Each…Next statement to cycle through all the items. Within the loop, you’ll notice a call to another function: the DoLinks function. With each cycle of the loop, an item of the collection is passed to DoLinks, which performs the process of collecting the link data for that item in the temporary database. I decided to process each item of the Favorites folder collection within a function because there’s a possibility that my Favorites folder might contain folder items, and folders don’t have link properties. If a folder exists in the collection, it in turn needs to be evaluated, and the items within it need to be collected as well. And of course, there’s always the possibility that some of these subfolders might have subfolders within them. By processing items within a separate function, I was able to recursively move through the folders simply by calling the DoLinks function within the DoLinks function itself. The only time DoLinks calls itself is when the item in the Favorites collection is a folder. Let’s leave the HotLinks subroutine briefly to inspect the code in the recursive DoLinks function and see what takes place there.

The Recursive DoLinks Function
At callout E, the DoLinks function starts by setting up two more shell objects similar to the objects set up in the HotLinks subroutine. This time, the WScript.Shell object is used with the CreateShortcut method, and the Shell.Application object is used in the same fashion as it was in the HotLinks subroutine. The Shell.Application object uses the Namespace method to return a folder object—but only if the Favorites item is a folder. And that’s pretty much the main order of business in this function: Check to see whether the item is a folder. This condition is tested inside the function with the statement

If LCase(ofav.Type) = "file folder" Then

If the item is a folder, you’ll see that I set up another folder object by calling the Namespace method, then setting up the same For Each…Next loop that appeared in the HotLinks subroutine and called the DoLinks function within it. (If you’re wondering about the conditional test comparing with "links", I’ll explain that in just a moment.)

So at this point, the only thing we haven’t seen yet is what happens when the item is a link. If you look at the Else branch of the outer If…Then…Else statement, you’ll see where collecting the link information to the database starts. First, the CreateShortcut method gets the URI of the link. It’s important to note that not only can CreateShortcut be used to create a shortcut—it can also be used to open an existing shortcut. The line of code

Set link = wShell.CreateShortcut(ofav.Path

opens a shortcut object and access to its properties. Of primary interest is the TargetPath, which holds the URI of the link. Now that I have the object’s properties available, I’m ready to finally add some data to the virtual database. The two pieces of data for the database are the TargetPath (the URI) and the name of the link, which was passed to the function. The database is updated in these lines of code:

LinkList("TargetPath") = _
LinkList("TargetName") = ofav

This process continues until all of the items from the Favorites collection are enumerated and added to the database. At which time, we return to our HotLinks subroutine to cycle through the database, creating the HTML code that will display the window with all of our favorite links. To learn how to accomplish this last task, return to the HotLinks subroutine at callout D.

The Last Hurrah
The first line at callout D simply sorts the database on the TargetName field. This field holds the name of the Favorite, not its URI. The second line moves the database to the first record. The third line begins a looping statement that steps through the entire database until it reaches the end-of-file character (EOF).

The fourth line creates the HTML code that will present all of the links. Note that everything is being stored in the strHTML variable. What’s actually being constructed in this line is an anchor element for all of the Favorites links. The code " translates to an anchor hypertext reference. What the reference equals is supplied by the database in the form of LinkList.Fields.Item("TargetPath"), which is the URI. Then the anchor title is added on where you see " title=" expression. This title is what you’ll see as a tooltip when you hover over the link long enough. In this case, the link name provided from the database is the tool tip. This information is concatenated onto the anchor string in the form of LinkList.Fields.Item("TargetName"). You’ll also notice the use of the Chr function with the character code of 34 to provide leading and trailing double quotes to surround this value. The last part of the fourth line, ">" & LinkList.Fields.Item("TargetName"), represents what you’ll see as the Favorite name. The very last part of the fourth line closes the anchor tag with , and the
adds a line break.

The fifth line simply moves the record pointer to the next record in the database, and the sixth lines causes the process to cycle over again until all of the records have been read. At that point strHTML has all of its anchors and the database is closed.

Finally, the application window is populated by passing the contents of strHTML to the HotLinkArea.InnerHTML. It’s at this point in the app’s execution that you see the window and all of your Favorites. You can scroll up, down, left, and right to find the desired link, then simply click it to be transported through hyperspace to the destination of your choosing.

A Final Note
In the DoLinks function, you might be wondering about the conditional statement that begins with

If LCase( <> "links" Then

If you happen to use Microsoft Internet Explorer's (IE’s) customizable Links toolbar, you may end up with duplicates in your HotLinks listings. That’s because the custom links are also part of your Favorites under the folder name Links. For the most part, I don’t see people using the Links toolbar feature, but to try it out, I dragged some links onto the toolbar. I didn’t like this feature because it’s such a pain to do, especially if you use a touchpad for a mouse. Furthermore, the links I dragged onto the toolbar were links I already had in Favorites, so I ended up with duplicates. In any event, if you really want your custom links listed, you can comment out the associated If and End If statements. I should also point out that if you happen to have duplicate links in your regular Favorites list (not including the ones mentioned above), this application will help you find them. Once you’ve removed the duplicates, they no longer will be listed in your HotLinks HTA.

I really like having my HotLinks handy on my desktop in a compact window. Accessing my Favorites on both XP and Vista is much easier.