32

Related to this: How to register file types/extensions with a WiX installer? but not a duplicate.

I need to handle existing file types (.jpg files).

I do not want my app to be the default handler for .jpg. I would just like to extend the "Open with" menu with a link to my app.

I see HKCR\.jpg\OpenWithList\ and HKCR\.jpg\OpenWithProgIds\ in the registry but I am not sure whether to write to these and how to do it correctly with WiX. Should I use something like this?

<ProgId Id='??what here?' Description='Jpeg handled by my App'>
  <Extension Id='jpg' ContentType='image/jpeg'>
    <Verb Id='openwithmyapp' Sequence='10' Command='OpenWithMyApp' Target='[!FileId]' Argument='"%1"' />
  </Extension>
</ProgId>

There are many ways to fail here (like Photo Mechanics did, the HKCR for image file types is a real mess after I have installed this software).

How to do this correctly with WiX?

Erik
  • 503
  • 1
  • 7
  • 26
Marek
  • 10,307
  • 8
  • 70
  • 106
  • Doesn't sasha's answer on the linked question provide this? In particular, look at the five RegistryValues including the OpenWith... keys. (Or maybe there's a cleaner way to specify this in WiX.) – Michael Urman May 06 '10 at 13:26
  • I am interested in correct way of doing what Sasha left out - I would like to learn which values to use for Description/contenttype etc. as outlined by e.g. ??what here? in my question. I would also like to learn which values are required and which not, the linked answer seems to include something that may not be necessary to simply provide a file handler. – Marek May 07 '10 at 11:30
  • Ugh... I wrote that answer a while back. Will post cleaner code asap. – saschabeaumont May 11 '10 at 05:23

1 Answers1

52

Here's a full, complete example with a bit more detail and cleaner code than in the linked question and should provide a better answer. Quite timely as I've recently finished porting the code posted previously, to use proper ProgId elements so this is fresh in my mind ;)

In regards to the 'what here', you can pretty much use whatever you like :)

<Icon Id="filetype.ico" SourceFile="filetype.ico" />
<Component Id="MyApp.exe" Directory="APPLICATIONFOLDER" Guid="*">
    <File Id="MyApp.exe" Name="MyApp.exe" KeyPath="yes"/>

    <Shortcut Id="startmenuShortcut" Directory="ProgramMenuFolder" Name="MyApp" Icon="$(var.product).ico" IconIndex="0" WorkingDirectory="APPLICATIONFOLDER" Advertise="yes" />

    <!-- Capabilities keys for Vista/7 "Set Program Access and Defaults" -->
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities" Name="ApplicationDescription" Value="!(loc.ApplicationDescription)" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities" Name="ApplicationIcon" Value="[APPLICATIONFOLDER]MyApp.exe,0" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities" Name="ApplicationName" Value="!(loc.ApplicationName)" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities\DefaultIcon" Value="[APPLICATIONFOLDER]MyApp.exe,1" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities\FileAssociations" Name=".xyz" Value="MyApp.Document" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities\MIMEAssociations" Name="application/xyz" Value="MyApp.Document" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\MyApp\Capabilities\shell\Open\command" Value="&quot;[APPLICATIONFOLDER]MyApp.exe&quot; &quot;%1&quot;" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\RegisteredApplications" Name="MyApp" Value="SOFTWARE\MyApp\Capabilities" Type="string" />

    <!-- App Paths to support Start,Run -> "myapp" -->
    <RegistryValue Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MyApp.exe" Value="[!MyApp.exe]" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MyApp.exe" Name="Path" Value="[APPLICATIONFOLDER]" Type="string" />

    <!-- Extend to the "open with" list + Win7 jump menu pinning  -->
    <RegistryValue Root="HKLM" Key="SOFTWARE\Classes\Applications\MyApp.exe\SupportedTypes" Name=".xyz" Value="" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\Classes\Applications\MyApp.exe\shell\open" Name="FriendlyAppName" Value="!(loc.ApplicationName)" Type="string" />

    <!-- MyApp.Document ProgID -->
    <RegistryValue Root="HKLM" Key="SOFTWARE\Classes\MyApp.Document" Name="FriendlyTypeName" Value="!(loc.DescXYZ)" Type="string" />
    <ProgId Id="MyApp.Document" Description="!(loc.DescXYZ)" Icon="filetype.ico" Advertise="yes">
        <Extension Id="xyz">
            <Verb Id="open" Command="!(loc.ExplorerMenuOpenXYZ)" Argument="&quot;%1&quot;" />
            <MIME Advertise="yes" ContentType="application/xyz" Default="yes" />
        </Extension>
    </ProgId>

    <!-- Optional: add an 'Edit with XYZ' to 'right click' even when not associated -->
    <RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.xyz\shell\edit.MyApp.exe" Value="!(loc.ExplorerMenuEditXYZ)" Type="string" />
    <RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.xyz\shell\edit.MyApp.exe\command" Value="&quot;[APPLICATIONFOLDER]MyApp.exe&quot; &quot;%1&quot;" Type="string" />
</Component>
saschabeaumont
  • 22,080
  • 4
  • 63
  • 85
  • Cool example! Where did you gleam the information needed for all these registry keys? Do you have links to MSDN articles? – Robert P Nov 18 '10 at 22:21
  • 1
    The example, especially in the ProgId section, looks a lot like my WiX code which takes over file extensions that are already registered. What is the trick to handle the original question, which is to prevent the ProgId/Extension/Verb elements from taking over existing extensions? Example: I install a program that handles JPG extension. I do NOT want to make my program the default. I want an advertised registration. I want to be available for "Open With". I have Default Programs, registering for Open With, etc. all figured out, but how to prevent forcing myself as the default? – James Johnston Nov 26 '12 at 22:45
  • With Windows 8, the problem sort-of goes away (finally!) for older operating systems you will face problems doing an advertised registration without taking over the default. You need un-advertised registry keys in a separate component with a condition that doesn't install if their is already an association present. I'm no longer working with Windows Installer, but pretty much just gave up on trying to cleanly handle older systems because the underlying windows logic seemed broken. – saschabeaumont Dec 05 '12 at 07:09
  • 1
    I know that this is an old answer, but using this code I seem to have a case sensitive problem. e.g. it works for TXT but not for txt. – melodiouscode Oct 07 '14 at 12:16
  • Is case sensitivity still a problem with this solution? – rollsch Feb 06 '18 at 06:17
  • What if you want multiple extensions. Can you simply duplicate the relevant lines? edit: case sensitivity doesnt appear to be an issue anymore. – rollsch Jul 06 '18 at 06:37
  • I find this answer very helpful. It seems to me that: (1) `Capabilities\DefaultIcon` and `Capabilities\shell\...` are not used by Windows. (2) `App Paths\MyApp.Exe` / `Path` adds to the PATH environment variable, what usually is neither necessary nor desirable. (3) `Applications\MyApp.exe\shell\open`: (3a) should not contain `FriendlyAppName`, (3b) should contain `\command`, `Value='"[APPLICATIONFOLDER]MyApp.Exe" "%1"'`. Not definitely sure, though. – Martin Mar 19 '19 at 11:41
  • There are multiple issues with your answer. First, the component is "composite", but its key path is the .exe file. This means that lifetime of file associations you attempt to set up with the many registry keys and values that are part of this component, is tied to the lifetime of the .exe file. So is whatever actions WI will do based on the rows in the ProgId, Extension and Verb tables. As a side note, I'd improve this answer by providing values for variables used in the .wxs file -- hard to know what `!(loc.ExplorerMenuOpenXYZ)` refers to, for example. Even if you know it's a variable. – Armen Michaeli Mar 30 '20 at 19:33
  • I'd like to add that if you have a software with multiple versions that could be installed at the same time and the .exe were all named MyApp.exe, then you'd probably want to set FriendlyAppName to have the version number. The registry keys to extend the "open with" list doesn't allow this however setting HKLM\SOFTWARE\Classes\\shell\open\FriendlyAppName will do the trick if you set to be unique to each version of your software e.g. MyApp_Version. – cechow Jun 04 '21 at 22:18