简体   繁体   中英

How do I manually edit the manifest of my Visual Studio project to explicitly specify referenced assemblies?

Due to a serious headache with log4net's strong naming and versioning, ie, the old 1.2.10 name, the new 1.2.11 name, and (heaven help me) the 1.2.10 one SAP made and shoved into the GAC with its own strong name, my application will refuse to run on any machine but my own. It keeps looking for version 1.2.11 of the strongly named SAP version, which doesn't exist.

As nothing in my project is strongly named, I want to stop the compiler from looking for a strongly named assembly and just load the one I put in the directory. Since it is complaining about the manifest not matching, I'm trying to find a reference in my project for that version and public key, but I am coming up short. It seems this manifest is created at compile time.

How can I override that? is there a property or switch or conditional compilation I can use to specify exactly which assembly I wish to reference?

Ultimately I want to use the 1.2.11 version of log4net, and force the assembly to ignore the version in the GAC, to look only in the local bin directory. This really shouldn't be this painful.

Runtime Directive

At runtime, you can use AppDomain.AssemblyResolve to combat the assembly versioning issue when you don't care what specific version is present, you just want to load what's in the /bin folder. This code was created with inspiration from here .

string[] ignoreAssembyVersions = new string[] { "log4net" };
AppDomain.CurrentDomain.AssemblyResolve += (_, assembly) =>
{
    //ignore the vesion number and return any version that has been loaded
    var name = new AssemblyName(assembly.Name);
    var shortName = name.Name; // retrieve short name
    if (ignoreAssembyVersions.Contains(shortName)) // compare against list of assemblies we ignore revisions for
    {
        // check if this assembly is already loaded under a different version #
        Assembly[] allAss = AppDomain.CurrentDomain.GetAssemblies();
        List<Assembly> list = new List<Assembly>(allAss);
        var loadedAssembly = list.Find(ass => new AssemblyName(ass.FullName).Name == shortName); // check if we have any version loaded yet
        if (loadedAssembly != null)
            return loadedAssembly;
        else // assembly has not yet been loaded in this domain
        {   // probe for assembly by name
            Assembly probedAssembly = Assembly.LoadFrom(string.Format("{0}.dll", shortName)); // probe for any match on assembly.dll 
            return probedAssembly;
        }
    }
    return null; // ignore binding failure -> pass up the stack
};

An alternative to handling the AssemblyResolve event would be to use a custom bindingRedirect policy . However - this only works if you know what version is present in the /bin or currently loaded in the App Domain.

Build-Time Directive

If you want control of which assembly version is used at build-time , you can use the Specific Version='true' for assembly references you add.

I hope I've understood your problem. You may consider using dependentAssembly configuration for supporting custom binding policy and assembly location for each assembly. This is the snapshot of my configuration policy for looking up for another version of the assembly System.Data.SQLite

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.0.81.0" newVersion="1.0.81.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM