73

I have a windows service and I need to create directory to store some info. The directory path must be relative to the windows service exe file. How can get this exe file path ?

  • 1
    I'm no Windows developer but are you sure you want this? Doesn't such info belong in the user's personal directory, or that of `LocalService`? – Pekka May 14 '10 at 12:11
  • 10
    @Pekka I'm no Unix Developer but system services (daemons) storing files in user's personal directories sounds downright insane. – BrainSlugs83 Sep 22 '11 at 06:33
  • The question doesn't specify from where I would need to find the executable path. Most answers only focus on getting the path from within that windows service. But I would need to find the path to the executable of any installed windows service, knowing only the service name. – NexX Aug 12 '22 at 11:46

10 Answers10

122

You can use AppDomain.CurrentDomain.BaseDirectory

Incognito
  • 16,567
  • 9
  • 52
  • 74
  • 16
    This solution won't work properly if you run the service with a different account... – Dennis Jul 06 '14 at 10:56
  • 7
    When I do this, for a service running as local system, it evaluates to c:\windows\system32 – schizoid04 Oct 09 '16 at 18:06
  • 1
    For the installer, this pointed to C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ and not the executable – Slate Jan 24 '19 at 17:46
  • @Lectere can you elaborate? I've been using this method and have never had issues with this property, but I don't want to be blindsided by a customer environment. It appears to work with Local System, Local Service, Network Service, a random local user I created ... – John Hargrove May 02 '19 at 17:34
  • Doesn't work Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\WINDOWS\TEMP\.net\FreshIQAppMessagingService\zu4jbgzc.let AppDomain.CurrentDomain.BaseDirectory when running as a windows service returned a WINDOWS\TEMP path. – Chris Ward Dec 18 '20 at 14:17
  • This works great for a Windows Service using .NET Core 7. – Dave Shinkle Apr 26 '23 at 00:54
50

Tip: If you want to find startup path of installed windows service, look here from registry .

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\ + ServiceName

There are keys about windows service

  • @user1034912 - I would think it reads fine (at least, I know on my work system I can read HKEY_LOCAL_MACHINE). Wouldn't be able to write though. – Broots Waymb May 25 '18 at 19:57
27

To get path for service you can use Management object. ref: https://msdn.microsoft.com/en-us/library/system.management.managementobject(v=vs.110).aspx http://dotnetstep.blogspot.com/2009/06/get-windowservice-executable-path-in.html

using System.Management;
string ServiceName = "YourServiceName";
using (ManagementObject wmiService = new ManagementObject("Win32_Service.Name='"+ ServiceName +"'"))
                {
                    wmiService.Get();
                    string currentserviceExePath = wmiService["PathName"].ToString();
                    Console.WriteLine(wmiService["PathName"].ToString());
                }
Abhay
  • 564
  • 6
  • 14
  • Good choose, thanks for it!. Do you similar way to get win service config path? Or just add ".config" to the path? – Oleh Udovytskyi Mar 21 '18 at 13:07
  • 2
    @OlehUdovytskyi. You can use `var config = System.Configuration.ConfigurationManager.OpenExeConfiguration(svcPath)` and then check `config.HasFile` and `config.FilePath` variables. – IgorStack Apr 11 '18 at 21:15
15

Instead of using a directory relative to the executable, and therefore needing admin privileges, why not use the common application data directory, which is accessible through

Environment.GetFolderPath(SpecialFolder.CommonApplicationData)

This way your app doesn't need write access to its own install directory, which makes you more secure.

Stewart
  • 3,978
  • 17
  • 20
  • 1
    Also, in Windows Vista and Windows 7, you can't write to the program files folder, even as an administrator! – Chris Dunaway May 14 '10 at 15:50
  • How would you solve having different, separate installations of the same service or program that way, like for tenants or different staging environments, having to be completely unaware of each other? I'd love to use that approach more, but shrink from it due to that. – Oliver Schimmer Aug 20 '21 at 21:38
11

Try this

System.Reflection.Assembly.GetEntryAssembly().Location
coder
  • 3,195
  • 2
  • 19
  • 28
9
string exe = Process.GetCurrentProcess().MainModule.FileName;
string path = Path.GetDirectoryName(exe); 

svchost.exe is the executable which runs your service which is in system32. Hence we need to get to the module which is being run by the process.

davervw
  • 171
  • 1
  • 5
Sachin
  • 880
  • 6
  • 7
5

The default directory for a windows service is the System32 folder. In your service, though, you can change the current directory to the directory that you specified in the service installation by doing the following in your OnStart:

        // Define working directory (For a service, this is set to System)
        // This will allow us to reference the app.config if it is in the same directory as the exe
        Process pc = Process.GetCurrentProcess();
        Directory.SetCurrentDirectory(pc.MainModule.FileName.Substring(0, pc.MainModule.FileName.LastIndexOf(@"\")));

Edit: an even simpler method (but I haven't tested yet):

System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
derek
  • 4,826
  • 1
  • 23
  • 26
4

This did the trick for me

Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);    
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
Danw25
  • 306
  • 2
  • 13
0

This will return you the correct path even if running under LocalSystem account which defaults to system32:

System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
Mecanik
  • 1,539
  • 1
  • 20
  • 50
-3

If you want to get access of Program Files folder or any other using programming you should use the below code which is provide rights to specific folder.

 private bool GrantAccess(string fullPath)
        {
            DirectoryInfo dInfo = new DirectoryInfo(fullPath);
            DirectorySecurity dSecurity = dInfo.GetAccessControl();
            dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
            dInfo.SetAccessControl(dSecurity);
            return true;
        }
Ebg Test
  • 91
  • 1
  • 11
  • 6
    If this does work (and I very much doubt it would, but I don't have a Windows machine handy to check) then it would open write access to the program files directory to anyone - including unauthenticated users. This is outright irresponsible as it opens a security hole a mile wide. – Stewart Apr 28 '18 at 13:19
  • @Stewart using service you can't able to write file directly using folder path if it is in C Drive. For that first you need to give the permission and then after once all operation done you need to take all rights back. – Ebg Test Oct 27 '18 at 12:34
  • Please noone do this. Terrible security practice – Milney Mar 13 '19 at 10:58