27

As you all know, the appdata folder is this

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

on windows 7

Since my application will be deployed on all kinds of Windows OSes i need to be able to get the folder 100% percent of the time. The question is how do you do it in C++? Since i don't know the the exact Windows OS it could be XP,Vista or 7 and most importantly i don't know what the Username is.

dikidera
  • 2,004
  • 6
  • 29
  • 36

6 Answers6

37

For maximum compatibility with all versions of Windows, you can use the SHGetFolderPath function.
It requires that you specify the CSIDL value for the folder whose path you want to retrieve. For the application data folder, that would be CSIDL_APPDATA.

On Windows Vista and later, you should use the SHGetKnownFolderPath function instead, which requires that you specify the folder's KNOWNFOLDERID value. Again, for the application data folder, the appropriate value is FOLDERID_RoamingAppData.

To use either of these functions from your C++ application, you'll need to include shlobj.h.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Which do you recommend? – dikidera May 07 '11 at 12:29
  • 2
    @mfce: Uh, the first one is what you should use on versions of Windows prior to Vista (like Windows 2000 and XP). However, it has been deprecated as of Windows Vista, and new applications written for Vista and 7 should always use the second one. So it depends on which version of Windows the program is running on. – Cody Gray - on strike May 07 '11 at 12:30
  • It's targeted for both. – dikidera May 07 '11 at 12:51
  • @mcfe: Okay... Then you'll need an `if` statement. Determine which version of Windows the program is running under and call the appropriate function. You'll need to use `LoadLibrary` and `GetProcAddress` for `SHGetKnownFolderPath`, as it's not defined for versions prior to XP. – Cody Gray - on strike May 07 '11 at 12:57
26

You can try the following:

char* appdata = getenv("APPDATA");

This code reads the environment variable APPDATA (you can also see it when you type SET in a command window). It is set by Windows when your system starts.

It will return the path of the user's appdata as an absolute path, including Username and taking into account whichever OS version they're using.

Abel
  • 56,041
  • 24
  • 146
  • 247
iptq
  • 657
  • 1
  • 7
  • 15
  • 3
    For those who are curious, this won't work on XP since appdata isn't a recognized environment variable. programfiles will work, however. – NinjaMid76 Sep 29 '14 at 19:17
  • with the years `getenv` got deprecated, and now it's recommended to use the safer `_dupenv_s` – itsho Mar 07 '21 at 21:00
  • `SHGetFolderPath` has a `CSIDL_APPDATA` option that works with XP FWIW, see other answers here... – rogerdpack Dec 23 '22 at 06:53
11

Perhaps fellow Googlers might find it interesting to have a look at std::filesystem. For instance, let's assume the default temp directory location and AppData directory structure in Windows 10:

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

In the case of OP, I am assuming this doesn't solve the problem. I do want to raise a word of caution against doing the above in a situation that requires a 100% robust implementation, as system configurations can easily change and break the above.

But perhaps new visitors to the question might find std::filesystem useful. Chances are, you're going to want to manipulate the items in the directory if you're looking for it, and for this, std::filesystem can be your friend.

Chris Mauer
  • 176
  • 1
  • 8
8

If someone is looking for a simple implementation, here's mine:

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

Ardent Coder
  • 3,777
  • 9
  • 27
  • 53
Phil Loctaux
  • 596
  • 6
  • 8
5

Use this Code to reads the environment variable "APPDATA"
Include stdio.h file in beginning

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

enter image description here

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
Akash das
  • 371
  • 4
  • 9
  • https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/dupenv-s-wdupenv-s?view=msvc-160 FYI: This function cannot be used with UWP. – Dinsdale Nov 25 '20 at 04:54
0

Here is a simple implementation for old C++ versions :

#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;
PJ127
  • 986
  • 13
  • 23