c# - tracer - ¿Cómo funciona la resolución de ruta predeterminada/relativa en.NET?
ruta predeterminada ipv6 (4)
La resolución de ruta relativa nunca funciona en contra de la ruta del archivo ejecutable de inicio. Siempre funciona en contra del Directorio actual del proceso, y realmente no se puede esperar que siempre se establezca en el directorio en el que vive .exe.
Si necesita ese comportamiento, tenga cuidado de encontrar la ruta correcta por su cuenta y proporcione una ruta completa a las operaciones de archivo.
Entonces ... solía pensar que cuando accedía a un archivo pero especificaba el nombre sin una ruta (CAISLog.csv en mi caso), .NET esperaría que el archivo residiera en la misma ruta que el .exe en ejecución.
Esto funciona cuando paso por una solución (C # .NET2. * VS2K5) pero cuando ejecuto la aplicación en modo normal (Iniciado por un monitor de activación de Websphere MQ y ejecutándose en segundo plano como un servicio de red) en lugar de acceder al archivo en la ruta donde el .exe se está buscando en C: / WINDOWS / system32. Si importa, el .exe de la tarea principal está en casi la misma estructura / ruta de carpeta que mi aplicación
Aparece un error coincidente: " System.UnauthorizedAccessException: se deniega el acceso a la ruta ''C: / WINDOWS / system32 / CAISLog.csv''. "
Mi solución es simplemente calificar completamente la ubicación de mi archivo. Sin embargo, lo que quiero entender es "¿Qué es la regla .NET que rige cómo se resuelve una ruta cuando solo se especifica el nombre de archivo durante IO?" Siento que me falta un concepto básico y me está molestando.
editar - No estoy seguro de que sea una regla .NET per se, pero Schmuli parece estar explicando el concepto un poco más claro. Definitivamente intentaré las sugerencias de Rob Prouse en el futuro así que +1 en eso también.
Si alguien tiene algunas sugerencias de reformulación que enfaticen que realmente no me importa encontrar la ruta a mi .exe, simplemente no entendí lo que estaba pasando con la resolución relativa de la ruta (y aún puedo tener mi terminología estropeada) ...
Puede usar esto para especificar una ruta que resida en la misma ruta de su exe @ ".. / CAISLog.csv". Tenga en cuenta que los puntos dobles hacen referencia al directorio padre de donde se encuentra su .exe.
RWendi
Cuando se inicia una aplicación (WinForms), el Environment.CurrentDirectory
contiene la ruta a la carpeta de la aplicación (es decir, la carpeta que contiene el ensamblado .exe). Usando cualquiera de los cuadros de diálogo de archivos, ej. OpenFileDialog
, SaveFileDialog
, etc. causará que el directorio actual cambie (si se seleccionó una carpeta diferente).
Cuando se ejecuta un Servicio de Windows, su carpeta contenedora es C: / Windows / System32, ya que esa es la carpeta del Sistema y es el Sistema (es decir, el Sistema de Operación) el que realmente está ejecutando su Servicio de Windows.
Tenga en cuenta que al especificar una ruta relativa en la mayoría de los objetos System.IO
, recurrirá a la propiedad Environment.CurrentDirectory
.
Como se mencionó, hay varias formas de obtener la ruta del ejecutable del servicio, utilizando Assembly.GetEntryAssembly()
o Assembly.GetExecutingAssembly()
y luego usando la propiedad Location
o la propiedad CodeBase
(tenga en cuenta que esta es la ruta del archivo, no directorio, del ejecutable).
Otra opción es usar:
`System.IO.Directory.SetCurrentDirectory( System.AppDomain.CurrentDomain.BaseDirectory );`
Haga la llamada en el método OnStart
del Servicio, aplicándolo a toda la aplicación.
Se basa en el directorio de trabajo actual, que puede ser o no el mismo que el de su aplicación, especialmente si se inició desde un programa diferente o un acceso directo con un directorio de trabajo diferente.
En lugar de codificar el camino, obtenga la ruta a su programa y úselo. Puedes hacer esto con algo como esto
Assembly ass = Assembly.GetEntryAssembly();
string dir = Path.GetDirectoryName(ass.Location);
string filename = Path.Combine( dir, "CAISLog.csv" );
Esto supone que el ensamblaje de entrada es donde se encuentra su archivo. Si no, puede cambiar obteniendo el ensamblado para algo así como;
Assembly ass = Assembly.GetAssembly( typeof( AClassInYourAssembly ) );