Bill Brooks
Bill Brooks

Reputation: 751

How to conditionally set a file extension using Wix?

I'd like to conditionally set a file extension during install. As I understand it, in order to do anything conditionally in Wix, it should be a self-contained component. So for each file type association I would like to allow the user to set, I've got a component similar to the following:

<Component Id="FileAssocComponent_PS" Guid="DAFE9461-2DF0-934A-F204-6B28CEA23C01">
  <Condition>FILE_ASSOC_PS</Condition>
  <RegistryValue Root="HKLM" Key="SOFTWARE\PrinterApp\Capabilities\FileAssociations" Name=".prn" Value="PrinterApp.ps" Type="string" />
  <RegistryValue Root="HKLM" Key="SOFTWARE\PrinterApp\Capabilities\MIMEAssociations" Name="application/postscript" Value="PrinterApp.ps" Type="string" />
  <RegistryValue Root="HKLM" Key="SOFTWARE\Classes\PrinterApp.ps" Name="FriendlyTypeName" Value="PostScript File" Type="string" />
  <ProgId Id="PrinterApp.ps" Description="PostScript File" Icon="PrinterApp.ico" Advertise="yes">
    <Extension Id="ps">
      <Verb Id="open" Command="Open" Argument="&quot;%1&quot;"/>
    </Extension>
  </ProgId>
</Component>

But this gives me the following error:

error LGHT0204: ICE19: Extension: 'ps' advertises component: 'FileAssocComponent_PS'. This component cannot be advertised because the KeyPath type disallows it.

I've tried setting KeyPath="yes" on one of the registry entries, but that doesn't work - and from what I've been able to find it's expecting a file KeyPath. But this is a component that doesn't contain any files!

How do I get around this error, or am I going about this the wrong way?

Upvotes: 0

Views: 1652

Answers (3)

Chaviv Perlman
Chaviv Perlman

Reputation: 31

I found a solution that worked for me. The issue I had was that I had a condition on the association of the extension to the exe. If the extension was unchecked to not associate, I needed the exe component to get installed but without the progid. Problem was that if a put a condition on the component, the progid wouldn't be created but the exe didn't get installed as well. The solution I found was two create two components. One with the condition and one with mutually exclusive condition. This is basically option 2 from Christopher Painters post.

See below:

<Component Id="My.exe" Guid="{D9CF6FDD-1234-4E90-85A1-3BF1F912C1E3}">
   <Condition>NOT FILES_ASSOCIATIONS_ABC</Condition>
    <File Id="My.exe.without_assoc" Name="My.exe" KeyPath="yes" Vital="yes" Compressed="yes" DiskId="1" Source=".\SourceDir\My.exe" />
  </Component>
  <Component Id="My.exe_assoc" Guid="{07F96643-5D74-1234-9DAE-CDEB5AC2D11E}">
    <File Id="My.exe.with_assoc" Name="My.exe" KeyPath="yes" Vital="yes" Compressed="yes" DiskId="1" Source=".\SourceDir\My.exe" />
    <Condition>FILES_ASSOCIATIONS_ABC</Condition>
    <ProgId Id="My.Document" Description="My exe" Icon="MyIcon" Advertise="yes">
      <Extension Id="abc">
        <Verb Id="open" Command="My Exe" Argument="&quot;%1&quot;" />
        <MIME Advertise="yes" ContentType="application/abc" Default="yes" />
      </Extension>
    </ProgId>
  </Component>

Upvotes: 0

saschabeaumont
saschabeaumont

Reputation: 22406

If you set Advertise="no" you should be able to use the code you wrote. Here's an example I posted a couple of years ago here using a separate component for optional file associations.

<Component ....>
    <ProgId Id="AcmeFoobar.Document" hDescription="ACME XYZ Document">
        <Extension Id="pdf" ContentType="application/xyz">
            <Verb Id="open" Command="Open" TargetFile="[APPLICATIONFOLDER]AcmeFoobar.exe" Argument="%1" />
        </Extension>
    </ProgId>

    <Condition><![CDATA[DEFAULTVIEWER=1]]></Condition>
</Component>

Upvotes: 1

Christopher Painter
Christopher Painter

Reputation: 55581

Advertised components require a keyfile so here are some ways around the error.

1)

Give the component a fake file ( printermimeinstalled.txt ) that won't harm the system.

2)

Author PrinterAppMime.ps as the keyfile of this component. Use the CopyFile element to get the file copied to PrinterApp.ps

Author PrinterAppNoMime.ps (same contents) as the keyfile of another component. Also use the CopyFile element to get the file copied to PrinterApp.ps. Give this component a mutually exclusive component condition so that only 1 component ever gets instaleld.

3)

Change the design of your app a little bit. Have PrinterApp.ps always installed and PrinterAppMimeServer.ps conditionally installed.

4)

Eliminate this custom action and use a custom action to author MSI temp table rows at installtime to defind the MIME stuff if the checkbox is selected.

Each of these 4 approaches have pro's and con's and I personally would choose #3.

Upvotes: 3

Related Questions