Single Package Authoring Example

The sample PUASample.msi is an example of a dual-purpose Windows Installer 5.0 package that is capable of being installed in either the per-user or per-machine installation context on Windows Server 2008 R2 and Windows 7. This sample package follows the development guidelines described in Single Package Authoring.

Obtaining a copy of the sample

A copy of this sample and a Windows Installer database table editor, Orca.exe, are in the Windows SDK Components for Windows Installer Developers. The sample and table editor are provided with the Windows Software Development Kit for Windows Server 2008 R2 and Windows 7 as the Windows Installer installation files PUASample1.msi and Orca.msi.

System Requirements

The database editor, Orca.exe, requires Windows Server 2008 R2 and earlier and Windows 7 and earlier. The dual-purpose package, PUASample1.msi, can be installed in either the per-machine or per-user installation context on Windows Server 2008 R2 and Windows 7. PUASample1.msi can be installed only in the per-machine context on Windows Server 2008 and earlier and Windows Vista and earlier. You can install the database editor to examine the contents of PUASample1.msi without installing the sample. To install the sample or editor packages, ensure that the DisableMSI policy is not set to a value that blocks application installations.

Identifying a Dual-Purpose Package

Dual-purpose packages should initialize the value of the MSIINSTALLPERUSER property to 1. This identifies the package as capable of being installed in either the per-machine or per-user context on Windows Server 2008 R2 and Windows 7. Set the MSIINSTALLPERUSER property in the package only if it has been written following the development guidelines described in Single Package Authoring and if you intend to provide users with the option to install the package in either the per-user or per-machine context. A dual-purpose package should also initialize the value of the ALLUSERS property to 2. This specifies per-user as the default installation context for the application. If the value of the ALLUSERS property is any value other than 2, Windows Installer ignores the MSIINSTALLPERUSER property.

Use a Windows Installer database editor, such as Orca.exe, to examine the contents of PUASample1.msi. The Property table in the sample package contains the following two entries.

Property Table (partial)

PropertyValue
ALLUSERS2
MSIINSTALLPERUSER1

 

Custom Dialog Box for Installation Context

The user interface of the sample package includes an example of a custom dialog box, VerifyReadyDialog, that enables users to select either the per-user or per-machine installation context at installation time. The Dialog table contains a record that describes the VerifyReadyDialog dialog box. The value entered in the Attributes field is 39 because this dialog box uses the msidbDialogAttributesVisible (1), msidbDialogAttributesModal (2), msidbDialogAttributesMinimize (4), and msidbDialogAttributesTrackDiskSpace (32) dialog style bits. The title bar of the dialog box displays a title given by the value of the ProductName property.

Dialog Table (partial)

DialogHCenteringVCenteringWidthHeightAttributesTitleControl_FirstControl_DefaultControl_Cancel
VerifyReadyDialog505048028039[ProductName]InstallPerUserNextCancel

 

The Control table contains entries for the controls displayed by the VerifyReadyDialog dialog box. The dialog box displays PushButton controls and a Text control. All the controls use the msidbControlAttributesEnabled (2) and msidbControlAttributesVisible (1) control attributes. The InstallPerMachine control also uses the ElevationShield control attribute, msidbControlAttributesElevationShield (8388608.) This control attribute adds the User Account Control (UAC) elevation icon (shield icon) to the InstallPerMachine control and informs the user that UAC credentials are required to install the application in the per-machine context. The value in the Text field of the Control table is the text-style and text displayed by the control. See the description of the Text field in the Control table topic for more information about adding text to a control using predefined styles.

Control Table (partial)

Dialog_ControlTypeAttributeTextControl_Next
VerifyReadyDialogCancelPushButton3{\Tahoma10}&CancelNext
VerifyReadyDialogPreviousPushButton3{\Tahoma10}<<&Previous Cancel
VerifyReadyDialogNextPushButton3{\Tahoma10}&Next >>InstallPerUser
VerifyReadyDialogText2Text3Are you ready to complete your suspended installation?
VerifyReadyDialogInstallPerUserPushButton3{\Tahoma10}Install Only for &MeInstallPerMachine
VerifyReadyDialogInstallPerMachinePushButton8388611{\Tahoma10}Install for &EveryonePrevious
VerifyReadyDialogCancelPushButton3{\Tahoma10}&CancelNext

 

The ControlEvent table specifies the ControlEvents, or actions, the installer performs when the user interacts with a control. When a user activates the InstallPerUser pushbutton, the user interface displays an OutOfDisk dialog box if the OutOfDiskSpace property is 1, sets the value of the MSIINSTALLPERUSER property to 1, sets the value of the ALLUSERS property to 2, sets the MSIFASTINSTALL property to 1, and returns . Because the MSIFASTINSTALL property is set, no System Restore point is generated for the installation. When a user activates the InstallPerMachine pushbutton, the user interface displays an OutOfDisk dialog box if the OutOfDiskSpace property is 1, sets the value of the ALLUSERS property to 1, and returns.

ControlEvent Table (partial)

Dialog_Control_EventArgumentConditionOrder
VerifyReadyDialogInstallPerUserSpawnDialogOutOfDiskOutOfDiskSpace = 11
VerifyReadyDialogInstallPerUserEndDialogReturnOutOfDiskSpace <> 15
VerifyReadyDialogInstallPerUser[MSIINSTALLPERUSER]112
VerifyReadyDialogInstallPerUser[ALLUSERS]213
VerifyReadyDialogInstallPerMachineSpawnDialogOutOfDiskOutOfDiskSpace = 11
VerifyReadyDialogInstallPerMachineEndDialogReturnOutOfDiskSpace <> 13
VerifyReadyDialogInstallPerMachine[ALLUSERS]112
VerifyReadyDialogInstallPerUser[MSIFASTINSTALL]114

 

The InstallPerUser control should be removed from the user interface of any installation using a Windows Installer version earlier than Windows Installer Windows Installer 5.0. The ControlCondition table in the sample package contains four entries that disable and hide the InstallPerUser control if the current version is less than Windows Installer 5.0. The table uses the value of the VersionMsi property and the conditional statement syntax to define this condition. The action specified in the Action field is performed only if the statement in the Condition field is true.

ControlCondition Table (partial)

Dialog_Control_ActionCondition
VerifyReadyDialogInstallPerUserEnableVersionMsi >= "5.00"
VerifyReadyDialogInstallPerUserDisableVersionMsi < "5.00"
VerifyReadyDialogInstallPerUserShowVersionMsi >= "5.00"
VerifyReadyDialogInstallPerUserHideVersionMsi < "5.00"

 

Specifying Directory Structure

Use the database editor to examine the Directory table of PUASample1.msi. The record of the Directory Table having an empty string in its Directory_Parent field represents the root directory of both the source and target directory trees. If the TARGETDIR property is undefined, the installer sets its value at installation time to the value of the ROOTDRIVE property. If the SourceDir property is undefined, the installer sets its value to the location of the directory containing the Windows Installer package (.msi file.) The directory names are specified using the short|long format.

Directory Table (partial)

DirectoryDirectory_ParentDefaultDir
TARGETDIRSourceDir
ProgramFilesFolderTARGETDIR.
ProgramMenuFolderTARGETDIR.
INSTALLLOCATIONMyVendorSample1|MSDN-PUASample1
MyVendorProgramFilesFolderMsft|Microsoft

 

At the source, this Directory table resolves to the following directory paths.

[SourceDir]\Msft\Sample1
[SourceDir]

At the target, the Directory table resolves to the paths in the following table. The installer sets the values of the ProgramFilesFolder and ProgramMenuFolder properties to locations that depend upon the installation context and whether the system is the 32-bit or 64-bit versions of Windows Server 2008 R2 and Windows 7. The paths to the target folders depend on whether the user selects a per-user or per-machine installation.

Installation ContextSystemExample Paths
Per-Machine

Windows Server 2008 R2 and Windows 7

32-bit version

%ProgramFiles%\Msft\Sample1

%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs

Per-Machine

Windows Server 2008 R2 and Windows 7

64-bit version

%ProgramFiles(x86)%\Msft\Sample1

%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs

Per-User

Windows Server 2008 R2 and Windows 7

32-bit or 64-bit version

%USERPROFILE%\AppData\Local\Programs\Msft\Sample1

%APPDATA%\Microsoft\Windows\Start Menu\Programs

 

Per-user applications should be stored in subfolders under the Programs folder specified by the value of ProgramFilesFolder property. Typically, the path to the application takes the following form.

%LOCALAPPDATA%\Programs\ISV name\AppName.

Per-user configuration data should be stored in the Programs folder specified by the value of the ProgramMenuFolder property. Typically, this folder is located at the following path.

%APPDATA%\Microsoft\Windows\Start Menu\Programs

If installing 32-bit Windows Installer Package components, use the ProgramFilesFolder and CommonFilesFolder property in the Directory table. If installing 64-bit Windows Installer Package components, use the ProgramFiles64Folder and CommonFiles64Folder properties. If your application contains 32-bit and 64-bit versions of the same component, with the same name, ensure that these versions are saved in different directories or give them different names.

The following Directory table provides an example of a directory layout compatible with a package that includes 32-bit and 64-bit components and includes some components that are shared across applications.

DirectoryDirectory_ParentDefaultDir
TARGETDIRSourceDir
ProgramFilesFolderTARGETDIR.:Prog32
ProgramFiles64FolderTARGETDIR.:Prog64
CommonFilesFolderTARGETDIR.:Share32
CommonFiles64FolderTARGETDIR.:Share64
ProgramMenuFolderTARGETDIR.:Sample1|MSDN-PUASample1
INSTALLLOCATIONMyVendorSample1|MSDN-PUASample1
INSTALLLOCATIONX64Vendorx64Sample1|MSDN-PUASample1
SHAREDLOCATIONShVendorSample1|MSDN-PUASample1
SHAREDLOCATIONX64ShVendorx64Sample1|MSDN-PUASample1
MyVendorProgramFilesFolderMsft|Microsoft
Vendorx64ProgramFiles64FolderMsft|Microsoft
ShVendorCommonFilesFolderMsft|Microsoft
ShVendorx64CommonFiles64FolderMsft|Microsoft
Shrx86SHAREDLOCATIONx32|32-bit components
Shrx64SHAREDLOCATIONX64x64|64-bit components
Binx86INSTALLLOCATIONx32|32-bit components
Binx64INSTALLLOCATIONX64x64|64-bit components
App32Binx86myapp|unshared 32-bit components
App64Binx64myapp|unshared 64-bit components
Share32Shrx86shared|shared 32-bit components
Share64Shrx64shared|shared 64-bit components

 

At the source, this Directory table resolves to the following directory paths.

[SourceDir]Prog32\Msft\Sample1\x32\myapp

[SourceDir]Share32\Common Files\Msft\Sample1\x32\shared

[SourceDir]Prog64\Msft\Sample1\x64\myapp

[SourceDir]Share64\Common Files\Msft\Sample1\x64\shared

[SourceDir]Sample1

At the target, this Directory table resolves to the following directory paths. The target paths depend on the installation context and system.

Installation ContextSystemExample Paths
Per-Machine

Windows Server 2008 R2 and Windows 7

32-bit version

%ProgramFiles%\Msft\Sample1\x32\myapp

%ProgramFiles%\Common Files\Msft\Sample1\x32\shared

%ProgramFiles(x86)%\Msft\Sample1\x64\myapp

%ProgramFiles(x86)%\Common Files\Msft\Sample1\x64\shared

%ProgramData%\Microsoft\Windows\Start Menu\Programs\Sample1

Per-Machine

Windows Server 2008 R2 and Windows 7

64-bit version

%ProgramFiles(x86)%\Msft\Sample1\x32\myapp

%ProgramFiles(x86)%\Common Files\Msft\Sample1\x32\shared

%ProgramFiles%\Msft\Sample1\x64\myapp

%ProgramFiles%\Common Files\Msft\Sample1\x64\shared

%ProgramData%\Microsoft\Windows\Start Menu\Programs\Sample1

Per-User

Windows Server 2008 R2 and Windows 7

32-bit or 64-bit version

%LOCALAPPDATA%\Programs\Msft\Sample1\x32\myapp

%LOCALAPPDATA%\Programs\Common\Msft\Sample1\x32\shared

%LOCALAPPDATA%\Programs\Msft\Sample1\x64\myapp

%LOCALAPPDATA%\Programs\Common\Msft\Sample1\x64\shared

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Sample1

 

Application Registration

The PUASample.msi adds a subkey to the App Paths registry key for the application and performs registrations that enable application information to be saved in the registry under this key. For more information about App Paths and application registration, see the PerceivedTypes, SystemFileAssociations, and Application Registration in the shell extensibility section of the Shell Developer's Guide. At installation time, the user makes the decision to install the application in either the per-user or per-machine installation context. At the time the dual-purpose package is authored, the package developer cannot know if the registrations should be performed under the HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER keys.

The package developer defines the file identifier for the application's executable file in the File field of the File Table.

File Table (partial)

FileComponent_FileNameFileSizeVersionLanguageAttributesSequence
MyAppFileProductComponentPUASAMP1.EXE|PUASample1.exe8192001

 

Values to be saved in the registry can be specified in the Value field of the Registry table as a Formatted string. Use the file identifier defined in the File field of the File table, and the [#filekey] convention of the Formatted type, to specify the default value for the App Paths registry key. The top-level INSTALL action performs the actions in the InstallExecuteSequence table. After the CostInitialize, FileCost, and InstallFinalize actions in this table have completed, the Windows Installer replaces the formatted substring [#MyAppFile] in the Registry table with the full path to the application file.

The sample defines a custom property, RegRoot, to contain the location of the root key and uses a custom action to reset the property value if the user chooses a per-machine installation. Use the custom property, RegRoot, in any formatted string values that reference the root location. In the Property table the PUASample.msi package defines the custom property and sets the value of RegRoot to HKCU. This initializes the value of the property for the per-user installation context, the recommended default context for dual-purpose packages.

Property Table (partial)

PropertyValue
RegRootHKCU

 

In the CustomAction table the package defines a custom action named Set_RegRoot_HKLM. The value in the Type field identifies this as a Custom Action Type 51 standard custom action. The meaning of the Source and Target fields in the CustomAction table depend upon the custom action type. For more information about the standard types of custom actions, see Custom Action Types. The Source field for the Set_RegRoot_HKLM custom action specifies that the value of the RegRoot property. If the installer performs the Set_RegRoot_HKLM custom action, this resets the value of the RegRoot property to HKLM.

CustomAction Table (partial)

ActionTypeSourceTarget
Set_RegRoot_HKLM51[RegRoot]HKLM

 

The top-level INSTALL action performs the actions in the InstallExecuteSequence table, in the sequence specified in the Sequence field of that table. The value authored in the Sequence field for the Set_RegRoot_HKLM custom action (1501) specifies that this custom action be performed after the InstallInitialize action (1500) and before the ProcessComponents action (1600.) This sequence ensures that the record for the Set_RegRoot_HKLM custom action is evaluated at installation time. For more information about the recommended sequence of actions in the InstallExecuteSequence table, see the Suggested InstallExecuteSequence topic. The conditional statement syntax authored in the Condition field specifies that the Set_RegRoot_HKLM action be performed only if the value of the ALLUSERS property evaluates to 1 at installation time. An ALLUSERS property value of 1 specifies a per-machine installation.

InstallExecuteSequence Table (partial)

ActionConditionSequence
Set_RegRoot_HKLMALLUSERS=1 1501

 

The following records in the Registry table perform the registrations if the ProductComponent component is installed. The value -1 in the Root field is required to perform the registration under HKEY_LOCAL_MACHINE for a per-user installation and under HKEY_CURRENT_USER for a per-user installation. The record with an empty string in the Registry field adds a subkey for the application under the AppPaths registry key and sets the "(Default)" value to the full path of the application's executable file. The MyAppPathAlias registration maps the executable file to an application alias and enables the application to be launched if the user types the alias "puapct" at a command line prompt. The MyAppPathRegistration registration maps the name of the executable file to the file's full path.

RegistryRootKeyNameValueComponent
-1Software\Microsoft\MyAppPathRegistrationLocation[RegRoot]\Software\Microsoft\Windows\CurrentVersion\App Paths\PUAPCT.exeProductComponent
MyAppPathAlias-1Software\Microsoft\Windows\CurrentVersion\App Paths\PUAPCT.exe[#MyAppFile]ProductComponent
MyAppPathRegistration-1Software\Microsoft\Windows\CurrentVersion\App Paths\PUASample1.exe[#MyAppFile]ProductComponent

 

AutoPlay Cancel Registration

The PUASample.msi performs registrations that enable the application user to prevent Hardware Autoplay from launching for selected devices. For information about registering a handler to cancel Autoplay in response to an event, see the Preparing Hardware and Software for Use with AutoPlay topic in the shell extensibility section of the Shell Developer's Guide. The following record registers the handler specified in the Name field when the ProductComponent component is installed. The value -1 in the Root field is required to specify to the Windows Installer that the registration should be redirected to a location that depends upon the installation context.

Registry Table

RegistryRootKeyNameValueComponent
MyAutoplayCancelRegistration-1SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers\CancelAutoplay\CLSID66A32FE6-229D-427b-A608-D273F40C034CProductComponent

 

Preview Handler Registration

The PUASample.msi performs registrations that are required to install a preview handler that enables a read-only preview of .pua files without launching the application. For information about registering preview handlers, see the Registering Preview Handlers topic in the shell extensibility section of the Shell Developer's Guide. The following records in the Registry table register the handler when the ProductComponent component is installed. The value -1 in the Root field is required to specify to the Windows Installer that the registration should be redirected to a location that depends upon the installation context.

Registry Table

RegistryRootKeyNameValueComponent
MyPreviewHandlerRegistration1-1Software\Classes\.puapuafileProductComponent
MyPreviewHandlerRegistration2-1Software\Microsoft\Windows\CurrentVersion\PreviewHandlers{1531d583-8375-4d3f-b5fb-d23bbd169f22}Microsoft Windows PUA TEST Preview HandlerProductComponent
MyPreviewHandlerRegistration3-1Software\Classes\puafile\ShellEx\{8895b1c6-b41f-4c1c-a562-0d564250836f}{1531d583-8375-4d3f-b5fb-d23bbd169f22}ProductComponent
MyPreviewHandlerRegistration4-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}Per-User Applicaton Sample 1 Preview HandlerProductComponent
MyPreviewHandlerRegistration5-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}AppID{6d2b5079-2f0b-48dd-ab7f-97cec514d30b}ProductComponent
MyPreviewHandlerRegistration6-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}DisplayName@shell32,-38242ProductComponent
MyPreviewHandlerRegistration7-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}Iconnotepad.exe,2ProductComponent
MyPreviewHandlerRegistration8-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}\InProcServer32ThreadingModelApartmentProductComponent
MyPreviewHandlerRegistration9-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}\InProcServer32#%%SystemRoot%\system32\shell32.dllProductComponent
MyPreviewHandlerRegistration10-1Software\Classes\CLSID\{1531d583-8375-4d3f-b5fb-d23bbd169f22}\InProcServer32ProgIDpuafileProductComponent

 

 

 

Community Additions

ADD
Show:
© 2014 Microsoft