9

ユーザーによって変更された (テキスト) ファイル (== InnoSetup によってインストールされたものとは異なる) をアンインストールしないように InnoSetup に指示する方法は?

あるいはもっと難しいかもしれません: 既存のバージョンの上に新しいバージョンをインストールする場合、InnoSetup は変更されたファイルを上書きするかどうかをユーザーに尋ねる必要がありますが、純粋なアンインストールでは、確認せずにアンインストールする必要があります。

4

2 に答える 2

6

私は最近、同様の問題を抱えていました。これは、テキスト ファイル (プロファイル) が前回のインストール実行時にインストールされたものから変更されているかどうかを検出するための私のソリューションでした。

ISPP (Inno Setup Pre-Processor) を使用して、コンパイル時にテキスト ファイルとそのハッシュのリストを作成します。

[Files]
; ...
#define FindHandle
#define FindResult
#define Mask "Profiles\*.ini"
#sub ProcessFoundFile
   #define FileName "Profiles\" + FindGetFileName(FindHandle)
   #define FileMd5 GetMd5OfFile(FileName)
   Source: {#FileName}; DestDir: {app}\Profiles; Components: profiles; \
      Check: ProfileCheck('{#FileMd5}'); AfterInstall: ProfileAfterInstall('{#FileMd5}');
#endsub
#for {FindHandle = FindResult = FindFirst(Mask, 0); FindResult; FindResult = FindNext(FindHandle)} ProcessFoundFile

「コード」セクションの上部で、いくつかの便利なものを定義します。

[Code]
var
   PreviousDataCache : tStringList;

function InitializeSetup() : boolean;
begin
   // Initialize global variable
   PreviousDataCache := tStringList.Create();
   result := TRUE;
end;

function BoolToStr( Value : boolean ) : string;
begin
   if ( not Value ) then
      result := 'false'
   else
      result := 'true';
end;

「Check」イベント ハンドラーで、以前のインストールと現在のファイルのハッシュを比較します。

function ProfileCheck( FileMd5 : string ) : boolean;
var
   TargetFileName, TargetFileMd5, PreviousFileMd5 : string;
   r : integer;
begin
   result := FALSE;
   TargetFileName := ExpandConstant(CurrentFileName());
   Log('Running check procedure for file: ' + TargetFileName);

   if not FileExists(TargetFileName) then
   begin
      Log('Check result: Target file does not exist yet.');
      result := TRUE;
      exit;
   end;

   try
      TargetFileMd5 := GetMd5OfFile(TargetFileName);
   except
      TargetFileMd5 := '(error)';
   end;
   if ( CompareText(TargetFileMd5, FileMd5) = 0 ) then
   begin
      Log('Check result: Target matches file from setup.');
      result := TRUE;
      exit;
   end;

   PreviousFileMd5 := GetPreviousData(ExtractFileName(TargetFileName), '');
   if ( PreviousFileMd5 = '' ) then
   begin
      r := MsgBox(TargetFileName + #10#10 + 
         'The existing file is different from the one Setup is trying to install. ' + 
         'It is recommended that you keep the existing file.' + #10#10 +
         'Do you want to keep the existing file?', mbConfirmation, MB_YESNO);
      result := (r = idNo);
      Log('Check result: ' + BoolToStr(result));
   end
   else if ( CompareText(PreviousFileMd5, TargetFileMd5) <> 0 ) then
   begin
      r := MsgBox(TargetFileName + #10#10 + 
         'The existing file has been modified since the last run of Setup. ' +
         'It is recommended that you keep the existing file.' + #10#10 +
         'Do you want to keep the existing file?', mbConfirmation, MB_YESNO);
      result := (r = idNo);
      Log('Check result: ' + BoolToStr(result));
   end
   else
   begin
      Log('Check result: Existing target has no local modifications.');
      result := TRUE;
   end;
end;

「AfterInstall」イベント ハンドラーで、後でレジストリに格納するファイル ハッシュをマークします。私のテストでは、ファイルの移動が失敗した場合でもイベントがトリガーされたため (ターゲット ファイルは読み取り専用です)、ハッシュを再度比較して、ファイルの移動が成功したかどうかを確認します。

procedure ProfileAfterInstall( FileMd5 : string );
var
   TargetFileName, TargetFileMd5 : string;
begin
   TargetFileName := ExpandConstant(CurrentFileName());
   try
      TargetFileMd5 := GetMd5OfFile(TargetFileName);
   except
      TargetFileMd5 := '(error)';
   end;
   if ( CompareText(TargetFileMd5, FileMd5) = 0 ) then
   begin
      Log('Storing hash of installed file: ' + TargetFileName);
      PreviousDataCache.Add(ExtractFileName(TargetFileName) + '=' + FileMd5);
   end;
end;

procedure RegisterPreviousData( PreviousDataKey : integer );
var
   Name, Value : string;
   i, n : integer;
begin
   for i := 0 to PreviousDataCache.Count-1 do
   begin
      Value := PreviousDataCache.Strings[i];
      n := Pos('=', Value);
      if ( n > 0 ) then
      begin
         Name := Copy(Value, 1, n-1);
         Value := Copy(Value, n+1, MaxInt);
         SetPreviousData(PreviousDataKey, Name, Value);
      end;
   end;
end;
于 2012-05-29T08:02:59.947 に答える
1

Innoはこのチェックをネイティブに行うことはできません。

インストール中に変更されたファイルを置き換えないようにするには、カスタム[Code]を使用してチェックサムを実行し、事前に計算された、または前回のインストールで保存された既知の適切な値と比較する必要があります。

アンインストール中にそれらが削除されないようにするには、そのファイルに対してInno自身のアンインストールを無効にし、削除する前に同じチェックサムをチェックする必要があります[Code]

この状況をより適切に処理し、アプリケーションガイドラインに正しく準拠するために、ユーザーがセットアップの外部で編集できるファイルを保持することをお勧めします。

于 2012-05-22T15:04:27.390 に答える