2010-09-03 21 views
8

Quiero cambiar la ubicación donde mi aplicación busca el archivo app.config.Cómo cambiar la ubicación de app.config

Sé que puedo usar ConfigurationManager.OpenExeConfiguration() para acceder a un archivo de configuración arbitrario; sin embargo, cuando .Net Framework lee el archivo de configuración (para ConnectionStrings o EventSources, por ejemplo), verá la ubicación predeterminada . Quiero cambiar la ubicación, globalmente, para todo el .Net Framework (para mi aplicación, por supuesto).

También sé que puedo usar AppDomainSetup para cambiar la ubicación de la aplicación.config para un nuevo dominio de aplicación. Sin embargo, eso no se aplica al dominio de aplicación principal de la aplicación.

También sé que puedo anular la función Main() y crear un nuevo AppDomain como el anterior y ejecutar mi aplicación en ese nuevo AppDomain. Sin embargo, eso tiene otros efectos secundarios, por ejemplo, Assembly.GetEntryAssembly() devolverá una referencia nula.

Dado que todo lo demás funciona en .Net, espero que haya alguna forma de configurar el entorno de inicio de mi aplicación, a través de un Manifiesto de aplicación, o algo así, pero no he podido encontrar ni un atisbo de espero en esa dirección.

Cualquier puntero sería útil.

David Mullin

Respuesta

9

Utilicé el enfoque al iniciar otro AppDomain desde Main(), especificando la "nueva" ubicación del archivo de configuración.

No hay problemas con GetEntryAssembly(); sólo se devuelve un valor nulo, cuando se llama desde código no administrado - o al menos no lo hace para mí, como yo uso ExecuteAssembly() para crear/ejecutar el segundo dominio de aplicación, muy parecido a éste:

int Main(string[] args) 
{ 
    string currentExecutable = Assembly.GetExecutingAssembly().Location; 

    bool inChild = false; 
    List<string> xargs = new List<string>(); 
    foreach (string arg in xargs) 
    { 
     if (arg.Equals("-child")) 
     { 
     inChild = true; 
     } 
     /* Parse other command line arguments */ 
     else 
     { 
     xargs.Add(arg); 
     } 
    } 

    if (!inChild) 
    { 
     AppDomainSetup info = new AppDomainSetup(); 
     info.ConfigurationFile = /* Path to desired App.Config File */; 
     Evidence evidence = AppDomain.CurrentDomain.Evidence; 
     AppDomain domain = AppDomain.CreateDomain(friendlyName, evidence, info); 

     xargs.Add("-child"); // Prevent recursion 

     return domain.ExecuteAssembly(currentExecutable, evidence, xargs.ToArray()); 
    } 

    // Execute actual Main-Code, we are in the child domain with the custom app.config 

    return 0; 
} 

Nótese que se están volviendo a ejecutar el EXE, solo como un Dominio de aplicación y con una configuración diferente. También tenga en cuenta que debe tener alguna opción "mágica" que evite que esto continúe sin fin.

Lo he creado a partir de un fragmento de código más grande (real), por lo que podría no funcionar como está, pero debería ilustrar el concepto.

+0

Hmmm. En mi prueba de este enfoque (que era diferente al tuyo), GetEntryAssembly devolvió nulo. Pero no hice ExecuteAssembly, encontré el "segundo Main" que había escrito y ejecutado. Probaré tu enfoque y veré si funciona para mí. –

+0

Creo que ExecuteAssembly hace la diferencia. Al menos los Documentos dicen que GetEntryAssembly devuelve el ejecutable, * o * el que pasó a ExecuteAssembly(). –

0

No estoy seguro de por qué desea cambiar la ubicación de su archivo de configuración - tal vez no puede haber enfoque diferente para resolver su problema real. Tenía un requisito en el que quería compartir el archivo de configuración en las aplicaciones relacionadas: había elegido usar un archivo xml propio, ya que me había dado un beneficio adicional de tener un control completo sobre el esquema.

En su caso, es posible externalizar secciones de su archivo de configuración en un archivo separado utilizando la propiedad configSource. Consulte here en "Uso de archivos de configuración externos" para verificar cómo se ha hecho para la sección de cadenas de conexión. Quizás, esto puede ayudarte.

+0

La razón principal para querer hacer esto es que la aplicación se instala a través de ClickOnce, que efectivamente oculta el archivo de configuración. Sin embargo, hay configuraciones (como entradas de TraceSource) que quiero que sean configurables en la máquina cliente y que persistan entre instalaciones (ya que una actualización de ClickOnce puede reemplazar el archivo de configuración). –

+0

Veo - ¿quizás pueda usar AppSettings (http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx) para eso? Son compatibles con el escenario de ClickOnce; consulte http://msdn.microsoft.com/en-us/library/ms228995.aspx. – VinayC

+0

No puedo usar AppSettings, porque .Net Framework no buscará TraceSources (ni ninguna otra configuración específica del framework). –

0
var configPath = YOUR_PATH; 
if (!Directory.Exists(ProductFolder)) 
{ 
    Directory.CreateDirectory(ProductFolder); 
} 

if (!File.Exists(configPath)) 
{ 
    File.WriteAllText(configPath, Resources.App); 
} 

var map = new ExeConfigurationFileMap 
{ 
    ExeConfigFilename = configPath, 
    LocalUserConfigFilename = configPath, 
    RoamingUserConfigFilename = configPath 
}; 

Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 

A continuación, utilice el miembro config como lo desee.

+0

Esto podría ser útil para otros usuarios, pero no hace nada para solucionar el problema del OP. Explica explícitamente por qué este enfoque no puede funcionar para él en la pregunta. Específicamente, varias clases de marco (configuración WCF, por ejemplo) obtienen configuraciones del archivo de configuración en la ubicación predeterminada ... no se puede influir en que usen la instancia 'Configuración' en su variable 'config'. – TCC

Cuestiones relacionadas