从IWinHttpRequest返回的二进制数据已更改,无法将Variant转换为字节数组

时间:2018-10-09 23:27:56

标签: inno-setup ole pascalscript winhttprequest

在安装过程结束时的安装场景中,每个客户端都从服务器下载应用程序密钥。该文件由〜64个随机字节组成,二进制,未编码。它应该存储在安装目录下的配置文件中。

该设置由Inno Setup处理,该创新在CurStepChanged事件期间调用密钥生成过程。创建OLE WinHttp.WinHttpRequest.5.1,发送包含客户端数据的POST请求,并应接收二进制响应。使用WinHttpReq.ResponseText提取响应,并使用SaveStringToFile存储到文件中。

但是,结果文件与从服务器发送的文件不同。例如,在服务器端记录的数据:

5a7868256a890e25735f431351f023c143f0cc397e6ec01e8a81806564eaa9f4fc8a005d9035c18fa32f95daaeff34955f3f6e4bfc5051bd33a522cc2aaddac8f29a1031dcb23728250c4f0a73db6a5bcc64e1ddef71a6

被接收为

5a7868256a3f0e25735f4313513f23c1433f49397e6e411e3f813f656465a9f4fc3f005d9035c13f4c2f3fdaae79343f5f3f6e4bfc505131335922492aadda456f3f1031dc323728250c4f0a73556a5b4964e1dd6971a6

(例如第6个字节不同)。没有此类问题,因为数据不包含非ASCII数据。

我的第一个想法是,在某些时候,将二进制数据编码/解码为文本会修改某些字节。我想使用IWinHttpRequest::ResponseBody来访问二进制版本而不是文本版本的数据。传递此属性将导致目标文件填充?个字符而不是数据。仅保留了ASCII字符。

我还尝试将ResponseBody转换为pascal字节数组,但收到Type Mismatch错误。 VarType的{​​{1}}返回dec 8209,它映射到ResponseBodyarray,但是将byte分配给ResponseBody会导致上述错误。

在Inno Setup中将二进制HTTP结果存储到文件的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

您没有向我们展示您的代码,因此很难说出您可能遇到的问题。

尽管我想您已经将WinHttpReq.ResponseText(宽string)直接传递给SaveStringToFile(需要AnsiString)。这涉及到UTF-16到ANSI的隐式编码转换,从而导致某些字符丢失或转换。

在Inno Setup的 Unicode 版本中,此方法工作正常:

var
  WinHttpReq: Variant;
  S: string;
  I: Integer;
  Data: AnsiString;
begin
  WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
  WinHttpReq.Open('GET', 'https://www.example.com/key.dat', False);
  WinHttpReq.Send('');
  if WinHttpReq.Status <> 200 then
  begin
    Log('HTTP Error: ' + IntToStr(WinHttpReq.Status) + ' ' + WinHttpReq.StatusText);
  end
    else
  begin
    S := WinHttpReq.ResponseText;
    SetLength(Data, Length(S));
    for I := 1 to Length(S) do
    begin
      Data[I] := S[I];
    end;

    SaveStringToFile(ExpandConstant('{app}\key.dat'), Data, False);
  end;
end;

该代码对于下载大型二进制文件可能效率不高。但是对于64个字节,就可以了。对于较大的文件,可能是can use ADODB.Stream class