使用 Inno Setup 中的缓冲区调用 DLL 函数 (GetPrivateProfileSection)
Calling a DLL function (GetPrivateProfileSection) using a buffer from Inno Setup
我想使用 Inno Setup 脚本中的 GetPrivateProfileSection
(来自 Windows Kernel32.dll
),这是一种 Delphi (Pascal) 程序。
但我不知道如何创建缓冲区,它是函数中的一个 Out 参数,以及它将我想要检索的有用信息放在哪里。
输入缓冲区是一个指向字符串的指针,您可以在函数导入原型中将其简单地声明为 string
,只要您导入函数的适当变体,ANSI 或 Unicode 相对于它您使用的 Inno Setup 变体。
关于返回的缓冲区,它是由空字符分隔的键值对组成的字符串,您需要在代码中对其进行处理。以下函数可以将 INI 部分读取到字符串列表中,例如:
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function GetPrivateProfileSection(lpAppName: string;
lpReturnedString: string; nSize: DWORD; lpFileName: string): DWORD;
external 'GetPrivateProfileSection{#AW}@kernel32.dll stdcall';
function GetIniSection(const FileName, Section: string; Strings: TStrings): Integer;
var
BufLen: DWORD;
Buffer: string;
begin
{ initialize the result }
Result := 0;
{ first attempt with 1024 chars; use here at least 3 chars so the function can }
{ return 1 as a signal of insufficient buffer failure }
SetLength(Buffer, 1024);
{ first attempt to call the function }
BufLen := GetPrivateProfileSection(Section, Buffer, Length(Buffer), FileName);
{ check the first call function result }
case BufLen of
{ the function failed for some reason, that the WinAPI does not provide }
0: Exit;
{ the function returned value of the passed buffer length - 2 to indicate that }
{ it has insufficient buffer }
Length(Buffer) - 2:
begin
{ second attempt with the maximum possible buffer length }
SetLength(Buffer, 32767);
{ this time it should succeed }
BufLen := GetPrivateProfileSection(Section, Buffer, Length(Buffer), FileName);
{ if the returned value is 0, or equals to the passed buffer length - 2, then }
{ even this call failed, so let's give it up }
if (BufLen = 0) or (BufLen = Length(Buffer) - 2) then
Exit;
end;
end;
{ the function call succeeded, so let's trim the result (note, that it will trim }
{ also the two terminating null characters from the end of the string buffer) }
Buffer := Trim(Buffer);
{ now replace all the null characters with line breaks so we can easily fill the }
{ output string list }
StringChangeEx(Buffer, #0, #13#10, True);
{ fill the output string list }
Strings.Text := Buffer;
{ and return the number of items in the output string list }
Result := Strings.Count;
end;
可能的用法:
var
Strings: TStringList;
begin
Strings := TStringList.Create;
try
{ if the function returns value greater than 0, it found a non-empty }
{ section called SectionName in the C:\MyFile.ini file }
if GetIniSection('C:\MyFile.ini', 'SectionName', Strings) > 0 then
{ process the Strings somehow }
finally
Strings.Free;
end;
end;
我想使用 Inno Setup 脚本中的 GetPrivateProfileSection
(来自 Windows Kernel32.dll
),这是一种 Delphi (Pascal) 程序。
但我不知道如何创建缓冲区,它是函数中的一个 Out 参数,以及它将我想要检索的有用信息放在哪里。
输入缓冲区是一个指向字符串的指针,您可以在函数导入原型中将其简单地声明为 string
,只要您导入函数的适当变体,ANSI 或 Unicode 相对于它您使用的 Inno Setup 变体。
关于返回的缓冲区,它是由空字符分隔的键值对组成的字符串,您需要在代码中对其进行处理。以下函数可以将 INI 部分读取到字符串列表中,例如:
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function GetPrivateProfileSection(lpAppName: string;
lpReturnedString: string; nSize: DWORD; lpFileName: string): DWORD;
external 'GetPrivateProfileSection{#AW}@kernel32.dll stdcall';
function GetIniSection(const FileName, Section: string; Strings: TStrings): Integer;
var
BufLen: DWORD;
Buffer: string;
begin
{ initialize the result }
Result := 0;
{ first attempt with 1024 chars; use here at least 3 chars so the function can }
{ return 1 as a signal of insufficient buffer failure }
SetLength(Buffer, 1024);
{ first attempt to call the function }
BufLen := GetPrivateProfileSection(Section, Buffer, Length(Buffer), FileName);
{ check the first call function result }
case BufLen of
{ the function failed for some reason, that the WinAPI does not provide }
0: Exit;
{ the function returned value of the passed buffer length - 2 to indicate that }
{ it has insufficient buffer }
Length(Buffer) - 2:
begin
{ second attempt with the maximum possible buffer length }
SetLength(Buffer, 32767);
{ this time it should succeed }
BufLen := GetPrivateProfileSection(Section, Buffer, Length(Buffer), FileName);
{ if the returned value is 0, or equals to the passed buffer length - 2, then }
{ even this call failed, so let's give it up }
if (BufLen = 0) or (BufLen = Length(Buffer) - 2) then
Exit;
end;
end;
{ the function call succeeded, so let's trim the result (note, that it will trim }
{ also the two terminating null characters from the end of the string buffer) }
Buffer := Trim(Buffer);
{ now replace all the null characters with line breaks so we can easily fill the }
{ output string list }
StringChangeEx(Buffer, #0, #13#10, True);
{ fill the output string list }
Strings.Text := Buffer;
{ and return the number of items in the output string list }
Result := Strings.Count;
end;
可能的用法:
var
Strings: TStringList;
begin
Strings := TStringList.Create;
try
{ if the function returns value greater than 0, it found a non-empty }
{ section called SectionName in the C:\MyFile.ini file }
if GetIniSection('C:\MyFile.ini', 'SectionName', Strings) > 0 then
{ process the Strings somehow }
finally
Strings.Free;
end;
end;