.net程序找不到DLL最有效方式?

原理:当程序启动加载程序集找不到时,会触发OnAssemblyResolve事件,再递归判断dll文件是否存在,如果存在则返回加载后的Assembly。
不用注册全局程序集,也不用强签名,非常有效。
public App()
{
    LoadEnvPaths();//对引用C++有效
    AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
}
//-------------------------------------------------------------------------
/// <summary>
/// 事件处理加载平台程序集(.net程序集路径)
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
    // 获取要加载的程序集的名称
    string assemblyName = new AssemblyName(args.Name).Name;
    if (assemblyName.Contains(".resources")) return null;
    // 从环境变量或配置文件中获取程序集路径
    //一般程序集只安排在以下两个文件夹
    List<string> paths = GetEnvPaths();
    foreach ( string path in paths )
    {
        // 组合程序集的完整路径
        string fullPath = System.IO.Path.Combine( path , assemblyName + ".dll" );
        if (File.Exists(fullPath))
        {
            // 从指定路径加载程序集
            return Assembly.LoadFrom( fullPath );
        }
    }
    // 返回 null 以表示加载失败
    return null;
}
//-------------------------------------------------------------------------
/// <summary>
/// 获取环境路径
/// </summary>
/// <returns></returns>
public static List<string> GetEnvPaths()
{
    List<string> paths = new List<string>();
    paths.AddRange(GetPaths(@"J:\Gui"       ));
    paths.AddRange(GetPaths(@"J:\Library"   ));
    return paths;
}
//-------------------------------------------------------------------------
/// <summary>
/// 设置MT平台环境路径(C++类库路径)
/// </summary>
public static void LoadEnvPaths()
{
    var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };
    List<string> paths = GetEnvPaths();
    string newPath = string.Join(System.IO.Path.PathSeparator.ToString(), path.Concat( paths ));
    Environment.SetEnvironmentVariable("PATH", newPath);
}
//-------------------------------------------------------------------------
/// <summary>
/// 获取指定目录下所有可能子目录
/// </summary>
/// <param name="rootPath">[输入] 指定目录</param>
/// <returns></returns>
static List<string> GetPaths( string rootPath )
{
    List<string> directories = new List<string>();
    directories.Add(rootPath);// 添加当前目录的路径 
    try
    {
        // 获取当前目录下的所有子目录
        string[] subdirectories = Directory.GetDirectories(rootPath);
        foreach (string subdirectory in subdirectories)
        {                          
            directories.AddRange( GetPaths( subdirectory ) );// 递归调用获取子目录的路径
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error accessing {rootPath}: {ex.Message}");
    }
    return directories;
}

 

posted @ 2024-09-01 17:22  高侃  阅读(92)  评论(0)    收藏  举报