Universal path in windows

I want to write a program that creates a file and save some data in it and the location of this file should always be in the desktop don't matter the windows machine.

How would I do that?
I want it to detect the path for desktop even when the Desktop folder is not in the drive C as in my case/
there are 2 places. you can get to an all-users desktop, so the file is visible and on the desktop for everyone, and an individual desktop for each user.

you can get to both via windows paths using predefined tokens.
cd %UserProfile%/desktop will get to the current active user's desktop.

%ALLUSERSPROFILE% may be what you want for everyone, if not, see if you can google it out, I can't recall
Last edited on
This question should be in the Windows forum, as you are asking how to do something with the Windows OS.

In any case, getting the user’s desktop path is surprisingly easy to do:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <filesystem>
#include <string>

#include <windows.h>
#include <shlobj.h>
#include <objbase.h>

#pragma comment(lib,"Shell32")
#pragma comment(lib,"Ole32")

std::filesystem::path
get_desktop_path()
{
  wchar_t* p;
  if (S_OK != SHGetKnownFolderPath( FOLDERID_Desktop, 0, NULL, &p )) return "";
  std::filesystem::path result = p;
  CoTaskMemFree( p );
  return result;
}

21
22
23
24
25
26
27
#include <iostream>

int main()
{
  auto path = get_desktop_path();
  std::cout << "User's desktop is at " << path.string() << "\n";
}

Hope this helps.

[edit] Oh, BTW, known paths you can get are:
https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid
Last edited on
that works too. I don't recall if you can read the environment versions without extra windows library clutter or not, if it matters (eg not writing a full bore windows program or not using VS). I mean, you can be barbaric about it, and system echo it to a file... but that isn't really what I meant.
Last edited on
I tend to put platform-specific stuff in separate compilation units so to avoid environmental clutter.

In fact, it is one of the few times I actually #include .cpp files:

platform.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...

#ifdef _WIN32

  #include "windows/platform.cpp"

#elif defined(__linux__)  // POSIX/Linux/Unix

  #include "unix/platform.cpp"

#else

  #error "blah blah blah"

#endif 

The header file is the same as you would normally expect:

platform.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...

#ifndef PROJECT_PLATFORM_HPP
#define PROJECT_PLATFORM_HPP

#include <filesystem>

namespace platform
{

  std::filesystem::path get_executable_path();
  std::filesystem::path get_documents_folder();
  // and so on...

}

#endif 


[edit]
Oh, yeah, as to your concern: the C-API version and the (un-spoofed) environment variable version will both return correct data, but you will need to manually perform substitutions on the environment variable version.

Since the DLLs involved are system DLLs, I don’t see any reason to go the hard way around.
Last edited on
@Duthomhas that works, thanks. Also was useful to know the platform specific code that can be used.

jonnin wrote:
I don't recall if you can read the environment versions without extra windows library clutter or not
Surprisingly, getenv works, as an alternative. Pick your poison.
1
2
3
4
5
6
7
8
9
10
11
#include <cstdlib>
#include <iostream>

int main()
{
	char* userprofile = std::getenv("USERPROFILE");
	if (userprofile) // idk what this will return if run as SYSTEM, etc.
	{
		std::cout << userprofile << "\\Desktop\n";
	}
}


(Duthomhas's method is better either way because maybe there's some hackish way to change the desktop's name? Not to mention Unicode support.)
Last edited on
Topic archived. No new replies allowed.