【问题标题】:How to open a folder in %appdata% with C++?如何使用 C++ 打开 %appdata% 中的文件夹?
【发布时间】:2011-08-20 17:19:18
【问题描述】:

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

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

在 Windows 7 上

由于我的应用程序将部署在各种 Windows 操作系统上,因此我需要能够 100% 地获取文件夹。 问题是你如何在 C++ 中做到这一点?由于我不知道确切的 Windows 操作系统,它可能是 XP、Vista 或 7,最重要的是我不知道 用户名 是什么。

【问题讨论】:

标签: c++ appdata


【解决方案1】:

为了最大限度地兼容所有版本的 Windows,您可以使用SHGetFolderPath function
它要求您为要检索其路径的文件夹指定 CSIDL 值。对于应用程序数据文件夹,这将是 CSIDL_APPDATA

在 Windows Vista 及更高版本上,您应该改用 SHGetKnownFolderPath function,这需要您指定文件夹的 KNOWNFOLDERID 值。同样,对于应用程序数据文件夹,适当的值为FOLDERID_RoamingAppData

要在您的 C++ 应用程序中使用这些函数中的任何一个,您需要包含 shlobj.h

【讨论】:

  • 你推荐哪个?
  • @mfce:嗯,第一个是您应该在 Vista 之前的 Windows 版本(如 Windows 2000 和 XP)上使用的。但是,它在 Windows Vista 中已被弃用,为 Vista 和 7 编写的新应用程序应始终使用第二个。所以这取决于程序在哪个版本的 Windows 上运行。
  • 两者都是针对的。
  • @mcfe:好的......那么你需要一个if 声明。确定程序在哪个版本的 Windows 下运行并调用相应的函数。对于SHGetKnownFolderPath,您需要使用LoadLibraryGetProcAddress,因为它没有为XP 之前的版本定义。
【解决方案2】:

您可以尝试以下方法:

char* appdata = getenv("APPDATA");

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

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

【讨论】:

  • 对于那些好奇的人来说,这在 XP 上是行不通的,因为 appdata 不是一个公认的环境变量。然而,程序文件将起作用。
  • 随着岁月的getenv被弃用,现在建议使用更安全的_dupenv_s
【解决方案3】:

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

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

【讨论】:

【解决方案4】:

也许其他 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 可以成为您的朋友。

【讨论】:

  • 注意:std::filesystem 仅在 C++17 后可用
【解决方案5】:

如果有人正在寻找一个简单的实现,这是我的:

#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;
}

【讨论】:

    【解决方案6】:

    这是旧 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;
    

    【讨论】:

      猜你喜欢
      • 2013-05-06
      • 2021-08-17
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多