File associations

In some scenarios is necessary to register a new file extension to be opened with the installed application or to modify an existing one. This section explains how to achieve this in the most common platforms.

Windows file associations

On Windows, InstallBuilder includes a built-in action to register new file extensions, <associateWindowsFileExtension>.

The code below creates a new extension named .myextension and associates it to the yourprogram.exe application:

<associateWindowsFileExtension>
    <extensions>.myextension</extensions>
    <progID>mycompany.package.4</progID>
    <icon>${installdir}\images\myicon.ico</icon>
    <mimeType>example/mycompany-package-myextension</mimeType>
    <commandList>
        <!-- Defining the 'Open' command -->
        <command>
            <verb>Open</verb>
            <runProgram>${installdir}\yourprogram.exe</runProgram>
            <runProgramArguments>"%1"</runProgramArguments>
        </command>
    </commandList>
</associateWindowsFileExtension>

Where its tags are:

  • <icon>: Path to the icon file that contains the icon to display.

  • <friendlyName>: Friendly Name for the progID.

  • <commandList>: List of commands that can be invoked on each given file type.

  • <extensions>: Space-separated list of extensions for which the given commands will be available.

  • <progID>: Programmatic Identifier to which the extensions are attached, contains the available commands to be invoked on each file type. The proper format of a <progID> key name is [Vendor or Application].[Component].[Version], separated by periods and with no spaces, as in Word.Document.6. The Version portion is optional but strongly recommended.

  • <mimeType>: MIME type associated to all the file extensions.

For each list of extensions defined, you can add multiple commands to execute. The example creates a new command with verb "Open" (it will be displayed in the right-click contextual menu) that will call the ${installdir}\yourprogram.exe passing the file to open as an argument.

The <runProgramArguments> tag allow some specifiers, like the %1 in the example:

  • %1 : is replaced by the short name of the file being executed

  • %L : is replaced by the long name

  • %* : is replaced by the name of any arguments to the file

InstallBuilder also includes an action to remove the association in the uninstaller:

<removeWindowsFileAssociation>
  <extensions>.myextension</extensions>
  <progID>mycompany.package.4</progID>
  <mimeType>example/mycompany-package-myextension</mimeType>
</removeWindowsFileAssociation>

Linux file associations

Linux systems use the XDG standard. This way you can abstract from the Desktop environment your customer is running if it supports the standard.

The process to create a new file association is more verbose than the Windows process but it is still pretty straight forward.

  • Create a new mime-type: This is only necessary if you are creating a new extension. If you are assigning an existing extension, you can skip this part. The first step is to create an XML file describing the new mime type:

<!-- bitock-x-my-mime.xml file -->
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
  <mime-type type="application/x-my-mime">
    <comment>My new file type</comment>
    <glob pattern="*.mymime"/>
  </mime-type>
</mime-info>

The above file describes your new mime type, application/x-my-mime, associated with the extension .mymime.

Once you have the file ready, it must be registered using the XDG tools:

$> xdg-mime install /path/to/bitock-x-my-mime.xml

The filename must start with the vendor, followed by a dash. This information is used to prevent conflicts. It could also be skipped adding the --novendor flag.

The process can be also automated with InstallBuilder:

   <actionGroup>
     <actionList>
        <writeFile>
           <path>${installdir}/${project.vendor}-x-my-mime.xml</path>
           <!-- The CDATA notation allow escaping a
            block of XML characters -->
           <text><![CDATA[
<!-- bitock-x-my-mime.xml file -->
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
  <mime-type type="application/x-my-mime">
    <comment>My new file type</comment>
    <glob pattern="*.mymime"/>
  </mime-type>
</mime-info>
           ]]></text>
        </writeFile>
        <runProgram>
            <program>xdg-mime</program>
            <programArguments>install ${installdir}/${project.vendor}-x-my-mime.xml</programArguments>
        </runProgram>
     </actionList>
   </actionGroup>
  • Create a .desktop file for your application: The file can be created under ~/.local/share/applications/ (for one user) or /usr/share/applications (for all users):

  <writeFile>
    <path>~/.local/share/applications/yourApplication.desktop</path>
    <encoding>utf-8</encoding>
    <text>
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=Your App
GenericName=Your App
Comment=Your Registered Application
Exec=${installdir}/yourApplication.bin
Terminal=false
Type=Application
Categories=Application;Utility;TextEditor;
MimeType=application/x-my-mime
    </text>
  </writeFile>

The new application must specify support for your mime type in the MimeType key.

  • Make the new registered application the default for your extension:

 <runProgram>
   <program>xdg-mime</program>
   <programArguments>default yourApplication.desktop application/x-my-mime</programArguments>
 </runProgram>

To reverse the new register association in the uninstaller, add the code below to your project:

<preUninstallationActionList>
  <runProgram>
   <program>xdg-mime</program>
   <programArguments>uninstall ${installdir}/${project.vendor}-x-my-mime.xml</programArguments>
 </runProgram>
 <deleteFile path="~/.local/share/applications/yourApplication.desktop"/>
</preUninstallationActionList>

OS X file associations

On OS X, associating an extension with an installed application is as easy as executing:

$> defaults write com.apple.LaunchServices LSHandlers -array-add "<dict><key>LSHandlerContentTag</key>
<string>myextension</string><key>LSHandlerContentTagClass</key>
<string>public.filename-extension</string><key>LSHandlerRoleAll</key>
<string>com.yourVendor.yourApplication</string></dict>"

$> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -domain local -domain system -domain user

Where the extension (myextension) must be provided without any leading dot and com.yourVendor.yourApplication is the CFBundleIdentifier key of your application (configured in its Info.plist file).

The below code performs the same process using InstallBuilder:

   <actionGroup>
     <actionList>
        <runProgram>
            <program>defaults</program>
           <!-- The CDATA notation allow escaping a
            block of XML characters -->
           <programArguments>write com.apple.LaunchServices LSHandlers -array-add <![CDATA["<dict><key>LSHandlerContentTag</key>
<string>myextension</string><key>LSHandlerContentTagClass</key>
<string>public.filename-extension</string><key>LSHandlerRoleAll</key>
<string>com.yourVendor.yourApplication</string></dict>"
           ]]></programArguments>
        </runProgram>
        <!-- Restart the launch services to reload the configuration -->
        <runProgram>
            <program>/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister</program>
            <programArguments>-kill -domain local -domain system -domain user</programArguments>
        </runProgram>
     </actionList>
   </actionGroup>