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:

  • Management of reference counting and version-checking of shared components-which helps ensure that applications co-exist better with one another.

  • Self-repair of damaged applications at runtime-When the application is launched, the Windows Installer will check to ensure that the application is properly installed, and if it is not, will automatically repair the application on-the-fly.

  • Transacted install-In the event that the installation is not completed (for example, if there is a network failure), the Windows Installer can roll back to the earlier installed version of the application without error.

  • Reliable and complete uninstall-including correct handling of shared components.

  • Ability to perform installation on secure systems-for non-administrators and non-power users.

  • Application installation-More readily supports mass deployment in organizations using Windows 2000 software management, and as a result of standard support for customization and unattended install.

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

  • Fewer problems arising from application install-Installation and uninstallation of applications is less likely to affect the functioning of another application because reference counting and version-checking are properly implemented.

  • Customers can properly uninstall your application.

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:

  • Most .SYS, .DLL, .EXE and .OCX files.

  • The following fonts: micross.ttf, tahoma.ttf, tahomabd.ttf; fixedsys.fon, dosapp.fon, modern.fon, script.fon and vgaoem.fon

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:

  • If you are upgrading a previously installed version of your application, it is acceptable to default to the directory where that version exists.

  • Exceptions to this requirement may be allowed for applications that prefer a dedicated drive for installation.

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.

  • Shared components that are private to a single software vendor must be installed in one of two places. Do not store these files in the system directory.

    	common files directory\<company name>
    	%ProgramFiles%\<company name>\Shared Files
    

    The common files directory can be accessed by passing
    CSIDL_PROGRAM_FILES_COMMON to the SHGetFolderPath API.

  • Non side-by-side OCXs and DLLs that are shared by multiple software vendors can be placed in the system directory to ensure backward compatibility with those applications.

Note You must document in your Vendor Questionnaire any cases where your software application writes to the system directory.

  • New control panel applets (CPLs) must be installed in the application directory on Windows 2000. Register the path by adding a value under either of the following registry keys:

    	HKLM\software\microsoft\windows\CurrentVersion\control panel\cpls 
    	HKCU\software\microsoft\windows\CurrentVersion\control panel\cpls 
    

    Example of a name / value pair under this key:

    	MyCpl = "%ProgramFiles%\MyCorp\MyApp\MyCpl.cpl"
    
  • Services and device drivers should be placed in the system directory.

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:

  • All non-shared application files and folders

  • Shared application files whose refcount reaches zero

  • Registry entries, except for keys that might be shared by other programs

  • All shortcuts from the Start menu that the application created at install-time

  • The uninstaller itself

The following should remain on the hard disk:

  • User data files.

  • Shared application files that have a non-zero refcount.

  • Other resources that other programs use, sharable fonts, and sharable registry entries.

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:

    • user created files

    • shared components that are still required by other programs

The VeriTest-Rational Install Analyzer for Windows 2000, available at https://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