Monday, February 21, 2011

How to map a network drive to be used by a service

Suppose some Windows service uses code that wants mapped network drives and no UNC paths. How can I make the drive mapping available to the service's session when the service is started? Logging in as the service user and creating a persistent mapping will not establish the mapping in the context of the actual service.

From stackoverflow
  • You wan't to either change the user that the Service runs under from "System" or find a sneaky way to run your mapping as System.

    The funny thing is that this is possible by using the "at" command, simply schedule your drive mapping one minute into the future and it will be run under the System account making the drive visible to your service.

    VoidPointer : the service does not run as "System". It is set up to run under a specific local account. Even I log in with that account, create a persistent network mapping, log out and restart the service, the mapping will not be available to the service.
  • You could us the 'net use' command:

    System.Diagnostics.Process.Start("net.exe", "use K: \\\\Server\\path");
    

    If that does not work in a service, try the Winapi and PInvoke WNetAddConnection2

    Edit: Obviously I misunderstood you - you can not change the sourcecode of the service, right? In that case I would follow the suggestion by mdb, but with a little twist: Create your own service (lets call it mapping service) that maps the drive and add this mapping service to the dependencies for the first (the actual working) service. That way the working service will not start before the mapping service has started (and mapped the drive).

    VoidPointer : with this mapping service setup, I think that the drive mapping established by the mapping service wouldn't be available in the context of the original service, would it?
    Treb : I think it should - there is only one environment for each winlogon session.
  • You'll either need to modify the service, or wrap it inside a helper process: apart from session/drive access issues, persistent drive mappings are only restored on an interactive logon, which services typically don't perform.

    The helper process approach can be pretty simple: just create a new service that maps the drive and starts the 'real' service. The only things that are not entirely trivial about this are:

    • The helper service will need to pass on all appropriate SCM commands (start/stop, etc.) to the real service. If the real service accepts custom SCM commands, remember to pass those on as well (I don't expect a service that considers UNC paths exotic to use such commands, though...)

    • Things may get a bit tricky credential-wise. If the real service runs under a normal user account, you can run the helper service under that account as well, and all should be OK as long as the account has appropriate access to the network share. If the real service will only work when run as LOCALSYSTEM or somesuch, things get more interesting, as it either won't be able to 'see' the network drive at all, or require some credential juggling to get things to work.

    VoidPointer : Very informative... Am I correct in assuming that logon scripts are also run only for interactive logon sessions and not for service sessions?
  • Hi,

    The reason why you are able to access the drive in when you normally run the executable from command prompt is that when u are executing it as normal exe you are running that application in the User account from which you have logged on . And that user has the privileges to access the network. But , when you install the executable as a service , by default if you see in the task manage it runs under 'SYSTEM' account . And you might be knowing that the 'SYSTEM' doesn't have rights to access network resources.

    There can be two solutions to this problem.

    1. To map the drive as persistent as already pointed above.

    2. There is one more approach that can be followed. If you open the service manager by typing in the 'services.msc'you can go to your service and in the properties of your service there is a logOn tab where you can specify the account as any other account than 'System' you can either start service from your own logged on user account or through 'Network Service'. When you do this .. the service can access any network component and drive even if they are not persistent also. To achieve this programmatically you can look into 'CreateService' function at http://msdn.microsoft.com/en-us/library/ms682450(v=vs.85).aspx and can set the parameter 'lpServiceStartName ' to 'NT AUTHORITY\NetworkService'. This will start your service under 'Network Service' account and then you are done.

    3. You can also try by making the service as interactive by specifying SERVICE_INTERACTIVE_PROCESS in the servicetype parameter flag of your CreateService() function but this will be limited only till XP as Vista and 7 donot support this feature.

    Hope the solutions help you.. Let me know if this worked for you .

    -Kushagra

0 comments:

Post a Comment