Peter Hinchley

Using Microsoft Orca and MakeCab to Add Additional Files to an MSI

Tagged: windows, msi

I frequently work with Windows Installer packages, also known as MSI files. An MSI is a database of files, registry entries, and associated logic, for installing and removing software. In this article I will explain how you can deploy additional files through an existing MSI. Why would you do this? Well, perhaps you want to copy a predefined configuration file to the computer during installation. Or maybe you want to deploy a license file, or additional documentation. Whatever the reason, this article will describe the steps required to add new files into an existing MSI.

Before we start, you will need the following free tools from Microsoft:

  • Orca. Used to edit MSI files and generate MSI transforms. It is officially available as part of the Windows Server 2008 SDK. The only component of the SDK that needs to be installed to access Orca is Win32 Development Tools (listed under Windows Development Tools, under Development Tools in the installation wizard). Installing the Win32 Development Tools will copy Orca.msi to C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin. Orca must then be manually installed using the MSI. This will create Orca.exe under C:\Program Files\Orca. If this all seems a bit long winded, you can just download Orca.msi from here.

  • MakeCab. Used to compile cabinet (CAB) files. It is officially available as part of the Cabinet SDK. The Cabinet SDK extracts a folder structure, which includes makecab.exe, to a nominated location in the file system. For example, C:\CabinetSDK.

  • GuidGen.exe. Used to create new Globally Unique Identifiers. It can be downloaded from Microsoft.

Now that we've got the tools, let's set up the scenario. For the purposes of this tutorial, let's assume you have a folder named C:\Package that includes a single file named setup.msi that has been provided by a vendor. The default behaviour is for the MSI to install into a folder named C:\Program Files\ProductABC. In addition to the files typically installed as part of the package, you want to include two extras: license.txt and readme.txt. The files are to be copied into the root of the ProductABC folder.

  1. Create a new folder under C:\Package called Cabinet.

  2. Copy the files to be included in the MSI (in this example, license.txt and readme.txt) into the Cabinet folder.

  3. Create a text file inside the Cabinet folder named cabinet.ddf. Add the text shown below and save the file.

    .OPTION EXPLICIT
    .Set CabinetNameTemplate=cabinet.cab
    .set DiskDirectoryTemplate=CDROM
    .Set CompressionType=MSZIP
    .Set UniqueFiles="OFF"
    .Set Cabinet=on
    .Set DiskDirectory1=.
    license.txt
    readme.txt
    

    In this example, cabinet.cab is the name of the cabinet file that will be created to hold license.txt and readme.txt. A cabinet file is a file archive format developed by Microsoft (kind of like zip). In this example, we are only adding two files into the cabinet, but additional files could be included by listing the name of each file on a new line at the bottom of the ddf file.

  4. In the Cabinet folder, create a batch file named MakeCab.cmd with the following commands:

    makecab.exe /f cabinet.ddf
    del setup.inf
    del setup.rpt
    move /Y cabinet.cab ..\cabinet.cab
    

    This script will create and copy a cab file named cabinet.cab into the directory containing the MSI. Note: If makecab.exe is not in the path, you can copy it to the Cabinet folder.

  5. Open a command prompt, navigate to the Cabinet directory, and run MakeCab.cmd.

  6. Open Orca.

  7. From the File menu select Open.

  8. Navigate to the MSI and click OK.

  9. From the Transform menu select New Transform. A transform is basically a set of alterations to an MSI that are stored in a separate database file called an MST. The MST is applied to the MSI during deployment, acting as delta to the existing installation logic. The use of an MST, although not essential, is highly recommended, as it avoids the need to change the MSI provided by the vendor.

  10. Navigate to the Media table (tables appear in the left window in Orca).

  11. Right click in the right window and from the context menu select Add Row.

  12. Provide a DiskId of one greater than the last DiskId in the table. Provide a LastSequence number equal to the previous LastSequence number plus the number of files inside the cabinet (e.g. if the last sequence number was 1202, and there are only two files inside cabinet.cab, set LastSequence to 1204). Set Cabinet to cabinet.cab. Click OK. These steps link cabinet.cab to the MSI.

  13. Navigate to the Component table.

  14. Right click in the right window and from the context menu select Add Row.

  15. Set Component to cabinet.cab. Set ComponentID to the value of a random GUID generated via GuidGen.exe (run the tool, select Registry Format, click New GUID and then Copy, return to Orca, and paste the result into the ComponentID field). Set Directory_ to TARGETDIR (assumes the files in cabinet.cab will be deployed to the ProductABC folder under Program Files). Other values for _Directory can be obtained by inspection of the Directory table. Set Attributes to 2. Refer to the Component Table documentation for information on the other allowed values for Attributes.

  16. Navigate to the File table.

  17. Right click in the right window and from the context menu select Add Row.

  18. Set File and FileName to the name of the first file added to cabinet.cab (in our example, license.txt). Set Component_ to cabinet.cab. Set FileSize to the size in bytes of the file added to cabinet.cab. This value can be obtained by getting the properties of the source file (in this example, license.txt) and noting the size in bytes (do not confuse this value with either the size in KB, or the size on disk). Set Attributes to 16384 (indicates the file is compressed inside cabinet.cab). Set Sequence to be 1 greater than the highest sequence number in the table (sort the table by sequence number to determine the highest number). Refer to the File Table documentation for information on the other allowed values for Attributes.

  19. Repeat step 18 for any other file inside the cabinet (in this case readme.txt); the files must be entered in the exact order in which they appear in the ddf file).

  20. Navigate to the FeatureComponents table.

  21. Right click in the right window and from the context menu select Add Row.

  22. Set Feature to the name of an existing feature in the table. Set Component_ to cabinet.cab. This steps is required to link the new component containing the cabinet, to an existing feature. When the feature is deployed by the MSI, so will the linked component, and hence the files within the referenced cabinet.

  23. Save the transform (Generate Transform from the Transform menu) to the same directory as the MSI, with the same name as the MSI, but with an .mst extension. In our example, this step exports the changes made above into a transform file called setup.mst that can be applied to the original MSI.

  24. From the File menu select Close.

Use the following command to deploy the customised MSI:

msiexec.exe /i setup.msi TRANSFORMS=setup.mst /qb

The command assumes that the MST, and the cabinet file, are located in the same directory as the MSI. In addition to installing the application, this command will copy the files inside cabinet.cab to the file system (in this example, license.txt, and readme.txt will be copied to the ProductABC folder under Program Files). The /qb arguments ensure the software is installed without the requirement for user interaction (q) and with only a basic (b) user interface.

The process isn't entirely straightforward, but hopefully this article has helped you understand what's involved in deploying additional files via an existing MSI.

The Mob Hath Spoken

James:

WOW WOW. Thankyou. This article just made my day. OK, I'm a geek, but this was just what I was looking for to add a single config file to a vendor's package. Perfect. Thanks, works a treat.

Your Say