Click here to Skip to main content
15,868,141 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Desktop applications can call SHGetKnownFolderPath[^] to find the path of common folders, such as "Documents" and "Downloads".

When it comes to a Windows Service, since services run isolated in session 0, the call to SHGetKnownFolderPath() will fail.

How can I find the currently logged in user's common path, or how can I call SHGetKnownFolderPath() from a Windows Service?

What I have tried:

LPWSTR wszPath = NULL;
HRESULT hr;

hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_CREATE, NULL, &wszPath);
Posted
Updated 5-Dec-19 5:20am

That is forbidden because of security reasons. Possible workarounds are to access some common folder.

Another not so great solution is to to use the LogonAsUser api to get some access rights. You need start another process/thread which does the needed stuff. The problem is how the credential are coming to the service like some entry in the registry (while installation) or some other way.
 
Share this answer
 
That will not work because the service is not running as the logged in user. It's, typically, running under the Local System account, which will not have a Documents folder.

Also, you're assuming Windows only ever lets a single user log into the console. That is not true. You can have multiple users logged into the machine at the same time. Hell, you can have no users logged into the machine!

How is your code supposed to know which user to get the path for?

Service applications should NEVER interact with the users logged into the machine, nor their profiles.

It seems you wrote an app as the wrong type of application. What you should have done is wrote a normal application and launched it form the Run key int he registry. That way, the app only runs when a user logs into the machine and will run AS THE USER THAT LOGGED IN. The app will then have access to the users profile folders just like any other...
 
Share this answer
 
v2
Comments
Michael Haephrati 5-Dec-19 13:57pm    
Right now, because of the scenarios you list here, SHGetKnownFolderPath() will fail and even cause a crash in applications used for both Desktop applications and Windows Service (for example, a Static library used by both types). My ideal answer would be a wraparound function that will call SHGetKnownFolderPath() and if possible return the correct path, let's say when a Windows Service is running, and there is one user logged in), and if not, return nullptr, or similar...
Dave Kreskowiak 5-Dec-19 16:10pm    
The only way that function is going to work for you is if you get a copy of the security token of a user that is logged in. Considering your service is not going to be able to ask the user for their credentials so it can create the token and impersonate the user, you're going to have a very hard time getting that token.

Good luck with that.

I've already told you, if you're interacting with a user or their profile AT ALL, you should NOT be writing a Service application to do this.
Michael Haephrati 6-Dec-19 10:13am    
Thanks Dave.
Michael Haephrati 25-Sep-22 9:50am    
Here is an interesting solution https://stackoverflow.com/a/67535631/1592639
Dave Kreskowiak 25-Sep-22 10:34am    
I've done something very similar to that for another purpose.

But, just because it works, does not mean it should be done. That code does not work in a multi-user environment. It will fail with more than one user logged into the machine, or give unexpected results when it returns the wrong user.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900