如何在 Pascal Script/Inno 安装程序中使用 WinAPI 中的 PathCombine()?

How do I use PathCombine() from WinAPI in Pascal Script/Inno Setup?

我正在尝试了解如何使用 Pascal Script/Inno 安装程序中的 WinAPI 函数。我没有找到太多代码示例如何去做,而且我不是 Pascal 程序员。这是我到目前为止所做的:

正在导入函数

function PathCombine (
    pszPathOut : PChar;
    pszPathIn  : PChar;
    pszMore    : PChar
) : PChar;
  external 'PathCombineA@Shlwapi.dll stdcall';

并像这样使用它:

function InitializeSetup(): Boolean;
var 
  a, b,c : PChar;
  s : string;
begin
   SetLength(s, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
   a := 'C:';
   b := 'one\two';
   c := PathCombine(s, a, b);
   MsgBox(s, mbInformation, MB_OK);
end;

输出是这样的:

预期输出为:

C:\one\two

我很确定我正在访问内存中的垃圾值,但我不知道为什么,我该如何解决这个问题?

我认为(虽然我有一段时间没有使用 Pascal/Delphi)问题是C "strings" (char *) 基于 0 索引,而 Pascal 字符串是基于 1 索引的(字节 0 用于存储长度)。

因此,如果您将 s 变量声明为:

s: array[0..255] of Char;  //Don't forget to change it to MAX_PATH afterwards

应该可以。也可以像这样使用 PathCombine 函数:

PathCombine(s, a, b);

无需将其结果(与 s 相同)分配给另一个变量(无论如何您都不会使用)。

您没有指定您使用的是 Ansi 还是 Unicode 版本的 Inno Setup。

但这应该适用于任一版本:

function PathCombine(
   pszPathOut : PAnsiChar;
   pszPathIn  : PAnsiChar;
   pszMore    : PAnsiChar
) : PAnsiChar; external 'PathCombineA@Shlwapi.dll stdcall';

function InitializeSetup(): Boolean;
var 
  a, b, c: AnsiString;
begin
   SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
   a := 'C:';
   b := 'one\two';
   PathCombine(c, a, b);
   MsgBox(c, mbInformation, MB_OK);
   Result := True;
end;

尽管我强烈建议您改用 Unicode version of Inno SetupPathCombineW

function PathCombine(
   pszPathOut : string;
   pszPathIn  : string;
   pszMore    : string
) : Cardinal; external 'PathCombineW@Shlwapi.dll stdcall';

function InitializeSetup(): Boolean;
var 
  a, b, c: string;
begin
   SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
   a := 'C:';
   b := 'one\two';
   PathCombine(c, a, b);
   MsgBox(c, mbInformation, MB_OK);
   Result := True;
end;

请注意,Inno Setup 缺少 PWideChar 类型。虽然它可以将 string 编组到 LPTSTR (PWideChar) 函数参数,但它不能编组 LPTSTR return 值。所以我使用 Cardinal 作为 return 类型。它与指针(指向 char)具有相同的大小,因此堆栈将匹配。我们实际上并不需要 returned 值。