我有这个功能:
function GetProfilePath: string;
const
SHGFP_TYPE_CURRENT = 0;
var
hToken: THandle;
ProfilePath: packed array[ 0..MAX_PATH ] of Char;
begin
ZeroMemory(@ProfilePath[0], SizeOf(ProfilePath));
OpenProcessToken( GetCurrentProcess, TOKEN_QUERY, hToken );
SHGetFolderPath( 0, CSIDL_APPDATA, hToken , SHGFP_TYPE_CURRENT, @ProfilePath[ 0 ] );
CloseHandle( hToken );
Result := ProfilePath;
end;
SHGetFolderPath返回E_FAIL(0x80004005)和一个空的ProfilePath缓冲区。 MSDN表示E_FAIL表示“nFolder中的CSIDL有效,但该文件夹不存在”。但文件夹确实存在,我很确定。当我创建一个简单的测试应用程序并运行相同的代码时,它运行良好。
这可能有什么问题?
更新: 我发现在Delphi下运行时我的应用程序运行不正常。当我单独运行时,一切正常。
谢谢, 罗马
答案 0 :(得分:2)
使用用户令牌看起来不必要复杂。但是,话说回来,当我在我的机器上运行你的代码时,它运行良好,没有错误。也许您的进程的用户令牌对该文件夹没有足够的权限。或者文件夹真的不存在!
对于它的价值,我认为您最好使用更简单的关闭API SHGetSpecialFolderPath
。我的包装器看起来像这样:
function GetSpecialFolderPath(const CSIDL: Integer): string;
var
Buffer: TWin32PathBuffer;
begin
if SHGetSpecialFolderPath(Application.Handle, @Buffer[0], CSIDL, False) then begin
Result := Buffer;
end else begin
RaiseLastOSError;
end;
end;
当然,如果文件夹确实不存在,这可能会以与版本相同的方式失败。
好的,我在你的问题中重新阅读了这条评论:
当我创建一个简单的测试应用程序并运行相同的代码时,它运行良好。
这听起来像是在不同的上下文中运行真实的代码。也许在服务中?或者用户模仿。也许这就是解决这个问题的线索。您没有告诉我们代码失败的环境/上下文/设置?
对您的代码进行一些非常轻微的评论。您已经为ProfilePath
添加了一个超过需要的元素,packed
对于数组来说是多余的:
ProfilePath: array[ 0..MAX_PATH-1 ] of Char;
或者,更好的是,重用Delphi RTL中定义的类型TWin32PathBuffer
。