如何解决在安装开始时卸载先前版本的产品会导致 Inno Setup 中的安装损坏
我想使用 Inno Setup 删除旧的程序实例。 该程序不必安装在系统的特定部分才能运行,但我想制定一个标准并通过复制文件来删除就在那里的旧实例。由于发生了一些更改,并且我想从注册表中删除以前安装的条目(32 位和 64 位安装是可能的,因此如果您想要两个安装程序,同一程序可能存在两个条目),我在假设中写了这个在 PreparetoInstall 部分运行卸载程序并删除文件后,安装将开始。
{ This is the part that is executed after you started the install }
function PreparetoInstall(var NeedsRestart: Boolean): String;
var
ResultCode: integer;
UninstallString: String;
AppId: String;
begin
AppId := '{#SetupSetting("AppId")}';
AppId := copy(AppId,2,Length(AppId) - 1);
if (IsWin64 And RegQueryStringValue(HKEY_LOCAL_MACHINE_64,'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppId+'_is1','UninstallString',UninstallString)) then begin
Exec(copy(UninstallString,Length(UninstallString) - 2),'/VERYSILENT','',SW_HIDE,ewWaitUntilTerminated,ResultCode)
if RegKeyExists(HKEY_LOCAL_MACHINE_64,'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppId+'_is1') then begin
RegDeleteKeyIncludingSubkeys(HKEY_LOCAL_MACHINE_64,'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppId+'_is1')
end;
end;
if (RegQueryStringValue(HKEY_LOCAL_MACHINE_32,ResultCode)
if RegKeyExists(HKEY_LOCAL_MACHINE_32,'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppId+'_is1') then begin
RegDeleteKeyIncludingSubkeys(HKEY_LOCAL_MACHINE_32,'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppId+'_is1')
end;
end;
If (DirIsSysLink(ExpandConstant('{app}')) = True) Then begin
RenameFile(ExpandConstant('{app}'),ExpandConstant('{app}_link'));
CreateDir(ExpandConstant('{app}'));
Directorycopy(ExpandConstant('{app}_link'),ExpandConstant('{app}'));
DelTree(ExpandConstant('{app}_link'),True,True);
End;
If (IsWin64) Then Begin
If (DirExists('C:\Program Files (x86)\TargetProgram')) then begin
CleanupFolder('C:\Program Files (x86)\TargetProgram','X86')
If (DirIsSysLink('C:\Program Files (x86)\TargetProgram') = False) Then begin
DelTree('C:\Program Files (x86)\TargetProgram',True)
end
end;
End;
If (DirExists('C:\Program Files\TargetProgram')) then begin
CleanupFolder('C:\Program Files\TargetProgram','X64')
end;
end;
{ Tries to remove existing installations and additional files in the folders that don't belong here before install starts }
function CleanupFolder(Folder: String; Num: String): Boolean;
var
BolTmpVal: Boolean;
FindRec: TFindRec;
FileList: String;
begin
BolcopyFailed := False;
If (DirExists(Folder)) then begin
FileList := '|a.file|b.dll|...|'
if (FindFirst(Folder+'\*',FindRec)) then begin
try
repeat
if (Pos('|'+LowerCase(FindRec.Name)+'|',FileList) <> 0) then begin//this is a file kNown to be installed later
DeleteFile(Folder+'\'+FindRec.Name);
end Else if ((Pos('unins0',FindRec.Name) = 1) And ((Pos('.exe',FindRec.Name) = 9) OR (Pos('.dat',FindRec.Name) = 9))) Then begin
{Deleting the uninstall files seems to remove the actual installer itself...}
//DeleteFile(Folder+'\'+FindRec.Name);
End Else If ((FindRec.Name = '.') OR (FindRec.Name = '..') OR (LowerCase(FindRec.Name) = 'backup')) Then Begin
// do nothing with main directories or backup folder
end Else begin
//... some copy and paste backup of possible user-files not involved in the problem
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end;
end;
如果我用它来清除旧的安装,安装有时只包含 15 个应该安装的文件中的 8 个(在 [Files]
中定义,我可以看到它们被添加到编译器输出和通常安装)。所以我唯一的猜测为什么我得到的文件少于 15 个是应该在预安装过程中删除的文件在安装过程中被删除。因此,如果我没有记错的话,所需的清理工作必须删除安装文件。但我找不到原因。
我认为安装本身在准备部分之后将内容放在目标文件夹中。那么我错了/如何修改代码以使安装有效?我知道我可以通过在安装程序结束前检查来测试这一点,但我想这不是一个神的练习......
我之前卸载的安装是这样的:
[Files]
Source: "Input\*"; DestDir: "{app}"; \
Flags: ignoreversion recursesubdirs createallsubdirs
[UninstallDelete]
Type: dirifempty; Name: "{app}" Type: dirifempty; Name: "C:\Program Files\A"
[Uninstallrun]
Filename: "{sys}\taskkill.exe"; Parameters: "/F /IM a.exe"; Flags:runhidden ; \
StatusMsg: "Closing process"
解决方法
主卸载程序进程仅在临时文件夹中创建自己的副本,并运行子进程进行实际卸载。
因此,您代码中的 Exec
,尽管有 ewWaitUntilTerminated
,但实际上并不等待安装完成。因此可能会发生卸载程序和安装程序同时运行的情况。这自然会导致安装损坏。
您必须等待子卸载程序完成才能解决您的问题。快速而肮脏的解决方案是查找名称包含 _iu
的任何进程。见Inno Setup Pascal Script to search for running process。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。