7

从 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
4

5 回答 5

12

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

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

现在,您可以切换到SHGetKnownFolderPath. 在调用之前进行版本检查,如果该函数不可用,则回退到SHGetFolderPath.

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

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

于 2013-08-28T16:43:28.263 回答
2

它在顶部链接,SHGetKnownFolderPath

CSIDL_COMMON_APPDATA 在新 API 中被 FOLDERID_ProgramData 取代。

于 2013-08-28T16:36:38.817 回答
1

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

我已经在打电话SHGetFolderPath并且也包括在内#include <ShlObj.h>,但它在不同的头文件中。在我添加新的库头文件之前,该解决方案正在编译,没有任何错误。

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

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

如本页所述SHGetFolderPathWindows Vista 或更高版本的操作系统上调用,将在内部调用SHGetKnownFolderPath.

于 2018-06-28T05:32:59.257 回答
0

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

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

正如大卫赫夫曼在他的回答中指出的那样,微软多年来一直保持向后兼容性,特别是当他们可以采用旧功能并使用适当的参数将其重定向到新功能时。这些CSIDL值似乎具有相应的KNOWNFOLDERID值。请参阅带有简短注释和相应值的量表。CSIDLKNOWNFOLDERID

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

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 及更高版本上的工作情况如何。

CSIDLWindows 7 及更高版本支持的常量存在限制。看起来在 Active Directory 或类似环境中的复杂、远程安装、重定向和/或共享文件夹中可能存在需要克服的问题。

另请参阅KNOWNFOLDERID,其中包含一个表,该表指示 和 的一些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

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

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

于 2016-08-04T14:53:59.620 回答
0

来自微软,altenate 是“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 文件夹”和“用户 Shell 文件夹”。

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

于 2020-05-19T16:09:41.150 回答