CLR/C++程序找不到DLL最有效方法?

高侃 / 2024-09-02 / 原文

 使用C++17及以上,支持 filesystem 处理
不需要程序集强签名 , 也不用注册全局程序集缓存,非常有效。
#include <iostream>
#include <filesystem>
using namespace std::filesystem;
namespace fs = std::filesystem;
//-----------------------------------------------------------------
 /// <summary>
 /// 获取子目录
 /// </summary>
 /// <param name="dir"></param>
 /// <param name="subdirs"></param>
 void GetPaths( const fs::path& dir , std::vector<fs::path>& subdirs ) {
     subdirs.push_back(dir);
     for (const auto& entry : fs::directory_iterator(dir)) {
         const auto& path = entry.path();
         if (fs::is_directory(path)) {
             //subdirs.push_back(path);
             GetPaths( path , subdirs ); // 递归获取子目录中的子目录
         }
     }
 }
 //-----------------------------------------------------------------
 int _tmain( int argc, _TCHAR* argv[] )
{
    AppDomain^ currentDomain = AppDomain::CurrentDomain;
    currentDomain->AssemblyResolve += gcnew ResolveEventHandler(MyResolveEventHandler);
}
//-----------------------------------------------------------------
static Assembly^ MyResolveEventHandler(Object^ sender, ResolveEventArgs^ args)
{
    String^ dll_name;
    AssemblyName^ myAssemblyName = gcnew AssemblyName(args->Name);
    Console::WriteLine("Resolving..." + myAssemblyName->Name);
    dll_name = myAssemblyName->Name;
    //-个dll文件会产生2次事件,比如abc.dll第一次是abc,需要自己添加dll扩展名,第二次会需要abc.resources,此时返回空即可
    if (dll_name->Contains(".resources")) return nullptr;
    dll_name += ".dll";
    string dll_name_str = marshal_as<std::string>(dll_name->ToString());   
    std::vector<fs::path> subdirs;
    GetPaths("J:\\Library\\C#", subdirs);
    GetPaths("J:\\Driver\\C#" , subdirs);
    std::string filePath;
    for ( const auto& subdir : subdirs ) {
        std::cout << subdir << std::endl;
        filePath = subdir.string();
        filePath += "\\";
        filePath += dll_name_str;if (fs::exists(filePath)) {
            std::cout << "文件存在:" << filePath  << std::endl;
            return Assembly::LoadFrom( marshal_as<String^>( filePath ) );
        }
    }
    return nullptr;
}