如何保持内部卸载程序卸载文件?(How keep uninstall files inside un

2019-07-19 19:17发布

有什么办法能让卸载文件(JPEG,DLL,PNG ...)留在里面unins000.exe ? 如果是的话,请给一个代码。

Answer 1:

没有任何办法做到这一点。 该创新科技卸载引擎不能包含嵌入的文件。

但在另一方面也没有特别需要为它这样做要么 - 你可以认为它需要的任何文件进行安装(到应用程序文件夹的子文件夹,如果你想保持整洁)。

唯一的真正原因是安装文件嵌入到安装程序是,它使下载更容易。 卸载程序不会有这样的借口。



Answer 2:

Inno Setup的具有嵌入文件中没有原生支持。

但也有一些创意,你可以嵌入到文件的代码(在某些固定的形式)。

不幸的是,Unicode的Inno Setup的是相当有限的二进制数据处理,因为它往往会尝试一切转换为UTF-8时。 但是,众多的尝试后我已经结束了与一些工作代码(使用从调用的PowerShell代码Inno Setup的预处理器 )。


地方添加以下代码到你的面前[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 预处理宏转换在编译时一个文件(或者更准确地说,当预处理),以十六进制字符串,如:

'4D5A50000200000004000F00FFFF0000B8000....'

在运行时,您可以使用十六进制字符串与一些功能WriteBinaryStringToStreamStreamFromBinaryStringLoadBitmapFromBinaryStringSaveBinaryStringToFile


因此,例如加载一个位图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编译器具有一个字符串约100M字符的限制。 虽然你实际上会先打[编译时]内存PowerShell脚本的比约20-30 MB的文件限制。 但即使对于较小尺寸(小于几MB的大),PowerShell脚本的编译时间时表现不好。 该脚本可以显著虽然进行优化。

由于十六进制编码,安装程序的大小增加了两倍多。 这可以通过使用一些更有效的编码,如Base64的(能够提高CRYPT_STRING_BASE64 )。 代码部分甚至没有压缩过,比较包含在文件[Files]部分(未如这些已被压缩的图像的问题,但使用的DLL例如差)。


该解决方案最初开发的问题Inno Setup的:在卸载过程中从读取安装文件


该代码需要创新安装的Unicode版本。 你不应该反正使用ANSI版本,在21世纪。 虽然讽刺的是,在ANSI版本实现,这将是比较容易的方式。 见我的回答写在Inno Setup的二进制文件的使用的CryptStringToBinary这与ANSI和创新安装的Unicode版本兼容。 尽管在ANSI版本你其实可以做一个二进制字符串,而不是一个十六进制字符串。



文章来源: How keep uninstall files inside uninstaller?
标签: inno-setup