2016-05-31 6 views
2

Verwendung des folgenden Codes während der DeinstallationInno Setup: eine Datei von Installationsprogramm bei der Deinstallation Lesen

BitmapImage := TBitmapImage.Create(InstallTopPanel); 
BitmapImage.AutoSize := True; 
BitmapImage.Bitmap.LoadFromFile(ExpandConstant('{tmp}\WizardSmallImageFile.bmp')); 
BitmapImage.Parent := InstallTopPanel; 
BitmapImage.Top := (InstallTopPanel.ClientHeight - 58)/2; 
BitmapImage.Left := InstallTopPanel.ClientWidth - 55 - 10; 

Ich erhalte eine Fehlermeldung:

Exception : can not open file. C:\users\xyz\AppData\Local\Temp\is-U3Q8P.tmp\WizardSmallImageFile.Bmp. File not found.

Ich habe auch versucht ExtractTemporaryFile zu verwenden, bevor ich LoadFromFile nennen was während der Deinstallation nicht unterstützt wird.

ExtractTemporaryFile('WizardSmallImageFile.bmp'); 

Also, die Frage, wie man ein Bild anzuzeigen oder zu speziell WizardSmallImageFile bei der Deinstallation?

+0

Warum sollten Sie erwarten, dass bei der Deinstallation Ihres Programms etwas extrahiert wird? Die Aufgabe des Deinstallationsprogramms besteht darin, Dateien * zu entfernen * und keine neuen hinzuzufügen. Sie verweisen auf * InstallTopPanel * in Ihrem Code, aber Sie ** installieren ** nicht und daher ist das * InstallTopPanel * nicht vorhanden. –

+0

Ich nehme an, Sie erstellen ein benutzerdefiniertes Deinstallationsformular gemäß [Inno-Setup Nur einige Komponenten deinstallieren] (http://stackoverflow.com/q/37507369/850848). Ich nehme auch an, dass 'InstallTopPanel' Ihr benutzerdefiniertes Steuerelement ist (nicht das Standard' WizardForm.InstallTopPanel'). Wenn das stimmt, mach es klar in deiner Frage, um den Lesern einen Kontext zu geben. –

+0

Ja, es ist ein benutzerdefiniertes Formular und das Installations-Panel ist auch ein benutzerdefiniertes Panel bei der Deinstallation. – Maverick

Antwort

3

Korrekt, extrahiert die ExtractTemporaryFile Dateien aus dem Installationsprogramm. Daher kann es im Deinstallationsprogramm nicht funktionieren, da das Installationsprogramm nicht mehr verfügbar ist.

Beachten Sie auch, dass Sie die Datei nicht ohnehin vom Installateur durch die WizardSmallImageFile directive verwiesen extrahieren kann. Sie müssen Ihre eigene Kopie hinzufügen.


Wenn Sie einige Datei bei der Deinstallation verwenden müssen, müssen Sie es im Installer installieren und dann in das Deinstallationsprogramm die installierte Kopie verwenden.

[Files] 
Source: "WizardSmallImageFile.bmp"; DestDir: "{app}"; 

[Code] 

function InitializeUninstall(): Boolean; 
begin 
    ... 
    BitmapImage := TBitmapImage.Create(...); 
    ... 
    BitmapImage.Bitmap.LoadFromFile(ExpandConstant('{app}\WizardSmallImageFile.bmp')); 
    ... 
end; 

Wenn Sie ohne die Installation die Datei tun möchten, können Sie die Bilddaten in den Code einbetten. Leider ist

der Unicode-Inno Setup recht begrenzt, wenn sie mit binären Daten zu tun, wie es alles in UTF-8 zu konvertieren, um zu versuchen tendiert. Aber nach zahlreichen Versuchen bin ich mit einem funktionierenden Code gelandet.

Beachten Sie, dass der Code einen PowerShell-Code verwendet, der von Inno Setup preprocessor aufgerufen wird. - Die PowerShell wird nur zur Kompilierzeit benötigt, nicht zur Laufzeit/Installationszeit.

Fügen Sie diesen Code irgendwo auf der Vorderseite Ihres [Code] Abschnitt:

function CryptStringToBinary(
    sz: string; cch: LongWord; flags: LongWord; binary: string; var size: LongWord; 
    skip: LongWord; flagsused: LongWord): Integer; 
    external '[email protected] 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] 

Und dann können Sie die FileToBinaryStringpreprocessor macro verwenden, um eine Datei auf Compile-Zeit (oder genauer gesagt, wenn die Vorverarbeitung) zu konvertieren ein hex-String wie:

'4D5A50000200000004000F00FFFF0000B800000....' 

On Laufzeit verwenden Sie die hex-String mit einigen der Funktionen WriteBinaryStringToStream, StreamFromBinaryString, LoadBitmapFromBinaryString oder SaveBinaryStringToFile.

In Ihrem Fall werden Sie verwenden:

LoadBitmapFromBinaryString(
    BitmapImage.Bitmap, {#FileToBinaryString("C:\path\WizModernSmallImage.bmp")}); 

Auf Compile-Zeit, dies in einen Code umgewandelt wird, wie:

LoadBitmapFromBinaryString(
    BitmapImage.Bitmap, '4D5A50000200000004000F00FFFF0000B800000....'); 

Der Vorprozessor/Pascal Compiler ein Limit von ca. 100M Zeichen für eine Zeichenfolge.Sie werden jedoch zuerst eine Speichergrenze für die [Kompilierungszeit] des PowerShell-Skripts für Dateien mit mehr als 20-30 MB erreichen. Auch für kleinere Größen (größer als einige MB) ist die Kompilierzeitleistung des PowerShell-Skripts jedoch schlecht. Das Skript kann jedoch erheblich optimiert werden.

Aufgrund der Hexadezimalcodierung nimmt die Größe des Installationsprogramms doppelt so stark zu. Dies könnte durch eine effizientere Codierung wie Base64 (CRYPT_STRING_BASE64) verbessert werden. Der Code-Abschnitt ist nicht einmal komprimiert, verglichen mit Dateien, die im Abschnitt [Files] enthalten sind (kein Problem für Bilder, da diese bereits komprimiert sind, aber bei DLLs einen Unterschied machen).

Der Code erfordert die Unicode-Version von Inno Setup. Sie sollten die Ansi-Version im 21. Jahrhundert sowieso nicht verwenden. Ironischerweise wäre die Implementierung in der Ansi-Version viel einfacher. Siehe my answer to Writing binary file in Inno Setup für eine Verwendung der , die sowohl mit Ansi-und Unicode-Version von Inno-Setup kompatibel ist. Obwohl Sie in der Ansi-Version tatsächlich eine binäre Zeichenfolge anstelle einer hexadezimalen Zeichenfolge verwenden können.

+0

Das ist richtig und ich dachte auch darüber nach, aber ich wollte keine internen Ressourcen-Dateien für den Deinstallationsvorgang im App-Zielordner verteilen. Im letzten Fall würde ein Ausnahmefehler auftreten, wenn der Benutzer das Bild manuell löscht und das will ich natürlich nicht. Wie ich verstehen kann, kann die Frage nicht mit der Einschränkung beantwortet werden, die ich gestellt habe. – Maverick

+0

Testen Sie einfach, ob die Datei existiert und laden Sie das Bild nicht, wenn dies nicht der Fall ist. Es ist nicht notwendig, dass das Deinstallationsprogramm fortfährt. –

+0

Über die erste Empfehlung ist es eine Option. Über die Sekunde, wenn ich gut verstehe, empfehlen Sie, eine Zeichenkette als Datenpuffer zu verwenden und dann jene Daten mit TStringStream zurückzurufen und sie mit Bitmapbildklasse zu verbinden. Es klingt gut, aber ich habe nicht die Fähigkeiten in Pascal, um das zu programmieren. Ich werde im Internet suchen und ich werde entscheiden, ob es keine Overkill-Strategie ist. – Maverick

Verwandte Themen