我正在使用Delphi XE2并从Shell32.dll导入SHGetFolderPath。我正在运行Windows Vista x64。运行SHGetFolderPathA时结果不清楚。
即:
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路径的路径。
再次感谢所有回复。
答案 0 :(得分:4)
您将SHGetFolderPath
的最终参数声明为类型PChar
。在Delphi 2009及更高版本(包括您的版本,Delphi XE2)中,PChar
是PWideChar
的别名,但您告诉Delphi将您声明的函数链接到“A”版本,该版本期望{{ 1}}字符。
当声明对字符类型敏感的函数时,我建议根本不使用AnsiChar
。明确使用PChar
或PWideChar
。
“A”和“W”后缀与运行程序的 machine 无关。 所有支持的Windows版本现在都是Unicode - 最后一个非Unicode版本是Windows ME。 “A”和“W”指的是参数的字符类型。
至于为什么你的代码在64位版本失败时在32位版本的Vista上工作,我没有解释。也许你很幸运,操作系统做了一些转换,碰巧在你的情况下运行正常。
答案 1 :(得分:1)
Char
在XE2中是Unicode,但您正在导入SHGetFolderPath()
的Ansi版本并将Unicode输出缓冲区传递给它。这就是你的MessageBox()
显示垃圾的原因 - 它试图在Unicode对话框中显示Ansi数据。您需要导入SHGetFolderPath()
的Unicode版本:
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.
BTW,XE2已经为您导入了SHGetFolderPath()
的Ansi和Unicode版本,并且定义了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.
答案 2 :(得分:0)
在你的代码中我看到两个错误一个错误:
- “Path”被声明为局部变量(即在堆栈上),因此它包含“随机”/陈旧数据。建议用零初始化它:fillChar(path [0],sizeOf(path),#0)