简体   繁体   中英

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

I'm trying to figure out how to use WinAPI functions from Pascal Script/Inno Setup. I didn't find much code examples how to do it and I'm not a Pascal programmer. Here's what I did so far:

Importing the function

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

and using it like this:

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;

The output is this:

在此处输入图片说明

The expected output is:

C:\\one\\two

I'm pretty sure I'm accessing garbage values in memory but I don't know why, how do I fix this?

You didn't specify if you are using Ansi or Unicode version of Inno Setup.

But this should work in either version:

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;

Though I strongly encourage you to use Unicode version of Inno Setup and PathCombineW instead.

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;

Note that Inno Setup lacks PWideChar type. While it can marshal string to LPTSTR ( PWideChar ) function arguments, it cannot marshal LPTSTR return value. So I've used Cardinal for return type. It has the same size as pointer (to char), so a stack will match. And we do not actually need the returned value.

I think (although I haven't worked with Pascal / Delphi for a while) that the problem is that C "strings" ( char * ) are 0 index based, while Pascal strings are 1 index based (byte 0 is used to store the length).

So, if you declare your s variable as:

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

it should work. Also use the PathCombine function like this:

PathCombine(s, a, b);

There's no need to assign its result (which is the same as s ) to another variable (that you aren't going to use anyway).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM