Inno 设置 URLDownloadToCacheFile

Inno Setup URLDownloadToCacheFile

每次我尝试编译此代码时,都会收到一条错误消息 -> 类型不匹配。为什么?

第一个变体使用相同的 "nil" 调用,编译器没有问题,但最后一个变体?

[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp
DefaultGroupName=MyApp
OutputDir=.

[Code]
function URLDownloadToCacheFile(const lpUnkcaller: variant; const szURL: PAnsiChar; var szFileName: PAnsiChar; const cchFileName: DWORD; const dwReserved: DWORD; IBindStatusCallback: variant): HRESULT; external 'URLDownloadToFileW@Urlmon.dll stdcall';

function InitializeSetup(): Boolean;
var
  szFileName, szURL : PAnsiChar;
  ErrorCode : HRESULT;
  MAX_PATH : DWORD;
begin
  szURL := 'http://fs2.directupload.net/images/user/150607/x3sugvzy.jpg';
  MAX_PATH := 512;
  SetLength(szFileName, MAX_PATH + 1);
  ErrorCode := URLDownloadToCacheFile(null, szURL, szFileName, MAX_PATH, 0, null);
end;

这样更改代码:

[Setup]
AppName=MyApp
AppVerName=MyApp
DefaultDirName={pf}\MyApp
DefaultGroupName=MyApp
OutputDir=.

[Code]
function URLDownloadToCacheFile(const lpUnkcaller: variant; const szURL: AnsiString; var szFileName: String; const cchFileName: DWORD; const dwReserved: DWORD; IBindStatusCallback: variant): HRESULT; external 'URLDownloadToFileW@Urlmon.dll stdcall';

function InitializeSetup(): Boolean;
var
    szFileName : String;
    szURL : AnsiString;
    ErrorCode : HRESULT;
    MAX_PATH : DWORD;
begin
    szURL := 'http://fs2.directupload.net/images/user/150607/x3sugvzy.jpg';
    MAX_PATH := 512;
    SetLength(szFileName, 513);
    ErrorCode := URLDownloadToCacheFile(null, szURL, szFileName, MAX_PATH, 0, null);
    MsgBox(szFileName,mbConfirmation, MB_OK);
end;

最初的问题是您将 nil 传递给 Variant 类型的参数。 Variant 类型的空值在 Pascal 脚本中是 NULL

但是,您的原型需要更改。当您使用函数的 Unicode 变体时,您需要使用 Unicode 数据类型,因此您不能在那里使用 PAnsiChar 类型。下一个问题是您用于接口类型参数的 Variant 类型。那行不通的。您可以在那里使用 IUnknown 类型,因为 lpUnkcaller 参数是指向此类型的指针,而 pBSC 是从 IUnknown 继承的 IBindStatusCallback 类型。最后一个问题就是MSDN这里错了。 szURL 是根据 LPCTSTR 类型的头文件,而不是 LPCSTR。 SDK 8.1 urlmon.h 头文件中的 Unicode 变体原型如下所示(由我格式化和注释):

STDAPI URLDownloadToCacheFileW(
    _In_opt_ LPUNKNOWN,
    _In_ LPCWSTR, // <- this is wrong on MSDN; this type would have to be LPCSTR here
    _Out_writes_(cchFileName) LPWSTR,
    DWORD cchFileName,
    DWORD,
    _In_opt_ LPBINDSTATUSCALLBACK
);

所以,你的脚本可能是这样写的(它应该也支持 ANSI 版本的 Inno Setup,但我还没有在那里测试过):

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program

[Code]
const
  MAX_PATH = 260;
  S_OK = [=11=]000000;

#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

function URLDownloadToCacheFile(lpUnkcaller: IUnknown; szURL: string; szFileName: string;
  cchFileName: DWORD; dwReserved: DWORD; pBSC: IUnknown): HRESULT;
  external 'URLDownloadToCacheFile{#AW}@urlmon.dll stdcall';

function TryDownloadToCache(const URL: string; out FileName: string): Boolean;
begin
  SetLength(FileName, MAX_PATH);
  Result := URLDownloadToCacheFile(nil, URL, FileName, Length(FileName), 0, nil) = S_OK;
end;

function InitializeSetup: Boolean;
var
  FileName: string;
  ErrorCode: Integer;
begin
  Result := True;

  if TryDownloadToCache('http://i.imgur.com/wKCsei6.png', FileName) then
    ShellExec('', FileName, '', '', SW_SHOW, ewNoWait, ErrorCode)
  else
    MsgBox('Downloading failed.', mbError, MB_OK);
end;