2009-04-30 14 views
8

Estoy intentando cambiar el elemento bindingRedirect en el momento de la instalación utilizando la clase XmlDocument y modificando el valor directamente. Esto es lo que se ve mi app.config como:Cómo modificar programáticamente assemblyBinding en 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> 
 

Entonces trato de utilizar el código siguiente para cambiar 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")); 

    } 

Sin embargo, se produce la excepción 'no encontrado'. Si respaldo la ruta hasta/configuration/runtime, funciona. Sin embargo, una vez que agregue assemblyBinding, no encuentra el nodo. Posiblemente esto tiene algo que ver con los xmlns? ¿Alguna idea de cómo puedo modificar esto? ConfigurationManager tampoco tiene acceso a esta sección.

Respuesta

8

Encontré lo que necesitaba. Se requiere XmlNamespaceManager ya que el nodo assemblyBinding contiene el atributo xmlns. He modificado el código para utilizar este y funciona:

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, tiro excepciones ya que esto es parte de un Proyecto de Configuración y así es como el instalador es notificado de cualquier error. Sería mejor que el método devuelva verdadero o falso si se realizó la modificación. – esac

-1

creo que la sintaxis XPath correcta es:

/configuración/runtime/assemblyBinding/dependentAssembly/bindingRedirect @ newVersion

(que tiene una barra demasiados).

O si esto no funciona, puede seleccionar el elemento bindingRedirect (usando SelectSingleNode):

/configuración/runtime/assemblyBinding/dependentAssembly/bindingRedirect

A continuación, modifique el atributo newVersion de este elemento.

+0

Ya ha pasado por este camino, se queja de un token no válido con bindingRedirect @ newVersion. En el segundo caso, se queja de que no pudo encontrar el camino especificado. – esac

8

Suena como que tienes el archivo de configuración ajustar a trabajar ahora, pero pensé que todavía puede estar interesado en saber cómo ajustar las redirecciones de enlace en tiempo de ejecución. La clave es usar el evento AppDomain.AssemblyResolve, y los detalles están en this answer. Prefiero usar el archivo de configuración, porque la comparación de mi número de versión puede ser un poco más sofisticada y no tengo que ajustar el archivo de configuración durante cada compilación.

+0

¡Amigo! Esta debería ser la respuesta aceptada. – Jupaol

+3

Esto funciona, si la carga de ensamblaje falla inicialmente. Sin embargo, si su aplicación logra cargar con éxito el ensamblaje _wrong_, AssemblyResolve nunca se dispara. Entonces la única opción en ese caso es modificar app.config. – Phil

+0

Desearía poder retirar mi voto. En realidad, esto no funciona si se establece el enlace, a partir de .NET 4.6.1. Todavía obtiene fallas de enlace de ensamblaje. – Nuzzolilo

Cuestiones relacionadas