Installation Q & A
Q
Can I install items both in /Applications and ~/Documents at the same time?
A

Yes, you can but, in most cases, you probably shouldn't.


Before looking at how this can be achieved, let's take some time to see why you probably shouldn't try to install in both /Applications and ~/Documents at the same time:

  • Installing in the "Anywhere" domain (/) and the "Current User Home" domain (~/) from within the same distribution/package is not supported by Apple's installation package format. There can only be one targeted domain during the installation.

  • If the items that are to be installed in ~/Documents are templates, why not install them in /Library/Application Support/MyApplication/Templates so that any user account can see them?

  • If the items that are to be installed in ~/Documents are default preferences for an application, couldn't it be possible for the application to define these default preferences on its first launch?

If you're still convinced that you need to install both in /Applications and ~/Documents at the same time, this can be done using 2 solutions:


First solution: Install everything in / and then move the appropriate items to ~/Documents


The installation procedure would proceed like this:

  1. Install everything in /.

  2. Move the appropriate items to ~/Documents and fix the owner, group and permissions using a post-installation script.

What we need to do is to:

  1. Open Packages.
  2. Create a new distribution project. (You could also create a raw package project)
  3. Add the items to be installed in /Applications to the /Applications folder in the Payload hierarchy.
  4. Add the items to be installed in ~/Documents to the /UsersShared folder in the Payload hierarchy. Better: add them to /UsersSharedACustomFolderName.
  5. Add a post-installation script that will perform the curation.
  6. Build.
The script would look something like this:
#!/bin/sh

DESTINATION_PATH="${HOME}/Documents"

/usr/bin/su $USER -c "/bin/cp /Users/Shared/_Temporary_/MyDocument ${DESTINATION_PATH}"

/bin/rm -f "/Users/Shared/_Temporary_/MyDocument"
/bin/rmdir "/Users/Shared/_Temporary_"

/usr/sbin/chown $USER:staff "${DESTINATION_PATH/MyDocument}"

exit 0
post-installation.sh

Pros:

  • Only one Packages project is needed.

  • This does not require a distribution project.

Cons:

  • The Installer receipts will not match the reality since the items installed in the temporary location have been moved.

  • The progression of the installation will not be exactly represented in the Installation step of Installer.app.

  • If, in the future, you need to install new items to another child directory of ~/, you will need to revisit your post-installation script accordingly.

  • If, in the future, you need to remove items you previously installed in ~/, you will need to revisit your post-installation script accordingly.

  • If an item with the same name as one of your items already exists in the temporary location, it will be overwritten.

  • Worse, if the ACustomFolderName already exists and contains some other items, these items will be moved to ~/Documents by the post-installation script.


Sample Project

Better solution: Install the appropriate items in /Applications and then install the remaining items in ~/Documents


The installation procedure would proceed like this:

  1. Install the appropriate items in /Applications.
  2. Launch the installation of the items in ~/Documents through a post-installation script.

What we need to do is to:

  1. Open Packages.
  2. Choose the Packages > Preferences… > Advanced pane.
  3. Check the Show Advanced User Options box
  4. Create a new distribution project. Let's name it HomeFolderDistribution.
  5. Check the domainscurrent user's home folder Advanced Options at the bottom of the Project > Settings pane.
  6. Create a custom "Documents" folder at the root of the payload hierarchy of the HomeFolderDistribution package of the distribution.
  7. Add the items to be installed in ~/Documents to the /Documents folder of the payload hierarchy.
  8. Build the distribution.
  9. Create a new distribution project.
  10. Set the "User sees" option to "Standard Install Only" in the Projects > Presentation > Installation Type pane.
  11. Add the items to be installed in /Applications to the /Applications folder of the payload hierarchy.
  12. Add the HomeFolderDistribution.pkg we built at step 8 to the Scripts > Additional Resources of the distribution package.
  13. Add a post-installation script of the distribution package to install the HomeFolderDistribution.pkg distribution as the current user.
  14. Build.
The script would look something like this:
#!/bin/sh

/usr/bin/su $USER -c  "/usr/sbin/installer -pkg ./HomeFolderDistribution.pkg -target CurrentUserHomeDirectory"

exit 0
post-installation.sh

Pros:

  • The Installer receipts will match the reality.

  • Adding new items in ~/ just requires to add new items to the payload of the HomeFolderDistribution distribution project and rebuild both projects.

  • Removing items in from the /Documents will automatically remove the items on disk if they had been installed by a previous installation.

Cons:

  • The progression of the installation will not be exactly represented in the Installation step of Installer.app since we're actually installing items when running the post-installation script.

  • You need to build the final distribution in 2 steps. But if you're using a shell script, it doesn't really matter.


Sample Project

Bonus Track: Installing the items in ~/Documents only during the first installation


Based on a few requests I received in the past, and which is the reason why I'm writing this Q&A in the first place, people who want to install both in /Applications and ~/ also want the items in ~/ not to be overwritten when the items in /Applications are updated by a more recent version of the installation package.

Good news, this can be achieved by modifying the distribution project a bit. We're going to modify the Better solution project. But you could adopt the same type of improvement for the first solution.

The idea is to use a separate package to install the distribution that contains the payload for the ~/Documents folder. And we will attach a requirement to the choice representing this package so that the package is not selected when the myDocument file already exists in its final destination.


What we need to do is to:

  1. Open Packages.
  2. Open our main distribution project.
  3. Select the package of the distribution.
  4. Remove the HomeFolderDistribution.pkg package from the Scripts > Additional Resources pane.
  5. Remove the post-installation script from the Scripts pane.
  6. Choose Project > New Package .
  7. Set the name of the package to HomeFolder.
  8. Set the Tag > Identifier value in the HomeFolder > Settings pane.
  9. Add the HomeFolderDistribution.pkg in the Scripts > Additional Resources of the HomeFolder package.
  10. Add the post-installation script to install the HomeFolderDistribution.pkg distribution as the current user to the HomeFolder package.
  11. Display the Project > Presentation > Installation Type pane.
  12. Select the HomeFolder choice in the Installation Type table.
  13. Select the Requirements tab and click + to add a new requirement.
  14. Select a "Result of External Script" type of requirement.
  15. Add a script that exits with the value 1 if the myDocument file exists in the ~/Documents folder.
  16. Click OK.
  17. Build.
The script would look something like this:
#!/bin/sh

if [ -f "$HOME/Documents/myDocument" ]; then

	exit 1
	
fi

exit 0
check.sh

Et voilà !


Sample Project

Revision History
10/29/19First version

Site Map

Copyright 2019 Stéphane Sudre. All rights reserved.