NAME

Win32::MSI::HighLevel - Perl wrapper for Windows Installer API

VERSION

Version 1.0008

SYNOPSIS

use Win32::MSI::HighLevel;

my $filename = 'demo.msi';

unlink $filename;
my $msi = HighLevel->new (-file => $filename, -mode => Win32::MSI::HighLevel::Common::kMSIDBOPEN_CREATE);

$msi->addFeature (
    -Feature => 'Complete',
    -Title => 'Full install', -Description => 'Install the whole ball of wax'
    );

$msi->createTable (
    -table => 'Feature',
    -columnSpec => [
        Feature  => ['Key', 'Identifier'], Feature_Parent => 'Identifier',
        Title => 'Text(64)', Description => 'Text(255)',
        Display => 'Integer', Level => 'Integer',
        Directory_ => 'Directory',
        Attributes => 'Integer',
        ]
    );

$msi->writeTables ();
$msi->commit ();
$msi = 0;

DESCRIPTION

Win32::MSI::HighLevel allows the creation (and editing) of Microsoft's Windows Installer technology based installer files (.msi files).

The initial impetus to create this module came from trying to find an automated build system friendly way of creating Windows installers. This has been very nicely achieved, especially as the core table information can be provided in text based table description files and thus managed with a revision control system.

Windows Installer files are simply database files. Almost all the information required for an installer is managed in tables in the database. This module facilitates manipulating the information in the tables.

Obtaining a database object

MSI::HighLevel::new ($filename, $mode) returns a new database object. $mode may be one of:

$Win32::MSI::MSIDBOPEN_READONLY

This doesn't really open the file read-only, but changes will not be written to disk.

$Win32::MSI::MSIDBOPEN_TRANSACT

Open in transactional mode so that changes are written only on commit. This is the default.

$Win32::MSI::MSIDBOPEN_DIRECT

Opens read/write without transactional behavior.

$Win32::MSI::MSIDBOPEN_CREATE

This creates a new database in transactional mode.

HighLevel Methods

Generally sample usage is provided for each method followed by a description of the method, then followed by any named parameters recognized by the method.

Most methods require named parameters. Named parameters with an uppercase first letter map directly on to table columns. Named parameters with a lower case first letter generally use contextual information to simplify using the method.

Table column names with a trailing _ are key columns for their table.

new

Create a new HighLevel instance given a file and open mode.

my $msi = HighLevel->new (-file => $file, -mode => Win32::MSI::HighLevel::Common::kMSIDBOPEN_DIRECT);
-file: required

the .msi file to open/create

-mode: optional

parameter - the open/create mode. Defaults to Common::kMSIDBOPEN_TRANSACT

Must be one of:

Win32::MSI::HighLevel::Common::kMSIDBOPEN_READONLY

open for read only assess only

Win32::MSI::HighLevel::Common::kMSIDBOPEN_TRANSACT

open existing file for transacted access

Win32::MSI::HighLevel::Common::kMSIDBOPEN_DIRECT

open existing file for direct (non-transacted) access

Win32::MSI::HighLevel::Common::kMSIDBOPEN_CREATE

create a new file for transacted access (see "commit" below)

Win32::MSI::HighLevel::Common::kMSIDBOPEN_CREATEDIRECT

create a new file for direct (non-transacted) access

-sourceRoot: optional

Provide the (absolute) source directory that corresponds to the TARGETDIR directory on the target system. Directories on the target system have the same relative path from TARGETDIR as directories on the source system have to the source folder.

-sourceRoot defaults to the cwd.

-targetRoot: optional

Provide the default (absolute) target directory for the install. Note that the actual location can be set at install time by the user.

-workRoot: optional

Provide the path to a scratch location that can be used to create intermediate files and folders during the installer build process.

autovivifyTables

$msi->autovivifyTables (qw(Components Dialog Feature Properties));

Ensure that a list of tables exist. Create any tables in the list that do not exist already.

This should be called after "populateTables" has been called if you are not dealing with a new .msi file.

close

Close the database. Generally "close" is not required to be called explicitly as the database should close cleanly when the HighLevel object is destroyed.

$msi->close ();

commit

"commit" is used to update the database in transacted mode. Although the .msi database API provides a commit which must be called in transacted mode, there doesn't seem to be anything like an explicit rollback! An implicit rollback happens when the database is closed without a commit however.

$msi->commit ();

addAppSearch

Add an entry to the AppSearch table.

-Property: required

Property that is set by the AppSearch action when it finds a match for the signature.

-Signature_: required

An entry into the Signature table (for a file) or a directory name.

addBinaryFile

Add a binary file to the installation.

-Name: required

Id to be used as the key entry in the binary file table. This entry must be unique.

-file: required

Path to the file to be added on the source system.

addCab

Adds a cabinet file the the Cabs table and updates the media table to match.

This routine is primarily used by createCabs and should not generally be required by users.

-name: required
-file: required
-disk: required
-lastSeq: required

addComponent

"addComponent" adds a component associated with a specific Directory table entry and a group of files.

my $newId = $msi->addComponent (-Directory_ => 'wibble', -features => ['Complete']);
-Attributes: optional

Component attribute flags ored together. Default value is 0 (no flags set).

-Condition: optional

A condition that is used at install time to determine if the component should be installed.

-Directory_: required

Identifier for the directory entry associated with the component.

-features: required

Array of Feature table Feature identifiers that the component is referenced by.

This parameter is required to generate appropriate entries in the FeatureComponents table.

-File: optional

Optional file name for the key file associated with the component.

If the directory is to be used in the CreateFolder table then the file name should be omitted and the directory name will be used as the key for the component.

-guidSeed: optional

Provide an UpgradeCode guid so that a component installer can provide an upgraded component for an product installed using a different installer.

The UpgradeCode guid must be the UprgadeCode guid used by the main product installer.

-guidSeed would normally be used with -requestedId.

-KeyPath: optional

Primary key into either the File, ODBCDataSource or Registry table. This is only required for generating a component that installs registry entries and doesn't install any files or directories.

Do not use -File and -KeyPath together.

-requestedId: optional

Desired id for component. If there exists a component with the same Id already then the suggested Id will be used as a base to generate a new Id.

addControlCondition

"addControlCondition" adds an entry to the control condition table.

$msi->addControlCondition (
    -Dialog_   => 'LicenseAgreementDlg',
    -Control_  => 'Install',
    -Action    => Disable,
    -Condition => 'IAgree <> "Yes"'
    );
-Dialog_: required

Id of the dialog containing the control.

-Control_: required

Id of the control affected by the entry.

-Action: required

Action to be taken if the condition is met.

-Condition: required

Condition to be met for the action to be performed.

addCreateFolder

"addCreateFolder" adds an entry to the create folder table for the given folder. Component and directory table entries will be generated as required.

my $entry = $msi->addCreateFolder (-folderPath => $dirPath);
-folderPath: required

Path name of the folder to create on the target system.

-features: required

-features provides an array reference for the list of feature ids for features that install the component that creates the folder.

addCustomAction

Add an entry to the custom action table.

$msi->addCustomAction (
    -Action => 'InstallDriver',
    -Type   => 3074,
    -Source => 'DriverInstaller',
    -Target => "[CommonFilesFolder]\\$Manufacturer\\driver.inf",
    );

This provides fairly raw access to the CustomAction table and is only part of the work required to set up a custom action. See the CustomAction Table section in the documentation referenced in the See Also section for further information.

-Action: required

Id for the custom action.

-Type: required

A number comprised of various bit flags ored together.

-Source: optional

A property name or external key into another table. This depends on the Type.

-Target: optional

Additional information depending on the Type.

addCustomActionJScriptFragment

Add an inline JScript entry to the custom action table.

$msi->addCustomActionJScriptFragment (
    -Action => 'GetName',
    -script => '["TheName"] = ["Path"].match (/".*\\(.*)/)[1]'
);

This adds a JScript custom action row.

-Action: required

Id for the custom action.

-script: required

The JScript to execute.

["..."] is expanded to Session.Property ("...")

The expanded string must be 255 characters or fewer. It may be multiple statements and may contain multiple lines. Line breaks will be removed however.

addCustomActionJScriptFile

Add JScript entry to the custom action table.

$msi->addCustomActionJScriptFile (
   -Action => 'GetRegString',
   -call => '["AppRelVers"] = CmpVersion ("foo.exe", "1.0.3");'
   -file => 'vercheck.js',
   );

This adds a JScript custom action row.

-Action: required

Id for the custom action.

-call: optional

A fragment (255 characters or fewer) of JScript to be executed after the script has been loaded.

Watch out for \ characters in file paths. You will need \\\\ to get a single \ in a quoted string by the time Perl has changed \\\\ to \\ then JScript changes \\ to \.

-item -file: required

Name of the file containing the script to be processed.

addCustomActionVBScriptFragment

Add an inline VBScript entry to the custom action table.

$msi->addCustomActionVBScriptFragment (
    -Action => 'GetName',
    -script => '["TheName"] = ["Path"].match (/".*\\(.*)/)[1]'
);

This adds a VBScript custom action row.

-Action: required

Id for the custom action.

-script: required

The VBScript to execute.

["..."] is expanded to Session.Property ("...")

The expanded string must be 255 characters or fewer. It may be multiple statements and may contain multiple lines. Line breaks will be removed however.

addCustomActionVBScriptFile

Add VBScript entry to the custom action table.

$msi->addCustomActionVBScriptFile (
   -Action => 'GetRegString',
   -call => '["AppRelVers"] = CmpVersion ("foo.exe", "1.0.3");'
   -file => 'vercheck.vbs',
   );

This adds a VBScript custom action row.

-Action: required

Id for the custom action.

-call: optional

A fragment (255 characters or fewer) of VBScript to be executed after the script has been loaded.

Watch out for \ characters in file paths. You will need \\\\ to get a single \ in a quoted string by the time Perl has changed \\\\ to \\ then VBScript changes \\ to \.

-item -file: required

Name of the file containing the script to be processed.

addDirectory

"addDirectory" adds a directory with a specified parent directory to the directory table.

my $entry = $msi->addDirectory (-Directory => $dir, -DefaultDir => $def, -Diretory_Parent => $parent);
-Directory: optional

Identifier for the directory entry to create. This identifier may be the name of a property set to the full path of the target directory.

-Directory_Parent: required

This must be a Directory table -Directory column entry or undef. If -Diretory_Parent is undef or has the same value as -Directory the added entry is for a root directory and the root directory name is specified by -DefaultDir. There must only be one root directory in the Directory table.

Except in the case of a root directory entry, the value given for -Diretory_Parent must already exist as a -Directory entry in the Directory table.

-DefaultDir: optional

-DefaultDir provides directory names for the source and target directories for this table entry. -target and -source may be used instead of -DefaultDir.

Different target and source directory names may be provided separated by a colon:

[targetname]:[sourcename]

Directory names may be given as [shortName]|[longName] pairs. [longName] may not include any of: \ ? | > < : / * "

[shortName] additionally may not include spaces or any of: + , ; = [ ]

A . may be used in place of [targetname] to indicate that the parent directory should be used rather than specifying a subdirectory.

If none of -DefaultDir, -target and -source are provided, -DefaultDir is set to '.' (use parent directory).

-target: optional

The [targetname] part of -DefaultDir.

-source: optional

addDirPath

"addDirPath" is not fully implemented should not be used. Use multiple calls to "addDirectory" instead.

addDrLocator

"addDrLocator" adds a DrLocator table row. It is used with addAppSearch and addSignature to provide the information needed by the AppSearch action.

addMsiDriverPackages

Adds a device driver package to the installer.

$msi->addMsiDriverPackages (-Component => 'InstallDriver', -Flags  => (2 | 4));
-Component: required

Id for the custom action.

-Flags: optional

A number comprised of various bit flags ored together.

See the MsiDriverPackages Custom Table Schema topic in the Windows Driver Kit: Device Installation documentation for the use of this parameter. the default value is 0.

-Sequence: optional

Determines driver installation order. Packages are installed in increasing order of sequence number. Packages with the same sequence value are installed in arbitrary order.

addFeature

Add an installation feature. Parent features must be added before child features are added. Multiple root features are allowed and provide different installation configurations.

my $root = $msi->addFeature (-name => 'Complete', -Title => 'Full install');

The following parameters are recognized by "addFeature"

-Attributes: optional

-Attributes is set to msidbFeatureAttributesFavorLocal by default. For a discussion of the -Attributes parameter see the Feature Table documentation (see See Also below).

-Description: optional

A textual description of the feature shown in the text control of the selection dialog.

-Directory_: optional

Directory associated with the feature that may be configured by the user at install time. The directory must already have been added with "addDirectory", "addDirPath" or "createDirectory".

-Display: optional

Determines the display state and order of this feature in the feature list.

If -Display is not provided it will be set so that the new feature is shown after any previous features and is shown collapsed.

If -Display is set to 0 it is not shown.

If -Display is odd is is shown expanded. If -Display is even it is shown collapsed.

Display values must be unique.

-Feature_Parent: optional

Identifier for the parent feature. If this parameter is missing a root feature is generated.

-Level: optional, default = 3

Initial installation level for the feature. See the Feature Table documentation for a discussion of installation level (see See Also below). For a single feature install a value of 3 (the default) is often used. 0 may be used for a feature that is not to be installed at all.

-name: required

The name of the feature to add.

-Title: optional

The name of the feature to add.

addFeatureComponents

Add FeatureComponent rows for a given Component and each of a list of Features.

$msi->addFeatureComponents (-Component_ => 'Wibble', -features => ['Complete']);

addFeatureComponents returns the number of rows actually added to the FeatureComponents table. Duplicate rows will not be added, but are not an error.

-Component_: required

The Component table key id.

-features: required

A reference to an array of Feature table key ids.

addFile

"addFile" is used to add a file to be installed. Adding a file associated with a feature (or features) updates the File and DiskId tables and may update the Component, FeatureComponent and DuplicateFile tables.

my $file = $msi->addFile (-source => $filepath, -featureId => 'Complete');

Default values are determined for -Sequence and -Version from the source file which must be available when "addFile" is called.

-cabFile: optional

Provide the name of a cab file the current file should be added to. By default the file is added to an internally generated cab file.

If the file is to not to be compressed and stored internally in a cab file -cabFile should be set to undef.

See also "createCabs".

-condition: optional

If provided the -condition is applied to the component the file is installed by. A new component will be created if the condition does not match the condition on an existing component that would otherwise have been used.

-featureId: required

Id of the Feature that the file is to be installed for.

-fileId: optional

Id to be used as the File column (and thus key) entry for the file being added. By default -fileName is used for this value.

-fileId must be unique. -skipDupAdd will be ignored if -fileId is provided.

-fileName: required

Name of the file to be installed. Note that a long file name should be given: "addFile" generates the required short file name.

-forceNewComponent: optional

If present this parameter forces a new component to be generated. If the value is scalar it is used as a suggested component name otherwise an array ref containing a list of parameters to be passed to addComponent is expected.

If a parameter list is provided it may be empty and required parameters for addComponent will be generated.

-isKey: optional

File is a key file for a component. Required to be set true if there is to be a shortcut to the file. If the file is a PE format file (.exe, .dll, ...) -isKey is implied.

-Language: optional

Specify the language ID or IDs for the file. If more than one ID is appropriate use a comma separated list.

If this parameter is omitted the value '1033' (US English) is used. To specify that no ID should be used (for font files for example) use an empty string.

-requestedId: optional

A suggested component name. If the name has been used and the file being inserted is not suitable for the existing component a new component name based on the requested name will be used.

-Sequence: optional

Determines the order in which files are installed. By default files are installed in the order that they are added. Setting -Sequence for a file sets the install position for that file and any files added subsequently.

If setting the sequence number for a file causes a collision with any file already added the previously added files are moved later in the install sequence (their sequence number is increased). Note that any subsequently added files may also cause previously added files to be installed later. In other words, setting -Sequence for a file allows a group of files to be inserted at a particular place in the install order.

Use:

-Sequence => undef

to reset to adding files at the end of the install order.

-sourceDir: required

Path to the directory containing the file to be installed.

-skipDupAdd: optional

Skip adding the file if an entry already exists for it. This option is ignored if -fileId is provided.

-targetDir: optional

Path to the directory the file is to be installed to on the target system.

If -targetDir is not provided the target directory will be set to be in the same relative location as the source directory is to the source root directory. -sourceDir must be in the directory tree below the source root directory if -targetDir is not provided.

-Version: optional

-Version should only be set to specify a companion file (see "Companion Files" in the SDK documentation). For a versioned file the version number is obtained from the file's version resource.

addIconFile

Add an icon file to the installation.

my $iconId = $msi->addIconFile ('path/to/unique_file_name.ico');

Note that an internal ID is generated from the file name (excluding the path to the file). The file name must thus only contain alphanumeric characters, periods and the underscore character.

Two icon files that differ only in their path, but have the same name will cause grief (only one of the files will be used). This condition is not checked for!

The generated internal Id is returned and may be used for the -Icon_ parameter required in other tables.

The file must exist at the time that addIconFile is called.

addIconFile may be called multiple times with the same file

addInstallExecuteSequence

Add an entry to the custom action table.

$msi->addInstallExecuteSequence (
    -Action    => 'InstallDriver',
    -Condition => 'NOT MYDRIVERINSTALLED AND NOT Installed',
    -Sequence  => 3959,
    );

This provides fairly raw access to the CustomAction table and is only part of the work required to set up a custom action. See the CustomAction Table section in the documentation referenced in the See Also section for further information.

-Action: required

Id for the action. This must be either a built-in action or a custom action.

A matching entry must exist in the CustomAction table if this is a custom action.

-Condition: optional

A conditional expression that must evaluate true at run time for the step to be executed.

-Sequence: required

Sequence position for execution of this action.

-secureProperties: optional

A public property or array ref containing a list of public properties used in the -Condition expression that need to be passed securely into the execute context.

The property names will be added to the SecureCustomProperties property during "writeTables".

addInstallUISequence

Add an entry to the custom action table.

$msi->addInstallUISequence (
    -Action    => 'SetDefTargetDir',
    -Condition => '',
    -Sequence  => 1100,
    );
-Action: required

Id for the action. This must be either a built-in action or a custom action.

A matching entry must exist in the CustomAction table if this is a custom action.

-Condition: optional

A conditional expression that must evaluate true at run time for the step to be executed.

-Sequence: required

Sequence position for execution of this action.

addLaunchCondition

Add an entry to the custom action table.

$msi->addLaunchCondition (
    -Condition => 'NOT Version9X',
    -Description  => 'Windows versions prior to XP are not supported.',
    );

This provides fairly raw access to the CustomAction table and is only part of the work required to set up a custom action. See the CustomAction Table section in the documentation referenced in the See Also section for further information.

-Condition: required

A conditional expression that must evaluate true at run time for the install to proceed.

-Description: required

Error text shown if the launch condition evaluates false.

-secureProperties: optional

A public property or array ref containing a list of public properties used in the -Condition expression that need to be passed securely into the execute context.

The property names will be added to the SecureCustomProperties property during "writeTables".

addMedia (see also "setProperty")

Add a cabinet file to the Media table.

$msi->addMedia (-Cabinet => '#cab1', -DiskId => 1, -LastSequence => 20);

If all the files required by the install are to be part of the .msi file then addMedia can be ignored - "createCabs" does all the work required.

-Cabinet: optional

Name of the cabinet file.

A # as the first character in the name indicates that the cabinet file will be stored in a stream in the .msi file. In this case the name is case sensitive.

If the first character in the name is not a # then the name must be given as a short file name (8.3 format) and the cabinet is stored in a separate file located at the root of the source tree specified by the Directory Table.

-DiskId: required

A number (1 or greater) that determines the sort order of the media table.

-LastSequence: required

Sequence number of the last file in this media.

-DiskPrompt: optional

Name (on the label for physical media) used to identify the physical media associated with this media entry.

-Source: optional

Source to be used for patching.

-VolumeLabel: optional

Volume label to be used to identify physical media.

addProperty (see also "setProperty")

Add a property value to the Property table. A new property id is generated based on the supplied id if a property of the same name exists already.

$msi->addProperty (-Property => 'Manufacturer', -Value => 'Wibble Corp.');

The actual property id used is returned.

-Property: required

Suggested property name

-Value: required

Property value

addRegistry

Add a registry entry.

$msi->addRegistry (
    -root => HighLevel::msidbRegistryRootClassesRoot,
    -Component_ => 'Application',
    -Key => '.app',
    -Name => undef,
    -Value => 'MyApp'
    );
-Component_: optional

Id of the component controlling installation of the registry value.

This parameter is required unless -genRegKey is used.

-genRegKey: optional

Generates the registry table key and returns it, but doesn't generate the table entry.

This option is required to solve a chicken and egg problem with components that use a Registry table key for their KeyPath.

-Key: required

Key path which may include properties but must not start or end with a backslash (\).

-Name: optional
-Root: required
-Value: required

Registry value to add.

addRegLocator

Add a RegLocator table entry.

$msi->addRegLocator (
    -Signature_ => 'MyDriver',
    -Root       => HighLevel::msidbRegistryRootLocalMachine,
    -Key => 'SYSTEM\CurrentControlSet\Control\Class\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}',
    -Name => 'Class',
    -Type => HighLevel::msidbLocatorTypeRawValue,
    );
-64Bit: optional

Set to search the 64-bit portion of the registry. The 32-bit portion of the registry will not be searched if -64Bit is set.

-directory: optional

A key into the Directory table to be set from the registry.

One of -directory, -file and -property is required.

-file: optional

A key into the File table to be set from the registry.

One of -directory, -file and -property is required.

-Key: required

Key path.

-Name: optional

Registry value name. If omitted the default value is used.

-property: optional

A key into the AppSearch table for the row that contains the property to be set to the registry value.

One of -directory, file and -property is required.

-Root: required

One of:

msidbRegistryRootClassesRoot: HKEY_CLASSES_ROOT
msidbRegistryRootCurrentUser: HKEY_CURRENT_USER
msidbRegistryRootLocalMachine: HKEY_LOCAL_MACHINE
msidbRegistryRootUsers: HKEY_USERS

addSelfReg

Add a SelfReg table entry.

$msi->addSelfReg (
    -File_ => $fileTableKey,
    -Cost  => HighLevel::msidbRegistryRootLocalMachine
    );
-Cost: required

The cost in bytes due to self registering this .dll.

-File_: required

The key in the File table for the .dll to self register.

addShortcut

The following parameters are recognized by "addShortcut":

-Arguments: optional

The command line arguments for the shortcut.

-Component_: optional (see also -target and -Target)

The id for the Component table entry which determines whether the the shortcut will be deleted or created. The shortcut is created if the component has been installed and is deleted otherwise.

If -Component_ is not provided the component associated with -target or -Target will be used.

-Description

The localizable description of the shortcut.

-Directory_: optional (see also -location)

The id for the Directory table entry which specifies where the shortcut file will be created. The Directory entry need not exist until "writeTables" is called and is not checked.

One only of -location and -Directory_ must be provided.

-featureId

The feature the shortcut is installed by.

-Hotkey

The hotkey for the shortcut. The low-order byte contains the virtual-key code for the key, and the high-order byte contains modifier flags.

-folderTarget: optional (see also -target and -Target)

The folder pointed to by the shortcut. Note that this folder must already have been provided using "addDirectory", "addDirPath" or "createDirectory".

One only of -folderTarget, -target and -Target must be provided.

-location: optional (see also -Directory_)

The directory where the shortcut file will be created. Note that the directory must already have been added with "addDirectory", "addDirPath" or "createDirectory".

The directory provided will be searched for in the Directory table to find the directory id to be used for -Directory_.

One only of -location and -Directory_ must be provided.

-name: required

Name to be shown for the shortcut. Note that the name need not be unique.

-Shortcut: optional

Suggested internal id to be used for the shortcut. Note that if there is another shortcut with the same id already a new id will be generated by appending a number to the given id. The id actually used is returned.

If -Shortcut is omitted a suitable id will be generated from the -Name value.

-ShowCmd: optional

The mode used to show the window used by the shortcut when run. May be one of the following constants:

SW_SHOWNORMAL - Show normalised
SW_SHOWMAXIMIZED - Show maximised
SW_SHOWMINNOACTIVE - Show iconised

If -ShowCmd is omitted default Windows behavior is used (SW_SHOWNORMAL).

-Target: optional (see also -folderTarget and -target)

The Feature id or a Property id that specifies the target of the shortcut.

If a Feature id is provided the target is the key file of the Component_ table entry associated with the Feature.

If a Property id is provided the target is the file or directory specified as the value of the property.

One only of -folderTarget, -target and -Target must be provided.

-target: optional (see also -folderTarget and -Target)

The file pointed to by the shortcut. Note that this file must already have been provided using "addFile" or "addFiles".

One only of -folderTarget, -target and -Target must be provided.

-WkDir: optional (see also -wkdir)

The Directory id that specifies the working directory for the shortcut.

One only of -wkdir and -WkDir may be provided.

-wkdir: optional (see also -WkDir)

The working directory for the shortcut.

A directory table will be created if required.

One only of -wkdir and -WkDir may be provided.

addSignature

Add an entry to the Signature table used by the AppSearch action to match previously installed applications.

The following parameters are recognized by "addSignature":

-FileName: required

The name of the file to search for.

-Languages: optional

Specify the language ID or IDs for the file. If more than one ID is specified use a comma separated list. Multiple entries require a file supporting all specified languages for a match.

-MaxDate: optional

The maximum creation date of the file. If this parameter is specified, then the file must have a creation date that is at most equal to MaxDate. This must be a non-negative number. The format of this field is two packed 16-bit values of type WORD. The high order WORD value specifies the date in MS-DOS date format. The low order WORD value specifies the time in MS-DOS time format. A value of 0 for the time value represents midnight.

The formula for calculating the value is:

(($Year - 1980) * 512 + $Month * 32 + $Day) * 65536 + $Hours * 2048 + $Minutes * 32 + $Seconds / 2
-MinDate: optional

The minimum modification date and time of the file. If this field is specified, then the file under inspection must have a modification date and time that is at least equal to MinDate.

See -MaxSize above.

-MinSize: optional

The minimum size of the file. If this parameter is specified, then the file under inspection must have a size that is at least equal to MinSize. This must be a non-negative number.

-MaxVersion: optional

The maximum version of the file. If this parameter is specified, then the file must have a version that is at most equal to MaxVersion.

-MinVersion: optional

The minimum version of the file, with a language comparison. If this field is specified, then the file must have a version that is at least equal to MinVersion. If the file has an equal version to the MinVersion field value but the language specified in the Languages column differs, the file does not satisfy the signature filter criteria.

Note The language specified in the Languages parameter is used in the comparison and there is no way to ignore language. If you want a file to meet the MinVersion field requirement regardless of language, you must enter a value in the MinVersion field that is one less than the actual value. For example, if the minimum version for the filter is 2.0.2600.1183, use 2.0.2600.1182 to find the file without matching the language information.

-Signature: required

This required parameter must be a unique id that is used as an external key by various tables involved in searching for applications and related files, directories and registry entries.

addStorage

Add a binary file to the installation as a storage.

-Name: required

Id to be used as the key entry in the storages table. This entry must be unique.

-file: required

Path to the file to be added on the source system.

addUpgrade

Add an upgrade table entry.

$msi->addUpgrade (
    -UpgradeCode => $UpgradeGUID,
    -VersionMin  => 1.0,
    -VersionMax  => 2.0
    );
-UpgradeCode: optional

UpgradeCode GUID associated with the product detected by the Upgrade table entry being added.

If this parameter is omitted the UpgradeCode Property table entry will be used. Calling setProduct sets the UpgradeCode Property table entry.

Version numbers (if provided) must be in the form x[.y[.z]]. y and z will be set to 0 if they are omitted. x, y, and z must be numeric. A fourth value is not allowed.

-VersionMin: optional

Minimum product version number that this table entry will detect.

If both -VersionMin and -VersionMax are omitted -VersionMin will be set to 0 to find all product versions.

-VersionMax: optional

Maximum product version number that this table entry will detect.

If both -VersionMin and -VersionMax are omitted -VersionMax will be set to null to find all product versions.

-Language: optional

Must be one of Microsoft's language codes. For example US English is 0x0409.

Language matching will be ignored if -Language is omitted.

-Attributes: optional

The following attributes may be ored together:

msidbUpgradeAttributesMigrateFeatures     Copy selected features
msidbUpgradeAttributesOnlyDetect          Detect only - don't uninstall
msidbUpgradeAttributesIgnoreRemoveFailure Ignore uninstall failure
msidbUpgradeAttributesVersionMinInclusive Include min version
msidbUpgradeAttributesVersionMaxInclusive Include max version
msidbUpgradeAttributesLanguagesExclusive  Include all langs except listed

See the MSDN documentation for further information about these attributes.

-Remove: optional

List of features to be removed during the install. A single feature name or an array reference containing feature names is expected.

-ActionProperty: required

Public property name (must be upper case) of the property that will be set to the list of product codes for installed products matching this upgrade entry.

This property name will be added to the SecureCustomProperties property during "writeTables".

createCabs

Creates the cab files as required from the files that have been added with "addFile" or "addFiles".

$msi->createCabs ();

Note that "createCabs" must be called after all files have been added and before "writeTables" is called.

Note too that makecab.exe must be available on the system being used. With versions of Windows from Windows 2000 on makecab.exe seems to be provided with the system so this should not generally be an issue. If "createCabs" generates a 'makecabs.exe not found' error copy makecabs.exe into the working directory or add the path to makecabs.exe to the PATH environment variable.

"createCabs" updates the Media table as appropriate.

Note that "createCabs" generates a cab.dff file that may be used as a manifest of the files added to the install (ignore lines starting with .).

createTable

Creates a new database table.

my $table = $msi->createTable (-table => 'Feature');
my $table = $msi->createTable (
    -table => 'Properties',
    -columnSpec => [
        Property => [qw(Key Identifier(72) Required)],
        Value => [qw(Text(0) Required)],
        ]
    );

createTable knows the column specification for the following commonly used tables: AppSearch, Binary, Component, CustomAction, Directory , Extension, Feature, FeatureComponents, File, Icon, LaunchCondition, Media, MsiDriverPackages, Property, ProgId, RegLocator, Shortcut, Verb.

Any other tables must be created by providing a suitable -columnSpec parameter. If there are tables that you use regularly that are not included in the list above contact the module maintainer with the column specification and suggest that it be added.

-columnSpec: optional

Specification for the table's columns. This is required for tables that Win32::MSI::HighLevel doesn't handle by default.

Note that custom tables may be added to the installer file.

The column specification comprises an array of column name => type pairs. Most of the types mentioned in the MSDN documentation are recognized, including:

AnyPath:
Cabinet: CHAR(255)
DefaultDir: CHAR(255)
Directory: CHAR(72)
Filename: CHAR(128) LOCALIZABLE
Formatted: CHAR(255)
Identifier: CHAR(38)
Integer: INT
Language: CHAR(20)
Long: LONG
Property: CHAR(32)
Required: NOT NULL
Shortcut: CHAR(255)
Text: CHAR(255) LOCALIZABLE
UpperCase: CHAR(255)
Version: CHAR(72)

Where the default type includes a size (number in parenthesis) a different size may be supplied by including it in parenthesis following the type:

Text(0)
-table: required

Name of the table to create.

dropTable

Removes a database table.

my $table = $msi->dropTable ('Feature');

expandPath

Expand a path including system folder properties to a path with the system folders resolved by examining Directory table entries.

my $path = expandPath ($filePath);

"expandPath" returns a long path.

exportTable

Saves a database table in a .csv file format.

my $table = $msi->exportTable ('Directory', '.\Tables');

Important! You must "writeTables" before calling "exportTable" to ensure that the database version of the table matches the internal cached version.

The sample code would export the Directory table as the file 'Directory.idt' to the sub-directory Tables in the current working directory.

If the table includes streams a sub-directory to the directory containing the exported file will be created with the same base name as the table. A file for each stream will then be created in the sub-directory. The created files will have the extension '.idb'.

Note that the table name _SummaryInformation may be used to write out the Summary Information Stream.

Also note that the exported file format is ideal for management using a revision control system.

See also "importTable".

getComponentIdFromFileId

Return the component Id for the given file Id.

my %entry = getComponentIdFromFileId ('Wibble.txt');

This call does not create a component or file entry. It returns null if there is not a matching file id.

getComponentIdForDirId

Return the component Id for the component that has a null KeyPath and a Directory_ value matching the directory id passed in.

my %entry = getComponentIdForDirId (-Directory => 'Wibble', -features => ['Complete']);

A component is created if there is not an appropriate existing component. FeatureComponent table entries will be generated if a Component table entry is generated.

-Directory: required

Directory Id to find (or create) a matching component Id for.

-features: required

The list of features that install the component associated with the directory.

getId

Return the table key id generated for a given id. For example:

my $dirId = $msi->getId ('MyDir', 'Directory', 'my\\path');

will return the unique id generated for the MyDir directory entry in the Directory table with 'my\path' as the parent path.

getParentDirID dirId

Returns the parent Directory table id given an existing directory id.

my $dirId = $msi->getParentDirID ('WibbleApp');

If the dirId passed in does not exist an undef will be returned, otherwise a string (which may be empty for a root dir) will be returned.

getProduct

Return a string containing product and major version information.

my $productString = $msi->getProduct ();

getProductCode

Return a GUID as a string containing product code for the installer.

my $productGUID = $msi->getProductCode ();

If a product code does not yet exist it will be generated as the MD5 sum of the ProductName, ProductLanguage, ProductVersion and Manufacturer property values.

getProperty

Return the Property value for the given property name. Returns undef of the property entry doesn't exist.

my %entry = $msi->getProperty ($propName);

getTableEntry

Return a reference to the table column data for a given table entry.

my $entry = $msi->getTableEntry ('File', {-File => 'wibble.exe'});

Returns undef if the table or key doesn't exist.

If fields within the $entry hash ref are edited "updateTableEntry" must be called.

A degree of caution is advised in using this member. Very little checking can be performed on the results of editing the hash returned. Generally errors will result in failures at "writeTables" time.

getTargetDirID targetpath [public [wantedId]]

"getTargetDirID" returns a Directory table id given an install time target file path. Entries in the Directory table will be created as required to generate an appropriate id.

my $dirId = $msi->getTargetDirID ('[ProgramFilesFolder]\Wibbler\WibbleApp');

An existing Directory table entry may be used as the first element of a directory path. If an existing Directory table entry is used it must be the first element of the directory path. Relative paths are with respect to the target install directory (TARGETDIR).

Where existing Directory table entries match a given path prefix the existing entries are used to reduce proliferation of table entries.

"getTargetDirID" generally takes a single unnamed parameter which is the install time (target) path to match.

Note that the paths may use either \ or / delimiters. All path components are assumed to be long (not short "filename"). Short "filenames" will be generated as required.

An optional (second) boolean parameter may be provided to indicate that the Directory is public. That is, that at install time the user may change the install location for the directory. If a true value is provided as the second parameter the directory Id is forced to upper case to make the entry a public directory entry.

An optional third parameter may be provided to suggest an Id. If provided the boolean 'public' parameter must be provided also.

The following system folder properties may be used directly as shown in the sample code above:

CommonAppDataFolder

Full path to the file directory containing application data for all users

CommonFilesFolder

Full path to the Common Files folder for the current user

StartMenuFolder

Full path to the Start Menu folder

haveDirId dirName

Returns a reference to the Directory table entry for given directory Id if it exists or undef otherwise.

my $dirEntry = $msi->haveDirId ('Wibble');

importTable

Imports an exported database table in a .csv file format.

my $table = $msi->importTable ('.\Tables', 'Directory');

$msi->writeTables ();
$msi->populateTables ();

Important! You should "writeTables" and then "populateTables" following calling "importTable" to ensure the cached table information matches the database version.

The sample code would import the Directory table from the file 'Directory.idt' in the Tables sub-directory of current working directory.

importTable will create an absolute path from the folder path passed in as the second parameter.

undef will be returned on success and an error string will be returned on failure.

Note that the table name _SummaryInformation may be used to import the Summary Information Stream.

installService

Install a Win32 service that runs its own process.

$msi->installService(-serviceName => 'MyService', -Component_ => $component);

At install time a previous instance of the service will be stopped and uninstalled. The new instance will then be installed and optionally started.

-serviceName: required

Name used to identify the service. This must uniquely identify the service on the target system or unhappy things will happen.

-Component_: required

The component that the service file is installed by. This is used by the installer to ensure the service is installed at the correct time.

-name: optional

The name of the service to be installed. If a name is not provided -serviceName is used.

-state: optional

One of 'auto' or 'demand' with 'auto' used by default.

If the state is 'auto' the service will be started at install time and when the system boots.

-type: optional

If the type is supplied it must currently be 'interactive' to set SERVICE_INTERACTIVE_PROCESS.

SERVICE_WIN32_OWN_PROCESS is assumed.

-Description: optional

A brief (fewer than 256 characters) description of the service. -name will be used by default.

option

Set various optional behavior.

fixExtraSep

Fix the separator bug which can generates bogus identifiers for Component names and in other situations. Note that this can lead to components with different names in installers where this setting has changed state and lead to bad behavior when updating installed components.

populateTables

Read the current .msi file and build an internal representation of it.

An optional boolean parameter may be passed. If set true populateTables will warn about any table files it finds that it doesn't know how to generate an internal representation for. Such unknown tables can not be manipulated and will be written to the output unchanged.

registerExtension

Add table entries to register a file extension and hook it up to an application. Note that Extension, ProgId and Verb tables may be affected by this call depending on the parameters supplied.

$msi->registerExtension (
    -Extension => 'myext',
    -Component_ => $componentId,
    -ProgId => 'MyApp.Data.1',
    -Feature_ => $featureId,
    -Description => 'MyApp data file',
    -Verb => 'Open',
    -Argument => '%1',
    );
-Argument: optional

Command line argument to be used when launching the application. %1 may be used to pass the file on the command line.

-Component_: required

Id of the component that controls installation of the extension.

-Extension: required

File extension (excluding the .) that is to be registered.

If multiple extensions need to be mapped to the same ProgId an array reference may be used for the value of this parameter:

$msi->registerExtension (..., -Extension => [qw(myext1 myext2)], ...);
-Description: optional

Text that is shown in explorer for the file type.

-Feature_: required

Feature that supplies the application associated with the extension.

-Icon_: optional

Entry in the Icon table that supplies an icon used for files of this type.

-iconFile: optional

Path to the file containing the icon referred to by -IconIndex.

Note that the file name must be a unique icon file name independently of the path and must only contain alphanumeric characters, periods and underscores. This is because registerExtension forms an ID that is used internally to identify the specific icon file. Multiple extensions may use the same icon file so it is important that registerExtension can generate a one to one mapping between the file name and the internally generated ID.

-IconIndex: optional

Index to the icon resource in the file provided by the -Icon_ table entry (which may be provided using -iconFile).

-MIME_: optional

MIME table Content Type entry specifying the MIME type of the contents of files of this extension.

A -MIMECLSID is required if this parameter is supplied.

-MIMECLSID: optional

CLSID for the COM server that is associated with the MIME type for files of this extension type.

This parameter is required only if a -MIME_ parameter is provided.

-ProgId_: optional

ProgId table entry for the application associated with the file extension.

Note that several extensions may reference the same ProgId. However, if more than one extension references the same ProgId the -Description and -Icon* parameters for the first registered (or pre-existing) entry is used.

-ProgId_Parent: optional
-Verb: optional

Explorer's right click menu entry text for an action associated with files of this type.

If a -Verb parameter is supplied a -ProgId_ is required also.

setProduct

Set various product related information.

$msi->setProduct (
    -Language => 1033,
    -Name => 'Wibble',
    -Version => '1.0.0',
    -Manufacturer => 'Wibble Mfg. Co.'
    );

For a new installer this should be called before any addComponent calls are made as information from the product details is used to generate information required to generate component table entries.

Property table entries are generated or updated by this call. In addition to the properties discussed in conjunction with the parameters described below, a ProductCode value is generated and added to the Property table.

The product code value is returned.

-Name: required

Product name.

-Manufacturer: required

Manufacturer's name.

-Language: required

Language code (LangId).

-Version: required

Product version

-upgradeCode: optional

A GUID that will be used as the UpgradeCode for Upgrade table entries and is used as part of the string used to generate Component GUIDs.

If not provided setProduct will generate an UpgradeCode GUID using the -Name and -Manufacturer values. By default this will allow different language version of a product to be upgraded interchangeably.

Do not include version information in -Name if you rely on the default UpgradeCode GUID generation unless the version information is invariant across all product versions you expect to be able to upgrade. For most upgrade purposes this means that including a major version number in the name is OK, but including a minor version number is not.

setProperty (see also "addProperty")

Set a property value in the Property table. The property is added if it didn't exist already.

$msi->setProperty (-Property => 'Manufacturer', -Value => 'Wibble Corp.');

The previous value is returned or undef is returned if a new property is added.

-Property: required

Property name

-Value: required

Property value

setTableEntryField

Sets specified fields in an existing table entry.

$msi->setTableEntryField (
    'Control',
    {-Dialog_ => 'Start_Installation_Dialog', -Control => InstallNow},
    {-Text => 'Install'}
    );

The first hash ref parameter must include entries for all the table's key fields.

Note that this method provides fairly raw access to table entries and does not perform very much validation. In particular fields that are linked to other tables should not be altered using "setTableEntryField"!

tableRows

Returns the count of the rows in a given table.

my $count = $msi->tableRows ('File');

A single parameter giving the name of the table is required. undef is returned if the table does not exist.

updateTableEntry

Update the table column data for a table entry obtained using getTableEntry.

my $entry = $msi->getTableEntry ('File', {-File => 'wibble.exe'});

$entry->{-File} = 'Wibble.exe';
$msi->updateTableEntry ($entry);

Use with caution. In particular, do not create new keys in the hash.

view

Creates a Win32::MSI::HighLevel::View into the database.

my $view = $msi->view (-table => 'Feature');

Generally other ways of manipulating the database are more useful than through a view. However a Win32::MSI::HighLevel::View can be created to search tables for specific information using the -columns, -where, -order and -tables parameters to return selected records.

writeTables

Write changes that have been made to the tables using the add* members. Until writeTables is called the changes that have been made are cached in memory. writeTables writes these changes through to the .msi database in preparation for a "commit".

"writeTables" also updates the SecureCustomProperties property with Upgrade table "-ActionProperty_" properties.

REMARKS

This module depends on Win32::API, which is used to import the functions out of the msi.dll. Microsoft's Windows Installer technology must be installed on your system for this module to work.

BUGS

Please report any bugs or feature requests to bug-win32-msi-highlevel at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Win32-MSI-HighLevel. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

This module is supported by the author through CPAN. The following links may be of assistance:

ACKNOWLEDGEMENTS

This module was inspired by, and is derived in part from Philipp Marek's http://search.cpan.org/dist/Win32-MSI-DB.

AUTHOR

Peter Jaquiery
CPAN ID: GRANDPA
grandpa@cpan.org

COPYRIGHT & LICENSE

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the LICENSE file included with this module.

SEE ALSO

Microsoft MSDN Installer Database documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installer_database.asp