我想使用 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, 2, 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, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'+AppId+'_is1', 'UninstallString', UninstallString)) then begin
Exec(Copy(UninstallString, 2, Length(UninstallString) - 2), '/VERYSILENT', '', SW_HIDE, ewWaitUntilTerminated, 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, 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, True, 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"
答案 0 :(得分:0)
主卸载程序进程仅在临时文件夹中创建自己的副本,并运行子进程进行实际卸载。
因此,您代码中的 Exec
,尽管有 ewWaitUntilTerminated
,但实际上并不等待安装完成。因此可能会发生卸载程序和安装程序同时运行的情况。这自然会导致安装损坏。
您必须等待子卸载程序完成才能解决您的问题。快速而肮脏的解决方案是查找名称包含 _iu
的任何进程。见Inno Setup Pascal Script to search for running process。