Mav*_*ick 4 inno-setup pascalscript
卸载时使用以下代码
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;
Run Code Online (Sandbox Code Playgroud)
我收到错误:
异常:无法打开文件。C:\users\xyz\AppData\Local\Temp\is-U3Q8P.tmp\WizardSmallImageFile.Bmp。文件未找到。
我还尝试ExtractTemporaryFile在调用之前使用LoadFromFile卸载过程中不支持的功能。
ExtractTemporaryFile('WizardSmallImageFile.bmp');
Run Code Online (Sandbox Code Playgroud)
那么问题来了,如何查看图像或特别WizardSmallImageFile是在卸载过程中?
我上面的代码构建了一个带有自定义面板的自定义表单。就像这里:Inno Setup 仅卸载一些组件。
正确,ExtractTemporaryFile从安装程序中提取文件。因此,它无法在卸载程序中工作,因为安装程序不再可用。
另请注意,无论如何您都无法从安装程序中提取WizardSmallImageFile指令引用的文件。您必须添加自己的副本。
如果您在卸载过程中需要使用某些文件,则必须在安装程序中安装它,然后在卸载程序中使用已安装的副本。
\n\n[Files]\nSource: "WizardSmallImageFile.bmp"; DestDir: "{app}";\n\n[Code]\n\nfunction InitializeUninstall(): Boolean;\nbegin\n ...\n BitmapImage := TBitmapImage.Create(...);\n ...\n BitmapImage.Bitmap.LoadFromFile(\n ExpandConstant(\'{app}\\WizardSmallImageFile.bmp\'));\n ...\nend;\nRun Code Online (Sandbox Code Playgroud)\n如果您不想安装文件,可以将图像数据嵌入到代码中。
\n不幸的是,Unicode Inno Setup 在处理二进制数据时非常有限,因为它倾向于尝试将所有内容转换为 UTF-8。但经过多次尝试,我最终得到了一些工作代码。
\n请注意,该代码使用从Inno Setup 预处理器\xe2\x80\x93 调用的 PowerShell 代码。仅在编译时需要 PowerShell,而不是在运行/安装时需要。
\n将此代码添加到您的部分前面的某个位置[Code]:
function CryptStringToBinary(\n sz: string; cch: LongWord; flags: LongWord; binary: string; var size: LongWord;\n skip: LongWord; flagsused: LongWord): Integer;\n external \'CryptStringToBinaryW@crypt32.dll stdcall\';\n\nconst\n CRYPT_STRING_HEX = $04;\n\nprocedure WriteBinaryStringToStream(S: string; Stream: TStream);\nvar\n Buffer: string;\n Size: LongWord;\n Len: Integer;\nbegin\n Len := Length(S);\n SetLength(Buffer, (Len div 4) + 1);\n Size := Len div 2;\n if (CryptStringToBinary(S, Len, CRYPT_STRING_HEX, Buffer, Size, 0, 0) = 0) or\n (Size <> Len div 2) then\n begin\n RaiseException(\'Error decoding binary string\');\n end;\n \n Stream.WriteBuffer(Buffer, Size);\nend; \n\nfunction StreamFromBinaryString(S: string): TStream;\nbegin\n Result := TStringStream.Create(\'\');\n WriteBinaryStringToStream(S, Result);\n Result.Position := 0;\nend;\n\nprocedure LoadBitmapFromBinaryString(Bitmap: TBitmap; S: string);\nvar\n Stream: TStream;\nbegin\n Stream := StreamFromBinaryString(S);\n try\n Bitmap.LoadFromStream(Stream);\n finally\n Stream.Free;\n end;\nend;\n\nprocedure SaveBinaryStringToFile(FileName: string; S: string);\nvar\n Stream: TStream;\nbegin\n Stream := TFileStream.Create(FileName, fmCreate);\n try\n WriteBinaryStringToStream(S, Stream);\n finally\n Stream.Free;\n end;\nend;\n\n#define FileToBinaryString(str FileName) \\\n Local[4] = ExtractFileName(FileName), \\\n Local[0] = AddBackslash(GetEnv("TEMP")) + Local[4] + ".pas", \\\n Local[1] = \\\n "-ExecutionPolicy Bypass -Command """ + \\\n "Write-Host \'Generating code for " + Local[4] + "\'; " + \\\n "$bytes = [System.IO.File]::ReadAllBytes(\'" + FileName + "\'); " + \\\n "$s = \'\'\'\' + (($bytes | foreach { $_.ToString(\'X2\') }) -join \'\') + \'\'\'\'; " + \\\n "Set-Content -Path \'" + Local[0] + "\' -Value $s;" + \\\n """", \\\n Exec("powershell.exe", Local[1], SourcePath, , SW_HIDE), \\\n Local[2] = FileOpen(Local[0]), \\\n Local[3] = FileRead(Local[2]), \\\n FileClose(Local[2]), \\\n DeleteFileNow(Local[0]), \\\n Local[3]\nRun Code Online (Sandbox Code Playgroud)\n然后您可以使用FileToBinaryString 预处理器宏在编译时(或更准确地说,在预处理时)将文件转换为十六进制字符串,例如:
\'4D5A50000200000004000F00FFFF0000B800000....\'\nRun Code Online (Sandbox Code Playgroud)\n在运行时,您可以将十六进制字符串与某些函数WriteBinaryStringToStream、StreamFromBinaryString或LoadBitmapFromBinaryString一起使用SaveBinaryStringToFile。
在您的情况下,您将使用:
\nLoadBitmapFromBinaryString(\n BitmapImage.Bitmap, {#FileToBinaryString("C:\\path\\WizModernSmallImage.bmp")});\nRun Code Online (Sandbox Code Playgroud)\n在编译时,这会转换为如下代码:
\nLoadBitmapFromBinaryString(\n BitmapImage.Bitmap, \'4D5A50000200000004000F00FFFF0000B800000....\');\nRun Code Online (Sandbox Code Playgroud)\n预处理器/Pascal 编译器对字符串的长度限制约为 100M 个字符。不过,对于大于 20-30 MB 的文件,您实际上首先会达到 PowerShell 脚本的[编译时]内存限制。尽管即使对于较小的大小(大于几个 MB),PowerShell 脚本的编译时性能也很差。不过,该脚本可以进行显着优化。
\n由于十六进制编码,安装程序的大小增加了一倍。这可以通过使用一些更有效的编码来改进,例如 Base64 ( CRYPT_STRING_BASE64)。与该部分中包含的文件相比,代码部分甚至也没有被压缩[Files](对于图像来说这不是问题,因为这些图像已经被压缩,但对于例如 DLL 来说却有所不同)。
该代码需要 Inno Setup 的 Unicode 版本。无论如何,在 21 世纪,你不应该使用 Ansi 版本。尽管讽刺的是,在 Ansi 版本中实现这一点会容易得多。请参阅我对在 Inno Setup 中编写二进制文件的回答,CryptStringToBinary了解与 Inno Setup 的 Ansi 和 Unicode 版本兼容的使用。尽管在 Ansi 版本中,您实际上可以使用二进制字符串,而不是十六进制字符串。
| 归档时间: |
|
| 查看次数: |
2576 次 |
| 最近记录: |