1

我正在使用 Delphi XE2 并从 Shell32.dll 导入 SHGetFolderPath。我正在运行 windows vista x64。运行 SHGetFolderPathA 时结果不清楚。

IE:

uses
  Windows;

function SHGetFolderPath(hwnd: Cardinal; csidl: Integer; hToken: Cardinal; dwFlags: Cardinal; pszPath: PChar): Cardinal; stdcall;external 'Shell32.dll' name 'SHGetFolderPathA';

Var
  Path:Array [0..MAX_PATH] of Char;
  AppData:String;

begin
  SHGetFolderPath(0,$001A,0,0,@path[0]);
  MessageBox(0,Path,'a',0);
end.

结果是:

在此处输入图像描述

与使用 SHGetFolderPathW 相比:

使用视窗;

function SHGetFolderPath(hwnd: Cardinal; csidl: Integer; hToken: Cardinal; dwFlags: Cardinal; pszPath: PChar): Cardinal; stdcall;external 'Shell32.dll' name 'SHGetFolderPathW';

Var
  Path:Array [0..MAX_PATH] of Char;
  AppData:String;

begin
  SHGetFolderPath(0,$001A,0,0,@path[0]);
  MessageBox(0,Path,'a',0);
end.

结果清楚地说明了我的 AppData 文件夹的路径,没有问题。

当使用 SHGetFolderPathA 在 x32 Vista 上运行相同的代码时,效果很好。

如果有人可以阐明这是为什么?我的印象是“W”api通常用于Unicode机器......?


编辑:

我现在正在使用以下代码,但出现相同的错误:

uses
  Windows;

function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWord; pszPath: PAnsiChar): HRESULT; stdcall; external 'SHFolder.dll' name 'SHGetFolderPathA';

var
  path: array[0..MAX_PATH] of char;
begin
  SHGetFolderPath(0,$001A,0,0, @path[0]);
  MessageBox(0,path,'a',0);
end.

最终编辑:

谢谢大家的回复。SHGetFolderPath 的上述声明很好。在查看了所有回复并获取了每个回复中的信息后,我得出了以下结果:

uses
  Windows;

function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWord; pszPath: PAnsiChar): HRESULT; stdcall; external 'shell32.dll' name 'SHGetFolderPathA';

var
  path: array[0..MAX_PATH] of ansichar;
  xRes:String;
begin
  If SHGetFolderPath(0,$001A,0,0, @path[0]) = S_OK Then Begin
    xRes := Path;
    MessageBox(0,PWideChar(xRes),'Result',0);
  End Else
    MessageBox(0,'An error has occurred.','Result',0);
end.

生成的消息框正确显示了我的 AppData 路径的路径。

再次感谢所有回复。

4

3 回答 3

4

您将 的最终参数声明SHGetFolderPath为具有 type PChar。在 Delphi 2009 及更高版本(包括您的版本 Delphi XE2)中,PChar是 的别名PWideChar,但您告诉 Delphi 将您声明的函数链接到需要AnsiChar字符的“A”版本。

在声明对字符类型敏感的函数时,我建议完全不要使用PChar。显式使用PWideCharPAnsiChar

“A”和“W”后缀与程序在哪种机器上运行无关。现在所有受支持的 Windows 版本都是 Unicode——最后一个非 Unicode 版本是 Windows ME。“A”和“W”是指参数的字符类型。

至于为什么你的代码在 32 位版本的 Vista 上运行,而在 64 位版本上失败,我没有解释。也许您很幸运,操作系统进行了一些转换,在您的情况下碰巧可以正常工作。

于 2012-10-31T22:19:13.920 回答
1

Char在 XE2 中是 Unicode,但是您正在导入 Ansi 版本SHGetFolderPath()并将 Unicode 输出缓冲区传递给它。这就是您MessageBox()显示垃圾的原因 - 它试图在 Unicode 对话框中显示 Ansi 数据。您需要导入 Unicode 版本SHGetFolderPath()

uses
  Windows;

function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWord; pszPath: PWideChar): HRESULT; stdcall; external 'SHFolder.dll' name 'SHGetFolderPathW';

var
  path: array[0..MAX_PATH] of Char;
begin
  SHGetFolderPath(0, $001A, 0, 0, path);
  MessageBox(0, path,'a', 0);
end.

顺便说一句,XE2 已经为您导入了 Ansi 和 Unicode 版本SHGetFolderPath(),并定义了 CSIDL 值,因此您无需手动执行:

uses
  Windows, ShlObj, SHFolder;

var
  path: array[0..MAX_PATH] of Char;
begin
  SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, path);
  MessageBox(0, path, 'a', 0);
end.
于 2012-10-31T23:16:29.893 回答
0

在你的代码中我看到两个错误一个错误:

- “路径”被声明为局部变量(即在堆栈上),因此它包含“随机”/陈旧数据。建议用零初始化:fillChar(path[0], sizeOf(path), #0)

  • SHGetFolderPath 是一个函数。它返回一个值。您永远不会测试函数的结果以查看它是否退出 - 您只是输出“路径”变量的内容。但是如果 SHGetFolderPath 由于某种原因失败了,内容是否有意义?
于 2012-10-31T23:01:06.553 回答