In C# I can do the following:
DirectoryInfo di = new DirectoryInfo(System.Environment.GetEnvironmentVariable("ALLUSERSPROFILE"));
Which will get me the path to the all users profile.
In C++ I can use the SHGetFolderPath, but it does not seem to have a CSLID for all users.
Is there an equlivant function that I can blow the %ALLUSERSPROFILE% out to its path value?
Use SHGetFolderPath with CSIDL_COMMON_APPDATA. Or SHGetKnownFolderPath since Vista with FOLDERID_ProgramData.
Alternatively, use the .NET native Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
Use ExpandEnvironmentStrings to expand the %ALLUSERSPROFILE% string. This method is part of Kernel32.dll.
For most purposes, you should be able to use SHGetFolderPath with one of the CSIDL_COMMON_... values (see here for a complete list) to get the subdirectory of the all users' path that you're interested in. (For Windows Vista and above, you can use SHGetKnownFolderPath with one of the FOLDERID_Public... values; see here.)
Note that in certain security situations that folder might not even be a real folder. There not being a CSIDL_ for it is always a strong hint that you're off the beaten path.
Are you sure you're not better off with _APPDATA?
You could use the getenv CRT function to get the value of the ALLUSERSPROFILE environment variable in much the same way as you are for C#.
Related
I'm working on a problem where I need to have a way to convert a user inputted filename to a unique path name. Let's say I let the user specify a path name that points to a file that contains some data. I can then do Data* pData=Open(PathName). Now if the user specifies the same path name again, I'd like to be able to have a table of already opened files and just return a pointer to the same data: Data* pData2=GetOpenedData(PathName). This is easy to accomplish with a simple std::map<std::string,Data*>, the problem is that different values of PathName can point to the same file. The simplest case is on Windows case insensitivity comes into play.
The code is cross platform C++ and I don't have access to .NET stuff (but I'm happy to #ifdef the differences between Windows and UNIX if needed). Does anyone know of either Windows API or POSIX functions that can take a path name and return a unique (to the system) string that I can key off of. The key doesn't have to be the same in both systems (Windows/POSIX), just unique within a running instance of my code.
For now, I'm not worried about links or two ways to get to the same file. Such as in Windows, if I had \myserver\share mapped to S: then \myserver\share\blah and S:\blah are the same file, but I can live with those being thought of as different. But S:\blah and S:\Blah should be the same. If there is a way to make \myserver\share and S:\ also be unique, that's a bonus and I'd be really happy, but I can live without it. (Likewise, if there are multiple links to the same file in UNIX).
Edited to add:
It's not as simple as just doing a case insensitive search in windows. For example: c://data/mydata.dat while that's an "invalid" filename, windows will accept it and it will actualy point to c:\data\mydata.dat
Edited to add another thing:
I'd also like c:\mydirectory\..\blah.dat to be recognized at the same as c:\blah.dat
For Windows, PathCanonicalize() is your friend. The shell path handing package in Windows has a few additional routines that'll help you out.
Unfortunately, I'm not sure what the Unix equivalents to this package is.
For Windows you can store the full path of a resource making all lowercase (or uppercase).
I don't use *nix so can't tell about that. But I believe in *nix systems case does matter (\home\a and \home\A are different). If that is the case then you can omit converting case of user input for *nix.
You can optionally instantiate std::map with a third template argument, which is the comparison function/functor (see e.g. http://www.cplusplus.com/reference/stl/map/). You could provide a case-insensitive string comparison function.
I believe Scott Meyers provides a good example of such a function in Effective STL; I can check this when I get home.
I wanna check if my string is valid windows file path. I was searching around and it seems that there is no reliable method to do that. Also I checked boost filesystem library , and no obvious function exist to do this check , maybe something like is_valid_windows_name
You could use _splitpath() function and parse the output (based on it, you could easily say if your path is valid or not).
See MSDN for additional information.
Note that this function is windows-specific.
I do not believe there is a standard c++ api for that.
Note that the Windows API allows more filenames than the Windows Shell (The filenames the user is allowed to use in windws explorer).
You should have a look at the windows shell api.
Another possibility is to use trial and error, this way you are truly independend of the current filesystem.
The easiest way is to disallow
\ / < > | " : ? *
and you should be fine.
Yes, there is a boost function that does what you want. Take a look at boost::filesystem::windows_name(...). You will need to include boost/filesystem/path.hpp as well as link against the correct (version- and architecture-specific) libboost_system and libboost_filesystem libraries since path is not a header-only lib.
It's a pity even the newest C++17 filesystem library doesn't have a function to verify file names.
You can use the Windows-specific Shell Lightweight Utility function PathFileExists or the Windows API GetFileAttributes and check the last error code specifically for ERROR_INVALID_NAME.
I think it's kind of a misuse (because there really should be a dedicated function for it) but serves the purpose.
I'd like to find the directory of the current user profile programmatically in C++.
SHGetSpecialFolderLocation is the best way to get at most of the special paths on Windows. Passed CSIDL_PROFILE it should retrieve the folder you are interested in.
If you are actually interested in the contents of the %UserProfile% environment variable you could try ExpandEnvironmentStrings
Simplest way on Windows & Linux:
char *szBuff;
szBuff=std::getenv("USERPROFILE"); //Returning value of %USERPROFILE%
To cover all user profile scenarios in Windows Vista and up there is SHGetKnownFolderPath. Here is the link to the docs page on it and related functions.
One of our developers used this call:
TzSpecificLocalTimeToSystemTime() but unfortunately we cannot keep it as the code must work on Win2K as well.
What alternatives are there for similar functionality?
There is no equivalent, not even with WINE. It relies on timezone info stored in the registry, retrieved with GetTimeZoneInformation(). Note how the WINE code ends up in find_reg_tz_info(). That info is just missing in Win2k.
You'd have to create your own timezones table.
If you're open to including LGPL code in your project, you could grab that function's implementation from Wine.
I am writing my first serious wxWidgets program. I'd like to use the wxConfig facility to make the program's user options persistent. However I don't want wxConfigBase to automatically use the Windows registry. Even though I'm initially targeting Windows, I'd prefer to use a configuration (eg .ini) file. Does anyone know a clean and simple way of doing this ? Thanks.
According to the source of wx/config.h file, all you need is to define the wxUSE_CONFIG_NATIVE symbol to 0 in your project and then it will always use wxFileConfig.
The cleanest and simplest way is to use wxFileConfig class.