2010-09-03 6 views
8

Je souhaite changer l'emplacement où mon application recherche le fichier app.config.Comment changer l'emplacement de app.config

Je sais que je peux utiliser ConfigurationManager.OpenExeConfiguration() pour accéder à un fichier de configuration arbitraire - cependant, lorsque le .Net Framework lit le fichier de configuration (pour ConnectionStrings ou EventSources, par exemple), il regarde l'emplacement par défaut . Je veux réellement changer l'emplacement, globalement pour l'ensemble. Net Framework (pour mon application, bien sûr).

Je sais également que je peux utiliser AppDomainSetup pour modifier l'emplacement de app.config pour un nouvel AppDomain. Toutefois, cela ne s'applique pas au domaine principal AppDomain de l'application.

Je sais aussi que je peux remplacer la fonction Main() et créer un nouveau AppDomain comme ci-dessus et exécuter mon application dans ce nouveau AppDomain. Cependant, cela a d'autres effets secondaires - par exemple, Assembly.GetEntryAssembly() renverra une référence null. Etant donné que tout le reste fonctionne dans .Net, je m'attendrais à ce qu'il y ait un moyen de configurer l'environnement de démarrage de mon application - via un manifeste d'application, ou quelque chose comme ça - mais je n'ai pas réussi à trouver une lueur espérons dans cette direction.

Tout pointeur serait utile.

David Mullin

Répondre

9

J'ai utilisé l'approche avec un autre AppDomain de Main(), en spécifiant le "nouvel" emplacement du fichier de configuration.

Aucun problème avec GetEntryAssembly(); il ne retourne que nul, lorsqu'il est appelé à partir du code non géré - ou du moins il ne fonctionne pas moi, comme je l'utilise ExecuteAssembly() pour créer/exécuter le deuxième AppDomain, un peu comme ceci:

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; 
} 

Notez que nous sont effectivement réexécuter le fichier EXE, tout comme un AppDomain et avec une config différente. Notez également que vous devez avoir une option "magique" qui empêche que cela ne se passe indéfiniment. Je l'ai conçu à partir d'un plus gros morceau (réel) de code, donc il pourrait ne pas fonctionner tel quel, mais devrait illustrer le concept.

+0

Hmmm. Dans mon test de cette approche (qui était différent du vôtre), GetEntryAssembly a renvoyé null. Mais, je n'ai pas fait ExecuteAssembly - j'ai trouvé le "second Main" que j'avais écrit et exécuté. Je vais essayer votre approche et voir si cela fonctionne pour moi. –

+0

Je pense que ExecuteAssembly fait la différence. Au moins les Docs disent que GetEntryAssembly renvoie l'exécutable, * ou * celui passé à ExecuteAssembly(). –

0

Je ne sais pas pourquoi vous voulez changer l'emplacement de votre fichier de configuration - peut-être il peut y avoir approche différente pour résoudre votre problème réel. J'avais une exigence où je voulais partager le fichier de configuration entre les applications connexes - j'avais choisi d'utiliser le propre fichier xml car cela m'avait donné un avantage supplémentaire d'avoir un contrôle complet sur le schéma.

Dans votre cas, il est possible d'externaliser des sections de votre fichier de configuration dans un fichier séparé à l'aide de la propriété configSource. Voir here sous "Utilisation de fichiers de configuration externes" pour vérifier comment cela a été fait pour la section des chaînes de connexion. Peut-être, cela peut vous aider.

+0

La principale raison de vouloir faire cela est que l'application est installée via ClickOnce, qui cache efficacement le fichier de configuration. Cependant, il existe des paramètres (comme les entrées TraceSource) que je veux être configurable sur l'ordinateur client et persister entre les installations (car une mise à jour de ClickOnce peut remplacer le fichier de configuration). –

+0

Je vois - peut-être que vous pouvez utiliser AppSettings (http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx) pour cela? Ils prennent en charge le scénario ClickOnce - voir http://msdn.microsoft.com/fr-fr/library/ms228995.aspx. – VinayC

+0

Je ne peux pas utiliser AppSettings, car le .Net Framework ne recherchera pas TraceSources (ou toute autre configuration spécifique au 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); 

Ensuite, utilisez le membre de configuration comme vous le souhaitez.

+0

Ceci peut être utile pour d'autres utilisateurs, mais ne fait rien pour résoudre le problème de l'OP. Il déclare explicitement pourquoi cette approche ne peut pas fonctionner pour lui dans la question. Plus précisément, diverses classes d'infrastructure (configuration WCF par exemple) obtiennent les paramètres du fichier de configuration dans l'emplacement par défaut ... vous ne pouvez pas les influencer à la place utiliser l'instance 'Configuration' dans votre variable" config ". – TCC