I'm trying to get a list of mapped drives on my machine as a Windows service. I can get a proper list if I run my code as a normal program, but not as a Windows service. I've seen several posts regarding this topic but none give a clear solution.
I'm running the service on the same account that created the service, and the service has admin rights.
Does anyone know how to properly do this?
It is not possible
please see the following MSDN article
https://msdn.microsoft.com/en-us/library/windows/desktop/ms685143%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
If a service is configured to run under a user account, the system always creates a new logon session for the user and starts the service in that new logon session. Therefore, a service cannot manage the drive mappings established within the user's other sessions.
If you are in Windows 7 with UAC enabled, then the administrative session has different mapped drives then the regular user session. Open an administrative command prompt and run net show and check the mapped drive status.
Update: I have EnabledLinkedConnections set on my Windows 10 workstation so I don't see this issue there.
Related
I've been asked to write a C# application to run on a Windows 7 machine to display the time of day, weather, etc.. That I can do. What I'm looking for is guidance to run the application on a Windows7 machine without logging as a user. In essence the machine would simply be a CPU with a screen. No keyboard or mouse. I've seen deployments done on MS-PixelSense (use to be MS-Surface) using a service ID.
If I need to signin, user policies kick in, screen savers enable, etc.. I'm assuming if I use an automatic Service ID, I can let the application override most of the settings keeping the screen on and needed privileges assigned / locked down to the service ID.
Any information / suggestions are appreciated....
First, some background informations:
Accessing a network share
If a process running on your client wants to access a (CIFS) share, it has to be run under a user account (or "Service ID") which has access rights to this share. There is a way (if the client is a member of Active Directory) that the machine name appended with $ (which is in fact the machine account’s name in AD) has to be entered in the ACL (Share / NTFS), but this is not a very "usual" way.
See also https://serverfault.com/questions/41130/network-service-account-accessing-a-folder-share
Windows Service running under a user account (aka technical account or Service ID)
A service running under a user account cannot access the GUI. There are some tricks, and some years ago I wrote a tool which allows a service to start another GUI program, where the GUI is displayed above the Ctrl-Alt-Del dialog. But this does not work under Windows 7 anymore.
But even a service which runs under local system cannot display a GUI on the logon screen.
You would have to write a Credential Provider.
See
Windows service showing a GUI when no user is logged in
https://stackoverflow.com/a/3074040/4547223
Another very deep technically article. It says it is possible to display a GUI on the secure desktop / logon screen. I have not yet tested this myself:
http://calebdelnay.com/blog/2012/01/displaying-a-program-on-the-windows-secure-desktop
Autologon
The most well known way is still the "classic" autologin.
See https://security.stackexchange.com/questions/10170/how-secure-is-windows-auto-logon for some explanations and links.
The medium secure way is to store the password as LSA secret (can be done in C# with P/Invoke or with some tools).
If I need to signin, user policies kick in, screen savers enable, etc.
Yes, but this can be handled, you probably have to create an own AD OU with an own policy for that.
I'm assuming if I use an automatic Service ID, I can let the application override most of the settings keeping the screen on and needed privileges assigned / locked down to the service ID.
A service ID /technical account is basically the same as a normal personal user account.
In some Active Directory enterprise environments a technical account has restrictions that it cannot log on interactively and other restrictions. But it still IS a "user account"
Logonexpert (http://www.logonexpert.com/)
I tested this (trial version). It is a nice, small tool which does it’s job. It is more safe than "normal autologon", however in the end, it is not much different from normal classic autologon. One benefit: it stores the password more recurely, but in theory, some hacker may still decompile the program and find out a way to decrypt it. And more important for you: Beside the more safe password store, it does not gain you much. You still have a user login same as normal autologon.
A few suggestions
Probably you can use a local user account on the client system and use normal autologon mechanism. And then you should consider that the client system does not poll for new data on a network share, but instead another server program (implemented as a service, running under a technical domain account) pushes data on a network share on the client.
Doing it this way, the client code does not need to access network shares, with the benefit, that a malicious attacker also has no access to network shares.
If you really need to access a network share from the local user context, you can probably logon to the server, as explained in my answer here:
https://stackoverflow.com/a/28749093/4547223
You have to to change the registry code part with the access to the CIFS share.
But doing it this way, you again have a password, which you have to encrypt and store. I do not recommend this.
In the end...
Windows does not make it easy what you want to do. If you are not strictly bound to Windows, you can consider using a Raspberry Pi with Raspbian (a Debian derived Linux). You can install Chromium browser, which displays a web page on the server and updates automatically. We use this with great success for some time.
I have a windows service developed in .NET C# using VS 2010, I'm calling the DriveInfo.GetDrives() but it is not getting the Z: drive (a mapped network drive),
I did some googling and found some results pointing to windows account privileges, so I have tried all account types of service installer such as LocalSystem, User, LocalService, NetworkService but none worked and I still can't get the drive Z:.
I did another test, debugging the windows service (as a console application) and I can get drive Z: that way.
Is there a solution to my problem?
You need to run the windows service with an account that has the network drive mapped, for example, the same account that you used to run as a console application. As Hans advised you should not be using mapped drives in windows services because they are a concept associated to a real user.
However if you really want to continue to use mapped drives see this related question for pitfalls and workarounds related to this specific situation:
How to map a network drive to be used by a service
Drive mappings are associated with LUID and you could have multiple Authentication ID under the same user (e.g. service, normal integrity level, high integrity level etc).
You can have a normal integrity level process running in the user's session to provide the mapped drive list created by the user. This is how Windows Explorer copies mapped drives for elevated setup programs.
I would like to print from a Windows Service in C# using Visual Studio 2010. So far, I have only been partially successful by using the code found here:
Print html document from Windows Service without print dialog
The current problem I am experiencing is two fold, which I have only discovered by allowing the service to interact with the desktop:
1) When the URL is entered in as the HTML location, it will request credentials for that location (a network shared IIS web server that I DO NOT have the ability to alter in any way, which requests a username and password to access the information).
2) After I enter credentials, the default printer is ALWAYS the XPS printer, no matter what I do to SetDefaultPrinter (two different ways I have found to do this). I have discovered this is because the printer I want to print to is also a network printer, which the Local System account cannot access (apparently). I have not found a way around this problem.
I would like to get around both of these problems by entering the credentials needed programmatically (this is a network share credential set) and then print to a network printer. In other desktop applications I have successfully printed to each of these network printers even though I do not have each one installed.
Attempting to log in using my credentials instead of the Local System account does not solve either problem. I am using Windows XP.
Assuming I get this to work, I will also need to install the service on another server, so if it is necessary to preinstall each printer I will need to know what steps to take to ensure the Local System account has access to them. The server I will install on will likely be a Windows Server 2003 or 2008, but will have the same network access as the development machine.
EDIT: I attempted a solution of having it Log on as other accounts, all of which should have credentials (and, in fact, if those credentials are entered when it is running as Local System with desktop interaction, those credentials are accepted). Each user that this has been attempted with has had the default printer set to the printer I am trying to test print to, but no print occurs. The only time I know for sure it is trying to use the XPS printer is when it is logged on as Local System with desktop interaction.
Don't run the service as Local System. It doesn't have the rights you need to access network resources. Create a user and run the service under that, if you're in a domain, make sure it's a domain user and not a local one. You will need to log on as that user and install the printers you want to use on the computer where your service runs. Also, if the IIS application is using Windows Authentication, see if the account you're running the service under can be granted permission to access the web application.
I had this issue, this trick solved it
Go to services ---> Double click the required service ---> proceed to logon tab
Supply the Log-in credentials from which printer was installed.
See screen shot below.
I'm writing a simple service to set the default printer based on where I'm connected, but I'm having trouble using WMI in my service. The more I think about it the less I think it's possible to do what I'm trying to do; as a service is not associated with a particular user, but I thought I would ask about it anyway in case my suspicions are wrong.
Here is what I'm doing.
Service subscribes to NetworkChange.NetworkAvailabilityChanged event.
When event is received query WMI SELECT * FROM Win32_Printer WHERE Network=true.
Loop through the ManagementObjectCollection and check the status of each printer.
If the printer is connected call ManagementObject.InvokeMethod("SetDefaultPrinter",null)
When I check the Security event log I noticed Failure Audit events "Unknown username or bad password", which I'm assuming is because I did not explicitly supply that information.
Is there a way to do this without specifying a username and password, or are credentials required for security purposes?
The service must run as some user, for example NETWORK SERVICE, LOCAL SERVICE or SYSTEM. You need to make sure the given account has permission to do what you want.
To change the permission of a deployed service on Windows go to Start > Administrative Tools > Services then you can change the service account for a given service.
I know this is an old question but i feel the existing answer doesn't quite provide a manageable solution.
As pointed out to effect a users default printer selection you need to be authenticated as that user and whilst it is possible to set a windows service to logon as a specific user a better solution would be to ...
Create a winforms program using a hidden form and launch it when the user logs on using Task Scheduler.
This way the PC can be used by many users and benefit from the application without having to change the service logon settings.
I suggested a winforms application as it has a low entry bar, you can use any other kind of invisible from a UI perspective project type.
you should use linqtowmi for this it works great!
I'm currently in the process of creating a Windows service application which will monitor changes to certain keys made in the HKEY_USERS registry. The way I do this is by collecting the SID of the current user. The issue I'm having is that its returning the administrators SID due to the service currently running as local system.
What I need the system to do is collect and return the SID of the currently logged in user (by this I dont mean the local service, local system or network service but the person whos logged into windows via the GINA), so what I need the service to do is run as that user. This will also allow the service to write back to the users network drive which is the intention of this program.
The issue I'm having is that when I try and install a user service using installutil.exe it asks for a username and password now I've tried my own credentials (I have an admin and non admin account) but it isn't having any of it plus I want the user to change depending on the person logging on and not to be fixed. Is there any way to do this?
The "The current user" assumption is a desktop Windows concept, and with Fast User Switching even that is not true anymore. The Windows services layer is rather common across desktop and server variants, and doesn't really deal well with this. It sits below the interactive sessions layer. One of the ways this manifests itself is in the ability to run services even if there are zero users logged in.
This all seems a bit confused. There can be any number of people logged on via remote desktops etc. If you as a service want to see their registry, you definitely wont get there via HKCU. If you want something like this, you should be using an autorun exe rather than a service. Anything like inspecting sessions and injecting stuff into them to access the loaded registry hive in the session is way overkill and not likely to be clean in any way.
You can find a process that runs with every user like explorer.exe then get the SID of the user that runs the process (you can use WMI like in the function here)