มีวิธีใดที่จะทำให้ไฟล์ถอนการติดตั้ง (JPEG, DLL, PNG...) ยังคงอยู่ใน unins000.exe
หรือไม่ ถ้ามีกรุณาแสดงรหัส
เก็บไฟล์ถอนการติดตั้งไว้ในโปรแกรมถอนการติดตั้งอย่างไร
คำตอบ (2)
ไม่มีวิธีใดที่จะทำเช่นนี้ กลไกการถอนการติดตั้ง Inno ไม่สามารถมีไฟล์ฝังตัวได้
แต่ในทางกลับกัน มันก็ไม่จำเป็นต้องทำเช่นนั้นเช่นกัน คุณสามารถติดตั้งไฟล์ใดก็ได้ที่มันต้องการ (ลงในโฟลเดอร์ย่อยของโฟลเดอร์แอป หากคุณต้องการให้สิ่งต่าง ๆ เป็นระเบียบเรียบร้อย)
เหตุผลที่แท้จริงเพียงประการเดียวที่ไฟล์ติดตั้งถูกฝังอยู่ในตัวติดตั้งก็คือทำให้การดาวน์โหลดง่ายขึ้น โปรแกรมถอนการติดตั้งไม่มีข้อแก้ตัวนั้น
Inno Setup ไม่มีการสนับสนุนดั้งเดิมสำหรับการฝังไฟล์
แต่ด้วยความคิดสร้างสรรค์ คุณสามารถฝังไฟล์ลงในโค้ดได้ (ในรูปแบบค่าคงที่)
น่าเสียดายที่การตั้งค่า Unicode Inno ค่อนข้างจำกัดเมื่อต้องจัดการกับข้อมูลไบนารี่ เนื่องจากมีแนวโน้มที่จะพยายามแปลงทุกอย่างเป็น UTF-8 แต่หลังจากพยายามหลายครั้ง ฉันก็ได้โค้ดที่ใช้งานได้ (ด้วยการใช้โค้ด PowerShell ที่เรียกใช้จาก ตัวประมวลผลล่วงหน้าการตั้งค่า Inno ก>)
เพิ่มโค้ดนี้ไว้ที่ด้านหน้าของส่วน [Code]
ของคุณ:
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]
จากนั้นคุณสามารถใช้ FileToBinaryString
มาโครตัวประมวลผลล่วงหน้า เพื่อแปลงไฟล์เป็นคอมไพล์- เวลา (หรือแม่นยำกว่านั้นเมื่อประมวลผลล่วงหน้า) เป็นสตริงเลขฐานสิบหกเช่น:
'4D5A50000200000004000F00FFFF0000B8000....'
บนรันไทม์ คุณใช้สตริงฐานสิบหกกับฟังก์ชันบางฟังก์ชัน WriteBinaryStringToStream
, StreamFromBinaryString
, LoadBitmapFromBinaryString
หรือ 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
flag:
function WrapTimerProc(callback:TTimerProc; paramcount:integer):longword;
external 'wrapcallback@{tmp}\innocallback.dll stdcall delayload';
พรีโปรเซสเซอร์/คอมไพเลอร์ Pascal มีขีดจำกัดประมาณ 100M อักขระสำหรับสตริง แม้ว่าคุณจะถึงขีดจำกัดหน่วยความจำ [เวลาคอมไพล์] ของสคริปต์ PowerShell สำหรับไฟล์ที่มีขนาดใหญ่กว่าประมาณ 20-30 MB ก็ตาม แม้ว่าจะมีขนาดเล็กกว่า (มากกว่าสองสาม MB) แต่ประสิทธิภาพเวลาคอมไพล์ของสคริปต์ PowerShell นั้นไม่ดี สคริปต์สามารถปรับให้เหมาะสมได้อย่างมาก
เนื่องจากการเข้ารหัสแบบ hex ขนาดของตัวติดตั้งจึงเพิ่มขึ้นเป็นสองเท่า ซึ่งสามารถปรับปรุงได้โดยใช้การเข้ารหัสที่มีประสิทธิภาพมากขึ้น เช่น Base64 (CRYPT_STRING_BASE64
) ส่วนของโค้ดจะไม่ถูกบีบอัดด้วยซ้ำ เมื่อเปรียบเทียบกับไฟล์ที่มาพร้อมกับส่วน [Files]
(ไม่ใช่ปัญหาสำหรับรูปภาพเนื่องจากไฟล์เหล่านี้ถูกบีบอัดไว้แล้ว แต่สร้างความแตกต่างให้กับ DLL เป็นต้น)
โซลูชันนี้ได้รับการพัฒนาในตอนแรกสำหรับคำถาม การตั้งค่า Inno: การอ่านไฟล์จากตัวติดตั้งระหว่างการถอนการติดตั้ง
โค้ดนี้ต้องใช้ Inno Setup เวอร์ชัน Unicode ด้วย Inno Setup 6 ล่าสุด จึงเป็นเวอร์ชันเดียวที่มีอยู่อยู่แล้ว แม้ว่าคุณจะใช้ Inno Setup 5 คุณก็ไม่ควรใช้เวอร์ชัน Ansi ในศตวรรษที่ 21 แม้ว่าการใช้งานสิ่งนี้ในเวอร์ชัน Ansi จะง่ายกว่ามากก็ตาม ดูคำตอบของฉันในการเขียนไฟล์ไบนารีใน Inno Setup สำหรับการใช้ CryptStringToBinary
ที่เข้ากันได้กับทั้งเวอร์ชัน Ansi และ Unicode ของการตั้งค่า Inno แม้ว่าในเวอร์ชัน Ansi คุณสามารถใช้สตริงไบนารี่ได้จริง แทนที่จะเป็นสตริงฐานสิบหก