2009-04-30 23 views
8

Sto cercando di modificare l'elemento bindingRedirect al momento dell'installazione utilizzando la classe XmlDocument e modificando direttamente il valore. Ecco ciò che il mio app.config assomiglia:Come modificare programatically assemblyBinding in app.config?

 

<configuration> 
    <configSections> 
     <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">    
      ... 
     </sectionGroup>  
    </configSections> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
      <assemblyIdentity name="MyDll" publicKeyToken="31bfe856bd364e35"/> 
      <bindingRedirect oldVersion="0.7" newVersion="1.0"/> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime>  
... 
</configuration> 
 

Allora provo a utilizzare il seguente codice per modificare 1.0 a 2,0

private void SetRuntimeBinding(string path, string value) 
    { 
     XmlDocument xml = new XmlDocument(); 


     xml.Load(Path.Combine(path, "MyApp.exe.config")); 
     XmlNode root = xml.DocumentElement; 

     if (root == null) 
     { 
      return; 
     } 

     XmlNode node = root.SelectSingleNode("/configuration/runtime/assemblyBinding/dependentAssembly/bindingRedirect/@newVersion"); 

     if (node == null) 
     { 
      throw (new Exception("not found")); 
     } 

     node.Value = value; 

     xml.Save(Path.Combine(path, "MyApp.exe.config")); 

    } 

Tuttavia, genera l'eccezione 'non trovato'. Se riporto il percorso fino a/configuration/runtime, funziona. Tuttavia, una volta aggiunto assemblyBinding, non trova il nodo. Forse questo ha qualcosa a che fare con gli xmlns? Qualche idea su come posso modificare questo? Anche ConfigurationManager non ha accesso a questa sezione.

risposta

8

Ho trovato ciò di cui avevo bisogno. XmlNamespaceManager è richiesto poiché il nodo assemblyBinding contiene l'attributo xmlns. Ho modificato il codice per utilizzare questo e funziona:

private void SetRuntimeBinding(string path, string value) 
    { 
     XmlDocument doc = new XmlDocument(); 

     try 
     { 
      doc.Load(Path.Combine(path, "MyApp.exe.config")); 
     } 
     catch (FileNotFoundException) 
     { 
      return; 
     } 

     XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable); 
     manager.AddNamespace("bindings", "urn:schemas-microsoft-com:asm.v1"); 

     XmlNode root = doc.DocumentElement; 

     XmlNode node = root.SelectSingleNode("//bindings:bindingRedirect", manager); 

     if (node == null) 
     { 
      throw (new Exception("Invalid Configuration File")); 
     } 

     node = node.SelectSingleNode("@newVersion"); 

     if (node == null) 
     { 
      throw (new Exception("Invalid Configuration File")); 
     } 

     node.Value = value; 

     doc.Save(Path.Combine(path, "MyApp.exe.config")); 
    } 
+1

Solo una nota, io lancio le eccezioni perché questo fa parte di un progetto di installazione e questo è il modo in cui l'installatore riceve una notifica di eventuali errori. Sarebbe meglio se il metodo restituisse true o false se la modifica è stata effettuata. – esac

-1

penso che la sintassi XPath giusta è:

/configurazione/runtime/assemblyBinding/dependentAssembly/bindingRedirect @ newVersion

(si dispone di una barra di troppo).

o se questo non funziona è possibile selezionare l'elemento bindingRedirect (utilizzando SelectSingleNode):

/configurazione/runtime/assemblyBinding/dependentAssembly/bindingRedirect

Poi modificare l'attributo newVersion di questo elemento.

+0

Già in questo percorso, si lamenta di token non valido con bindingRedirect @ newVersion. Secondo caso, si lamenta che non è stato possibile trovare il percorso specificato. – esac

8

Suona come avete ottenuto il vostro file di configurazione di tweak ora di lavoro, ma ho pensato che potrebbe essere ancora interessato a come regolare redirect vincolanti in fase di esecuzione. La chiave è utilizzare l'evento AppDomain.AssemblyResolve ei dettagli sono in this answer. Preferisco usare il file di configurazione, perché il mio confronto tra numeri di versione può essere un po 'più sofisticato e non devo modificare il file di configurazione durante ogni build.

+0

Amico! Questa dovrebbe essere la risposta accettata. – Jupaol

+3

Questo funziona, se inizialmente il carico dell'assieme non riesce. Tuttavia, se l'app riesce a caricare correttamente l'assembly _wrong_, AssemblyResolve non viene mai attivato. Quindi l'unica opzione in questo caso è modificare l'app.config. – Phil

+0

Vorrei poter ritirare il mio voto. Questo in realtà non funziona se l'associazione è impostata, come da .NET 4.6.1. Ancora errori di associazione all'assemblaggio. – Nuzzolilo