我们使用 Inno Setup 作为安装程序。最近有用户在安装过程中报告如下错误:
尝试复制文件时发生错误:源文件已损坏
这是由于安装文件确实以某种方式损坏了。
理想情况下,安装 EXE 会在初始化时执行某种检查,以查看整个 EXE 是否有效。但显然它只是逐个文件地执行此操作。是否可以让 InnoSetup 来做到这一点?
我在 Inno Setup 文档中查找了“check”、“hash”等关键字,但没有看到任何内容 - 也许我错过了。
非常相似的问题(大约 10 年前 - 尽管专门询问 MD5):How to Implement MD5 check into Inno Setup installer to get 'like NSISintegrity check'? 。 这个问题似乎表明这样的检查应该已经发生。因此,也许问题不在于安装 EXE 是否经过验证,而在于何时使用/向用户显示此信息。另外,接受的答案似乎相当手动,理想情况下我希望 Inno 自己做这件事。
具有不同错误消息的类似问题:Inno Setup 中的“源文件已损坏:SHA-1 哈希不匹配”错误
向安装程序添加校验和,并在安装程序启动时验证它。标准(也是推荐)的方法是使用代码签名证书对安装程序进行签名。 无论如何,这都是必须的。
Get-AuthenticodeSignature
。为此,您需要 PowerShell 5.1。它与 Windows 10 Build 14393(2016 年 8 月)及更高版本捆绑在一起。以下代码使用它(并跳过对旧版本 Windows 的检查)。
function InitializeSetup(): Boolean;
var
WindowsVersion: TWindowsVersion;
S: string;
ResultCode: Integer;
begin
Result := True;
GetWindowsVersionEx(WindowsVersion);
Log(Format('Windows build %d', [WindowsVersion.Build]));
// TODO: Better would be to check PowerShell version
if WindowsVersion.Build < 14393 then
begin
Log('Old version of Windows, skipping certificate check');
end
else
begin
S := ExpandConstant('{srcexe}');
// Possibly this check be might need to be more strict
// (e.g. allowing only letters, digits and dots)
if (Pos('''', S) > 0) or (Pos('"', S) > 0) then
RaiseException('Possible code injection');
S := 'if ((Get-AuthenticodeSignature ''' + S + ''').Status -ne ''Valid'') ' +
'{ exit 1 }';
if ExecAsOriginalUser(
'powershell', '-ExecutionPolicy Bypass -command "' + S + '"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode) and
(ResultCode = 0) then
begin
Log('Installer signature is valid');
end
else
begin
S := 'Installer signature is not valid. Are you sure you want to continue?';
Result := (MsgBox(S, mbError, MB_YESNO) = IDYES);
end;
end;
end;
如果需要支持旧版本的Windows,则必须使用更复杂的方法,例如:
signtool
(不确定此处的许可证);X509Certificate
类。请参阅如何检查文件是否具有数字签名。