使用 Inno Setup 中的缓冲区调用 DLL 函数 (GetPrivateProfileSection)

Car*_*rro 3 dll inno-setup pascalscript

我想使用GetPrivateProfileSection(从 Windows Kernel32.dll)Inno Setup 脚本,它是一种 Delphi (Pascal) 程序。

但我不知道如何创建缓冲区(该缓冲区是函数中的 Out 参数)以及它在哪里放置我想要检索的有用信息。

TLa*_*ama 5

输入缓冲区是一个指向字符串的指针,您可以像string在函数导入原型中一样简单地声明它,只要您将导入函数的正确变体,即与您使用的 Inno Setup 变体相关的 ANSI 或 Unicode。

关于返回的缓冲区,它是一个由以空字符分隔的键值对组成的字符串,您需要在代码中对其进行处理。以下函数可以将 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;
Run Code Online (Sandbox Code Playgroud)

一种可能的用法:

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;
Run Code Online (Sandbox Code Playgroud)