如何将数据写入服务器上的安装程序? [英] How to write data to an installer on the server?

查看:51
本文介绍了如何将数据写入服务器上的安装程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的处境很复杂.
Web上有一个可下载链接到我的安装程序.
在任何人下载安装程序之前,他们必须在浏览器中填写表格.
我想将表单中填写的信息保存在安装程序本身中.
我该怎么做?
*每次有人填写表格时,都无法在服务器上编译安装程序,因为安装程序非常繁琐,此过程将花费大量时间.
*在安装程序中创建表单不是一种选择.
*我只需要在可执行文件中保存一个数字即可.

解决方案

这是一个有趣的问题.我在这上面与TLama一起使用.在已经安装了安装程序的情况下,唯一的机会就是修改应用程序/可执行文件资源.

ResourceHacker 之类的工具可能有助于自动完成此任务. http://angusj.com/resourcehacker/resource_hacker.zip

在服务器端,您可以使用PHP接受表单数据,然后将其转发到用wine执行并从PHP执行的ResourceHacker,例如:

exec("wine ResourceHacker.exe -script ScriptFile");.

对于如何将数据从表单传递到ResourceHacker,您有一些选择:cli参数,文件等.对于服务器端的自动化,我建议使用ScriptFile.

ScriptFile可能像...

[FILENAMES]
Exe=Installer.exe
SaveAs=ModifiedInstaller.exe
Log=file.log

[COMMANDS]
-modify       ResourceSrc, ResourceMask

为了找到要更改的元素,您可以在Windows系统上使用ResourceHacker GUI并进行播放,直到它起作用为止,然后相应地在服务器端更改脚本以实现自动化.


好吧,在大致解释了如何修改资源之后,让我们详细介绍一下:

就像我指出的那样,也可以为此使用语言字符串并对其进行更改,但是我将提供分步说明以在可执行文件的VERSION_INFO部分中插入新字段.出于测试目的,我致力于 \innosetup\Examples\MyProg.exe

我们的目标是添加带有序列号的新值"PrivateBuild".

(根据 https: //msdn.microsoft.com/de-de/library/windows/desktop/aa381049(v=vs.85).aspx ,也有"Comments"和"SpecialBuild"可用于输入信息.)

1.从MyProg.exe提取版本信息到VersionInfo.rc

ResourceHacker.exe -extract MyProg.exe, VersionInfo.rc, versioninfo,,

VersionInfo.rc的内容如下:

1 VERSIONINFO
FILEVERSION 1,5,0,0
PRODUCTVERSION 1,5,0,0
FILEOS 0x4
FILETYPE 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 VERSIONINFO
FILEVERSION 1,5,0,0
PRODUCTVERSION 1,5,0,0
FILEOS 0x4
FILETYPE 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.exe
SaveAs=MyProgNew.exe
Log=MyProg.log

[Commands]
-delete VERSIONINFO,1,1033
-add VersionInfo.res, VERSIONINFO,1,1033

让我们检查一下日志:

[08 Sep 2015, 11:21:33]

[FileNames]
Exe=MyProg.exe
SaveAs=MyProgNew.exe
Log=MyProg.log

[Commands]
-delete VERSIONINFO,1,1033
  Deleted: VERSIONINFO,1,1033
-add VersionInfo.res, VERSIONINFO,1,1033
  Added: VERSIONINFO,1,1033

Done.

确定.已插入新的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"
#endif
function 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, SpecialBuild
var
  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.exewindres.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.zip

On 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.exe
SaveAs=ModifiedInstaller.exe
Log=file.log

[COMMANDS]
-modify       ResourceSrc, ResourceMask

In 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.exe

Our 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.rc

ResourceHacker.exe -extract MyProg.exe, VersionInfo.rc, versioninfo,,

The content of VersionInfo.rc looks like this:

1 VERSIONINFO
FILEVERSION 1,5,0,0
PRODUCTVERSION 1,5,0,0
FILEOS 0x4
FILETYPE 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 Info

We 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 VERSIONINFO
FILEVERSION 1,5,0,0
PRODUCTVERSION 1,5,0,0
FILEOS 0x4
FILETYPE 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 VersionInfo

windres -i VersionInfo.rc -o VersionInfo.res -O res

Now the VersionInfo text is a resource again.

4. Insert resource into exe

ResourceHacker.exe -script ScriptFile.rh

where ScriptFile.rh contains

[FileNames]
Exe=MyProg.exe
SaveAs=MyProgNew.exe
Log=MyProg.log

[Commands]
-delete VERSIONINFO,1,1033
-add VersionInfo.res, VERSIONINFO,1,1033

Let's check the log:

[08 Sep 2015, 11:21:33]

[FileNames]
Exe=MyProg.exe
SaveAs=MyProgNew.exe
Log=MyProg.log

[Commands]
-delete VERSIONINFO,1,1033
  Deleted: VERSIONINFO,1,1033
-add VersionInfo.res, VERSIONINFO,1,1033
  Added: VERSIONINFO,1,1033

Done.

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"
#endif
function 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, SpecialBuild
var
  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.

这篇关于如何将数据写入服务器上的安装程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆