是什么导致SHGetFolderLocation在Lasterror设置为59的情况下返回false?

时间:2019-05-16 09:18:26

标签: windows delphi winapi

我有一个应用程序,有时无法获取AppData文件夹的路径。

这种情况似乎只发生在我们的Citrix服务器场上,并非针对每个用户,而且并非一直如此(我几乎无法复制)。

问题通过以下方式表现出来:

SHGetFolderLocation的调用方式为:

 Value := SHGetFolderLocation (0, CLSID, 0, 0, pidl);
 try
   case Value of
     S_OK:
     begin
       if not ShGetPathfromIDList(pidl, Path) then
         RaiseLastOSError();
       Result := trim(string(Path));
       break;
     end;
   else
     RaiseLastOSError();
   end;
 finally
   CoTaskMemFree(pidl);
 end;

({CLSID设置为CSIDL_APPDATA,定义为0x001a

根据堆栈跟踪,我们看到的是SHGetFolderLocation返回false,触发了对RaiseLastOSError的调用,这表明最后一个错误代码是59:

System Error. Code: 59. An unexpected network error occurred

我正在全力以赴,试图找出如何收到这样的错误消息:即使出现网络问题,我也看不到任何SHGetFolderLocation受其影响的原因。 / p>

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

SHGetFolderLocation()SHGetPathfromIDList()不会通过GetLastError()报告错误代码,因此在这种情况下您不能使用RaiseLastOSError()

SHGetFolderLocation()返回一个HRESULT值。您可以将该值传递给RTL的OleCheck()函数,如果HRESULT值表示错误,则会引发异常。

不幸的是,SHGetPathfromIDList()根本不报告错误代码,因此,如果您想引发异常,则如果失败,则必须手动引发自己的异常。

除非CoTaskMemFree()返回SHGetFolderLocation(),否则您不应调用S_OK,因为这是将pidl更新为指向已分配内存的唯一条件。任何其他返回值都会将pidl指针设置为nil

尝试一下:

OleCheck(SHGetFolderLocation(0, CLSID, 0, 0, pidl));
try
  if not SHGetPathFromIDList(pidl, Path) then
    raise Exception.Create('Cannot get filesystem path from PIDL');
  Result := string(Path);
finally
  CoTaskMemFree(pidl);
end;

只需使用SHGetFolderPath()即可大大简化:

OleCheck(SHGetFolderPath(0, CSIDL, 0, SHGFP_TYPE_CURRENT, Path));