繁体   English   中英

SHGetFolderPath 已弃用:检索 Windows 文件夹路径的替代方法是什么?

[英]SHGetFolderPath Deprecated: What is alternative to retrieve path for Windows folders?

从 Windows Vista 开始不推荐使用SHGetFolderPath()函数: http : //msdn.microsoft.com/en-us/library/bb762181%28v=VS.85%29.aspx

在 Windows 中检索应用程序文件夹路径的替代方法是什么?

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

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

您在编辑中提出的另一个问题是如何调用SHGetFolderPath 您需要遵守您在问题中链接到的 MSDN 文档主题底部列出的要求。 具体而言,包括Shlobj.h并传递Shlobj.lib给链接器。

它链接在顶部, SHGetKnownFolderPath

CSIDL_COMMON_APPDATA 被新 API 中的 FOLDERID_ProgramData 替换。

当我向已经工作的解决方案添加几个新的头文件时,我遇到了同样的错误。

我已经在调用SHGetFolderPath并且还包含了#include <ShlObj.h>但它位于不同的头文件中。 在我向它添加新的库头文件之前,该解决方案在编译时没有任何错误。

我尝试用SHGetKnownFolderPath()替换SHGetFolderPath()但这只是将标识符未找到错误重定向到SHGetKnownFolderPath

#include <ShlObj.h>添加到调用SHGetFolderPath的类的头文件后,错误停止并且解决方案再次成功编译。

正如提到的这个页面,调用SHGetFolderPath在Windows Vista或更高的操作系统,将在内部调用SHGetKnownFolderPath

我已经在 Windows 10 PC 上使用带有 Visual Studio 2015 Enterprise 的SHGetFolderPath()进行了测试,它编译并运行得很好,可以找到当前用户的主文件夹。 SHGetFolderPath() SHGetFolderPath 函数的 Windows Dev Center 页面中,有以下注释:

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

正如大卫赫夫曼在他的回答中指出的那样,微软多年来一直保持向后兼容性,特别是当他们可以采用旧函数并使用适当的参数将其重定向到新函数时。 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常量可用于通过使用按位 OR 运算符来修改函数的结果,例如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 路径处理函数是一个很好的用于操作文件路径的方法库。

另请参阅将常见的可写应用程序文件放在哪里?

从微软,替代是“SHGetKnownFolderPath” https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpatha

在我看来,这些函数适用于 c、c++ 和类似的语言。 从powershell,我只是读取注册表:PS> cd hkcu:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ PS> dir

在这里查看“Shell Folders”和“User Shell Folders”。

顺便说一句:这些是为了获取值。 我会说这是相当安全的。 对于设置值,最好不要直接使用注册表,因为它会毁了你的一天。 使用资源管理器 -> 这些“目录”的属性来移动它们,也会移动内容。 不幸的是,我不知道在 powershell 中使用它的钩子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM