11.2 Creating an Installation Program

An installation program typically has the following goals:

To place files in the correct location

To notify the user if the installation program is replacing an existing file with a version that is significantly different—for example, replacing a German file with an English file, or replacing a newer file with an older file

When writing the installation program, you must have the following information for each file on the installation disk(s):

The name and location of the file (referred to as the source file).

The name of the equivalent file on the user's hard disk (referred to as the destination file). This name is usually the same as the filename on the installation disk.

The sharing status of the file—that is, whether the file is private to the application being installed or could be shared by multiple applications.

For each file on the installation disk(s), the installation program must, at least, call the VerFindFile and VerInstallFile functions. These functions are described briefly in the rest of this section.

You use the VerFindFile function with the destination-file name to determine where the file should be copied to on the disk. This function also enables you to specify whether the file is private to the application or can be shared. If a problem occurs in finding the file, VerFindFile returns an error value. For example, if Windows is using the destination file, VerFindFile returns VFF_FILEINUSE. The installation program must notify the user of the problem and respond to the user's decision to continue or end the installation.

The VerInstallFile function copies the source file to a temporary file in the directory specified by VerFindFile. If necessary, VerInstallFile expands the file by using the functions in the data decompression library, LZEXPAND.DLL.

VerInstallFile compares the version information of the temporary file to that of the destination file. If they differ, VerInstallFile returns one or more error values. For example, it returns VIF_SRCOLD if the temporary file is older than the destination file and VIF_DIFFLANG if the files have different language identifiers or code-page values. The installation program must notify the user of the problem and respond to the user's decision to continue or end the installation.

Some VerInstallFile errors are recoverable. That is, the installation program
can call VerInstallFile again, specifying the VIFF_FORCEINSTALL option,
to install the file regardless of the version conflict. If VerInstallFile returns VIF_TEMPFILE and the user chooses not to force the installation, the installation program should delete the temporary file.

VerInstallFile could encounter a nonrecoverable error when attempting to force installation, even though the error did not exist previously. For example, the file could be locked by another user before the installation program tried to force installation. If an installation program attempts to force installation after a nonrecoverable error, VerInstallFile fails. The installation program must deal with this situation.

The recommended solution is to display a common dialog box with the buttons Install, Skip, and Install All for all errors. The Install All button should prevent the installation program from prompting the user about similar errors by including the VIFF_FORCEINSTALL option in all subsequent uses of VerInstallFile. For nonrecoverable errors, the Install and Install All buttons should be disabled.

To display a useful error message to the user, the installation program usually must retrieve information from the version resources of the conflicting files. The file installation library provides four functions the installation program can use for this purpose: GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue, and VerLanguageName. The GetFileVersionInfoSize function returns the size of the version information. The GetFileVersionInfo function then uses information retrieved by GetFileVersionInfoSize to retrieve a structure that contains the information. The VerQueryValue function retrieves a specific member from that structure.

For example, if VerInstallFile returns the VIF_DIFFTYPE error, the installation program should use GetFileVersionInfoSize, GetFileVersionInfo, and VerQueryValue on the temporary and destination files to obtain the general type of each file. If the languages of the files conflict, the installation program should also use the VerLanguageName function to translate the binary language identifier into a text representation of the language. (For example, 0x040C translates to the string French.)

If VerInstallFile returns a file error, such as VIF_ACCESSVIOLATION, the installation program should use MS-DOS Interrupt 21h Function 59h (Get Extended Error) to obtain the most recent error value. The program should translate this value into an informative message to display to the user. The program must not yield control between calling VerInstallFile and calling Get Extended Error. If it does, the MS-DOS error value could reflect a later error. (An error could also occur while the program is making the MS-DOS call.)

For more information about the version-stamping functions, see the Microsoft Windows Programmer's Reference, Volume 2. For more information about Interrupt 21h Function 59h, see the Microsoft MS-DOS Programmer's Reference.