Tôi đang sử dụng Inno Setup để tạo trình cài đặt.
Tôi muốn trình cài đặt tự động gỡ cài đặt phiên bản đã cài đặt trước đó, thay vì ghi đè nó. Làm thế nào tôi có thể làm điều đó?
Tôi đang sử dụng Inno Setup để tạo trình cài đặt.
Tôi muốn trình cài đặt tự động gỡ cài đặt phiên bản đã cài đặt trước đó, thay vì ghi đè nó. Làm thế nào tôi có thể làm điều đó?
Câu trả lời:
Bạn sẽ có thể đọc chuỗi gỡ cài đặt từ sổ đăng ký, với AppId (tức là giá trị bạn đã sử dụng AppID
trong [Setup]
-section). Nó có thể được tìm thấy dưới Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(có thể là một trong hai HKLM
hoặc HKCU
, vì vậy tốt nhất hãy kiểm tra cả hai) ở đâu {AppId}
nên được thay thế bằng giá trị thực mà bạn đã sử dụng. Tìm kiếm các giá trị UninstallString
hoặc QuietUninstallString
và sử dụng Exec
hàm để chạy nó từ InitializeSetup()
hàm sự kiện của bạn .
Cập nhật: đã loại bỏ giải pháp thay thế không hoạt động bằng cách sử dụng [Run]
mục nhập -section with {uninstallexe}
- cảm ơn tất cả những người bình luận đã chỉ ra điều này!
[Run]
giải pháp phần sẽ hoạt động, vì nó chạy quá muộn trong quá trình cài đặt. Từ hướng dẫn sử dụng Inno Setup: Phần [Run] là tùy chọn và chỉ định bất kỳ số lượng chương trình nào sẽ thực thi sau khi chương trình đã được cài đặt thành công, nhưng trước khi chương trình Setup hiển thị hộp thoại cuối cùng.
Tôi đã sử dụng những điều sau đây. Tôi không chắc đó là cách đơn giản nhất để làm điều đó nhưng nó hoạt động.
Điều này sử dụng {#emit SetupSetting("AppId")}
dựa vào Bộ xử lý Inno Setup. Nếu bạn không sử dụng, hãy cắt và dán ID ứng dụng của bạn vào trực tiếp.
[Code]
{ ///////////////////////////////////////////////////////////////////// }
function GetUninstallString(): String;
var
sUnInstPath: String;
sUnInstallString: String;
begin
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
Result := sUnInstallString;
end;
{ ///////////////////////////////////////////////////////////////////// }
function IsUpgrade(): Boolean;
begin
Result := (GetUninstallString() <> '');
end;
{ ///////////////////////////////////////////////////////////////////// }
function UnInstallOldVersion(): Integer;
var
sUnInstallString: String;
iResultCode: Integer;
begin
{ Return Values: }
{ 1 - uninstall string is empty }
{ 2 - error executing the UnInstallString }
{ 3 - successfully executed the UnInstallString }
{ default return value }
Result := 0;
{ get the uninstall string of the old app }
sUnInstallString := GetUninstallString();
if sUnInstallString <> '' then begin
sUnInstallString := RemoveQuotes(sUnInstallString);
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
Result := 3
else
Result := 2;
end else
Result := 1;
end;
{ ///////////////////////////////////////////////////////////////////// }
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep=ssInstall) then
begin
if (IsUpgrade()) then
begin
UnInstallOldVersion();
end;
end;
end;
Giải pháp thay thế
Xem thêm bài đăng trên blog này "Mẫu tập lệnh thiết lập đổi mới để so sánh phiên bản" tiến thêm một bước và đọc số phiên bản của bất kỳ phiên bản nào đã được cài đặt trước đó và so sánh số phiên bản đó với số phiên bản của gói cài đặt hiện tại.
... UserSIDs: TArrayOfString; I: Integer; ... if not RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString) then if isAdminLoggedOn() and RegGetSubkeyNames( HKEY_USERS, '', UserSIDs ) then for I := 0 to GetArrayLength( UserSIDs ) - 1 do begin if RegQueryStringValue( HKEY_USERS, UserSIDs[I] + '\' + sUnInstPath, 'UninstallString', sUnInstallString ) then break; end;
Nếu bạn "chỉ muốn xóa các biểu tượng cũ" (vì của bạn đã thay đổi / cập nhật), bạn có thể sử dụng điều này:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
Thao tác này được chạy "khi bắt đầu cài đặt" vì vậy về cơ bản loại bỏ các biểu tượng cũ và các biểu tượng mới của bạn sẽ vẫn được cài đặt ở đó sau khi hoàn tất.
Tôi chỉ làm điều này với mỗi lần cài đặt biểu tượng "trong trường hợp mọi thứ đã thay đổi" khôn ngoan (tất cả đều được cài đặt lại).
Khi sử dụng Inno Setup, không có lý do gì để gỡ cài đặt phiên bản trước trừ khi phiên bản đó được cài đặt bởi một chương trình cài đặt khác. Nếu không, các nâng cấp sẽ được xử lý tự động.
[InstallDelete]
phần để xóa các tệp / thư mục cũ. Các tệp mới sau đó sẽ được đặt vào đúng vị trí trong quá trình cài đặt.
Câu trả lời được cung cấp bởi Craig McQueen là hoàn toàn khả thi. Mặc dù, tôi sẽ thêm những nhận xét đó:
{#emit SetupSetting("AppId")}
mã này không làm việc cho tôi, vì vậy tôi chỉ cần thêm App ID của tôi.Vì vậy, liên quan đến mã của Craig McQueen, những thay đổi là:
InstallLocation
chìa khóa thay vì UninstallString
chìa khóa.DelTree
hàm thay vìExec(sUnInstallString, ...)
Đối với bất kỳ ai sử dụng GetUninstallString()
đề xuất ở trên để buộc gỡ cài đặt bên trong CurStepChanged()
và gặp sự cố bộ nhớ đệm đĩa, hãy xem bên dưới để biết giải pháp liên quan thực sự đợi một lúc sau khi gỡ cài đặt để xóa exe trình gỡ cài đặt!
Bạn có thể thực thi một trình gỡ cài đặt trong phần [mã]. Bạn phải tìm ra cách lấy đường dẫn đến trình gỡ cài đặt hiện có. Để đơn giản hơn khi cài đặt ứng dụng của mình, tôi thêm giá trị chuỗi đăng ký trỏ đến thư mục chứa trình gỡ cài đặt và chỉ thực thi trình gỡ cài đặt trong lệnh gọi lại InitializeWizard.
Hãy nhớ rằng tên của trình gỡ cài đặt Inno setup đều có dạng uninsnnn.exe, bạn cần phải tính đến điều đó trong mã của mình.
tôi đã chỉnh sửa mã @Crain Mc-Queen, tôi nghĩ mã này tốt hơn vì không cần phải sửa đổi trong dự án khác:
[Code]
function GetNumber(var temp: String): Integer;
var
part: String;
pos1: Integer;
begin
if Length(temp) = 0 then
begin
Result := -1;
Exit;
end;
pos1 := Pos('.', temp);
if (pos1 = 0) then
begin
Result := StrToInt(temp);
temp := '';
end
else
begin
part := Copy(temp, 1, pos1 - 1);
temp := Copy(temp, pos1 + 1, Length(temp));
Result := StrToInt(part);
end;
end;
function CompareInner(var temp1, temp2: String): Integer;
var
num1, num2: Integer;
begin
num1 := GetNumber(temp1);
num2 := GetNumber(temp2);
if (num1 = -1) or (num2 = -1) then
begin
Result := 0;
Exit;
end;
if (num1 > num2) then
begin
Result := 1;
end
else if (num1 < num2) then
begin
Result := -1;
end
else
begin
Result := CompareInner(temp1, temp2);
end;
end;
function CompareVersion(str1, str2: String): Integer;
var
temp1, temp2: String;
begin
temp1 := str1;
temp2 := str2;
Result := CompareInner(temp1, temp2);
end;
function InitializeSetup(): Boolean;
var
oldVersion: String;
uninstaller: String;
ErrorCode: Integer;
vCurID :String;
vCurAppName :String;
begin
vCurID:= '{#SetupSetting("AppId")}';
vCurAppName:= '{#SetupSetting("AppName")}';
//remove first "{" of ID
vCurID:= Copy(vCurID, 2, Length(vCurID) - 1);
//
if RegKeyExists(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1') then
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1',
'DisplayVersion', oldVersion);
if (CompareVersion(oldVersion, '{#SetupSetting("AppVersion")}') < 0) then
begin
if MsgBox('Version ' + oldVersion + ' of ' + vCurAppName + ' is already installed. Continue to use this old version?',
mbConfirmation, MB_YESNO) = IDYES then
begin
Result := False;
end
else
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1',
'UninstallString', uninstaller);
ShellExec('runas', uninstaller, '/SILENT', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
Result := True;
end;
end
else
begin
MsgBox('Version ' + oldVersion + ' of ' + vCurAppName + ' is already installed. This installer will exit.',
mbInformation, MB_OK);
Result := False;
end;
end
else
begin
Result := True;
end;
end;
Chắc chắn là tôi đang thiếu gì đó. Các tệp mới được sao chép vào thư mục đích trước khi việc xóa cài đặt cũ xảy ra. Sau đó, trình gỡ cài đặt sẽ xóa chúng và xóa thư mục.
Không sử dụng phần [Chạy] mà sử dụng phần [UninstallRun]. Infact, chương trình trong [Run] được thực thi sau khi cài đặt, khiến chương trình của bạn phải gỡ cài đặt ngay sau khi cài đặt: - | Thay vào đó, phần [UninstallRun] được đánh giá trước khi cài đặt.
[UninstallRun]
không phải là một giải pháp cho câu hỏi.
Theo liên kết này: http://news.jrsoftware.org/news/innosetup/msg55323.html
Trong hàm InitializeSetup (), bạn có thể gọi "MSIEXEC / x {your program ID}" sau khi người dùng nhắc gỡ cài đặt phiên bản cũ cũ