Chapter 2. Install/Uninstall

Summary of Install/Uninstall Requirements

Rationale

Install and uninstall issues are some of the most common sources of application interoperability problems. These requirements help to ensure that the user has successful installation and uninstallation experiences, and that the application co-exists in a friendly way with other applications.

Note   It is highly recommended that you use the Windows Installer service for the installation of your application. The Windows Installer service is an operating system component that centrally manages application installation configuration, as well as application uninstall. Using the Windows Installer service allows the operating system to manage application setup and configuration, which enables the following:

The Windows Installer service enables all of this functionality using packages that describe application configurations. The Windows Installer ships in Windows 2000 and is also available for redistribution on Windows NT 4.0, Windows 98, and Windows 95.

For more information, see the Windows Installer Programmer's reference in the Microsoft Platform SDK.

Customer benefits

Requirements

  1. Do not attempt to replace files that are protected by Windows File Protection.

  2. Do not overwrite non-proprietary files with older versions.

  3. Install to Program Files by default.

  4. Install shared files to the correct locations.

  5. Refcount all shared application files during installation.

  6. Support Add/Remove Programs properly.

  7. Decrement the count on shared application files during uninstall.

  8. Ensure correct uninstall.

How to Comply with Install/Uninstall Requirements

Note   If your application uses the Windows Installer, the install/uninstall requirements from Chapter 2 of the Desktop Application Specification supercede Requirements 2.2 through 2.8 in this chapter, with the exception that Desktop Requirement 2.6 (Support Advertising) is not required for server applications.

1. Do Not Attempt To Replace Files Protected by Windows File Protection

Your application must not attempt to replace files that are protected by Windows File Protection (WFP). To ensure that you do not invoke WFP, call SfcIsFileProtected when installing any file you did not create. The Windows Installer service version 1.1 automatically does this for you.

Protected files include the following files that ship on the Windows 2000 CD:

Note   Some redistributable files, such as specific versions of Microsoft Foundation Classes (MFC) DLLs, are installed by Windows 2000 and are protected by WFP.

Protected files form the core of the operating system, and it is essential for system stability that the proper versions be maintained. These files can only be updated via Service Packs, operating system upgrades, QFE hotfixes, and Windows Update. Applications cannot replace them, and attempting to replace these files by means other than those listed above will result in the files being restored by the Windows File Protection feature (see below).

Note   If your application requires newer versions of these components, your application must update these components using an approved Microsoft Service Pack that installs the required versions.

About Windows File Protection:

Windows File Protection is a feature of Windows 2000 that prevents the replacement of essential system files. WFP runs as a background process on Windows 2000 and monitors the files listed in the preceding section. When WFP detects that a protected file has been changed, it restores the original.

The following code shows how to check if a file (in this case "ntdll.dll") is protected by WFP. Note that SfcIsFileProtected is Unicode-only and requires a fully qualified path.

SHGetFolderPath(NULL,CSIDL_SYSTEM, NULL, 0, szSystemDir);
PathAppend(szSystemDir,"ntdll.dll");
MultiByteToWideChar(CP_ACP, 0, szSystemDir, -1, wzFileName, 265);

if ( SfcIsFileProtected(wzFileName) )
   MessageBox(hWnd,szProtected,szSystemDir,MB_OK);
else
   MessageBox(hWnd,szNotProtected,szSystemDir,MB_OK);

2. Do Not Overwrite Non-Proprietary Files With Older Versions

Your application's install must properly version-check to ensure the latest file versions are installed. Installing an application must never regress any files that you do not produce or that are shared by applications you don't produce.

The VerInstall or GetFileVersionInfo APIs are recommended for performing the version check. VerInstall is easiest because it uses GetFileVersionInfo internally and simplifies the process. Below is a simplified example for how to use VerInstall:

TCHAR szOldDir[MAX_PATH], szTempDir[MAX_PATH];
UINT cchTemp = MAX_PATH;
DWORD dwResult = VerInstallFile(0, TEXT("file.dll"), TEXT("file.dll"), g_tszSetupDirectory, g_tszInstallDirectory, szOldDir, szTempDir, &cchTemp);
if (dwResult != 0) {
   Error(dwResult);
}

3. Install to Program Files by Default

By default, your application must install non-shared components into an appropriate subdirectory where the user's program files are stored (e.g., Program Files). This folder is represented by CSIDL_PROGRAM_FILES. On English systems, this folder is often "C:\Program Files." However, do not hardcode that path, as it is not universal.

The recommended way to locate this folder by using SHGetFolderPath (CSIDL_PROGRAM_FILES,…). If you are using the Windows Installer, this folder is represented by the ProgramFilesFolder property in the Windows Installer-based package.

Exceptions   Note the following exceptions:

Considerations for shared components

In some cases, shared components may need to be placed in locations other than the application directory. See next requirement.

4. Install Shared Files to the Correct Locations

The proper location for shared components depends on whether these components are shared across companies or by a single company.





Note   The system directory is not locked down when the user is a power user or administrator, so legacy components or globally shared components can still be placed there. However, Windows File Protection prevents the replacement of protected operating system files. See Requirement 2.

5. Refcount All Shared Application Files During Installation

If your application does not use the Windows Installer, the application installer must refcount all shared components. This must be done under the following registry key:

[HKEY_LOCAL_MACHINE]\SOFTWARE\Microsoft\Windows\Current Version\SharedDLLs

If your installer finds a shared component already on the system that is not registered, the SharedDLL count should be incremented by one plus the number of components in your application that consume this component. For example, if your application installs three components that use a shared file and the shared file is already registered, your installer will bump the SharedDLL count by three. However, if the shared file was already on the system but no SharedDLL exists for it (that is, a previous installer did not create the refcount), then set the SharedDLL count to four. That way, when your application is uninstalled, it leaves the shared file on the system with a refcount of one.

Components that are shared with applications that don't use Windows Installer service need to properly implement the DLLRegisterServer and DLLUnregisterServer entry points if they need to do any registration at install time. (DLLs that use the Windows Installer should use the registration services provided by the Windows Installer.)

6. Support Add/Remove Programs Properly

Your application must supply all the information in the following table so that Add/Remove Programs in the Control Panel can obtain information about the application as needed. You can write this information directly to the registry during install, or if you are using the Windows Installer service, you can set these values using properties in the Windows Installer-based package.

The registry values should be written under the following key:

HKEY_LOCAL_MACHINE
 \Software
  \Microsoft
   \Windows
    \CurrentVersion
     \Uninstall
      \{ProductCode}
Registry
Value
Type Corresponding
Windows Installer
Property
Contains
DisplayName REG_SZ ProductName Display name of application
UninstallPath REG_EXPAND_SZ N/A Full path to the application's uninstall program
InstallLocation REG_EXPAND_SZ ARPINSTALLLOCATION Full path where application is located (folder or .exe)
Publisher REG_SZ Manufacturer Publisher/Developer of application
VersionMajor DWORD ProductVersion Major version number of application
VersionMinor DWORD ProductVersion Minor version of application

Note   Property names are case-sensitive.

You can also provide additional properties to present in Add/Remove Programs, if you like, such as product ID, online support information, etc. See the platform SDK for full details.

7. Decrement the Count on Shared Application Files During Uninstall

The uninstaller must accurately decrement the count on all the components your application uses that are installed as shared components. Delete them when the refcount reaches zero.

8. Ensure Correct Uninstall

Your application must provide an automated uninstaller that removes the application. The uninstaller must be properly registered as specified in the Requirement 2.7, and it must remove the following:

The following should remain on the hard disk:

You must explain in the Vendor Questionnaire everything you leave behind.

Tip   If your application creates temporary files that should be removed during uninstallation, create a zero-length (0) file with the same name at installation time. Examples of such files would be .gid files created by Help.

Note   If your application uses the Windows Installer service, follows componentization rules, and uses only native Windows Installer actions to modify the computer, uninstall capability is provided automatically.

How to Pretest Applications for Install/Uninstall Requirements

To Pretest Uninstallation

  1. Take a snapshot of a computer's directory tree and registry, install the application, uninstall the application, and take another snapshot.

  2. Verify that the snapshots before the install and after the uninstall are the same, except for the following, which should be left on the machine:

The VeriTest-Rational Install Analyzer for Windows 2000, available at http://www.veritest.com/mslogos/windows2000/, can help you do this.

To Pretest Interoperability with Other Applications That Share Components

To ensure that your application interoperates well with other applications (that do not use the Windows Installer) that share some of the same components that your application uses, you should test and verify each of the following scenarios:

    Scenario 1 Scenario 2 Scenario 3 Scenario 4
Step 1 Install your app Install your app Install "other" app Install "other" app
Step 2 Install "other" app Install "other" app Install your app Install your app
Step 3 Uninstall your app Uninstall "other" app Uninstall "other" app Uninstall your app
Step 4 Verify "other" app still works Verify your app still works Verify your app still works Verify "other" app still works
Step 5 Uninstall "other" app Uninstall your app Uninstall your app Uninstall "other" app
Step 6 Verify that shared components are deleted Verify that shared components are deleted Verify that shared components are deleted Verify that shared components are deleted