アンインストール ファイル (JPEG、DLL、PNG...) を .xml ファイル内に残す方法はありunins000.exe
ますか? もしそうなら、コードを見せてください。
2 に答える
これを行う方法はありません。Inno アンインストール エンジンには、埋め込みファイルを含めることはできません。
しかし一方で、そうする必要は特にありません。必要なファイルをインストールするだけで済みます (物事を整理したい場合は、アプリ フォルダーのサブフォルダーにインストールします)。
セットアップ ファイルがインストーラーに組み込まれている唯一の本当の理由は、ダウンロードを容易にするためです。アンインストーラーにはその言い訳はありません。
Inno Setup には、埋め込みファイルのネイティブ サポートはありません。
ただし、創造性を働かせれば、ファイルを (何らかの定数の形で) コードに埋め込むことができます。
残念ながら、Unicode Inno Setup は、バイナリ データを扱う場合、すべてを UTF-8 に変換しようとする傾向があるため、かなり制限されています。しかし、何度も試行した後、いくつかの機能するコードになりました ( Inno Setup プリプロセッサから呼び出された PowerShell コードを使用して)。
このコードを[Code]
セクションの先頭に追加します。
function CryptStringToBinary(
sz: string; cch: LongWord; flags: LongWord; binary: string; var size: LongWord;
skip: LongWord; flagsused: LongWord): Integer;
external 'CryptStringToBinaryW@crypt32.dll stdcall';
const
CRYPT_STRING_HEX = $04;
procedure WriteBinaryStringToStream(S: string; Stream: TStream);
var
Buffer: string;
Size: LongWord;
begin
SetLength(Buffer, (Length(S) div 4) + 1);
Size := Length(S) div 2;
if (CryptStringToBinary(S, Length(S), CRYPT_STRING_HEX, Buffer, Size, 0, 0) = 0) or
(Size <> Length(S) div 2) then
begin
RaiseException('Error decoding binary string');
end;
Stream.WriteBuffer(Buffer, Size);
end;
function StreamFromBinaryString(S: string): TStream;
begin
Result := TStringStream.Create('');
WriteBinaryStringToStream(S, Result);
Result.Position := 0;
end;
procedure LoadBitmapFromBinaryString(Bitmap: TBitmap; S: string);
var
Stream: TStream;
begin
Stream := StreamFromBinaryString(S);
try
Bitmap.LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
procedure SaveBinaryStringToFile(FileName: string; S: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
WriteBinaryStringToStream(S, Stream);
finally
Stream.Free;
end;
end;
#define FileToBinaryString(str FileName) \
Local[4] = ExtractFileName(FileName), \
Local[0] = AddBackslash(GetEnv("TEMP")) + Local[4] + ".pas", \
Local[1] = \
"-ExecutionPolicy Bypass -Command """ + \
"Write-Host 'Generating code for " + Local[4] + "'; " + \
"$bytes = [System.IO.File]::ReadAllBytes('" + FileName + "'); " + \
"$s = '''' + (($bytes | foreach { $_.ToString('X2') }) -join '') + ''''; " + \
"Set-Content -Path '" + Local[0] + "' -Value $s;" + \
"""", \
Exec("powershell.exe", Local[1], SourcePath, , SW_HIDE), \
Local[2] = FileOpen(Local[0]), \
Local[3] = FileRead(Local[2]), \
FileClose(Local[2]), \
DeleteFileNow(Local[0]), \
Local[3]
次に、FileToBinaryString
プリプロセッサ マクロを使用して、コンパイル時 (より正確には前処理時) にファイルを次のような 16 進文字列に変換できます。
'4D5A50000200000004000F00FFFF0000B8000....'
実行時に、関数WriteBinaryStringToStream
、StreamFromBinaryString
、LoadBitmapFromBinaryString
またはの一部で 16 進文字列を使用しますSaveBinaryStringToFile
。
たとえば、ビットマップを にロードするにはTBitmapImage
、次を使用します。
LoadBitmapFromBinaryString(
BitmapImage.Bitmap, {#FileToBinaryString("C:\path\WizModernSmallImage.bmp")});
コンパイル時に、これは次のようなコードに変換されます。
LoadBitmapFromBinaryString(
BitmapImage.Bitmap, '4D5A50000200000004000F00FFFF0000B8000....');
DLL を抽出するには、次を使用します。
SaveBinaryStringToFile(
ExpandConstant('{tmp}\InnoCallback.dll'), {#FileToBinaryString("InnoCallback.dll")});
実行時に抽出された DLL を使用するには、次のdelayload
フラグを使用する必要があります。
function WrapTimerProc(callback:TTimerProc; paramcount:integer):longword;
external 'wrapcallback@{tmp}\innocallback.dll stdcall delayload';
プリプロセッサ/Pascal コンパイラには、文字列に対して約 1 億文字の制限があります。ただし、実際には、約 20 ~ 30 MB を超えるファイルの場合、最初に PowerShell スクリプトの [コンパイル時の] メモリ制限に達します。サイズが小さい (数 MB より大きい) 場合でも、PowerShell スクリプトのコンパイル時のパフォーマンスは良くありません。ただし、スクリプトは大幅に最適化できます。
16 進エンコーディングのため、インストーラーのサイズは 2 倍になります。これは、Base64 ( ) などのより効率的なエンコーディングを使用することで改善される可能性がありますCRYPT_STRING_BASE64
。セクションに含まれるファイルと比較して、コード セクションも圧縮されてい[Files]
ません (これらは既に圧縮されているため、画像の問題ではありませんが、たとえば DLL では違いが生じます)。
このソリューションは、当初、 Inno Setup: Reading a file from installer during uninstallingという質問に対して開発されました。
コードには Inno Setup の Unicode バージョンが必要です。最新の Inno Setup 6 では、これが利用可能な唯一のバージョンです。Inno Setup 5 を使用していても、21 世紀の Ansi バージョンは使用しないでください。皮肉なことに、これを Ansi バージョンに実装する方がはるかに簡単です。Ansi と Unicode の両方のバージョンの Inno Setup と互換性のある の使用については、Inno Setup でのバイナリ ファイルの書き込みに対する私の回答を参照してください。CryptStringToBinary
Ansi バージョンでは、実際には 16 進文字列の代わりにバイナリ文字列を使用できます。