如何使用C++打开%appdata%文件夹?

27

众所周知,appdata文件夹就是这个。

 C:\Users\*Username*\AppData\Roaming

在Windows 7上,由于我的应用程序将部署在各种Windows操作系统上,所以我需要能够100%的时间获取文件夹。问题是如何在C++中实现?由于我不知道确切的Windows操作系统版本,它可能是XP、Vista或7,更重要的是我不知道用户名是什么。


1
可能重复:https://dev59.com/v1HTa4cB1Zd3GeqPPzsE - razlebe
3
那是C语言的,我正在询问有关C++语言的内容。 - dikidera
6个回答

37
为了确保与所有版本的Windows最大兼容性,您可以使用SHGetFolderPath函数。它需要您指定要检索路径的文件夹的CSIDL值。对于应用程序数据文件夹,这应该是CSIDL_APPDATA
在Windows Vista及更高版本中,您应该使用SHGetKnownFolderPath函数,它需要您指定该文件夹的KNOWNFOLDERID值。同样地,对于应用程序数据文件夹,适当的值是FOLDERID_RoamingAppData
要从您的C++应用程序中使用这些函数,您需要包含shlobj.h

你推荐哪个? - dikidera
2
@mfce:嗯,第一个应该在Vista之前的Windows版本上使用(如Windows 2000和XP)。然而,自Windows Vista以来,它已被弃用,为Vista和7编写的新应用程序应始终使用第二个。因此,这取决于程序运行的Windows版本。 - Cody Gray
它面向两者。 - dikidera
@mcfe: 好的...那么你需要写一个if语句。判断程序运行的Windows版本并调用相应的函数。由于SHGetKnownFolderPath在XP以前的版本中没有定义,所以你需要使用LoadLibraryGetProcAddress函数。 - Cody Gray

26
你可以尝试以下方法:
char* appdata = getenv("APPDATA");

这段代码读取环境变量 APPDATA(在命令窗口中键入SET也可以看到它)。当您的系统启动时,Windows 会设置该变量。

它将返回用户的 appdata 路径,包括 用户名 并考虑他们使用的操作系统版本,作为绝对路径。


3
对于那些好奇的人,这个方法在XP上行不通,因为appdata不是一个被认可的环境变量。但是,programfiles可以使用。 - NinjaMid76
随着时间的推移,getenv已经被弃用,现在建议使用更安全的_dupenv_s - itsho
SHGetFolderPath有一个CSIDL_APPDATA选项,可以在XP中使用,参见这里的其他答案... - rogerdpack

12

也许其他谷歌员工会发现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可以帮助您。

1
注意:std::filesystem 仅自 C++17 起可用。 - M_N1

8

如果有人正在寻找简单的实现方法,这里是我的实现:

#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://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
     * https://learn.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;
}


5

使用此代码读取环境变量"APPDATA"
在开头包含stdio.h文件

char *pValue;
size_t len;
errno_t err = _dupenv_s(&pValue, &len, "APPDATA");

enter image description here


请参考以下链接:https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/dupenv-s-wdupenv-s?view=msvc-160顺便提一下,此函数无法与 UWP 一起使用。 - Dinsdale

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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接