Inno Setup:以前にインストールしたバージョンを自動的にアンインストールする方法は?


88

InnoSetupを使用してインストーラーを作成しています。

インストーラーに、以前にインストールしたバージョンを上書きするのではなく、自動的にアンインストールしてもらいたい。どうやってやるの?


2
mlaanが言ったように、Inno以外のバージョンからアップグレードする場合を除いて、通常はInnoベースのセットアップでこれを行う必要はないことに注意してください。
Deanna 2012

7
ディアナ:それは場合によって異なります。フォルダ内のすべてを読み取る自動プラグインシステムを備えた一部のプログラムでは、新しいバージョンをインストールするときに古いファイルを削除することが絶対に必要です。通常、アンインストールを実行するのが最もクリーンな方法です。
Nyerguds 2013

1
@Nyergudsしかし、InnoSetupは、インストールを開始する前に特定のファイル/フォルダーを削除するオプション( "InstallDelete"フラグ)を備えているため、古いバージョンを最初にアンインストールする必要はありません。
NickG 2015

3
@NickG:繰り返しますが、場合によって異なります。それは理想的な状況です、はい、そしてはるかに好ましい状況ですが、実際には、理想的ではない状況がかなりたくさんあります。そのような例の1つは、多くの可能なターゲットバージョンで登録されたdllファイルです。
Nyerguds 2015

回答:


27

あなたはAPPID(あなたが使用すなわち値与えられ、レジストリからアンインストール文字列を読むことができるはずAppID[Setup]-section)。これは、下見つけることができるSoftware\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\(いずれかであるHKLMか、HKCUその両方をチェックするので、最高の)どこ{AppId}に使用した実際の値に置換する必要があります。UninstallStringまたはのQuietUninstallString値を探し、Exec関数を使用してInitializeSetup()イベント関数から実行します。

更新:これを指摘したすべてのコメント提供者に感謝し[Run]{uninstallexe}-セクションエントリを使用して機能しない代替ソリューションを削除しました!


+1ですが、スクリプトを使用して古いアンインストーラー名を読み取るようにしてください。そうしないと、ユーザーが別のパスを入力した場合に機能しなくなります。
mghie 2010年

3
[Run]セクションソリューションは、インストールプロセスの実行が遅すぎるため、機能しないと思います。Inno Setupマニュアルから:[Run]セクションはオプションであり、プログラムが正常にインストールされた後、セットアッププログラムが最後のダイアログを表示する前に実行するプログラムの数を指定します。
Craig McQueen

この投稿を編集して[実行]部分を削除してください。機能しません。ただし、2番目の部分は機能します。ありがとう:
SauliusŽemaitaitis2011

11
1つの警告:64ビットWindows上の32ビットアプリケーションの場合、パスは `Software \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall \ {AppId}`の場合があります
Adrian Cox

4
@Adrian:それは物理層でも当てはまるかもしれませんが、少なくともsetup.exe自体が32ビットプロセスである場合は、Innoで使用されるWinAPI呼び出しがすでにそれを処理していると思います。
オリバーギーゼン2013

112

私は以下を使用しました。それが最も簡単な方法かどうかはわかりませんが、機能します。

これは{#emit SetupSetting("AppId")}、Inno SetupPreprocessorに依存するものを使用します。それを使用しない場合は、アプリIDを直接カットアンドペーストしてください。

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

代替案

このブログ投稿「バージョン比較用のInnoSetupスクリプトサンプル」も参照してくださいこれはさらに一歩進んで、以前にインストールされたバージョンのバージョン番号を読み取り、そのバージョン番号を現在のインストールパッケージのバージョン番号と比較します。


3
私のブログ投稿を参照していただきありがとうございます。その投稿の完全なサンプルは、code.google.com / p / lextudio / source / browser / trunk / trunk / setup /…
Lex Li

ここで欠落しているのは、HKLMではなくHKCUでのアンインストールエントリのサポートだけです。
オリバーギーゼン2011

1
ユーザーがアプリケーションをインストールした場合、特に現在のユーザーが管理者である場合は、アンインストール機能を追加することをお勧めしますか? ... 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;
テランス2012年

2
素晴らしい解決策、うまく機能します。ただし、インストール中に「[ソフトウェア名]のアンインストール」というウィンドウが開きます。このウィンドウがポップするのを防ぐことは可能ですか?私のソフトウェアのインストール、アンインストール・ウィンドウの前にウィンドウが閉じをインストールすることを非常に高速であり、それは...奇妙に見えるので
アンドレ・Santaló

4
@AndréSantaló/ SILENTの代わりに/ VERYSILENTを使用
Gautam Jain

7

「古いアイコンを削除したいだけ」の場合(アイコンが変更/更新されたため)、次のように使用できます。

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

これは「インストールの開始時に」実行されるため、基本的に古いアイコンが削除され、これが完全に完了した後も新しいアイコンがインストールされます。

これは、「何かが変更された場合に備えて」アイコンごとにインストールするたびに行います(とにかくすべてが再インストールされます)。


アイコンを更新している場合は、アイコンを上書きしてください。それらを削除する必要はありません。それらを削除したい場合は、このオプションを使用できます。それは正しい方法です。とにかく、あなたが話していた人(mlaan、Martijn Laan)はInno Setupの作者であり、彼は彼が話していることを知っていると思います:-)
TLama 2014年

1
ええ、これが必要なのは、アイコンの名前を変更したり移動したりするときです。たとえば、v5に「run」という名前のアイコンがあり、ユーザーがv5をインストールしてからv6をインストールすると、v6の名前が「runbasic」に変更された場合、本当に1つ必要なときに2つのアイコンが表示されます(「runbasic」)。したがって、このトリックが必要になります(innosetupのデフォルトの動作を古いアイコンを削除してこれを必要としないように変更するための@mlaan +1 ...)
rogerdpack 2014

6

Inno Setupを使用する場合、そのバージョンが別のインストーラープログラムによってインストールされていない限り、以前のバージョンをアンインストールする理由はありません。それ以外の場合、アップグレードは自動的に処理されます。


6
プログラムの構造が変更されたため、古いバージョンをアンインストールする必要があります。
Quan Mai 2010

11
いいえ、そうではありません。スクリプトにエントリを追加して、更新中の構造変更を処理できます。
mlaan 2010年

@mlaanそしてそれらはどのようなエントリでしょうか?
mythofechelon 2013

1
[InstallDelete]セクションを使用して、古いファイル/ディレクトリを削除するだけです。新しいファイルは、インストール中に正しい場所に配置されます。
daiscog 2014

2
DLL名にバージョン番号が含まれているDevExpressなどのサードパーティライブラリをアップグレードする場合(以前にインストールされた15.1や現在は15.2など)、古いバージョンを削除する必要があります。私見それは正当な理由です。
トーマスウェラー2016

2

クレイグマックイーンによって提供された答えは完全に実行可能です。しかし、私はそれらのコメントを追加します:

  • {#emit SetupSetting("AppId")}私はちょうど私のApp IDを追加するように、コードは、私のために動作しません。
  • アンインストーラーによって削除されたAppData /フォルダーにINI構成ファイルが保存されており、新しいバージョンをインストールするときにそれを消去したくないため、アンインストールプログラムを実行したくありませんでした。そこで、Craig McQueenから提供されたコードを少し変更して、プログラムがインストールされているディレクトリを、そのパスを取得した後に削除しました。

したがって、Craig McQueenのコードに関して、変更点は次のとおりです。

  • InstallLocationキーの代わりにキーを取得しますUninstallString
  • DelTree代わりに関数を使用してくださいExec(sUnInstallString, ...)

1

GetUninstallString()上記の提案を使用して内部のアンインストールを強制し、CurStepChanged()ディスクキャッシュの問題がある場合は、アンインストーラexeが削除されるのをアンインストール後に実際にしばらく待機する関連ソリューションについて、以下を参照してください。

inno-setupでのディスクキャッシュの問題?


0

[コード]セクションでアンインストーラーを実行できます。既存のアンインストーラーへのパスを取得する方法を理解する必要があります。アプリをインストールするときに簡単にするために、アンインストーラーを含むフォルダーを指すレジストリ文字列値を追加し、InitializeWizardコールバックでアンインストーラーを実行するだけです。

Inno Setupアンインストーラー名はすべてuninsnnn.exeの形式であることに注意してください。コードでは、それを考慮する必要があります。


0

@Crain Mc-Queenコードを編集しました。別のプロジェクトで変更する必要がないため、このコードの方が優れていると思います。

[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

私は何かが足りないに違いない。新しい古いインストールの削除が発生する前に、ファイルがターゲットディレクトリにコピーされます。 次に、アンインストーラーがそれらを削除し、ディレクトリを削除します。


2
何を言おうとしているのかわかりませんが、ファイルをコピーするだけではないことに注意してください。製品をインストールしたと想像してください。次のリリースでは、ファイル構造が完全に変更され、元のファイルの多くが削除され、新しいファイルの名前が異なり、異なるディレクトリに保存されます。アップグレードする最も簡単な方法は何でしょうか?それは以前のバージョンをアンインストールすることではないでしょうか?
TLama 2014

INNOを使用してドライバーとそれに付随するアプリケーションをインストールします。当然、実際のドライバのインストール/削除はINNOによって直接行われるわけではありません。むしろ、INNOはドライバーインストーラー/リムーバーアプリをコピーして実行します。アンインストールも同様に行われます。INNOはドライバーリムーバーを実行してから、ファイルを削除します。
Shaul 2014

-8

[Run]セクションではなく、[UninstallRun]を使用してください。実際、[実行]の下のプログラムはインストールに実行されるため、インストール直後にプログラムがアンインストールされます:-| 代わりに、[UninstallRun]セクションはインストールに評価されます。


3
[UninstallRun]質問の解決策ではありません。
Craig McQueen 2011

-8

このリンクをたどってください:http//news.jrsoftware.org/news/innosetup/msg55323.html

InitializeSetup()関数では、ユーザープロンプトの後に「MSIEXEC / x {プログラムID}」を呼び出して、古い古いバージョンをアンインストールできます。


5
MSIEXECは、MSIパッケージに対してのみ機能します。これは、InnoSetupには適用されません。
Lex Li
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.