2

In our application, we have the need to dynamically load 3rd-party assemblies where we do not know in advance all released assembly version numbers. All we know is, for example, that the major version number for the assembly must be "12". On a PC, multiple versions of the same assembly may be installed, having both higher and lower major version numbers.

I.e. we would need something like

Assembly myAssembly = Assembly.Load("SampleAssembly, Version=12.*.*.*");

and if the assembly versions 11.1.2.3, 12.7.6.5, and 13.9.8.7 are installed, it should load version 12.7.6.5.

I.e. it should be possible to specify wildcards for version number components and it also should be possible to omit Culture and PublicKeyToken. When we do this with Assembly.Load(), we get a FileNotFoundException.

We cannot use Assembly.LoadWithPartialName() because it always loads the assembly with the highest version number, but we want a specific major version number instead, which possibly is less than the greatest installed assembly version number.

Is it possible to do this?

  • what you ask is clear, just as backup, if you do not find the best/exact way to load with woldcards, I would use the custom way with AssemblyResolve event and version check in there, see this answer: http://stackoverflow.com/questions/1235253/how-is-an-assembly-resolved-in-net – Davide Piras Feb 13 '12 at 11:00
  • @Davide: If I understand AssemblyResolve correctly, it is raised only if loading the assembly fails and then the event handler must return the correct assembly location. I do not see how this would help for my requirement (because AssemblyResolve's event argument do not provide a list of available assemblies with the same name). –  Feb 13 '12 at 11:12
  • This is just not possible. Use the `` element in the app's .config file. – Hans Passant Feb 13 '12 at 13:45

1 Answers1

0

You could manually list the content of the GAC and compare it to your wildcards as so

class Program
{
    static void Main(string[] args)
    {
        var assemblyName = "SimpleAssembly";
        var versionRegex = new Regex(@"^12\.");
        var assemblyFile = FindAssemblyFile(assemblyName, versionRegex);

        if (assemblyFile == null)
            throw new FileNotFoundException();

        Assembly.LoadFile(assemblyFile.FullName);
    }

    static FileInfo FindAssemblyFile(string assemblyName, Regex versionRegex)
    {
        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "assembly", "GAC_MSIL", assemblyName);
        var assemblyDirectory = new DirectoryInfo(path);

        foreach (var versionDirectory in assemblyDirectory.GetDirectories())
        {
            if (versionRegex.IsMatch(versionDirectory.Name))
            {
                return versionDirectory.GetFiles()[0];
            }
        }

        return null;
    }
}
Francis
  • 3,335
  • 20
  • 46
  • Thanks, that worked for me. I was afraid that this kind of directory search might be too slow, but I did some tests and it actually was pretty fast. –  Feb 13 '12 at 15:25