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;
每次我尝试编译此代码时,都会收到一条错误消息 -> 类型不匹配。为什么?
第一个变体使用相同的 "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;