2010-04-26 3 views
12

У меня есть служба Windows, которая пытается получить доступ к XML-файлу из каталога приложений.Относительный путь с .Net Windows Service ..?

службы Windows установлен каталог: C: \ Services \ MyService \ MyService.exe
Путь файла XML: C: \ Services \ MyService \ MyService.xml

Я пытаюсь получить доступ файл, используя следующий код.

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

Я получаю следующее сообщение об ошибке.

«Не удается найти файл C: \ WINDOWS \ system32 \ MyService.xml»

Моя служба работает с учетной записью локальной системы, и я не хочу, чтобы использовать абсолютный путь.

ответ

22

Существует элегантное решение для этого по следующей ссылке.

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

В моей службе работает как в консоли/службы я просто позвонил

Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory) 

перед запуском его в качестве службы Э.Г.

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

Спасла мою жизнь .. – user2617750

4

Вы должны найти путь к сборке своей службы, как это:

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

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

В данном случае более надежно использовать 'Location', а не' CodeBase' ... см. Документы MSDN для информации. – Noldorin

+0

Другая проблема заключается в том, что вы используете 'typeof (MyClass) .Assembly', чтобы получить основную сборку программы. 'Assembly.GetEntryAssembly()' более надежно, снова. – Noldorin

+0

@ Noldorin # 2: Напротив. Его код должен работать независимо от того, кто назвал его сборку. – SLaks

2

Когда служба Windows запускается, текущий каталог системного каталога, как вы на самом деле, кажется, найти. Это текущий каталог, который используется для разрешения относительных путей в абсолютные пути, а не в каталог вашего приложения (службы). (Проверьте переменную Environment.CurrentDirectory, если вы хотите, чтобы подтвердить это.)

Следующий вспомогательный метод может пригодиться здесь:

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

Что вы можете использовать как:

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

Путь затем разрешит C:\Services\MyService\MyService.xml, как вы хотите.

+1

Не разрешит ли путь к C: \ Services \ MyService \ MyService.xml, что требуется? Я думаю, что это просто опечатка. –

+0

@ Waleed: Извините, вы правы. Он разрешает правильный путь, я просто написал неверный «правильный путь».;) – Noldorin

+0

GetAbsolutePath (string relativePath) может быть лучшим именем метода. – Zorayr