เก็บไฟล์ถอนการติดตั้งไว้ในโปรแกรมถอนการติดตั้งอย่างไร

มีวิธีใดที่จะทำให้ไฟล์ถอนการติดตั้ง (JPEG, DLL, PNG...) ยังคงอยู่ใน unins000.exe หรือไม่ ถ้ามีกรุณาแสดงรหัส


person Andrezork    schedule 13.02.2013    source แหล่งที่มา
comment
สิ่งนี้เหมาะสมกับ SuperUser หรือไม่   -  person Piccolo    schedule 13.02.2013
comment
@boj ไม่ มันเป็นคำถามการพัฒนา   -  person Deanna    schedule 13.02.2013


คำตอบ (2)


ไม่มีวิธีใดที่จะทำเช่นนี้ กลไกการถอนการติดตั้ง Inno ไม่สามารถมีไฟล์ฝังตัวได้

แต่ในทางกลับกัน มันก็ไม่จำเป็นต้องทำเช่นนั้นเช่นกัน คุณสามารถติดตั้งไฟล์ใดก็ได้ที่มันต้องการ (ลงในโฟลเดอร์ย่อยของโฟลเดอร์แอป หากคุณต้องการให้สิ่งต่าง ๆ เป็นระเบียบเรียบร้อย)

เหตุผลที่แท้จริงเพียงประการเดียวที่ไฟล์ติดตั้งถูกฝังอยู่ในตัวติดตั้งก็คือทำให้การดาวน์โหลดง่ายขึ้น โปรแกรมถอนการติดตั้งไม่มีข้อแก้ตัวนั้น

person Miral    schedule 13.02.2013
comment
สวัสดีมิราล ขอบคุณสำหรับความช่วยเหลือของคุณ - person Andrezork; 13.02.2013
comment
จริงๆ แล้ว ด้วยความคิดสร้างสรรค์ มันก็มีหนทางอยู่ ดูคำตอบของฉัน - person Martin Prikryl; 12.07.2016
comment
@MartinPrikryl True แต่โดยทั่วไปแล้วความพยายามที่จะทำเช่นนั้นมีมากกว่าผลประโยชน์ ง่ายกว่าเพียงแค่ติดตั้งไฟล์ ยังคงมีคะแนนสำหรับความคิดสร้างสรรค์ :) - person Miral; 13.07.2016

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 คุณสามารถใช้สตริงไบนารี่ได้จริง แทนที่จะเป็นสตริงฐานสิบหก

person Martin Prikryl    schedule 12.07.2016