How to Get Windows' Special Folders for Currently Logged-In User

How to get Windows' special folders for currently logged-in user?

You can do it with the pywin32 extensions:

from win32com.shell import shell, shellcon
print shell.SHGetFolderPath(0, shellcon.CSIDL_MYPICTURES, None, 0)
# prints something like C:\Documents and Settings\Username\My Documents\My Pictures
# (Unicode object)

Check shellcon.CSIDL_xxx for other possible folders.

I think using pywin32 is the best way. Else you'd have to use ctypes to access the SHGetFolderPath function somehow (other solutions might be possible but these are the ones I know).

Get special folder for different user without credentials

Assuming that it isn't too late to modify the application to support your uninstaller, you could create a folder in ProgramData at install time, and then each time your application starts up it could write a file for the current user containing the path(s) to the directories and/or files in question. (You could possibly even retrofit this in as an update, though it wouldn't work for users that hadn't logged in between the time the update was installed and the time the product was uninstalled.)

You'd need to be a bit careful about security. Non-admin users should only have "create files" access to the folder, which should be set to be non-inheritable. That way they can't see or manipulate one another's files. You might also want to assign inheritable full access to CREATOR OWNER.

You also need validate the saved path information rather than trusting it blindly, or a malicious user could make your uninstaller delete the wrong files. I'd suggest that you check that the file or folder you're about to delete is owned by the same person who owns the file containing the saved path information, and if not, call for help. For additional safety, your application could also tag the files that it creates which should be deleted on uninstall, perhaps by using an alternate data stream.

How can I get the path of a Windows special folder for a specific user?

I would mount the user's registry hive and look for the path value. Yes, it's a sub-optimal solution, for all the reasons mentioned (poor forwards compatibility, etc.). However, like many other things in Windows, MS didn't provide an API way to do what you want to do, so it's the best option available.

You can get the SID (not GUID) of the user by using LookupAccountName. You can load the user's registry hive using LoadUserProfile, but unfortunately this also requires a user token, which is going to require their password. Fortunately, you can manually load the hive using RegLoadKey into an arbitrary location, read the data, and unload it (I think).

Yes, it's a pain, and yes, it's probably going to break in future versions of Windows. Perhaps by that time MS will have provided an API to do it, back-ported it into older versions of Windows, and distributed it automatically through Windows update... but I wouldn't hold my breath.

P.S. This information intended to augment the information provided in your related question, including disclaimers.

Get Documents folder path of current logged on user

How about save the User Document Path before changing to Admin and use it later...

Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)

How to obtain Windows special paths for a user account from a service

I'm no expert on this, but it seems you can use the hToken argument to SHGetFolderPath to pass in another user's token. I think you can create such a token using impersonation.

If that does not work: these folders are in the registry under HKEY_USERS/<user's-sid>/Software/Microsoft/Windows/CurrentVersion/Explorer/Shell Folders. How to get the SID is explained in this question. It's in C# but I think it'll actually be easier in C++.

Get AppData\Local folder for logged user

To get that information for another user, you'll need to know that user username/password, as is explained in this question.

So I'd like to throw an alternative solution:

1.- Instead of using the requestedExecutionLevel for the aplication, remove it and run it as the logged user. That way you'll have access to the special folders path easily and may log it.

2.- Restart your application as Administrator.

Sample code (in App.xaml.cs):

private void Application_Startup(object sender, StartupEventArgs e)
{
if (!IsRunAsAdmin())
{
// here you should log the special folder path
MessageBox.Show(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
// Launch itself as administrator
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
proc.Verb = "runas";

try
{
Process.Start(proc);
}
catch
{
// The user refused the elevation.
// Do nothing and return directly ...
return;
}

System.Windows.Application.Current.Shutdown(); // Quit itself
}
else
{
MessageBox.Show("The process is running as administrator", "UAC");
}
}

internal bool IsRunAsAdmin()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}

This sample code is for a WPF Application, but could be done the same in a winforms Application.

Reference: UAC Self Elevation



Related Topics



Leave a reply



Submit