2010-04-26 14 views
12

Tengo un servicio de Windows que está tratando de acceder a un archivo xml desde el directorio de la aplicación.Problema de ruta relativa con .Net Windows Service ..?

servicio de Windows Directorio instalado: C: \ Services \ MyService \ MiServicio.exe
de ruta del archivo XML: C: \ Servicios \ MyService \ MyService.xml

Estoy intentando acceder el archivo usando el siguiente código.

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

Recibo el siguiente error.

"No se puede encontrar el archivo: C: \ WINDOWS \ system32 \ MyService.xml"

Mi servicio se ejecuta con la cuenta del sistema local y no quiero utilizar la ruta absoluta.

Respuesta

22

Hay una solución elegante para esto en el siguiente enlace.

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

Como mi servicio se está ejecutando tanto como consola/servicio acabo de llamar a

Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory) 

antes de ejecutar como servicio P. ej

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

Me salvó la vida ... – user2617750

4

es necesario encontrar el camino a la asamblea de su servicio, así:

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

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

Es más confiable usar 'Location' en este caso en lugar de' CodeBase' ... ver los documentos de MSDN para obtener información. – Noldorin

+0

Otro problema es que está utilizando 'typeof (MyClass) .Assembly' para obtener el ensamblaje principal del programa. 'Assembly.GetEntryAssembly()' es más confiable, de nuevo. – Noldorin

+0

@ Noldorin # 2: al contrario. Su código debería funcionar sin importar quién llamó a su asamblea. – SLaks

2

Cuando se pone en marcha un servicio de Windows, el directorio actual es el directorio de sistema, como parece en efecto estar encontrando. Es el directorio actual que se utiliza para resolver las rutas relativas en rutas absolutas, no su directorio de aplicaciones (servicio). (Compruebe la variable Environment.CurrentDirectory si desea confirmar esto.)

El siguiente método de ayuda puede venir aquí a mano:

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

que luego se puede utilizar como:

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

El camino luego se resolverá a C:\Services\MyService\MyService.xml, como lo desee.

+1

¿No se resolverá la ruta en C: \ Services \ MyService \ MyService.xml, que es lo que se necesita? Creo que es solo un error tipográfico. –

+0

@Waleed: Lo siento, tienes razón. Se resuelve en la ruta correcta, acabo de escribir el "camino correcto" equivocado.;) – Noldorin

+0

GetAbsolutePath (string relativePath) podría ser un mejor nombre de método. – Zorayr

Cuestiones relacionadas