SHGetFolderPath不推荐使用什么替代方法来检索Windows文件夹的path?

Windows Vista开始,已弃用SHGetFolderPath()函数: http : //msdn.microsoft.com/zh-cn/library/bb762181%28v=VS.85%29.aspx

在Windows中检索应用程序文件夹path的另一种方法是什么?

 SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath) 

除此之外,为什么我在使用这个函数时会遇到这些错误:

 Error 1 error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier Error 2 error C3861: 'SHGetFolderPath': identifier not found 

替代方法在您链接的文档中进行了描述。 即它是SHGetKnownFolderPath

但是, SHGetKnownFolderPath仅在Vista或更高版本上可用。 所以,如果你使用加载时间链接,并运行XP上调用SHGetKnownFolderPath的程序,那么该程序将无法启动。 这显然是一个问题,如果你想支持XP。

现在,您可以切换到运行时SHGetKnownFolderPath链接。 在调用之前进行版本检查,如果函数不可用,则返回到SHGetFolderPath

就我个人而言,我不会让这种贬低过度担心。 微软以维护向后兼容性而闻名。 不要期望SHGetFolderPath很快消失。 你会发现SHGetFolderPath存在于Windows 8中,我预计它现在仍然存在于10年后的任何Windows中。 我的建议是坚持加载时间链接,只有切换到SHGetKnownFolderPath当你放弃支持XP。

你的另一个问题,就是如何调用SHGetFolderPath 。 您需要尊重在您的问题中链接到的MSDN文档主题底部所列出的要求。 具体来说,包括Shlobj.h并将Shlobj.h传递给链接器。

它被链接在顶部, SHGetKnownFolderPath 。

CSIDL_COMMON_APPDATA被新的API中的FOLDERID_ProgramData所取代。

我已经在Windows 10 PC上使用SHGetFolderPath()与Visual Studio 2015 Enterprise进行了测试,并且编译并正常工作以找到当前用户的主文件夹。 在SHGetFolderPath() SHGetFolderPath函数的Windows开发人员中心页面中有以下注释:

注意从Windows Vista开始,此函数仅仅是SHGetKnownFolderPath的包装器。 将CSIDL值转换为与其关联的KNOWNFOLDERID ,然后SHGetKnownFolderPath 。 新的应用程序应该使用已知的文件夹系统,而不是旧版本的CSIDL系统,后者仅支持向后兼容。

正如David Heffman在答复中指出的那样,微软在多年的时间里保持向后兼容性的历史,尤其是当他们可以采用旧的功能,并将其重定向到具有适当参数的新功能时。 CSIDL值似乎有一个相应的KNOWNFOLDERID值。 请参阅此CSIDL常量表,其中包含简短的注释和相应的KNOWNFOLDERID值。

下面是一个使用该功能的例子。 此用法检索当前用户的用户文件夹(例如Windows 7下的“C:\ Users \ myuser \ Documents”),然后使用PathAppend()函数将文件夹名称添加到路径PathAppend()

 TCHAR achDevice[MAX_PATH]; HRESULT hr; // include file ShlObj.h contains list of CSIDL defines however only a subset // are supported with Windows 7 and later. // for the 3rd argument, hToken, can be a specified Access Token or SSID for // a user other than the current user. Using NULL gives us the current user. if (SUCCEEDED(hr = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, achDevice))) { // append a folder name to the user's Documents directory. // the Path Handling functions are pretty handy. PathAppend(achDevice, L"xxx"); } 

一个可能的失败是一个或多个无效参数(hr == E_INVALIDARG )。 S_OK的返回值表示调用成功。

有几个CSIDL常量可以用来修改函数的结果,如CSIDL_FLAG_CREATE通过使用按位或运算符。 我不确定这些操作员能够在Windows 7及更高版本中工作得如何。

Windows 7及更高版本支持的CSIDL常量有限制。 在Active Directory或类似的环境中,复杂,远程安装,重定向和/或共享文件夹也可能需要克服。

另请参见KNOWNFOLDERID ,其中包含一个表,指出CSIDLSHGetFolderPath()一些限制。 CSIDL常量表中的一些示例可能有用。

 CSIDL_LOCAL_APPDATA - %USERPROFILE%\AppData\Local CSIDL_MYDOCUMENTS - %USERPROFILE%\Document CSIDL_PERSONAL - %USERPROFILE%\Documents CSIDL_FONTS - %windir%\Fonts CSIDL_MYMUSIC - %USERPROFILE%\Music CSIDL_MYPICTURES - %USERPROFILE%\Pictures CSIDL_COMMON_APPDATA - %ALLUSERSPROFILE% (%ProgramData%, %SystemDrive%\ProgramData) CSIDL_COMMON_DOCUMENTS - %PUBLIC%\Documents 

顺便说一下, Shell路径处理函数是一个很好的操作文件路径的方法库。

另请参见在何处放置常用的可写应用程序文件?