SHGetFolderPath对我不起作用

时间:2011-11-25 12:14:00

标签: delphi winapi

我有这个功能:

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下运行时我的应用程序运行不正常。当我单独运行时,一切正常。

谢谢, 罗马

1 个答案:

答案 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