Inno setup Inno安装程序:卸载期间从安装程序读取文件

Inno setup Inno安装程序:卸载期间从安装程序读取文件,inno-setup,Inno Setup,在卸载过程中使用以下代码 BitmapImage:=TBitmapImage.Create(InstallTopPanel); BitmapImage.AutoSize:=True; BitmapImage.Bitmap.LoadFromFile(ExpandConstant({tmp}\WizardSmallImageFile.bmp'); BitmapImage.Parent:=InstallTopPanel; BitmapImage.Top:=(InstallTopPanel.Client

在卸载过程中使用以下代码

BitmapImage:=TBitmapImage.Create(InstallTopPanel);
BitmapImage.AutoSize:=True;
BitmapImage.Bitmap.LoadFromFile(ExpandConstant({tmp}\WizardSmallImageFile.bmp');
BitmapImage.Parent:=InstallTopPanel;
BitmapImage.Top:=(InstallTopPanel.ClientHight-58)/2;
BitmapImage.Left:=InstallTopPanel.ClientWidth-55-10;
我得到一个错误:

异常:无法打开文件。 C:\users\xyz\AppData\Local\Temp\is-U3Q8P.tmp\WizardSmallImageFile.Bmp。 找不到文件

在调用
LoadFromFile
之前,我还尝试使用
ExtractTemporaryFile
,这在卸载过程中不受支持

ExtractTemporaryFile('WizardSmallImageFile.bmp');

因此,问题是,如何在卸载期间查看图像或特别是
向导SmallImageFile

正确,
提取临时文件
从安装程序中提取文件。因此,它无法在卸载程序中工作,因为安装程序不再可用

还要注意的是,您无法从安装程序中提取由引用的文件。您必须添加自己的副本


如果在卸载过程中需要使用某些文件,则必须在安装程序中安装该文件,然后在卸载程序中使用已安装的副本

[文件]
来源:“WizardSmallImageFile.bmp”;DestDir:“{app}”;
[守则]
函数InitializeUninstall():布尔值;
开始
...
BitmapImage:=TBitmapImage.Create(…);
...
BitmapImage.Bitmap.LoadFromFile(ExpandConstant({app}\WizardSmallImageFile.bmp');
...
结束;

如果不想安装文件,可以将图像数据嵌入代码中

不幸的是,Unicode Inno设置在处理二进制数据时非常有限,因为它倾向于将所有内容转换为UTF-8。但是经过多次尝试,我最终得到了一些工作代码

请注意,该代码使用从调用的PowerShell代码-PowerShell仅在编译时需要,而不是在运行/安装时需要

将此代码添加到
[code]
部分的前面:

函数CryptStringToBinary(
sz:string;cch:LongWord;标志:LongWord;二进制:string;变量大小:LongWord;
跳过:长单词;标记使用:长单词):整数;
外部的CryptStringToBinaryW@crypt32.dllstdcall';
常数
密码字符串十六进制=$04;
过程WriteBinaryStringToStream(S:string;Stream:TStream);
变量
缓冲区:字符串;
大小:长字;
开始
SetLength(缓冲区)(长度(S)第4部分)+1);
尺寸:=第2部分的长度;
如果(CryptStringToBinary(S,长度,CRYPT_字符串,十六进制,缓冲区,大小,0,0)=0)或
(尺寸长度第2部分)然后
开始
RaiseException('Error decoding binary string');
结束;
Stream.WriteBuffer(缓冲区,大小);
结束;
函数StreamFromBinaryString(S:string):TStream;
开始
结果:=TStringStream.Create(“”);
WriteBinaryStringToStream(S,结果);
结果.位置:=0;
结束;
过程LoadBitmapFromBinaryString(位图:TBitmap;S:string);
变量
溪流:尖沙咀;;
开始
Stream:=StreamFromBinaryString;
尝试
LoadFromStream(Stream);
最后
免费;
结束;
结束;
过程SaveBinaryStringToFile(文件名:string;S:string);
变量
溪流:尖沙咀;;
开始
Stream:=TFileStream.Create(文件名,fmCreate);
尝试
WriteBinaryStringToStream(S,Stream);
最后
免费;
结束;
结束;
#定义FileToBinaryString(str文件名)\
本地[4]=提取文件名(文件名)\
本地[0]=AddBackslash(GetEnv(“TEMP”))+Local[4]+“.pas”\
本地[1]=\
-ExecutionPolicy旁路-命令“”+\
“写入主机”生成“+Local[4]+”;“+\
“$bytes=[System.IO.File]::ReadAllBytes(“+FileName+”);”+\
“$s=''”+($bytes | foreach{$\ ToString('X2')})-连接“”)+''”;”+\
“设置内容-路径”“+Local[0]+”'-值$s;“+\
"""", \
Exec(“powershell.exe”、本地[1]、源路径、软件隐藏)\
本地[2]=文件打开(本地[0])\
本地[3]=文件读取(本地[2])\
FileClose(本地[2])\
DeleteFileNow(本地[0])\
本地[3]
然后可以使用
filetobinarysting
在编译时(或者更准确地说,在预处理时)将文件转换为十六进制字符串,如:

“4D5A50000200004000F00FF0000B800000…”
在运行时,将十六进制字符串与一些函数一起使用
WriteBinaryStringToStream
StreamFromBinaryString
LoadBitmapFromBinaryString
SaveBinaryStringToFile

在您的情况下,您将使用:

LoadBitmapFromBinaryString(
位图,{#FileToBinaryString(“C:\path\WizModernSmallImage.bmp”)};
在编译时,会将其转换为如下代码:

LoadBitmapFromBinaryString(
位图“4D5A50000200004000F00FF0000B800000…”;

预处理器/Pascal编译器对字符串的限制约为100M个字符。不过,对于大于20-30 MB的文件,实际上首先会达到PowerShell脚本的[编译时]内存限制。尽管即使对于较小的大小(大于几MB),PowerShell脚本的编译时性能也很差。不过,脚本可以进行显著优化

由于十六进制编码,安装程序的大小增加了两倍。这可以通过使用一些更有效的编码来改进,比如Base64(
CRYPT\u STRING\u Base64
)。与
[files]
部分中包含的文件相比,代码部分甚至没有被压缩(这对于图像来说不是问题,因为它们已经被压缩了,但是与DLL相比,这就有了区别)

该代码需要Unicode版本的Inno安装程序。无论如何,在21世纪,你不应该使用Ansi版本。尽管讽刺的是,在Ansi版本中实现这一点要容易得多。有关
CryptStringToBin的用法,请参阅