我会尽量简明扼要,而不附上所有相关的源文件。我已尽我的 Pascal 知识所允许的范围找到了这个问题...
据我所知,我发现在步骤 ssInstall 中出现了磁盘缓存问题。我有一个应用程序的安装程序,如果它发现安装了较旧的应用程序版本,它将调用这样的卸载:
procedure CurStepChanged(CurStep: TSetupStep);
var
uninstallStr: String;
ResultCode: Integer;
begin
if (CurStep = ssInstall) and IsUpdatableApplicationInstalled() then
begin
uninstallStr := GetUninstallString();
uninstallStr := RemoveQuotes(uninstallStr);
Result := Exec(uninstallStr, '/SILENT /NORESTART /SUPPRESSMSGBOXES', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
if Result and (ResultCode = 0) then
Log('CurStepChanged = ssInstall; uninstall OK');
//-------------
//Sleep(30000);
//-------------
end;
文件夹/文件也是这样定义的:
[Dirs]
Name: "{app}\db"; Flags: uninsalwaysuninstall
[Files]
Source: "..\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion createallsubdirs recursesubdirs
Source: "..\java\jre\*"; DestDir: "{app}\jre"; Flags: ignoreversion recursesubdirs createallsubdirs
blah...
Test case1; 正常安装:一切顺利。 日志文件部分:
Starting the installation process.
Creating directory: C:\Program Files <---
Creating directory: C:\Program Files\MyApp <---
Creating directory: C:\Program Files\MyApp\db <---
Creating directory: C:\Program Files\MyApp\jre <---
Creating directory: C:\Program Files\MyApp\jre\lib
Creating directory: C:\Program Files\MyApp\jre\lib\applet
Directory for uninstall files: C:\Program Files\MyApp
Creating new uninstall log: C:\Program Files\MyApp\unins000.dat <--- !!!
-- File entry --
Dest filename: C:\Program Files\MyApp\unins000.exe <--- !!!
blah...
测试用例 2; 更新旧版本:当进入步骤 ssInstall 时,卸载程序启动,完成后开始安装。 日志文件部分:
CurStepChanged = ssInstall; uninstall OK
Starting the installation process.
Creating directory: C:\Program Files\MyApp\jre\lib
Creating directory: C:\Program Files\MyApp\jre\lib\applet
Directory for uninstall files: C:\Program Files\MyApp
Creating new uninstall log: C:\Program Files\MyApp\unins001.dat <--- !!!
-- File entry --
Dest filename: C:\Program Files\MyApp\unins001.exe <--- !!!
blah...
如您所见,有些文件夹没有创建,我的应用稍后尝试写入 'db' 文件夹时失败。
如果我取消对 Sleep() 命令的注释,一切都会顺利进行并且两个日志文件都是相同的。
看来磁盘有足够的时间刷新更改! inno-setup 中一定缺少 flush() 命令。
任何创新大师都可以发表评论或以某种方式提供帮助吗? 有没有我可以调用的 flush() 而不是 sleep()? 任何帮助表示赞赏。我只想在提交错误请求之前确定。
最佳答案
只是总结一下这个问题的评论线索:
不要卸载
最好的解决办法是根本不运行卸载程序。您可以通过 [InstallDelete]
部分删除冗余文件;例如。要完全删除“jre”子文件夹(作为安装的一部分进行替换),然后执行以下操作:
[InstallDelete]
Type: filesandordirs; Name: "{app}\jre"
(只对像这样的子文件夹使用它,而且要少用;如果你删除太多东西,你可能会给自己带来麻烦。)
对于以前版本安装的正常单个应用程序文件现在是多余的,您可以像这样删除它们:
[InstallDelete]
Type: files; Name: "{app}\redundant.dll"
(如果他们在安装时有“regserver”或“sharedfile”,你需要做一些更高级的事情。)
如果无论如何都卸载,请等待更长的时间
卸载程序在运行时无法删除自身或所在的文件夹。虽然 Inno 确实以能够删除卸载程序和文件夹的方式处理此问题,但这确实意味着您对卸载程序的 Exec
调用将在删除发生之前和卸载之前返回过程实际上结束了。
在 Exec
之后,您需要等待更长时间才能真正完成卸载,然后才能继续安装。使用 Sleep 非常简单,并且在大多数情况下都能正常工作,但如果您想要获得最佳结果,则需要调用 WinAPI 来检查正在运行的进程列表。
此外,您应该使用 PrepareToInstall
事件函数来执行实际的卸载。这将更好地允许您处理卸载错误或在卸载和重新安装之间需要重新启动等情况。 (并且因为它在安装过程中的“正确”时间执行。)
关于caching - inno-setup 的磁盘缓存问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18902060/