creating install requirements with PackageMaker

There are a variety of tools that you can use to package software for distribution: Iceberg, Composer, and Packagemaker to name a few. Despite it’s less than adequate packaging performance, some people are either locked into using Packagemaker or prefer using it over other packaging and distribution tools. When working with Packagemaker you will inevitably run across the need to create InstallationCheck tests.

Packagemaker utilizes XML and Javascript to create the UI of an install package and govern how a user interacts with it. I find it easiest to create InstallationChecks that use bash scripts, and have the package I create simply reference the script(s) rather than embedding them into the distribution.dist file created with all distribution packages.

Here we are only concerned about running external scripts and passing return values to the package, so you must check the Result of a script. Note that this is not the Result of a Javascript. For this example we are going to test for the nonexistence of a file. The lack of said file will result in the installation of the package payload, in this case a printer driver. Adding this test will allow us to continually rerun the installer without fear of the driver being installed on top of itself. In order to do this, you first must specify a package requirement like so: Required; true; “Result of script” is equal to true. This means that the test is a required test every time the package runs, installation will continue to the next step if true, and we are testing if the return value of an external script is true.

Second, fire up your favorite text editor to start writing your shell script that will test for the existence of the driver file:

#!/bin/sh
if [ -f  "/Library/Printers/PPDs/Contents/Resources/en.lproj/Fiery E10 50-45C-KM PS1.0" ]; then
     $(exit 0)
else
     $(exit 1)
fi

There’s nothing to out of the ordinary here except for the exit statuses. Traditionally bash scripts exit with a 0 to signal success and other than 0 to signal failure. Since this script is to check for the existence of the file and fail if the file exists, it would make sense to exit with a code of 1, for failure. But since this value is being passed to our install package and inverted as a final check, we need to exit with a success (0) to get the right result. Once this script is written, save it, make it executable, and copy it into the Resources folder in the Packagemaker GUI (make sure to toggle Raw Editing Mode to access the Resources folder in the package).

Finally, you’ll need to edit the Distribution file for the package to instruct it to call your external script. The following is an excerpt from the Distribution file that specifies where and how to call the external script:

<script>
function pm_install_check() {
  if(!(system.run('./Resources/FieryCheck.sh') == true)) { 
my.result.title = 'Failure'; 
my.result.message = 'This Mac already has the requisite drivers.'; 
my.result.type = 'Fatal'; 
return false; 
} 
return true; 
} 
</script>

The ./Resources location of the script ensures portability to other Macs by relying on the FieryCheck.sh script located in the Resources directory inside the package.

I’ve linked to a copy of the package created with Packagemaker so you can examine the contents with Pacifist or Flat Package Editor. Packagemaker creates all packages as flat packages, so you cannot just “Show package contents” in the finder. http://dl.dropbox.com/u/5413877/Fiery%20E10%2050-45C_KM%20PS%201.0.pkg


About this entry