gpt4 book ai didi

inno-setup - 在安装开始时卸载以前版本的产品会导致 Inno Setup 中的安装损坏

转载 作者:行者123 更新时间:2023-12-05 04:48:25 24 4
gpt4 key购买 nike

我想使用 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"

最佳答案

主卸载程序进程仅在临时文件夹中创建其自身的副本,并运行子进程以进行实际卸载。

引用 Inno Setup documentation :

Note that at the moment you get an exit code back from the uninstaller, some code related to uninstallation might still be running. Because Windows doesn't allow programs to delete their own EXEs, the uninstaller creates and spawns a copy of itself in the TEMP directory. This "clone" performs the actual uninstallation, and at the end, terminates the original uninstaller EXE (at which point you get an exit code back), deletes it, then displays the "uninstall complete" message box (if it hasn't been suppressed with /SILENT or /VERYSILENT).

所以尽管 ewWaitUntilTerminated,您代码中的 Exec 实际上并不等待卸载完成。所以可能会出现卸载程序和安装程序同时运行的情况。这自然会导致安装损坏。

您必须等待子卸载程序完成才能解决您的问题。快速而肮脏的解决方案是查找名称包含 _iu 的任何进程。参见 Inno Setup Pascal Script to search for running process .

关于inno-setup - 在安装开始时卸载以前版本的产品会导致 Inno Setup 中的安装损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68113854/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com