Saya menggunakan Pengaturan Inno untuk membuat penginstal.
Saya ingin penginstal mencopot pemasangan versi sebelumnya secara otomatis, alih-alih menimpanya. Bagaimana saya bisa melakukan itu?
Saya menggunakan Pengaturan Inno untuk membuat penginstal.
Saya ingin penginstal mencopot pemasangan versi sebelumnya secara otomatis, alih-alih menimpanya. Bagaimana saya bisa melakukan itu?
Jawaban:
Anda harus bisa membaca uninstall string dari registri, mengingat AppId (yaitu nilai yang Anda digunakan untuk AppID
di [Setup]
-bagian). Ini dapat ditemukan di bawah Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(bisa jadi salah satu HKLM
atau HKCU
, jadi sebaiknya periksa keduanya) di mana {AppId}
harus diganti dengan nilai sebenarnya yang Anda gunakan. Cari UninstallString
atau QuietUninstallString
nilai dan gunakan Exec
fungsi untuk menjalankannya dari InitializeSetup()
fungsi acara Anda .
Pembaruan: hapus solusi alternatif yang tidak berfungsi menggunakan [Run]
entri -bagian dengan {uninstallexe}
- terima kasih kepada semua pemberi komentar yang menunjukkan hal ini!
[Run]
solusi bagian akan berfungsi, karena terlambat dalam proses instalasi. Dari panduan Inno Setup: Bagian [Run] adalah opsional, dan menentukan sejumlah program yang akan dijalankan setelah program berhasil diinstal, tetapi sebelum program Setup menampilkan dialog terakhir.
Saya telah menggunakan yang berikut ini. Saya tidak yakin ini cara termudah untuk melakukannya tetapi berhasil.
Penggunaan ini {#emit SetupSetting("AppId")}
bergantung pada Inno Setup Preprocessor. Jika Anda tidak menggunakannya, potong dan tempel ID Aplikasi Anda secara langsung.
[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;
Alternatif
Lihat juga entri blog ini "Contoh Skrip Pengaturan Inno untuk Perbandingan Versi" yang melangkah lebih jauh, dan membaca nomor versi dari versi yang diinstal sebelumnya, dan membandingkan nomor versi itu dengan nomor versi paket penginstalan saat ini.
... 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;
Jika Anda "hanya ingin menghapus ikon lama" (karena milik Anda telah diubah / diperbarui) Anda dapat menggunakan ini:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
Ini dijalankan "pada awal penginstalan" jadi pada dasarnya menghapus ikon lama, dan yang baru akan tetap dipasang di sana setelah ini selesai.
Saya hanya melakukan ini dengan setiap penginstalan ikon "jika ada yang berubah" (semuanya tetap diinstal ulang).
Saat menggunakan Inno Setup, tidak ada alasan untuk menghapus versi sebelumnya kecuali versi tersebut diinstal oleh program penginstal yang berbeda. Jika tidak, peningkatan akan ditangani secara otomatis.
[InstallDelete]
bagian untuk menghapus file / direktori lama. File baru kemudian akan ditempatkan di lokasi yang benar selama instalasi.
Jawaban yang diberikan oleh Craig McQueen benar-benar layak. Meskipun, saya akan menambahkan komentar itu:
{#emit SetupSetting("AppId")}
kode tidak bekerja untuk saya, jadi saya hanya menambahkan saya App ID.Jadi, terkait kode Craig McQueen, perubahannya adalah:
InstallLocation
kunci, bukan UninstallString
kunci.DelTree
fungsi alih-alihExec(sUnInstallString, ...)
Bagi siapa pun yang menggunakan yang GetUninstallString()
disarankan di atas untuk memaksa uninstall di dalam CurStepChanged()
dan memiliki masalah cache disk, lihat di bawah untuk solusi terkait yang benar-benar menunggu beberapa saat setelah unistallation untuk uninstaller exe untuk dihapus!
Anda dapat menjalankan uninstaller di bagian [code]. Anda harus mencari cara untuk mendapatkan path ke uninstaller yang ada. Untuk mempermudah ketika saya menginstal aplikasi saya, saya menambahkan nilai string registri yang mengarah ke folder yang berisi uninstaller, dan hanya menjalankan uninstaller di callback InitializeWizard.
Perlu diingat bahwa nama uninstaller penyiapan Inno semuanya dalam bentuk uninsnnn.exe, Anda harus memperhitungkannya dalam kode Anda.
Saya mendapat kode @Crain Mc-Queen diedit, saya pikir kode ini lebih baik karena tidak perlu dimodifikasi di proyek yang berbeda:
[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;
Saya pasti melewatkan sesuatu. File baru disalin ke direktori target sebelum penghapusan instalasi lama terjadi. Kemudian datang uninstaller menghapusnya dan menghapus direktori.
Jangan gunakan bagian [Run], tetapi [UninstallRun]. Sebenarnya, program di bawah [Run] dijalankan setelah penginstalan, menyebabkan penginstalan program Anda segera setelah penginstalan: - | Sebaliknya, bagian [UninstallRun] dievaluasi sebelum instalasi.
[UninstallRun]
bukanlah solusi untuk pertanyaan tersebut.
Ikuti tautan ini: http://news.jrsoftware.org/news/innosetup/msg55323.html
Dalam fungsi InitializeSetup (), Anda dapat memanggil "MSIEXEC / x {ID program Anda}" setelah pengguna meminta untuk menghapus versi lama