【问题标题】:Why does ShGetFolderPath return nil when the folder exists on some Vista pc's当文件夹存在于某些 Vista 电脑上时,为什么 ShGetFolderPath 返回 nil
【发布时间】:2010-02-09 14:53:48
【问题描述】:

在测试我们的应用程序时,我们发现使用 ShGetFolderPath 返回 AppData 路径,即使该文件夹存在于测试 PC 上,该函数也会返回 nil。在开发 PC 上 ShGetFolderPath 返回 AppData 路径,没有错误。

开发PC和测试PC都运行Vista。

function GetShellFolder( ID: Cardinal; Create: Boolean = False ): string;
// This function is a superset of SHGetSpecialFolderPath, included with
// earlier versions of the Shell. On systems preceeding those including
// Shell32.dll version 5.0 (Windows Millennium Edition (Windows Me) and
// Windows 2000), SHGetFolderPath was obtained through SHFolder.dll,
// distributed with Microsoft Internet Explorer 4.0 and later versions.

// Takes the CSIDL of a folder and returns the path or 'Could not determine
// folder path' if it does not exist.  Creates the folder if it does not
// exist if Create is true.
var
  Res: HResult;
  Path: array [ 0 .. Max_Path ] of Char;
begin
  if Create then
    ID := ID or csidl_Flag_Create;
  Res := ShGetFolderPath( 0, ID, 0, shgfp_Type_Current, Path );
  if S_OK <> Res then
  begin
    Result := 'Could not determine folder path';
    raise Exception.Create( 'Could not determine folder path' );
  end;
  Result := Path;
end;

GetShellFolder( CSIDL_LOCAL_APPDATA, False );

在开发机上成功返回 CSIDL_LOCAL_APPDATA 路径,但在测试机上没有返回 CSIDL_LOCAL_APPDATA 文件夹。

有谁知道为什么 CSIDL_LOCAL_APPDATA 文件夹在测试 PC 上没有返回,即使该文件夹存在于硬盘上?测试机返回 CSIDL_HISTORY 的历史文件夹,但它没有返回本地 appdata 文件夹的 CSIDL_LOCAL_APPDATA。

在测试 PC 资源管理器中,CSIDL_LOCAL_APPDATA 文件夹显示为 users\user\AppData\Local。在测试 PC 资源管理器中,CSIDL_HISTORY 文件夹显示为 users\user\AppData\Local\Microsoft\Windows\History。

如果我们调用 GetShellFolder(CSIDL_LOCAL_APPDATA, True) 函数仍然不会返回文件夹路径。

我做错了什么或者我该如何解决这个问题?

【问题讨论】:

  • 您的函数没有“返回”“无法确定文件夹路径”。当函数引发异常时,根本没有没有返回值。您正在检查S_OK 的结果,但没有考虑任何其他可能的返回值,例如S_FalseE_FailE_InvalidArg。当 ShGetFolderPath 失败时,它应该告诉你原因。不要忽视这些信息。另一件事:您的程序是服务,还是以提升的权限运行?
  • 这是一个没有提升权限的普通应用程序。
  • 为什么要硬编码错误代码而不是使用 RaiseLastOSError?您将获得更多有用的本地化错误消息以及错误代码

标签: delphi


【解决方案1】:

一些可能会派上用场的附加信息:1. 什么 delphi 版本(unicode 或 ansi) 2. 是否引发了异常?如果是,那么 shGetFolderPat 调用的确切结果是什么?调用(我们现在不是 S_OK,但它是什么?)

至于实际答案,根据规范,PATH-应该是长度为 MAX_PATH 的以零结尾的字符串。目前,í 根本没有初始化(局部变量),这可能解释了两台机器之间的差异。您可能想先尝试将其填充为零。远射,我承认。

【讨论】:

  • Delphi 版本为 Delphi 2010。
  • 我更改了函数以返回所有标准 HRESULT 代码以及 HResult。在失败的测试 PC 中,返回错误代码 -2147024891。
  • 该错误代码 0x80070005 表示 E_ACCESSDENIED。考虑到这一点,您可能会发现 bit.ly/9MEp7x 很有帮助。
  • 感谢您的错误代码。我将 E_ACCESSDENIED 添加到 GetShellFolder 现在报告为异常的错误代码中。如果我以管理员身份在测试 PC 上运行应用程序,GetShellFolder 找到 appdata 文件夹,但它作为我妻子的用户名返回......所以现在的问题是,当我是 PC 的管理员时,为什么访问被拒绝,为什么 AppData路径用户不是我?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
相关资源
最近更新 更多