Inno Setup: Önceki kurulu sürüm otomatik olarak nasıl kaldırılır?


90

Bir yükleyici oluşturmak için Inno Setup kullanıyorum.

Yükleyicinin, üzerine yazmak yerine önceki yüklü sürümü otomatik olarak kaldırmasını istiyorum. Bunu nasıl yapabilirim?


2
Mlaan'ın dediği gibi, Inno olmayan bir sürümden yükseltme yapmadığınız sürece, normalde bunu Inno tabanlı bir kurulumla yapmaya gerek olmadığını unutmayın.
Deanna

7
Deanna: duruma göre değişir. Bir klasördeki her şeyi okuyan otomatik eklenti sistemlerine sahip bazı programlar için, yeni bir sürüm yüklerken eski dosyaların kaldırılması mutlak bir zorunluluktur ve bunu yapmanın en temiz yolu genellikle kaldırmayı çalıştırmaktır.
Nyerguds

1
@Nyerguds Ancak InnoSetup, kurulum başlamadan önce belirli dosyaları / klasörleri silme seçeneğine sahip olarak ("InstallDelete" bayrağı), böylece ilk önce eski sürümü kaldırmanız gerekmemesi için bunu karşılar.
NickG

3
@NickG: Yine duruma göre değişir. İdeal durum bu olurdu, evet ve şimdiye kadar tercih edilen durumdur, ancak gerçekte pek çok ideal olmayan durum vardır. Böyle bir örnek, birçok olası hedef sürümde kayıtlı dll dosyalarıdır.
Nyerguds

Yanıtlar:


28

Sen AppId (eğer kullanılan yani değer verilen, kayıt defterinden kaldırma dize okumak mümkün olmalıdır AppIDiçinde [Setup]-bölümü). Altında bulunabilir Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\(biri HKLMveya olabilir HKCU, bu nedenle en iyisi her ikisini de kontrol edin), nerede {AppId}kullandığınız gerçek değerle değiştirilmelidir. UninstallStringVeya QuietUninstallStringdeğerlerini arayın ve olay işlevinizden Execçalıştırmak için işlevi kullanın InitializeSetup().

Güncelleme: çalışmayan alternatif çözüm ile bir [Run]bölüm girişi kullanılarak kaldırıldı {uninstallexe}- buna dikkat çeken tüm yorumcular sayesinde!


+1, ancak eski kaldırıcı adını okumak için kesinlikle komut dosyası kullanın, çünkü aksi takdirde kullanıcı tarafından farklı bir yol girilirse çalışmaz.
mghie

3
[Run]Kurulum sürecinde çok geç çalıştığı için bölüm çözümünün işe yarayacağını düşünmüyorum . Inno Kurulum kılavuzundan: [Çalıştır] bölümü isteğe bağlıdır ve program başarıyla yüklendikten sonra, ancak Kurulum programı son iletişim kutusunu görüntülemeden önce yürütülecek herhangi bir sayıda programı belirtir.
Craig McQueen

Lütfen bu gönderiyi düzenleyin ve [Çalıştır] bölümünü kaldırın, çalışmaz. İkinci bölüm yine de çalışıyor. Teşekkür ederim :-)
Saulius Žemaitaitis

11
Bir uyarı: 64 bit Windows'ta 32 bit uygulama için yol şu olabilir: `Software \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall \ {AppId}`
Adrian Cox

4
@Adrian: Bu fiziksel katmanda doğru olsa da, Inno tarafından kullanılan WinAPI çağrılarının zaten bunu halledeceğini düşünüyorum - en azından setup.exe'nin kendisi 32bit bir işlemse.
Oliver Giesen

114

Aşağıdakileri kullandım. Bunu yapmanın en basit yolu olduğundan emin değilim ama işe yarıyor.

Bu {#emit SetupSetting("AppId")}, Inno Kurulum Ön İşlemcisine dayanan kullanır . Bunu kullanmazsanız, Uygulama Kimliğinizi doğrudan kesip yapıştırın.

[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;

Alternatifler

Ayrıca , bir adım daha ileri giden ve önceden yüklenmiş herhangi bir sürümün sürüm numarasını okuyan ve bu sürüm numarasını mevcut yükleme paketinin sürüm numarasıyla karşılaştıran "Sürüm Karşılaştırması için Inno Kurulum Komut Dosyası Örneği" blog gönderisine bakın .


3
blog yazıma başvurduğunuz için teşekkürler. Bu gönderinin tam örneğini burada bulabilirsiniz, code.google.com/p/lextudio/source/browse/trunk/trunk/setup/…
Lex Li

Burada eksik olan tek şey, HKLM yerine HKCU altında bir Kaldırma girişi desteğidir.
Oliver Giesen

1
Uygulamayı herhangi bir kullanıcı yüklediyse, özellikle de mevcut kullanıcı bir Yönetici ise, kaldırma özelliğini eklemeyi önerebilir miyim? ... 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;
Terrance

2
Harika çözüm, iyi çalışıyor. Ancak, kurulum sırasında "[Yazılım adı] kaldırılıyor" şeklinde bir pencere açar. Bu pencerenin açılmasını önlemek mümkün mü? Yazılımımın kurulumu o kadar hızlı ki, yükleme penceresi kaldırma penceresinden önce kapanıyor ve garip görünüyor ...
André Santaló

4
@ AndréSantaló Kullanın / SILENT yerine VERYSILENT
Gautam Jain

7

"Yalnızca eski simgeleri kaldırmak istiyorsanız" (sizinki değiştiği / güncellendiği için) şunu kullanabilirsiniz:

; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;

Bu, "kurulumun başında" çalıştırılır, bu nedenle temelde eski simgeleri kaldırır ve yenileriniz, bu tamamen yapıldıktan sonra da oraya kurulur.

Bunu her kurulumda "herhangi bir şeyin değişmesi durumunda" ikon bilge olarak yapıyorum (yine de hepsi yeniden yüklenir).


Simgeleriniz için güncellemeniz varsa, üzerine yazmalarına izin verin. Bunları çıkarmaya gerek yok. Peki, onları kaldırmak istiyorsanız, bu seçeneği kullanabilirsiniz. Bu doğru yoldur. Her neyse, konuştuğunuz adam (mlaan, Martijn Laan) Inno Kurulumunun yazarı ve sanırım neden bahsettiğini biliyor :-)
TLama

1
Evet, buna ihtiyacınız olan bir simgeyi yeniden adlandırmak veya taşımak istediğinizde. Örneğin, v5'te "çalıştır" adında bir tane varsa ve v6 bunu "temel çalıştır" olarak yeniden adlandırmışsa, bir kullanıcı v5 ve ardından v6'yı yüklerse, gerçekten 1 istediğinizde ("temel çalıştır") 2 simge ile sonuçlanır. Gerekli olmak kadar bu hile uçları Yani (varsayılan davranışı innosetup değişen için 1 @mlaan eski simgeleri kaldırmak olabilir ve almamak için bu ... gerekir)
rogerdpack

6

Inno Setup'ı kullanırken, bu sürüm farklı bir yükleme programı tarafından yüklenmedikçe önceki bir sürümü kaldırmanız için hiçbir neden yoktur. Aksi takdirde yükseltmeler otomatik olarak yapılır.


7
Programımızın yapısında bir değişiklik olduğu için eski sürümün kaldırılması gerekiyor.
Quan Mai

11
Hayır yok, güncelleme sırasında yapı değişikliğini işlemek için komut dosyanıza girişler ekleyebilirsiniz.
mlaan

@mlaan Peki bunlar hangi girişler olurdu?
mythofechelon 02

1
[InstallDelete]Eski dosyaları / dizinleri kaldırmak için bir bölüm kullanabilirsiniz . Yeni dosyalar daha sonra kurulum sırasında doğru yerlere yerleştirilecektir.
daiscog

2
DevExpress gibi DLL adlarında sürüm numaraları olan bir üçüncü taraf kitaplığını yükseltirseniz (daha önce yüklenmiş 15.1 ve şimdi 15.2 gibi), eski sürümü kaldırmak istersiniz. IMHO bu iyi bir neden.
Thomas Weller

2

Craig McQueen tarafından sağlanan cevap tamamen geçerli. Yine de şu yorumları eklerdim:

  • {#emit SetupSetting("AppId")}Sadece benim Uygulama Kimliğini ekleyin böylece kod benim için çalışmaz.
  • Kaldırma programımı yürütmek istemedim çünkü AppData / klasöründe depolanan ve kaldırıcı tarafından kaldırılan bir INI yapılandırma dosyam var ve yeni bir sürüm yüklerken bu dosyanın silinmesini istemiyorum. Bu yüzden, yolunu aldıktan sonra programın kurulu olduğu dizini kaldırmak için Craig McQueen tarafından sağlanan kodu biraz değiştirdim.

Yani, Craig McQueen'in koduyla ilgili değişiklikler şunlardır:

  • Al InstallLocationyerine anahtarını UninstallStringtuşu.
  • Yerine DelTreeişlevi kullanınExec(sUnInstallString, ...)

1

GetUninstallString()Kaldırma işlemini zorlamak için yukarıda önerilenleri kullanan CurStepChanged()ve disk önbelleğe alma sorunları yaşayan herkes için kaldırıcı exe'nin silinmesi için kaldırıldıktan sonra gerçekten bir süre bekleyen ilgili bir çözüm için aşağıya bakın!

İnno-setup ile disk önbelleğe alma sorunu mu yaşıyorsunuz?


0

[Kod] bölümünde bir kaldırıcı çalıştırabilirsiniz. Mevcut kaldırıcıya giden yolu nasıl bulacağınızı bulmanız gerekir. Basit olması için, uygulamalarımı yüklediğimde, kaldırıcıyı içeren klasöre işaret eden bir kayıt defteri dizesi değeri ekliyorum ve kaldırıcıyı yalnızca InitializeWizard geri aramasında çalıştırıyorum.

Inno kurulum kaldırıcı adlarının tümünün uninsnnn.exe biçiminde olduğunu unutmayın, bunu kodunuzda hesaba katmanız gerekir.


0

@ Crain Mc-Queen kodunu düzenledim, bu kodun daha iyi olduğunu düşünüyorum çünkü farklı bir projede değiştirilmeye gerek yok:

[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;

-1

Bir şey kaçırıyor olmalıyım. Yeni eski tesisatın kaldırılması oluşmadan önce dosyaları hedef dizine kopyalanır. Ardından kaldırıcı gelir onları siler ve dizini kaldırır.


2
Ne söylemeye çalıştığından emin değilim, ancak bunun her zaman sadece dosyaları kopyalamakla ilgili olmadığını unutmayın. Bir sonraki sürümde tamamen değiştirilmiş dosya yapısıyla gelen, orijinal dosyaların çoğunun kaldırıldığı ve yeni dosyaların farklı adlara sahip olduğu ve farklı dizinlerde depolandığı ürününüzü kurduğunuzu hayal edin. Yükseltmenin en kolay yolu ne olabilir? Bu, önceki sürümü kaldırmak olmaz mıydı?
tlama

Bir sürücü ve beraberindeki uygulamaları yüklemek için INNO kullanıyorum. Doğal olarak, gerçek sürücü Kurulum / Kaldırma işlemi doğrudan INNO tarafından yapılmaz. Bunun yerine, INNO bir sürücü yükleyici / kaldırıcı uygulamasını kopyalayıp çalıştırır. Kaldırma işlemi benzer şekilde yapılır: INNO, sürücü kaldırıcısını çalıştırır, ardından dosyaları siler.
Shaul

-8

[Çalıştır] bölümünü değil, [UninstallRun] bölümünü kullanın. Aslında, [Çalıştır] altındaki program kurulumdan sonra yürütülür ve programınızın kurulumdan hemen sonra kaldırılmasına neden olur: - | Bunun yerine, kurulumdan önce [UninstallRun] bölümü değerlendirilir .


3
[UninstallRun]soru için bir çözüm değil.
Craig McQueen

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.