Inno Setup 常见问题解答(中文翻译:王苏) |
Inno Setup 常见问题解答包含了在帮助文档中没有的补充信息。
此页面的内容也可以在 GitHub 上找到,您可以使用编辑按钮建议新的条目或其他改进。
将 Inno Setup 的文本翻译为其他语言不需要修改源代码。只需复制 Default.isl 文件(包括在 Inno Setup 中),并开始编辑其中的文本。(不要直接编辑 Default.isl 文件,否则当您安装新的 Inno Setup 版本时,您的更改将丢失。有关某些重要提示,请参阅帮助文档中的 "[Messages] 区段" 主题。
一旦你完成了创建新的 .isl 文件,创建一个 [Languages] 区段,告诉编译器使用它:
[Languages]
Name: mytrans; MessagesFile: "compiler:MyTranslation.isl"在 Inno Setup Translations 网页上有许多贡献的翻译可供下载。
请注意,消息框中的按钮标题无法翻译。这些字幕始终与 Windows 本身的语言相同。因此,如果用户正在运行 Windows 的英文版,他们将看到英文按钮字幕。对于使用 Windows MessageBox() 函数显示消息框的任何应用程序,这是正常行为。
支持。它在所有文件名和常量解析中都进行了前导字节检查,因此不会将尾字节误认为反斜杠 ("\") 或大括号 ("{")。
目前,没有计划推出 Inno Setup 的 Windows Installer 版本。"支持" Windows Installer 可能会涉及程序的近乎完全重写。
安装程序的图标可以通过设置 [Setup] 区段的 SetupIconFile 指令来更改。要设置卸载程序的图标,可设置 UninstallDisplayIcon。
可以,可通过 Pascal 脚本功能。
有,可以通过 Pascal 脚本功能。请参阅 CodeDownloadFiles.iss 示例脚本示例。
不可以,也没有计划此类功能(它可能被滥用)。如果您打算将用户交互保持在最低限度,请使用禁用* [Setup] 区段指令。
可以。在 DefaultDirName 中使用 {reg:...} 常量。例如:
[Setup]
DefaultDirName={reg:HKA\Software\My Program,Path|{autopf}\My Program}
有关 {reg:...} 常量和 {autopf} 常量的更多信息,请参阅帮助文档中的常量主题。
有关 HKA 键值的详细信息,请参阅帮助文档中的非管理安装模式主题。
不可以。没有简单的方法可以访问属于其他用户的注册表项。
为了访问给定的用户注册表配置单元,必须首先加载用户的配置文件,为此,必须进行身份验证。卸载者不会知道用户的密码。
"但它不能调用 RegLoadKey 手动安装用户的注册表配置单元 (NTUSER.DAT) 吗?" 在不冒充用户的情况下,运行卸载程序的用户需要在用户的配置文件目录上写入权限。在 Windows XP 上,用户配置文件可以标记为"私有",除了用户本人,任何人都无法访问其中的文件。
在 Roaming 配置文件设置中,如果不首先进行身份验证,甚至不可能知道给定用户的配置文件所在的路径。
要处理这种情况,像其他安装程序那样:只需保留其他用户的 HKCU 项即可。
这主要取决于您的应用程序是使用哪个开发工具创建的。检查其文档。
如果您确定您的应用程序依赖于特定的 Microsoft DLL,而该 DLL 不是随 Windows 预装的,那么首先不要从自己的 Windows 目录中部署 DLL。您自己的 Windows 目录中的文件通常针对特定版本的 Windows 量身定做,并且不会在其他版本的 Windows 上工作 -- 或者更糟(参见下文)。当您运行最新版本的 Windows 时,情况尤其如此。
相反,在微软网站上搜索被视为"可重新分配"的 DLL 版本。(http://www.microsoft.com/downloads/ 是一个很好的开始。) 此类版本通常可以安全地安装在任何 Windows 版本上(但请查看 README 文件以确定)。
如果出现任何情况,则可能不允许单独部署有问题的 DLL。
在将"更新"(或"附加")的安装部署到现有安装时,您可能希望满足以下标准:
- 更新必须安装到与原始应用程序相同的目录。
- 卸载原始应用程序时,必须删除更新安装的任何新文件。
- 更新不应在添加/删除程序 列表中创建新条目,也不应更改原始应用程序的条目。卸载程序显示的应用程序名称也不应更改。
1 和 2 可以通过为更新安装提供与原始应用程序相同的 AppId 设置来实现。(如果您从未在原始应用程序中设置 AppID,则将 AppID 设置为原始应用程序中使用的 AppName 的值。) 如此,当与 UsePreviousAppDir=yes(默认设置)组合时,将导致更新安装默认为相同目录作为原始应用程序,并共享相同的卸载日志文件 (unins???.dat)。有关详细信息,请参阅帮助文档中的相同的应用程序主题。
3 可以通过设置 CreateUninstallRegKey=no 和 UpdateUninstallLogAppName=no 来实现。
如果尝试在参数数据中嵌入引号 (") 字符,则通常会显示此消息,但不会根据需要将其加倍。请阅读文档中的 "区段中的参数" 主题以获取更多信息。
您的应用程序很可能没有在它试图打开的文件上指定路径名,因此它期望在当前目录中找到它们。默认情况下,Inno Setup 不会在其创建的快捷方式上设置"开始"字段:这会导致 Windows 自行选择目录,这通常不会包含您的应用程序的目录。
在几乎所有情况下,这都是应该在应用级别上纠正的。正确设计的 GUI 应用程序不应期望从特定目录开始;他们应该总是在打开的文件上指定完整的路径名。例如,在 Delphi 或 C++Builder 中,可以通过调用: ExtractFilePath(ParamStr(0)) 来获取包含应用程序 EXE 目录的完整路径名。要获取应用程序目录中名为“file.txt”文件的完整路径,可使用: ExtractFilePath(ParamStr(0)) + 'File.txt'。
如果由于某种原因无法在应用程序层面解决此问题,可以告诉 Inno Setup 通过在 [Icons] 条目中添加 "WorkingDir: {app}" 来设置“Start In”字段。
当与安装有关的文件 (如 setup.exe, setup.1) 大小错误,或者文件的一部分未通过 CRC 检查时,将显示此错误消息。它不会因为任何其他原因而显示。
如果您的安装通过互联网分发,并且您收到大量有关此错误的报告,则可能是您的 Web 服务器通过过早断载连接来提供部分文件。让受影响的用户检查他们下载的文件的字节中的大小。
如果您的安装是通过 CD-ROM 或软盘分发的,则可能是 CD-ROM 或软盘不好,或者驱动器可能有缺陷。
当您在版本之间更改 AppId,或者未指定 AppId 时,就会发生这种情况。如果这样做,安装程序就无法知道这两个版本是同一个应用程序,因此将在添加/删除程序 中创建一个新条目。此外,一个新的卸载日志文件 (unins???.dat) 将被创建。这显而易见的解决方案是不要更改 AppId 或 AppName。
如果必须在新版本中更改 AppName,则将 AppId 设置为上一版本的 AppId 或 AppName 的值。
此消息通常意味着您指定了不具备注册能力的文件上的 "regserver" 标志。从 [Files] 条目中删除 "regserver" 标记,消息将消失。
目录可能无法删除的原因有几个:
- 它在安装前已经存在。默认情况下,卸载程序可以安全地播放它,并且不会删除安装程序未创建的目录。
- 它包含文件或子指示。如果您需要卸载程序来删除其他文件/目录,请使用 [UninstallDelete]。
- 运行进程将目录作为当前目录。
来自 Tim Rude:
要让批处理文件在退出时自动关闭,最简单的方法是用 CLS 命令在批处理文件结束时清除屏幕。---批处理文件 1---
@echo off
echo 你好,世界
echo 该批处理文件在退出时不关闭---批处理文件 2---
@echo off
echo 你好,世界
echo 该批处理文件在退出时关闭
cls
在启动时,安装程序会在注册表中查看是否有相同的应用程序被安装,如果有,它将使用上一个安装的目录作为向导中向用户呈现的默认目录。如果卸载应用程序并再次运行安装程序,它将使用新的 DefaultDirName 设置。如果您希望禁用此功能,请将 UsePreviousAppDir 设置为 "no"。
两个文件不能具有相同的名称,并且由于快捷方式是文件,因此两个快捷方式不能具有相同的名称。
首先,确保你没有 在 [Run] 条目上使用 "nowait" 或 "waituntilidle" 标记。这些标志阻止安装程序等待,直到进程完全终止。
如果您没有使用这些标志,并且它似乎仍未等待程序完成,那么可能发生的情况是,您正在运行的 EXE 可能会生成其他进程,然后立即终止自身,导致安装程序认为程序已完成。众所周知,基于 InstallShield 的旧版安装程序会出现这种情况 (要解决它,请尝试使用 /SMS 开关)。
检查程序是否这样做的简单方法是从命令行运行 "START /WAIT ProgramName.exe",并在程序退出之前查看是否返回到命令提示。
您正在使用旧的非 Unicode 版本的 Inno Setup。
您的安装需要管理员权限,并且正在提升:
映射驱动器(默认情况下)不可用到任何提升的应用程序。这是在 Windows Vista 中介绍的。
有一个选项使他们可用于相同的用户级别,但这对从 LUA 运行时用户发生变化的情况没有帮助。
使用 Pascal 脚本功能或 [Run] 区段:
[Run] 区段是一种通常被忽视但简单的执行自定义安装任务的方法。首先,在您选择的开发工具(最好是创建独立的 EXE (如 Delphi )中编写一个小程序,以执行所需的任务,并将其 EXE 复制到脚本目录。接下来,在 [Files] 脚本区段放置一个条目,告诉安装程序将 EXE 复制到安装的临时目录 ("{tmp}"):
[Files]
Source: "ModifyAutoexec.exe"; DestDir: "{tmp}"然后添加 [Run] 区段条目,告诉安装程序在所有其他安装步骤后执行 EXE:
[Run]
Filename: "{tmp}\ModifyAutoexec.exe"如果程序需要其他信息,例如 "{app}" 常量值,则可以通过命令行参数,即:
[Run]
Filename: "{tmp}\ModifyAutoexec.exe"; Parameters: """{app}"""您也可以将安装任务纳入应用程序的主要 EXE,并在调用特殊命令行参数时将其执行该任务。 例如:
[Run]
Filename: "{app}\MyProgram.exe"; Parameters: "/DoTheTask"
如果在 [Files] 区段条目中使用以下通配符:
[Files]
Source: "*.htm"; DestDir: "{app}"您可能会发现它不仅匹配扩展名为 .htm 的文件,还匹配扩展名为 .html 的文件。
这是因为在 Windows 中,通配符匹配长文件名和 8.3 别名("短文件名")。默认情况下,名为“webpage.html”的文件将具有 8.3 别名 "WEBPAG~1.HTM"; 因此,*.htm 匹配该文件。
要避免这种情况,请添加一个 Excludes 参数明确过滤掉扩展名为 .html 的文件:
[Files]
Source: "*.htm"; Excludes: "*.html"; DestDir: "{app}"
将 createallsubdirs 标记添加到您的 [Files] 区段条目中,空目录将在安装时创建。
[Dirs] 区段也可用于创建空目录。
通过在 Windows 资源管理器中右键单击它们并选择属性 来比较现有文件和新文件上的版本号。默认情况下,Inno Setup 不会替换现有文件,除非现有文件没有版本信息或具有较低的版本号。
文件的二进制版本号是 Inno Setup 实际比较的内容,/LOG 在这里的切换很方便。日志将显示文件的二进制版本号以及某些文件未被替换的原因。
如果您想强制更换文件,无论其版本号如何,请将 ignoreversion 标记添加到 [Files] 区段条目中。此标志仅应用于与您的应用程序私有文件,而不应用于共享系统文件。
首先创建一个名为 "website.url" 的文件,并将这些行放在其中:
[InternetShortcut]
URL=http://web.site.address/然后将这些行添加到脚本中:
[Files]
Source: "website.url"; DestDir: "{app}"
[Icons]
Name: "{group}\Visit My Web Site"; Filename: "{app}\website.url"
在 [Icons] 区段条目上使用 WorkingDir 参数。
首先设置 [Setup] 区段指令 "ChangesAssociations" 为 "yes"。然后创建以下 5 个 [Registry] 条目,以创建文件关联。
[Registry]
Root: HKA; Subkey: "Software\Classes\.myp\OpenWithProgids"; ValueType: string; ValueName: "MyProgramFile.myp"; ValueData: ""; Flags: uninsdeletevalue".myp" 是我们关联的扩展名。"MyProgramFile.myp" 是存储在注册表中的文件类型的内部名称。请确保为此使用唯一的名称,这样您就不会无意中覆盖其他应用程序的注册表项。Root: HKA; Subkey: "Software\Classes\MyProgramFile.myp"; ValueType: string; ValueName: ""; ValueData: "My Program File"; Flags: uninsdeletekey
上面的 "My Program File" 是资源管理器中显示的文件类型的名称。Root: HKA; Subkey: "Software\Classes\MyProgramFile.myp\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\MyProg.exe,0"
"DefaultIcon" 是注册表项,该项指定包含图标的文件名,以便与文件类型关联。",0" 告诉资源管理器使用 MyProg.exe 的第一个图标。(",1" 将表示第二个图标。)Root: HKA; Subkey: "Software\Classes\MyProgramFile.myp\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\MyProg.exe"" ""%1"""
"shell\open\command" 是注册表项,该注册表项指定在资源管理器中双击该类型的文件时执行的程序。周围的引号在命令行中,因此它可以正确处理长文件名。Root: HKA; Subkey: "Software\Classes\Applications\MyProg.exe\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: ""
有关 HKA 键值的详细信息,请参阅帮助文档中的非管理安装模式主题。
环境变量以字符串值存储在注册表中,因此可以使用 [Registry] 区段操作它们。系统范围的环境变量位于:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment特定于用户的环境变量位于:
HKEY_CURRENT_USER\Environment
使用 [Icons] 区段中的 "closeonexit" 和 "dontcloseonexit" 标志。
Inno Setup 目前没有用于执行此操作的特定功能,但您可以在文件被替换之前使用类似于此的 [Files] 区段条目进行复制:
Source: "{app}\MyProg.exe"; DestDir: "{app}\backup"; Flags: external skipifsourcedoesntexist uninsneveruninstall
这可以通过输入中的 MinVersion 和/或 OnlyBelowVersion 参数完成。有关详细信息,请参阅帮助文档中的公共参数主题。
[Dirs]、[Files] 和 [Registry] 区段分别支持用于设置目录、文件和注册表项权限的权限参数。
如果您有更高级的需求,请查看 SetACL。
有两种不同的方法可以做到这一点:
- 要么在启动组中创建快捷方式:
[Icons]
Name: "{autostartup}\My Program"; Filename: "{app}\MyProg.exe"- 或在注册表的 Run 项中创建值:
[Registry]
Root: HKA; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "MyProg"; ValueData: """{app}\MyProg.exe"""; Flags: uninsdeletevalue有关 {autostartup} 常量的更多信息,请参阅帮助文档中的常量主题。
有关 HKA 键值的详细信息,请参阅帮助文档中的非管理安装模式主题。
您可以通过直接在 [Run] 区段条目的 Filename 参数中指定文件名来运行批处理文件:
[Run]
Filename: "{app}\YourBatchFile.bat"
默认情况下,AppMutex 找不到在运行安装/卸载程序的用户会话之外的用户会话中创建的互斥体。这是因为每个用户会话都有自己的内核命名空间。
要检测在其他会话中创建的互拆体,您的应用程序必须创建两个互拆体:一个带有 Global\ 前缀,另一个没有。
从任何用户会话都可以访问带有 Global\ 前缀的互拆体。在会话命名空间(即没有 Global\ 前缀)中还必须创建一个类似名称的互拆体,以防由于安全限制而无法创建全局互拆体。
此外,必须在每个 CreateMutex() 调用中传递特殊的安全描述符,以确保不同用户访问互拆体。
下面是如何在 Delphi 创建两个互拆体的示例:
procedure CreateMutexes(const MutexName: String);
{ 创建安装/卸载程序检查的两个互斥体,以查看程序是否仍在运行。}
const
SECURITY_DESCRIPTOR_REVISION = 1;
var
SecurityDesc: TSecurityDescriptor;
SecurityAttr: TSecurityAttributes;
begin
{ 默认情况下,创建的互拆体只能由运行进程的用户访问。我们需要所有用户都能访问互斥体,以便互拆体检测可以跨用户会话工作。为此,我们使用带有空 DACL 的安全描述符。}
InitializeSecurityDescriptor(@SecurityDesc, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@SecurityDesc, True, nil, False);
SecurityAttr.nLength := SizeOf(SecurityAttr);
SecurityAttr.lpSecurityDescriptor := @SecurityDesc;
SecurityAttr.bInheritHandle := False;
CreateMutex(@SecurityAttr, False, PChar(MutexName));
CreateMutex(@SecurityAttr, False, PChar('Global\' + MutexName));
end;
...
begin
CreateMutexes('YourMutexNameGoesHere');
end;在脚本中,将 AppMutex 设置如下:
[Setup]
AppMutex=YourMutexNameGoesHere,Global\YourMutexNameGoesHere
建议安装 OCX 文件的方法如下。
[Files]
Source: "ComCtl32.ocx"; DestDir: "{sys}"; Flags: restartreplace sharedfile regserver
请参阅 "关于"页面。
典型的 Inno Setup 安装不需要管理权限。但是,下面指出了一些例外情况。
需要管理权限的情况:
- 在脚本的 [Setup] 区段使用 "PrivilegesRequired=admin"。如果用户缺少管理权限,这将导致安装程序中止并显示错误消息。
- 使用 [Files] 区段中的 "restartreplace" 标记。此标志导致 Inno Setup 调用 MoveFileEx 函数,该函数试图写到 "HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Control\ Session Manager"。编写此项的访问仅限于管理员。
- 使用 [Registry] 区段写入到 HKEY_USERS\.DEFAULT 下的任何项。编写此项的访问仅限于管理员。
- 使用 [Files] 区段中的 "regserver" 标记。在大多数情况下,注册 DLL 涉及写入给 HKEY_CLASSES_ROOT,不授予普通用户的特权。
- 使用 "sharedfile" 标志是 [Files] 区段。此标志导致 Inno Setup 在 "HKEY_LOCAL_MACHINE\ SOFTWARE\ Microsoft\ Windows\ CurrentVersion\ SharedDLLs" 中创建/更新一个值。普通用户不允许写到该项。
- 使用 [Registry] 区段向 HKEY_LOCAL_MACHINE 或 HKEY_CLASSES_ROOT 下的任何项写入。普通用户不允许向这些项写入。
Inno Setup 本身不需要写入 Windows 目录或上述任何其他注册表项。
当安装由没有 管理权限的用户运行时,有什么不同?
- 添加/删除程序 控制面板条目的注册表项是在 HKEY_CURRENT_USER 下创建的,而不是 HKEY_LOCAL_MACHINE。因此,只有安装程序的用户才会看到其添加/删除程序 条目。
- "{group}" 常量始终指向当前用户的配置文件,而不是 "所有用户" 配置文件。
- 程序可能由任何用户卸载。(当管理员安装程序时,仅允许管理员卸载它。)
有关详细信息,请参阅帮助文档中的非管理安装模式主题。
Inno Setup 对安装中可能包含的文件、快捷方式、注册表条目等数量没有任何限制。
点击 "取消" 后,安装程序将开始以与卸载程序完全相同的方式还原其进行的更改。因此,不会遗留部分已安装的应用程序。
卸载使用 Inno Setup 为安装程序的程序时,会创建一个名称为 "_iu14D2N.tmp" 的临时文件。卸载进程完成后,文件仍保留在目录中的原因是 Windows 不允许运行可执行文件自行删除。因此,它所做的是安排下次重新启动计算机时自动删除文件。如果您不想等到那时,手动删除文件是完全安全的,前提是当前没有卸载程序正在运行。
请注意,此行为并非 Inno Setup 所独有。
当文件具有 regserver 标志时,即使在安装期间未更换文件(例如,如果现有文件是较新版本),安装程序也会尝试注册该文件。
这种行为表面上似乎是多余的,但事实上这是很有必要的。因为最初安装该文件的人可能没有注册该文件。或者,现有的文件可能以某种方式被取消注册而没有被删除。如果安装程序仅替换已注册文件,那么在这两种情况下,文件在安装结束时将保持未注册状态,这样您的应用程序将无法工作。
经常有新用户想知道为什么卸载 EXE 的名称中有数字(例如 unins000.exe )。
这是因为 Inno Setup 允许将多个应用程序安装到同一目录中。当这种情况发生时,第一个应用程序的卸载程序被命名为 unins000.exe,第二个应用程序的卸载程序被命名为 unins001.exe,等等。如果使用了固定名称,则只能卸载最近安装的应用程序。
如果你的应用程序需要动态创建安装,则允许在遵守 Inno Setup 许可证条款的情况下,将其随 Inno Setup 编译器的文件一起部署。