web-dev-qa-db-fra.com

Définir un chemin personnalisé pour les DLL référencées?

J'ai un projet C # (appelez-le MainProj) qui référence plusieurs autres projets DLL. En ajoutant ces projets aux références de MainProj, il les construira et copiez leurs DLL résultantes dans le répertoire de travail de MainProj.

Ce que j'aimerais faire, c'est que ces DLL référencées soient situées dans un sous-répertoire du répertoire de travail de MainProj, c'est-à-dire MainProj/bin/DLL, plutôt que dans le répertoire de travail lui-même.

Je ne suis pas un programmeur C # très expérimenté, mais venant du monde C++, je suppose qu'une approche serait de supprimer les références du projet et de charger explicitement les DLL requises par chemin et nom de fichier (c'est-à-dire en C++, LoadLibrary). Ce que je préférerais faire cependant, s'il y a un moyen, serait de définir une sorte de "chemin binaire de référence", afin qu'ils soient tous automatiquement copiés dans ce sous-répertoire lorsque je construis (puis référencés à partir de là sans me besoin de charger explicitement chacun). Une telle chose est possible?

Sinon, quelle est la méthode préférée en C # pour accomplir ce que je recherche (c'est-à-dire quelque chose avec Assembly.Load/Assembly.LoadFile/Assembly.LoadFrom? Quelque chose dans AppDomain peut-être, ou System.Environment?)

49
Metal450

De cette page (non testé par moi):

Quelque part dans l'initialisation de votre programme (avant d'accéder à des classes à partir d'un assembly référencé), procédez comme suit:

AppDomain.CurrentDomain.AppendPrivatePath(@"bin\DLLs");

Modifier: Cet article dit que AppendPrivatePath est considéré comme obsolète, mais donne également une solution de contournement.

Modifier 2: Il semble que la façon la plus simple et la plus casher de le faire soit dans le fichier app.config (voir ici ):

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-Microsoft-com:asm.v1">
      <probing privatePath="bin\DLLs" />
    </assemblyBinding>
  </runtime>
</configuration>
78
Aaron

De Tomek répondez à: Chargement des dll à partir du chemin spécifié dans SetdllDirectory en c #

var dllDirectory = @"C:/some/path";
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory)

Cela fonctionne parfaitement pour moi!

22
Pedro77

Voici une autre façon de procéder sans utiliser AppendPrivatePath obsolète. Il intercepte une sorte d'événement " DLL associée non trouvée " (il ne sera donc appelé que si la DLL n'est pas trouvée dans le répertoire par défaut).

Fonctionne pour moi (.NET 3.5, pas testé d'autres versions)

/// <summary>
/// Here is the list of authorized assemblies (DLL files)
/// You HAVE TO specify each of them and call InitializeAssembly()
/// </summary>
private static string[] LOAD_ASSEMBLIES = { "FooBar.dll", "BarFooFoz.dll" };

/// <summary>
/// Call this method at the beginning of the program
/// </summary>
public static void initializeAssembly()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
    {
        string assemblyFile = (args.Name.Contains(','))
            ? args.Name.Substring(0, args.Name.IndexOf(','))
            : args.Name;

        assemblyFile += ".dll";

        // Forbid non handled dll's
        if (!LOAD_ASSEMBLIES.Contains(assemblyFile))
        {
            return null;
        }

        string absoluteFolder = new FileInfo((new System.Uri(Assembly.GetExecutingAssembly().CodeBase)).LocalPath).Directory.FullName;
        string targetPath = Path.Combine(absoluteFolder, assemblyFile);

        try
        {
            return Assembly.LoadFile(targetPath);
        }
        catch (Exception)
        {
            return null;
        }
    };
}

PS: je n'ai pas réussi à utiliser AppDomainSetup.PrivateBinPath, c'est trop laborieux.

8
56ka