1.从MyProg.exe提取版本信息到VersionInfo.rc ResourceHacker.exe -extract MyProg.exe, VersionInfo.rc, versioninfo,, VersionInfo.rc的内容如下:1 VERSIONINFOFILEVERSION 1,5,0,0PRODUCTVERSION 1,5,0,0FILEOS 0x4FILETYPE 0x0{BLOCK "StringFileInfo"{ BLOCK "040904b0" { VALUE "CompanyName", "My Company" VALUE "FileDescription", "My Program" VALUE "FileVersion", "1.5.0.0" VALUE "InternalName", "MyProg" VALUE "LegalCopyright", "Copyright (C) My Company" VALUE "OriginalFilename", "MyProg.exe" VALUE "ProductName", "My Program" VALUE "ProductVersion", "1.5" }}BLOCK "VarFileInfo"{ VALUE "Translation", 0x0409, 0x04B0}} 2.修改版本信息 我们将以下行添加到VersionInfo.rc VALUE "PrivateBuild", "123-123-123" (稍后:使用PHP修改文件.可能对包含ProductVersion的行进行preg_match并在新行之后附加值行.) VersionInfo.rc的新内容如下:1 VERSIONINFOFILEVERSION 1,5,0,0PRODUCTVERSION 1,5,0,0FILEOS 0x4FILETYPE 0x0{BLOCK "StringFileInfo"{ BLOCK "040904b0" { VALUE "CompanyName", "My Company" VALUE "FileDescription", "My Program" VALUE "FileVersion", "1.5.0.0" VALUE "InternalName", "MyProg" VALUE "LegalCopyright", "Copyright (C) My Company" VALUE "OriginalFilename", "MyProg.exe" VALUE "ProductName", "My Program" VALUE "ProductVersion", "1.5" VALUE "PrivateBuild", "123-123-123" }}BLOCK "VarFileInfo"{ VALUE "Translation", 0x0409, 0x04B0}} 3.编译VersionInfo windres -i VersionInfo.rc -o VersionInfo.res -O res 现在,VersionInfo文本再次成为资源. 4.将资源插入exe ResourceHacker.exe -script ScriptFile.rh 其中ScriptFile.rh包含[FileNames]Exe=MyProg.exeSaveAs=MyProgNew.exeLog=MyProg.log[Commands]-delete VERSIONINFO,1,1033-add VersionInfo.res, VERSIONINFO,1,1033让我们检查一下日志:[08 Sep 2015, 11:21:33][FileNames]Exe=MyProg.exeSaveAs=MyProgNew.exeLog=MyProg.log[Commands]-delete VERSIONINFO,1,1033 Deleted: VERSIONINFO,1,1033-add VersionInfo.res, VERSIONINFO,1,1033 Added: VERSIONINFO,1,1033Done.确定.已插入新的VERSIONINFO. 5.如何使用或从InnoSetup中提取值? InnoSetup仅提供称为 GetStringFileInfo()的预处理器功能.所以不能使用 #define SERIAL GetStringFileInfo("path/to/MyProgNew.exe", "PrivateBuild") 因此,我们必须找到一种解决方法来访问信息,并且可能使用WinAPI可以正常工作.这是一种实现方法,尚有待改进.它是由 El Sanchez在OsZone.net上撰写的.[Code]#ifdef UNICODE #define A "W"#else #define A "A"#endiffunction GetFileVersionInfoSize(lptstrFilename: String; lpdwHandle: Integer): Integer;external 'GetFileVersionInfoSize{#A}@version.dll stdcall delayload';function GetFileVersionInfo(lptstrFilename: String; dwHandle, dwLen: Integer; var lpData: Byte): Boolean;external 'GetFileVersionInfo{#A}@version.dll stdcall delayload';function VerQueryValue(var pBlock: Byte; lpSubBlock: String; var lplpBuffer: DWord; var puLen: Integer): Boolean;external 'VerQueryValue{#A}@version.dll stdcall delayload';function GetFileVerInfo(FileName, VerName: String): String;//VerName://Comments, LegalCopyright, CompanyName, FileDescription, FileVersion, ProductVersion,//InternalName, LegalTrademarks, OriginalFilename, ProductName, PrivateBuild, SpecialBuildvar dwLen, puLen, i: Integer; lpFileVerInfo: array of Byte; lplpBufferCP, lplpBufferVN: DWord; LangCodepage: String;begin Result := ''; if FileExists(FileName) then begin dwLen := GetFileVersionInfoSize(FileName, 0); if dwLen > 0 then begin SetArrayLength(lpFileVerInfo, dwLen); if GetFileVersionInfo(FileName, 0, dwLen, lpFileVerInfo[0]) then begin if VerQueryValue(lpFileVerInfo[0], '\VarFileInfo\Translation', lplpBufferCP, puLen) then begin LangCodepage := Format('%.2x%.2x%.2x%.2x', [lpFileVerInfo[(dwLen div 2)-5], lpFileVerInfo[(dwLen div 2)-6], lpFileVerInfo[(dwLen div 2)-3], lpFileVerInfo[(dwLen div 2)-4]]); if VerQueryValue(lpFileVerInfo[0], Format('\%s\%s\%s', ['StringFileInfo', LangCodepage, VerName]), lplpBufferVN, puLen) then begin i := (dwLen div 2) + lplpBufferVN - lplpBufferCP - 6; repeat if lpFileVerInfo[i] <> 0 then begin SetLength(Result, Length(Result)+1); Result[Length(Result)] := Chr(lpFileVerInfo[i]); end; i := i + 1; #ifdef UNICODE until i > (dwLen div 2) + lplpBufferVN - lplpBufferCP - 8 + puLen; #else until lpFileVerInfo[i] = 0; #endif end; end; end; end; end;end;然后GetFileVerInfo(ExpandConstant('{srcexe}'), "PrivateBuild"); 6.签署安装程序 更新资源会破坏安装程序的代码签名吗?是的,插入将更改可执行文件.修改后,您将必须对其进行签名.事先使用未签名的安装程序,然后插入,然后在服务器上签名.-您可以在服务器端使用PHP执行所有步骤.您需要服务器上的ResourceHacker.exe和windres.exe以及执行它们的wine.I have a complicated situation.There is a downloadable link to my installer on the web.Before anyone downloads the installer they have to fill out a form in the browser.I would like to save the information filled out in the form in the installer itself.How could I accomplish this?*Compiling the installer on the server each time anyone fills out the form is not an option because the installer is very heavy and this process would take a lot of time.*Creating the form in the installer is not an option.*I only need to save a single number in my executable. 解决方案 Its an interesting question. I'm with TLama on this one. When the installer is already build, your only chance is to modify the application / executable resources.A tool like ResourceHacker might help in automating this task. http://angusj.com/resourcehacker/resource_hacker.zipOn the server-side you might use PHP to accept the form data and then forward them to ResourceHacker executed with wine and from PHP, e.g.:exec("wine ResourceHacker.exe -script ScriptFile");. You have some options on how to pass the data from the form to ResourceHacker: cli argument, from a file, etc. For automation on server-side, i suggest to use a ScriptFile.A ScriptFile could start like...[FILENAMES]Exe=Installer.exeSaveAs=ModifiedInstaller.exeLog=file.log[COMMANDS]-modify ResourceSrc, ResourceMaskIn order to find the element to change, you can use the ResourceHacker GUI on a Windows system and play around until it works, then alter the script for automation on the server-side accordingly. Ok, after explaining how to modify a resource in general lets go into details:Like i pointed out, its also possible to use a language string for this and change it, but i will give step-by-step instructions for inserting a new field in the VERSION_INFO section of an executable. For testing purposes i work on\innosetup\Examples\MyProg.exeOur goal is to add a new VALUE "PrivateBuild" with kind of a serial number.(According to https://msdn.microsoft.com/de-de/library/windows/desktop/aa381049(v=vs.85).aspx, there is also "Comments" and "SpecialBuild" to enter information.)1. Extract Version Info from MyProg.exe into VersionInfo.rcResourceHacker.exe -extract MyProg.exe, VersionInfo.rc, versioninfo,,The content of VersionInfo.rc looks like this:1 VERSIONINFOFILEVERSION 1,5,0,0PRODUCTVERSION 1,5,0,0FILEOS 0x4FILETYPE 0x0{BLOCK "StringFileInfo"{ BLOCK "040904b0" { VALUE "CompanyName", "My Company" VALUE "FileDescription", "My Program" VALUE "FileVersion", "1.5.0.0" VALUE "InternalName", "MyProg" VALUE "LegalCopyright", "Copyright (C) My Company" VALUE "OriginalFilename", "MyProg.exe" VALUE "ProductName", "My Program" VALUE "ProductVersion", "1.5" }}BLOCK "VarFileInfo"{ VALUE "Translation", 0x0409, 0x04B0}}2. Modify Version InfoWe add the following line to VersionInfo.rc VALUE "PrivateBuild", "123-123-123"(Later: modify the file with PHP. Probably preg_match for the line containing ProductVersion and append a new line followed by the value line.)The new content of VersionInfo.rc looks like this:1 VERSIONINFOFILEVERSION 1,5,0,0PRODUCTVERSION 1,5,0,0FILEOS 0x4FILETYPE 0x0{BLOCK "StringFileInfo"{ BLOCK "040904b0" { VALUE "CompanyName", "My Company" VALUE "FileDescription", "My Program" VALUE "FileVersion", "1.5.0.0" VALUE "InternalName", "MyProg" VALUE "LegalCopyright", "Copyright (C) My Company" VALUE "OriginalFilename", "MyProg.exe" VALUE "ProductName", "My Program" VALUE "ProductVersion", "1.5" VALUE "PrivateBuild", "123-123-123" }}BLOCK "VarFileInfo"{ VALUE "Translation", 0x0409, 0x04B0}}3. Compile VersionInfowindres -i VersionInfo.rc -o VersionInfo.res -O resNow the VersionInfo text is a resource again.4. Insert resource into exeResourceHacker.exe -script ScriptFile.rhwhere ScriptFile.rh contains[FileNames]Exe=MyProg.exeSaveAs=MyProgNew.exeLog=MyProg.log[Commands]-delete VERSIONINFO,1,1033-add VersionInfo.res, VERSIONINFO,1,1033Let's check the log:[08 Sep 2015, 11:21:33][FileNames]Exe=MyProg.exeSaveAs=MyProgNew.exeLog=MyProg.log[Commands]-delete VERSIONINFO,1,1033 Deleted: VERSIONINFO,1,1033-add VersionInfo.res, VERSIONINFO,1,1033 Added: VERSIONINFO,1,1033Done.Ok... new VERSIONINFO was inserted. 5. How to use or extract the value from InnoSetup?InnoSetup provides only a preprocessor function called GetStringFileInfo()so one can not use#define SERIAL GetStringFileInfo("path/to/MyProgNew.exe", "PrivateBuild")And so we have to find a workaround to access the info and that works probably using the WinAPI. Here is one way to do it, which has some room for improvement. Its written by El Sanchez over at OsZone.net.[Code]#ifdef UNICODE #define A "W"#else #define A "A"#endiffunction GetFileVersionInfoSize(lptstrFilename: String; lpdwHandle: Integer): Integer;external 'GetFileVersionInfoSize{#A}@version.dll stdcall delayload';function GetFileVersionInfo(lptstrFilename: String; dwHandle, dwLen: Integer; var lpData: Byte): Boolean;external 'GetFileVersionInfo{#A}@version.dll stdcall delayload';function VerQueryValue(var pBlock: Byte; lpSubBlock: String; var lplpBuffer: DWord; var puLen: Integer): Boolean;external 'VerQueryValue{#A}@version.dll stdcall delayload';function GetFileVerInfo(FileName, VerName: String): String;//VerName://Comments, LegalCopyright, CompanyName, FileDescription, FileVersion, ProductVersion,//InternalName, LegalTrademarks, OriginalFilename, ProductName, PrivateBuild, SpecialBuildvar dwLen, puLen, i: Integer; lpFileVerInfo: array of Byte; lplpBufferCP, lplpBufferVN: DWord; LangCodepage: String;begin Result := ''; if FileExists(FileName) then begin dwLen := GetFileVersionInfoSize(FileName, 0); if dwLen > 0 then begin SetArrayLength(lpFileVerInfo, dwLen); if GetFileVersionInfo(FileName, 0, dwLen, lpFileVerInfo[0]) then begin if VerQueryValue(lpFileVerInfo[0], '\VarFileInfo\Translation', lplpBufferCP, puLen) then begin LangCodepage := Format('%.2x%.2x%.2x%.2x', [lpFileVerInfo[(dwLen div 2)-5], lpFileVerInfo[(dwLen div 2)-6], lpFileVerInfo[(dwLen div 2)-3], lpFileVerInfo[(dwLen div 2)-4]]); if VerQueryValue(lpFileVerInfo[0], Format('\%s\%s\%s', ['StringFileInfo', LangCodepage, VerName]), lplpBufferVN, puLen) then begin i := (dwLen div 2) + lplpBufferVN - lplpBufferCP - 6; repeat if lpFileVerInfo[i] <> 0 then begin SetLength(Result, Length(Result)+1); Result[Length(Result)] := Chr(lpFileVerInfo[i]); end; i := i + 1; #ifdef UNICODE until i > (dwLen div 2) + lplpBufferVN - lplpBufferCP - 8 + puLen; #else until lpFileVerInfo[i] = 0; #endif end; end; end; end; end;end;then GetFileVerInfo(ExpandConstant('{srcexe}'), "PrivateBuild");6. Sign the installer Will updating my resources ruin my code signing of the installer?Yes, the insert will change the executable. You will have to sign it after the modification. Use an unsigned installer beforehand, then insert, then sign (on the server).-- You can execute all steps with PHP on server-side.You need ResourceHacker.exe and windres.exe on the server and wine for executing them. 这篇关于如何将数据写入服务器上的安装程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-26 19:51