Relative Path issue with .Net Windows Service..?

I have a windows service which is trying to access an xml file from the Application directory.

Windows Service Installed directory : C:\Services\MyService\MyService.exe Path of the xml file : C:\Services\MyService\MyService.xml

I am trying to access the file using the following code.

using (FileStream stream = new FileStream("MyService.xml", FileMode.Open, FileAccess.Read))
  {
         //Read file           
  }

I get the following error.

"Can not find file : C:\WINDOWS\system32\MyService.xml"

My service is running with local system account and I don't want to use absolute path.

Answers


There is an elegant solution for this from the following link.

http://haacked.com/archive/2004/06/29/current-directory-for-windows-service-is-not-what-you-expect.aspx/

As my service is running both as console/service I just called

Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory) 

before running it as Service E.g.

static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
                RunAsService();
            }
            else
            {
                RunAsConsole();
            }
        }

You need to find the path to your service's assembly, like this:

static readonly string assemblyPath = 
    Path.GetDirectoryName(typeof(MyClass).Assembly.Location);

using (FileStream stream = File.OpenRead(Path.Combine(assemblyPath, "MyService.xml"))

When a Windows Service is launched, the current directory is the system directory, as you indeed seem to be finding. It is the current directory that is used to resolve relative paths into absolute paths, not your application (service) directory. (Check the Environment.CurrentDirectory variable if you want to confirm this.)

The following helper method may come in handy here:

public static string GetAppRelativePath(string path)
{
    return Path.Combine(Path.GetDirectoryName(
        Assembly.GetEntryAssembly().Location), path);
}

Which you can then use as:

using (FileStream stream = new FileStream(Utilities.GetAppRelativePath(
    "MyService.xml"), FileMode.Open, FileAccess.Read))
{
    // Read file
}

The path will then resolve to C:\Services\MyService\MyService.xml, as you want.


Need Your Help

CSS media queries for iPhone

css media-queries

I have a website that will be displayed on both the desktop and on an iPhone using media queries to serve different stylesheets so for example ALWAYS load reset.css, but if on desktop load desktop....

Java Deployment Rule Set not working as expected with applets

java deployment applet jvm jvm-hotspot

I need to create a deployment rule set which decides whether an application (webstart or applet) will be executed using Java 1.6.0_31 or 1.8.0_45. Initially I want to use 1.6.0_31 for all internally