Я не нашел явного ответа на этот вопрос в документации WiX (или в Google, если на то пошло). Конечно, я мог бы просто написать соответствующие ключи реестра в HKCR, но это заставляет меня чувствовать себя грязным, и я ожидал, что это будет стандартная задача, которая должна иметь хорошее решение по умолчанию.
Что касается бонусных баллов, я хотел бы знать, как сделать его «безопасным», т.е. не перезаписывать существующие регистрации для типа файла и удалять регистрацию при удалении, только если она была зарегистрирована во время установки и не изменилась.





"Если ваше приложение обрабатывает свой собственный тип данных файла, вам нужно будет зарегистрировать для него файловую ассоциацию. Поместите ProgId в свой компонент. FileId должен ссылаться на атрибут Id элемента File, описывающий файл, предназначенный для обработки файлов этого расширение. Обратите внимание на восклицательный знак: он вернет короткий путь к файлу вместо длинного: "
<ProgId Id='AcmeFoobar.xyzfile' Description='Acme Foobar data file'>
<Extension Id='xyz' ContentType='application/xyz'>
<Verb Id='open' Sequence='10' Command='Open' Target='[!FileId]' Argument='"%1"' />
</Extension>
</ProgId>
Ссылка: https://www.firegiant.com/wix/tutorial/getting-started/beyond-files/
После дополнительных исследований я нашел частичный ответ на этот вопрос в Учебное пособие по WiX. Он показывает рекламируемое решение и не работает с WiX 3.0, но, учитывая эту информацию, я понял это. Добавьте элемент ProgId в компонент, содержащий ваш исполняемый файл, как показано ниже:
<ProgId Id = "MyApplication.MyFile" Description = "My file type">
<Extension Id = "myext" ContentType = "application/whatever">
<Verb Id = "open" Command = "open" TargetFile = "MyApplication.exe" Argument = ""%1""/>
</Extension>
</ProgId>
myext - это расширение файла без точки, а MyApplication.exe - это идентификатор (а не имя) исполняемого файла (т. е. атрибут Id элемента File). Это зарегистрирует тип файла с вашим исполняемым файлом и предоставит значок по умолчанию (белая страница со значком приложения на нем), которого достаточно для моих нужд. Если вы хотите указать специальный значок, кажется, вам все равно придется сделать это самостоятельно, как показано ниже (код из связанного руководства):
<Registry Id='FooIcon1' Root='HKCR' Key='.xyz' Action='write' Type='string' Value='AcmeFoobar.xyzfile' />
<Registry Id='FooIcon2' Root='HKCR' Key='AcmeFoobar.xyzfile' Action='write' Type='string' Value='Acme Foobar data file' />
<Registry Id='FooIcon3' Root='HKCR' Key='AcmeFoobar.xyzfile\DefaultIcon' Action='write' Type='string' Value='[INSTALLDIR]Foobar.exe,1' />
Однако я не нашел хорошего решения для своего вопроса о бонусе.
Обновлено: я начал писать это до того, как пришел предыдущий ответ. Однако мое решение действительно работает, в отличие от предыдущего ответа.
Я использовал этот код, но мое приложение не было установлено как приложение по умолчанию.
Это не следует путать с установкой приложения по умолчанию, оно регистрирует только команду открытия для определенного типа файла и будет использоваться по умолчанию только в том случае, если другой тип файла уже не зарегистрирован. Вам нужно быть более конкретным в том, чего вы хотите достичь. Вы также можете посмотреть ответ, связанный с saschabeaumont, в котором используется реклама.
К сожалению, нет возможности сделать «безопасное» соединение с установщиком Windows.
Мы просто записываем все в реестр, а затем у нас есть отдельный компонент, который принимает на себя общесистемные значения по умолчанию и устанавливается только в том случае, если никакое другое приложение еще не зарегистрировалось по умолчанию.
В Vista появился новый интерфейс «программ по умолчанию», вы снова записываете все в реестр. Вот полный пример, который мы используем в нашем установщике. (WiX 3.0)
Обновлять: С момента моего первоначального ответа прошло 12 месяцев, и я лучше понимаю ассоциации файлов. Вместо того, чтобы писать все вручную, я теперь использую правильные определения ProgId, которые улучшают обработку рекламируемых пакетов. См. Обновленный код опубликовано в ответ на этот вопрос.
<Component ....>
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities" Name = "ApplicationDescription" Value = "ACME Foobar XYZ Editor" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities" Name = "ApplicationIcon" Value = "[APPLICATIONFOLDER]AcmeFoobar.exe,0" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities" Name = "ApplicationName" Value = "ACME Foobar" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities\DefaultIcon" Value = "[APPLICATIONFOLDER]AcmeFoobar.exe,1" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities\FileAssociations" Name = ".xyz" Value = "AcmeFoobar.Document" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities\MIMEAssociations" Name = "application/xyz" Value = "AcmeFoobar.Document" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\AcmeFoobar\Capabilities\shell\Open\command" Value = ""[APPLICATIONFOLDER]AcmeFoobar.exe" "%1"" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\RegisteredApplications" Name = "Acme Foobar" Value = "SOFTWARE\AcmeFoobar\Capabilities" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\.xyz" Name = "Content Type" Value = "application/xyz" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\.xyz\AcmeFoobar.Document\ShellNew" Value = "" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\.xyz\OpenWithList\AcmeFoobar.exe" Value = "" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\.xyz\OpenWithProgids" Name = "AcmeFoobar.Document" Value = "" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\Applications\AcmeFoobar.exe\SupportedTypes" Name = ".xyz" Value = "" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\Applications\AcmeFoobar.exe\shell\open" Name = "FriendlyAppName" Value = "ACME Foobar" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcmeFoobar.exe" Value = "[!AcmeFoobar.exe]" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcmeFoobar.exe" Name = "Path" Value = "[APPLICATIONFOLDER]" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\SystemFileAssociations\.xyz\shell\edit.AcmeFoobar.exe" Value = "Edit with ACME Foobar" Type = "string" />
<RegistryValue Root = "HKLM" Key = "SOFTWARE\Classes\SystemFileAssociations\.xyz\shell\edit.AcmeFoobar.exe\command" Value = ""[APPLICATIONFOLDER]AcmeFoobar.exe" "%1"" Type = "string" />
</Component>
<Component ....>
<ProgId Id = "AcmeFoobar.Document" Description = "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>
@saschabeumont Разве мы не должны изменять записи HKCR, а не HKLM для сопоставления типов файлов?
становится ли xyz чувствительным к регистру?
Что делать, если вы хотите иметь несколько расширений файлов для одного и того же приложения?
Каким будет .... для компонента, дочерним элементом которого является ProgId? Каким будет "ключевой путь" для компонента?
@VK: Есть. Что именно вам не подходит? Код, подобный этому, находится здесь в производстве примерно с 2008 года, никогда не менялся и все еще работает. С другой стороны, теперь вы можете использовать Icon для рекламируемого решения без необходимости устанавливать файл значка (или просто использовать File, если вы можете установить файл или все равно включить его в исполняемый файл). Итак, что у вас здесь не работает?