How do I get the application data path in Windows using C++? - c++

I looked all over the internet and there doesn't seem to be a decent solution that I could find. I want to be able to programmatically in C++ obtain the path "%ALLUSERSPROFILE%\Application Data" that explorer can translate into a real path.
Can I do this without relying on third-party code?

Use SHGetFolderPath with CSIDL_COMMON_APPDATA as the CSIDL.
TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
{
//....
}

Just to suppliment interjay's answer
I had to include shlobj.h to use SHGetFolderPath.
Often you may need to read a file from appdata,
to do this you need to use the pathAppend function (shlwapi.h is needed for this).
#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
#include "shlobj.h"
TCHAR szPath[MAX_PATH];
// Get path for each computer, non-user specific and non-roaming data.
if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath ) ) )
{
// Append product-specific path
PathAppend( szPath, _T("\\My Company\\My Product\\1.0\\") );
}
See here for more details.

you can also read the value from the registry
path = HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
key = Common AppData

Related

ShellExecuteA - executable won't run from %appdata% [duplicate]

As above, how do I get the AppData folder in Windows using C?
I know that for C# you use Environment.SpecialFolder.ApplicationData
Use SHGetSpecialFolderPath with a CSIDL set to the desired folder (probably CSIDL_APPDATA or CSIDL_LOCAL_APPDATA).
You can also use the newer SHGetFolderPath() and SHGetKnownFolderPath() functions.
There's also SHGetKnownFolderIDList() and if you like COM there's IKnownFolder::GetPath().
If I recall correctly it should just be
#include <stdlib.h>
getenv("APPDATA");
Edit: Just double-checked, works fine!
Using the %APPDATA% environment variable will probably work most of the time. However, if you want to do this the official Windows way, you should use use the SHGetFolderPath function, passing the CSIDL value CSIDL_APPDATA or CSIDL_LOCAL_APPDATA, depending on your needs.
This is what the Environment.GetFolderPath() method is using in .NET.
EDIT: Joey correctly points out that this has been replaced by SHGetKnownFolderPath in Windows Vista. News to me :-).
You might use these functions:
#include <stdlib.h>
char *getenv(
const char *varname
);
wchar_t *_wgetenv(
const wchar_t *varname
);
Like so:
#include <stdio.h>
char *appData = getenv("AppData");
printf("%s\n", appData);
Sample code from MSDN:
TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL,
0,
szPath)))
{
PathAppend(szPath, TEXT("MySettings.xml"));
HANDLE hFile = CreateFile(szPath, ...);
}
CSIDL_APPDATA = username\Application Data. In Window 10 is: username\AppData\Roaming
CSIDL_FLAG_CREATE = combine with CSIDL_ value to force folder creation in SHGetFolderPath()
You can also use:
CSIDL_LOCAL_APPDATA = username\Local Settings\Application Data (non roaming)

How to get a PIDL from a Windows library's GUID?

How can I get the PIDL of a library from its GUID?
For example, if I have the GUID of the Documents library ("{7B0DB17D-9CD2-4A93-9733-46CC89022E7C}"), how can I convert that into the library's ID list?
I thought SHParseDisplayName would do the job, but it returns "file not found."
Bear in mind that what I need is the PIDL of the library, not of its default folder.
This is straight C++, no .Net.
TIA
Edit: This is the code that works, from the response below (without error checks). guid is a GUID string prepended with 'shell:::', e.g., 'shell:::{7B0DB17D-9CD2-4A93-9733-46CC89022E7C}'.
IShellFolder* pDesktop;
LPITEMIDLIST pidl;
SHGetDesktopFolder(&pDesktop);
pDesktop->ParseDisplayName(nullptr, nullptr, guid, nullptr, &pidl, 0);
Edit 2: Even easier: SHParseDisplayName works if the 'shell:::' is prepended:
SHParseDisplayName(guid, nullptr, &pidl, 0, nullptr);
According to the documentation for IShellFolder::ParseDisplayName you can simply pass it a filename in the form ::{GUID} if you are using the desktop folder.
Edit: the documentation appears to be incomplete, according to this answer you need to add shell: to the start of the string.
p->ParseDisplayName(m_hWnd, NULL, _T("shell:::{7B0DB17D-9CD2-4A93-9733-46CC89022E7C}"), NULL, &pidl, NULL);
You want the function SHGetKnownFolderIDList.
Given a KnownFolderID guid (e.g. FOLDERID_DocumentsLibrary - {7B0DB17D-9CD2-4A93-9733-46CC89022E7C})
returns you the absolute pidl of that KNOWNFOLDER
For example:
PIDLIST_ABSOLUTE pidl;
HRESULT hr = SHGetKnownFolderItem(FOLDERID_DocumentsLibrary, 0, NULL, out pidl);
Bonus Chatter
There are three shell functions for dealing with KNOWNFOLDERs
SHGetKnownFolderPath : Get the full path of a known folder (e.g. C:\Users\Chris\Documents)
SHGetKnownFolderIDList: Get the absolute pidl of a known folder
SHGetKnownFolderItem: Get the IShellItem of a known folder

ShellExecute isn't opening an HTML file

ShellExecute(NULL, TEXT("open"), TEXT("report\index.html"), NULL, NULL, SW_SHOWNORMAL);
Above is my line of code and I, for some reason, cannot get the file to open. Below are all the lines I have tried.
ShellExecute(NULL, TEXT("open"), TEXT("report/index.html"), NULL, NULL, SW_SHOWNORMAL);
ShellExecute(NULL, L"open", L"report\index.html", NULL, NULL, SW_SHOWNORMAL);
ShellExecute(NULL, _T("open"), _T("report\index.html"), NULL, NULL, SW_SHOWNORMAL);
Below is list of what I have included.
// Windows Header Files:
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <Shellapi.h>
My file structure is structured out like this:
Downloads/test/program.exe
Downloads/test/report/index.html
This is the first time writing this code and I'm really not sure when to tell when I need to differentiate between "/" and "\". I believe I need to be using TEXT() because when I go to my VS2010 project, Properties > Character Set it says: Use Unicode Character Set. Or at least I believe I have to use TEXT(), I am really not sure.
Also do I need to provide the full path of the file instead of making the assumption it's traveling from where my exe is located? If so is there a quick and easy function call to get the full directory path? Is it just an include file I am missing?
If you are passing an hardcoded path, the path must be Windows style, with backslashes, and of course the backslash must be twice to escape it.
ShellExecute(NULL, TEXT("open"), TEXT("report\\index.html"), NULL, NULL, SW_SHOWNORMAL);
If you are using not a full path, you must of course make sure that the path is actually reachable, from the current working directory of your application.

How to get the full path to the Windows Explorer in C++

Can I safely assume that Windows Explorer is always started from a Windows system directory? Also, is its process always named "explorer.exe"?
And if not, how to get its full file path?
EDIT: Forgot to mention -- I need this to later find out the process ID of the Windows Explorer running in a given user session. Thus my search for its full path.
EDIT 2: Thanks everyone who contributed, and especially to sehe! After his post I found this page that explains how to set up your own shell. I made a wild test by completely replacing explorer.exe with my own process and here's the result:
Here's the full-size link if you it gets re-sized.
As you can see, I can technically replace explorer.exe with whatever process I may come up with. As you can also see in my screenshot Windows gives me a complete control over the Shell (the screenshot is my entire window.)
So the bottom line, the only way to get "explorer.exe" file path (or whatever Shell process is used) is to use those registry keys from the link I quoted above -- pretty much close to what sehe suggested, with just a few more checks to do, but it's a pretty straightforward stuff.
As for Sean Cline's suggestion, it would be a very elegant solution ONLY if we have the "stock" Windows Explorer running that comes with a tray window with that specific class name.
It is probably safe to assume that explorer.exe is always in the %windir% or %SystemRoot% as it hasn't moved for years. But, if you are trying to invoke something via Explorer, chances are you want to use the ShellExecute() function instead.
If you really do need the path, the easiest way to get it is probably with a call to SHGetKnownFolderPath() using FOLDERID_Windows as the first argument.
Edit:
Here is my stab at some code knowing that you are looking for the PID of the shell process:
DWORD trayPID;
HWND trayWnd = FindWindow("Shell_TrayWnd", NULL);
GetWindowThreadProcessId(trayWnd, &trayPID);
It looks for the hWnd of the taskbar and finds the owning PID. You will likely need to add some error handling for the case that explorer is not running and that window does not exist - unlikely, but possible.
No you can't safely assume that and none of this has to do with C++.
Also, you didn't show any code. Here goes:
The registry key for this is Software\Microsoft\Windows NT\CurrentVersion\WinLogon\Shell (see here).
#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <string>
LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{
strValue = strDefaultValue;
WCHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError;
nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
strValue = szBuffer;
}
return nError;
}
int main()
{
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon", 0, KEY_READ, &hKey);
bool bExistsAndSuccess (lRes == ERROR_SUCCESS);
bool bDoesNotExistsSpecifically (lRes == ERROR_FILE_NOT_FOUND);
std::wstring shell;
GetStringRegKey(hKey, L"Shell", shell, L"");
}
Yes to both. Windows Explorer is always located at %WINDIR%\Explorer.exe.

MFC: GetCurrentDirectory function

I know that GetCurrentDirectory() and SetCurrentDirectory() functions exist on the MFC framework, but I don't have a CFtpConnection object in my application. I have a simple CWinApp-derived class, and I would like to retrieve its working directory upon program startup. What's the easiest method to achieve this goal? Thanks in advance for the advices.
GetCurrentDirectory is a simple Win32 API function, so just call it like this:
TCHAR currentDir[MAX_PATH];
GetCurrentDirectory( MAX_PATH, currentDir );
I assume you are trying to get the directory where your .exe file is located instead of the current directory. This directory can be different from the current directory.
TCHAR buff[MAX_PATH];
memset(buff, 0, MAX_PATH);
::GetModuleFileName(NULL,buff,sizeof(buff));
CString strFolder = buff;
strFolder = strFolder.Left(strFolder.ReverseFind(_T('\\'))+1);