众所周知,appdata文件夹是这个
C:\Users\*Username*\AppData\Roaming
在 Windows 7 上
由于我的应用程序将部署在各种 Windows 操作系统上,因此我需要能够 100% 地获取文件夹。问题是你如何在 C++ 中做到这一点?因为我不知道确切的 Windows 操作系统,它可能是 XP、Vista 或 7,最重要的是我不知道用户名是什么。
为了最大程度地兼容所有版本的 Windows,您可以SHGetFolderPath
使用.
它要求您为要检索其路径的文件夹指定CSIDL值。对于应用程序数据文件夹,这将是CSIDL_APPDATA
.
在 Windows Vista 和更高版本上,您应该改用该SHGetKnownFolderPath
函数,这需要您指定文件夹的KNOWNFOLDERID
值。同样,对于应用程序数据文件夹,适当的值为FOLDERID_RoamingAppData
.
要在 C++ 应用程序中使用这些函数中的任何一个,您需要包含shlobj.h
.
您可以尝试以下方法:
char* appdata = getenv("APPDATA");
此代码读取环境变量 APPDATA(您SET
在命令窗口中键入时也可以看到它)。它是在系统启动时由 Windows 设置的。
它将用户的appdata
路径作为绝对路径返回,包括用户名并考虑到他们使用的任何操作系统版本。
或许 Google 同事会觉得看看 std::filesystem 很有趣。例如,让我们假设 Windows 10 中的默认临时目录位置和 AppData 目录结构:
#include <filesystem>
auto path = std::filesystem::temp_directory_path()
.parent_path()
.parent_path();
path /= "Roaming";
if (!std::filesystem::exists(path))
std::filesystem::create_directories(path);
在 OP 的情况下,我假设这不能解决问题。在需要 100% 健壮的实现的情况下,我确实想提醒大家不要执行上述操作,因为系统配置很容易改变和破坏上述操作。
但也许这个问题的新访客可能会发现 std::filesystem 很有用。如果您正在寻找目录中的项目,您可能会想要操作它,为此,std::filesystem 可以成为您的朋友。
如果有人正在寻找一个简单的实现,这是我的:
#include <windows.h>
#include <shlobj.h>
#include <filesystem>
#include <iostream>
int main(void)
{
std::filesystem::path path;
PWSTR path_tmp;
/* Attempt to get user's AppData folder
*
* Microsoft Docs:
* https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
* https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid
*/
auto get_folder_path_ret = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &path_tmp);
/* Error check */
if (get_folder_path_ret != S_OK) {
CoTaskMemFree(path_tmp);
return 1;
}
/* Convert the Windows path type to a C++ path */
path = path_tmp;
/* Free memory :) */
CoTaskMemFree(path_tmp);
std::cout << path << std::endl;
return 0;
}
这是旧 C++ 版本的简单实现:
#include <shlobj.h>
// ...
wchar_t* localAppDataFolder;
if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) {
std::cerr << "problem getting appdata folder" << std::endl;
}
else std::wcout << L"folder found: " << localAppDataFolder << std::endl;