C++ SHGetFolderPath已弃用:检索Windows文件夹路径的替代方法是什么?
从Windows Vista开始,不推荐使用C++ SHGetFolderPath已弃用:检索Windows文件夹路径的替代方法是什么?,c++,windows,winapi,known-folders,C++,Windows,Winapi,Known Folders,从Windows Vista开始,不推荐使用SHGetFolderPath()函数: 在Windows中检索应用程序文件夹路径的替代方法是什么 SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath) 除此之外,为什么在使用此函数时会出现这些错误: Error 1 error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier Error 2 error
SHGetFolderPath()
函数:
在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
它链接在顶部的右侧
CSIDL_COMMON_APPDATA在新API中被FOLDERID_ProgramData替换。您链接到的文档中描述了替代方案。也就是说它是 但是,
SHGetKnownFolderPath
仅在Vista或更高版本上可用。因此,如果您使用加载时间链接,并在XP上运行调用SHGetKnownFolderPath
的程序,那么该程序将无法启动。如果您希望支持XP,这显然是一个问题
现在,您可以切换到运行时链接SHGetKnownFolderPath
。在调用之前执行版本检查,如果该函数不可用,则返回到SHGetFolderPath
就我个人而言,我不会让这种批评让你过分担心。微软以保持向后兼容性而闻名。不要期望SHGetFolderPath
很快消失。你会发现SHGetFolderPath
存在于Windows 8中,我希望它在10年后的任何Windows中都会存在。我的建议是坚持加载时间链接,只有当您放弃支持XP时才切换到SHGetKnownFolderPath
您在编辑中提出的另一个问题是如何调用
SHGetFolderPath
。您需要遵守您在问题中链接到的MSDN文档主题底部列出的要求。具体来说,包括Shlobj.h
并将Shlobj.lib
传递给链接器。我已经在Windows 10 PC上使用Visual Studio 2015 Enterprise上的SHGetFolderPath()
进行了测试,它编译后运行良好,可以找到当前用户的主文件夹。在SHGetFolderPath()
上的Windows开发中心页面中,有以下注释:
注意从Windows Vista开始,此函数仅是
SHGetKnownFolderPath
。CSIDL
值被转换为其关联的
KNOWNFOLDERID
然后调用SHGetKnownFolderPath
。新的
应用程序应使用已知的文件夹系统,而不是旧的文件夹系统
CSIDL
系统,仅支持向后兼容
正如David Heffman在他的回答中指出的那样,微软多年来一直保持向后兼容性,特别是当他们可以使用旧函数并使用适当的参数将其重定向到新函数时。CSIDL
值似乎具有相应的KNOWNFOLDERID
值。请参阅此内容,并附上简短注释和相应的KNOWNFOLDERID
值
下面是使用该函数的示例。此用法检索当前用户的用户文件夹(例如Windows 7下的“C:\Users\myuser\Documents”),然后使用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\u FLAG\u CREATE
使用按位OR运算符。我不确定这些操作员在Windows7和更高版本上的工作情况如何
Windows 7及更高版本支持的CSIDL
常量存在限制。在Active Directory或类似环境中的复杂、远程装载、重定向和/或共享文件夹中,似乎也可能存在需要克服的问题
另请参见,其中包含一个表,该表指出了CSIDL
和SHGetFolderPath()
的一些限制。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
顺便说一下,是一个很好的操纵文件路径的方法库
另请参见当我在已经在工作的解决方案中添加了几个新的头文件时,我遇到了相同的错误集 我已经在调用
SHGetFolderPath
,并且也包含了#include
,但它位于不同的头文件中。在我向解决方案添加新的库头文件之前,该解决方案编译时没有出现任何错误
我尝试用SHGetKnownFolderPath()
替换SHGetKnownFolderPath()
,但这只是将标识符未找到错误重定向到SHGetKnownFolderPath
将#include
添加到调用SHGetFolderPath
的类的头文件时
错误停止,解决方案再次成功编译
如第页所述,在Windows Vista或更高版本的操作系统上调用
SHGetFolderPath
,将从microsoft内部调用SHGetKnownFolderPath
,替代名称为“SHGetKnownFolderPath”
从我的观点来看,这些函数是C语言、C++语言和类似语言的函数。
在powershell中,我刚刚阅读了注册表:
PS>cd hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\
PS>dir
这里我们来看看“Shell文件夹”和“用户Shell文件夹”
顺便说一句:这些是用来获取值的。我想那是相当安全的。为了设置值,最好不要直接使用注册表,因为它会毁了你的一天。使用资源管理器->这些“目录”的属性来移动它们,也会移动内容。不幸的是,我不知道如何在powershell中使用这个钩子。请参阅:以及最后一点,但是如何访问应用程序数据文件夹?但是如何访问应用程序数据文件夹?这是一个完全不同的问题。我更新了答案以涵盖它,bu