Inno Setup 中的文件关联

Posted

技术标签:

【中文标题】Inno Setup 中的文件关联【英文标题】:File association in Inno Setup 【发布时间】:2014-12-19 14:09:21 【问题描述】:

我正在使用 Inno Setup 并尝试关联位于 Windows 7 中 Program Files (x86) 中的程序。我有以下内容:

#define MyAppName "MyView"

#define MyAppExeName "MyView.exe"

[Setup]
AppName=#MyAppName

[Registry]
Root: HKCR; Subkey: ".mpl"; ValueType: string; ValueName: ""; ValueData: "MyView"; Flags: uninsdeletevalue
Root: HKCR; Subkey: "MyView"; ValueType: string; ValueName: ""; ValueData: "MyView"; Flags: uninsdeletekey
Root: HKCR; Subkey: "MyView\delta.ico"; ValueType: string; ValueName: ""; ValueData: "app\GeoView.EXE,0"
Root: HKCR; Subkey: "MyView\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """app\MYVIEW.EXE"" ""%1""" 

关于为什么协会不起作用的任何建议?

【问题讨论】:

此问题的答案中描述的技术已过时。它们不应在现代版本的 Windows 上使用,除非您将应用程序与您的自定义文件类型相关联。这些技术绝不能用于常见类型,因为您的应用程序会与其他应用程序竞争。见Associate my QT application with video/image files in Inno Setup。 【参考方案1】:

这行得通:

    Root: HKCR; Subkey: ".mpl"; ValueType: string; ValueName: ""; ValueData: "#MyAppName"; Flags: uninsdeletevalue
    Root: HKCR; Subkey: ".tvd"; ValueType: string; ValueName: ""; ValueData: "#MyAppName"; Flags: uninsdeletevalue
    Root: HKCR; Subkey: ".log"; ValueType: string; ValueName: ""; ValueData: "#MyAppName"; Flags: uninsdeletevalue
    Root: HKCR; Subkey: "#MyAppName"; ValueType: string; ValueName: ""; ValueData: "MyView"; Flags: uninsdeletekey
    Root: HKCR; Subkey: "#MyAppName\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "app\delta.ico,0"
    Root: HKCR; Subkey: "#MyAppName\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """app\#MyAppExeName"" ""%1""" 

【讨论】:

【参考方案2】:

如果您想将程序与扩展相关联,只需在您的 iss 文件中添加此指令:

在部分

[Setup]

ChangesAssociations = yes

^-Setup 将告诉 Explorer 在安装结束时刷新其文件关联信息,而 Uninstall 将在卸载结束时执行相同的操作。

在部分

[Registry]

Root: HKCR; Subkey: ".mpl";                             ValueData: "#MyAppName";          Flags: uninsdeletevalue; ValueType: string;  ValueName: ""
Root: HKCR; Subkey: "#MyAppName";                     ValueData: "Program #MyAppName";  Flags: uninsdeletekey;   ValueType: string;  ValueName: ""
Root: HKCR; Subkey: "#MyAppName\DefaultIcon";             ValueData: "app\#MyAppExeName,0";               ValueType: string;  ValueName: ""
Root: HKCR; Subkey: "#MyAppName\shell\open\command";  ValueData: """app\#MyAppExeName"" ""%1""";  ValueType: string;  ValueName: ""

说明

Root: HKCR; Subkey: ".magi"; ValueData: "MyMAGIApplication"; ValueType: string; ValueName: ""; Flags: uninsdeletevalue。该指令在注册表中添加“.magi”键,在 HKEY_CLASSES_ROOT (HKCR) 中更准确。在这条指令中,我们还有ValueName="",所以它在注册表中获得了默认值。

Root: HKCR; Subkey: "MyMAGIApplication"; ValueData: "Program MAGI"; ValueType: string; ValueName: ""; Flags: uninsdeletekey 为了在 HKCR 中添加键 MyMAGIApplication,其值为“Program MAGI”。

Root: HKCR; Subkey: "MyMAGIApplication\DefaultIcon"; ValueData: "app\MAGI.EXE,0"; ValueType: string; ValueName: ""为了关联一个图标包含在可执行文件中。 “0”表示它是可执行 MAGI.EXE 中出现的第一个图标。

Root: HKCR; Subkey: "MyMAGIApplication\shell\open\command"; ValueData: """app\MAGI.EXE"" ""%1"""; ValueType: string; ValueName: "" 为了添加子键 shell\open\command。使用此指令,当用户单击扩展名为“.magi”的文件时,Windows 能够启动应用程序 MAGI.EXE。

结果在注册表中:

【讨论】:

广告到 shell\open\command 键描述,或具有此类扩展名的文件被某些 Shell API 函数打开(例如 ShellExecute)。此主题还有一个FAQ entry。 [+1] 谢谢,复制粘贴 Reg 选择并操作 horz 滚动在 Edge 中丢失选择。编辑答案和复制/意大利面和取消会阻碍它。【参考方案3】:

总结一下Windows文件关联 有 3 个主要的注册表设置需要处理:

    HKCR MyMAGICApplication -> 应用程序的路径和图标 HKCR .magi -> '将 .magiMyMAGICApplication 关联(系统默认) HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.magi\UserChoice ->'将 .magiMyMAGICApplication(用户默认)

关于 1. 和 2. 这些在之前的答案中都有很好的介绍。 (除了 .magi 之前可能与 SomeOtherMAGICApplication 相关联。此设置将被覆盖,卸载时不会恢复。) 但是要让它在现实中充分发挥作用 3. 还必须考虑到。

好的,我们从 FileSample.iss 开始:

#define MyAppName    "MovToAvi"
#define MyAppNameExt ".mov"

[Setup]

ChangesAssociations=yes

[Languages]
Name: "german"; MessagesFile: "compiler:Languages\German.isl"

[CustomMessages]
german.Assoc=Verknüpfung:


[Tasks]
Name: "desktopicon"; Description: "cm:CreateDesktopIcon"; GroupDescription: "cm:AdditionalIcons"
; Flags: unchecked
Name: fileassoc; Description: "cm:AssocFileExtension,#MyAppName,#MyAppNameExt"; GroupDescription: "cm:Assoc"


[Run]
Filename: "app\install FileAssoc\AssocBak.cmd"; Parameters: "#MyAppNameExt #MyAppName"; StatusMsg: "cm:AssocingFileExtension,#MyAppName,#MyAppNameExt"; Tasks: fileassoc

[UninstallRun]
Filename: "app\install FileAssoc\AssocBak.cmd"; Parameters: "UnAssoc"; RunOnceId: "RemoveAssoc"


[Registry]

;Handled by AssocBak.cmd
;Root: HKCR;  Subkey: "#MyAppNameExt";                ValueData: "#MyAppName";                Flags: uninsdeletekeyifempty; ValueType: string;  ValueName: ""  ; Tasks: fileassoc

;Doesn't work like this - also handled by AssocBak.cmd
;Root: HKCU;  Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\#MyAppNameExt\UserChoice"; ValueData: "#MyAppName";  ValueType: string;  ValueName: "Progid" ; Tasks: fileassoc

Root: HKCR;  Subkey: "#MyAppName";                    ValueData: "Program #MyAppName";              ValueType: string;  ValueName: "" ; Flags: uninsdeletekey;   
Root: HKCR;  Subkey: "#MyAppName\DefaultIcon";        ValueData: "app\Pipe_icon.ico";               ValueType: string;  ValueName: "" ;
Root: HKCR;  Subkey: "#MyAppName\shell\open\command"; ValueData: """app\#MyAppExeName"" ""%1""";  ValueType: string;  ValueName: "" ;

所以在这里说什么。好吧,只有 1. 已经完成了。 2.(和 3.)的完成取决于 Task associate 是否已启用并且其工作是通过调用 AssocBak.cmd 来完成的

请原谅这里使用批处理文件而不是 Inno Pascal 代码/请随意实施。但是,只要它有效,我就会保留它。

@prompt -$G
@set BakFile=BeforeInstallAssoc.dat


    @if "%1"==""        @goto :ShowHelp

    @pushd %~dp0

    @if   %1==UnAssoc (
        @call :Restore
    ) else (
        @call :DoAndMakeBak %1 %2
    )   

    @popd
@goto :eof

:DoAndMakeBak


    @if not exist "%BakFile%" (
        @assoc %1 >"%BakFile%"
        @assoc %1 %2

        @call :ResetUserFileExt %1

    ) else (
        @echo Skipped - Backupfile already exist! Run '%~nx0 u' first or delete '%BakFile%'.
    )

@goto :eof

:Restore
    :: Attentions putting %BakFile% in quotes gives the Filename and not the File content
    @FOR /f "delims== tokens=1,2" %%i IN (%BakFile%) DO @(
        set Ext=%%i
        set Verb=%%j
    )
    assoc %Ext%=%Verb%

    @call :ResetUserFileExt %Ext%

    ::@del "%BakFile%"
@goto :eof

:ShowHelp
    @echo Assoc with backup
    @echo ================= 
    @echo.
    @echo Restore:
    @echo   %~nx0 UnAssoc
    @echo.
    @echo Set:
    @echo   %~nx0 ^<AssocExt^> ^<Assochandle^>
    @echo   Example %~nx0 .mov MovToAvi

@goto :eof

:ResetUserFileExt

    ::Workaround for 
    ::REG DELETE "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\%1\UserChoice" /f /va

    @REG ADD    "HKCU\emptyKey" /f >nul
    @REG SAVE   "HKCU\emptyKey" empty.hiv /y >nul
    @REG DELETE "HKCU\emptyKey" /f >nul

    @REG RESTORE "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\%1" empty.hiv >nul
    @del empty.hiv

@goto :eof

总结该脚本,它只是 assoc 命令添加的一种包装

    在 BeforeInstallAssoc.dat 中保存/恢复之前的设置 通过 REG RESTORE 重置/删除 3. (Explorer\FileExts) 会好的 REG DELETE "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\%1\UserChoice" /f /va 会工作。只需删除当前用户设置,以便使用系统设置。但只是得到 ACCESS DENIED.。愚蠢的 Windows 版本越高,它就越卑鄙。所以你必须为自己的权利而战。 REG RESTORE 是解决此问题的一些解决方法。有关详细信息,请参阅脚本末尾的 :ResetUserFileExt 函数。

好的,就是这样:D

【讨论】:

【参考方案4】:

之前在 SO 上已经回答了创建文件关联。但是核心文档引用了它:

http://www.jrsoftware.org/isfaq.php#assoc

创建文件关联

首先将[Setup] 部分指令ChangesAssociations 设置为yes。然后创建[Registry] 条目,如下所示。

[Registry]
Root: HKCR; Subkey: ".myp"; ValueType: string; ValueName: ""; ValueData: "MyProgramFile"; Flags: uninsdeletevalue

.myp 是我们关联的扩展名。 MyProgramFile 是存储在注册表中的文件类型的内部名称。请确保为此使用唯一名称,以免无意中覆盖另一个应用程序的注册表项。

Root: HKCR; Subkey: "MyProgramFile"; ValueType: string; ValueName: ""; ValueData: "My Program File"; Flags: uninsdeletekey

My Program File 以上是资源管理器中显示的文件类型的名称。

Root: HKCR; Subkey: "MyProgramFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "app\MYPROG.EXE,0"

DefaultIcon 是注册表项,它指定包含要与文件类型关联的图标的文件名。 ,0 告诉 Explorer 使用来自 MYPROG.EXE 的第一个图标。 (,1 表示第二个图标。)

Root: HKCR; Subkey: "MyProgramFile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """app\MYPROG.EXE"" ""%1"""

shell\open\command 是注册表项,指定在资源管理器中双击该类型的文件时要执行的程序。周围的引号在命令行中,因此它可以正确处理长文件名。

【讨论】:

太好了,除了 DefaultIcon 之外的一切都很好,改为空白图标

以上是关于Inno Setup 中的文件关联的主要内容,如果未能解决你的问题,请参考以下文章

将我的 QT 应用程序与 Inno Setup 中的视频/图像文件相关联

程序打包(安装包制作,Inno setup打包教程,QT程序打包)

程序打包(安装包制作,Inno setup打包教程,QT程序打包)

程序打包(安装包制作,Inno setup打包教程,QT程序打包)

如何使用inno setup来读取配置文件中的参数

Inno Setup 5 安装包制作!reg2iss,Inno Setup 问题。Inno Setup 怎么批量导入reg文件,(像nsis