Once the Visual Basic 6.0 developer leaves the familiar array of features and services offered by the Visual Basic environment and by the more commonly used object models (such as DAO, ADO, or the more commonly used Microsoft Office object models), learning how to perform a particular task and selecting the appropriate technology to do it often becomes confusing. This is particularly true of creating desktop shortcuts. In this article, we'll examine how you can use Visual Basic to create desktop shortcuts pro grammatically (when your application or component is running) and as part of an installation program (using the Package and Deployment Wizard included with VB6).

Microsoft offers two technologies that the Visual Basic developer can use to create shortcuts. The first is the Shell Library, a collection of COM automation objects and standard C/C++ functions found in Shell32.dll. The library, however, is really geared toward the C/C++ developer. Much more accessible and straightforward is the Windows Scripting Host Object Library (wshom.dll), which in this case, merely wraps the IShellLink interface of Shell32.dll. Although Windows Script Host (WSH) is most commonly called by scripted languages, such as VBScript or JScript, most of its object model is also accessible from Visual Basic. WSH has the advantage of being a very "flat" object model; you don't have to navigate through an extensive hierarchy of objects to either instantiate or retrieve the object in which you're interested.

WSH offers two different objects that can be used in creating desktop shortcuts. The first is the WshShortcut object, which represents a shortcut to a file system object on the local computer or network. The second is the WshURLShortcut object, which represents a shortcut to an Internet resource. Either of these two objects is returned by the CreateShortcut method of the WSH Shell object. CreateShortcut requires a single argument, PathLink, the path and filename of the link file to be created or retrieved. So, the general code needed to instantiate a shortcut object is:

  ' Use late binding to accommodate both WshShortcut and WshURLShortcut objects
  Dim sShortcutPath As String
  Dim oShortcut As Object		' Use late binding
  Dim oShell As New WshShell
  sShortcutPath = < path and filename of link file >
  Set oSh = oScr.CreateShortcut(fn)

Note that this code uses late binding (oShortcut is declared to be of type Object, Visual Basic's generic object type, rather than the more specific WshShortcut or WshURLShortcut), since we don't know beforehand whether we're going to create a shortcut or an Internet shortcut. If you know in advance what type of shortcut your code will handle, you can, of course, use early binding. Alternatively, you can simply define your object to be of type WshShortcut and link it either to a local file system resource or to an Internet resource, since the target of a WshShortcut object can be defined either by a local filesystem path or by an Internet URL.

Whether CreateShortcut returns a WshShortcut object or a WshURLShortcut object depends on the file extension supplied with the PathLink argument. If the file extension is .lnk, CreateShortcut returns a WshShortcut object; if .url, it returns a WshURLShortcut object. Any other file extension generates an automation error. (You can, incidentally, extract the file extension easily by using the GetExtensionName method of the FileSystemObject object, found in the Microsoft Scripting Runtime Library, scrrun.dll. So, you could determine what type of link you're working with by using code such as the following:

  Dim sShortcutPath As String, sExtension As String,fs As New FileSystemObject
  Dim oShell As New WshShell, oShortcut As WshShortcut, oURLShortcut As WshURLShortcut      
  sShortcutPath = InputBox("Enter path and filename of link file: ")
  If sShortcutPath <> "" Then
    sExtension = fs.GetExtensionName(sShortcutPath)
    Select Case sExtension
      Case "lnk": Set oShortcut =  oShell.CreateShortcut(sShortcutPath)
      Case "url": Set oURLShortcut = oShell.CreateShortcut(sShortcutPath)
      Case Else: Exit Sub  ' user input an invalid path or filename; display an error and exit
    End Select 
  End If

If the argument supplied to the CreateShortcut object is the path and name of an existing file, then the property values of the WshShortcut or WshURLShortcut object are updated from the existing file. Otherwise, a new file is created. The WshShortcut object has the members shown in Table 1.

Table 1. Members of the WshShortcut Object

Member NameData TypeDescription
Arguments PropertyString Any command-line arguments that are to be passed to the executable (defined by the TargePath property). To be meaningful, the target must be capable of recognising the argument or arguments.
Description PropertyString A text description of the file. It is displayed in the Comments textbox of the link file's Properties dialog.
FullName PropertyString Read-only. The path and filename of the link file. The property value is set by the PathLink parameter of the WshShell object's CreateShortcut method.
Hotkey PropertyString A key combination that will automatically invoke the link. It typically consists of a special key (Alt, Ctrl, Shift), a plus sign, and a regular key or function key (F1, F2, etc.). For instance, the following code defines the Alt-F11 control key sequence as the hotkey for a link file:

oShortcut.Hotkey = "Alt+F11"

The Hotkey string is not case-sensitive.

IconLocation PropertyString The path and filename of an icon resource in an executable or dynamic link library, along with its zero=based index in the .exe or .dll. For instance, the following code assigns the third icon in Shell32.dll to the link

file:oShortcut.IconLocation = "C:\Windows\System32\Shell32.dll,2

Note that the value of the IconLocation property cannot be an icon (.ico) or other graphics file. If a value is not explicitly provided to the IconLocation property, it defaults to the first icon in the application defined by the TargetPath property or the application associated with the data file defined by the TargetPath property. If no icon is present, it defaults to the icon found at Shell32.dll,0.

Load MethodNone A hidden, private method. During instantiation, Load is called automatically by the CreateShortcut method if PathLink designates an existing file. Attempting to call the method in code generates a compiler error.
RelativePath PropertyString Write-only. Defines a target path and filename that are relative to the shortcut's path. This allows the target to be found if both shortcut and target are moved to new locations with the same relative relationship.
Save MethodNone Saves the current values of the link file. Its syntax is: WshShortcut.Save()
TargetPath PropertyString The target of the link. That is, the path and name of the executable, file, or folder to which the shortcut refers. For desktop shortcuts, this is typically the application launched when the user clicks on the shortcut.
WindowStyle PropertyLong An integer that defines the target's window style. This can also be a selected member of the WshWindowStyle enumeration.

It's important to note that, once you modify an existing shortcut's property values or assign property values to a new shortcut, the new shortcut property values are not actually written to the shortcut file until you call the Save method.

The WshURLShortcut object is similar to the WshShortcut object, except that it has only two properties: the FullName property, which defines the path and name of the Internet shortcut; and the TargetPath directory, which defines the resource to which the Internet shortcut points. The WshURLShortcut object also supports the Load method (which, as in the case of the WshShortcut method, is private and cannot be called from Visual Basic code) and the Save method.

Shortcut Viewer, a downloadable Visual Basic application that allows shortcuts to be created and edited, illustrates the use of the WshShortcut and WshURLShortcut objects. Although we won't present the code here (you can download the file and examine it for yourself), several comments about the code are in order. By default, the utility's File New and File Open dialogs create and retrieve shortcut files found on the user's desktop. Although there are several ways to retrieve this location, the application uses the SpecialFolders property of the WshShell object, as follows:

  strDesktop = oShell.SpecialFolders("Desktop")

Along with the folder representing the user's desktop items, Windows has a shared folder containing desktop items for all users of a system. Its path can be retrieved as follows:

  strDesktop = oShell.SpecialFolders("AllUsersDesktop")

There are also a number of other locations where shortcuts are commonly stored, all of which can be retrieved using the SpecialFolders property. These include the following:

Although the WshShortcut object allows you to select the shortcut file's icon from an executable or DLL containing icon resources, the WshURLShortcut object does not. (Interestingly, though, the Properties dialog for an Internet Shortcut does allows you to change the icon.) Instead, the location of a default icon for the shortcut is retrieved from the system registry. This location is determined by the default value stored to the HKEY_CLASSES_ROOT\InternetShortcut\DefaultIcon key.

Finally, since the CreateShortcut method generates an error if we attempt to create or retrieve a shortcut with an extension other than .lnk or .url, it is important that we verify the file extension prior to calling the method. We can do this easily using the GetExtensionName method of the FileSystemObject object, which is part of the Microsoft Scripting Runtime Library.

Although it's useful to create shortcuts pro grammatically from a standard Visual Basic application, it is most common to create desktop shortcuts pro grammatically from an installation program. By default, the Package and Deployment Wizard bundled with Visual Basic does not allow you to create desktop shortcuts. However, you can easily add this capability by customising the Setup1.vbp project used by the wizard. Typically, the wizard's source files are found in C:\Program Files\Microsoft Visual Studio\VB98\Wizards\PDWizard\Setup1, while its executables are found in the C:\Program Files\Microsoft Visual Studio\VB98\Wizards\PDWizard\Setup1 folder. Be sure to make a backup copy of the project's files before beginning modification.

Interestingly, the Package and Deployment Wizard features a dynamic link library, vb6stkit.dll, that includes fCreateShellLink, a function capable of creating shortcuts. It is intended primarily to add items to program groups or to the Start menu, but it is poorly documented and does not appear to work reliably when creating desktop shortcuts. Rather than relying on it, we'll make use of Windows Script Host and the Scripting Runtime Library. Hence, you should add references to these two libraries to the Setup1 project.

The Package and Deployment Wizard invokes the code responsible for creating a desktop shortcut when the user clicks the Continue button of a form named frmGroup. We should be able to confine our modifications to it.

If the installation program you're creating is going to ask the user whether it should create a desktop shortcut, you'll have to modify the installation interface. In the case of a desktop shortcut, the installation program would need to know whether to create a shortcut only on the user's desktop, or on all users of a system. So, to make this change to the interface, begin by lengthening the form so that it is long enough to accommodate a frame containing two option buttons underneath the lstGroups list box. Move the two command buttons so that they are near the bottom of the form. Next, add the frame and place the two option buttons inside it. Set the following properties:

 CaptionCreate Desktop Shortcut
First Option ButtonNameoptCurrent
 Captionfor Current User
Second Option ButtonNameoptAll
 Captionfor All Users

The completed form as it appears in Design Mode should look something like the one shown in Figure 1.

Figure 1. Here's how the completed form will appear in Design Mode.

Our code modifications can be confined to the following portion of the cmdContinue_Click event procedure, which is executed after items are successfully added to a program group:

    ' The group got created ok, so unload dialog and continue on with setup.
    Unload Me
  End If

The following is the complete code block after modifications, with new lines appearing in bold:

  Dim sDesktop As String, sTarget As String, sAppName As String
  Dim oShell As New WshShell, oShortcut As WshShortcut, oFS As New FileSystemObject
    ' Check whether to add desktop shortcut
    If Me.optCurrent.Value Or Me.optAll.Value Then
      sTarget = gstrDestDir & gstrAppExe	' Get name of target
      ' Get Desktop location
      If Me.optCurrent.Value Then 
          sDesktop = oShell.SpecialFolders("Desktop") 
          sDesktop = oShell.SpecialFolders("AllUsersDesktop") 
      End If
      sAppName = oFS.GetBaseName(sTarget)	' Get root application name
      sDesktop = sDesktop & "\" & sAppName & ".lnk" ' Form shortcut filename
      ' Create shortcut
      Set oShortcut = oShell.CreateShortcut(sDesktop)
      oShortcut.TargetPath = sTarget
    End If      
    Unload Me	' The group got created ok, so dialog and continue on with setup.
  End If

Except for the use of some of the global variables defined by the Package and Deployment Wizard, this code is fairly straightforward. We use the SpecialFolders property of the Shell object to get the location of the user's desktop or of the items common to all users' desktops. We also extract the root filename of the target application by calling the FileSystemObject object's GetBaseName method. Then it's simply a matter of performing some string concatenation, and creating and saving our shortcut object.

Ron Petrusha is the author and coauthor of many books, including "VBScript in a Nutshell."