VC++自定義加載DLL,從任意位置加載依賴的DLL
隱藏VS開發(fā)的程序目錄下的DLL,可以將依賴的DLL放到指定位置去。
1.一直使用第三方控件,編譯后依賴的控件都在運(yùn)行目錄,或者system32目錄,看的很別扭,尋找過(guò)很多方法重定義加載,發(fā)現(xiàn)太復(fù)雜,最后無(wú)意間使用反射時(shí)發(fā)現(xiàn),同一個(gè)DLL放在不同的地方只會(huì)被加載一次,因?yàn)槊總€(gè)dll都有一個(gè)唯一的KEY,利用這個(gè)方法,人為的加載這些DLL,可以從任意位置加載,可以解決程序運(yùn)行目錄下一堆DLL文件的問(wèn)題。
這個(gè)方法只適用于反射方式加載的控件所依賴的DLL,不能對(duì)直接引用的DLL進(jìn)行預(yù)加載。
//初始化加載一些用到的DLL文件 try { System::Reflection::Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\DevComponents.DotNetBar2.dll"); //加載DLL System::Reflection::Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\DevExpress.Data.v14.2.dll"); //加載DLL System::Reflection::Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\DevExpress.Utils.v14.2.dll"); //加載DLL System::Reflection::Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\DevExpress.XtraEditors.v14.2.dll"); //加載DLL System::Reflection::Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\IPAddressControlLib.dll"); //加載DLL } catch?(System::IO::FileNotFoundException^?e) { System::Windows::Forms::MessageBox::Show(e->Message,?"加載控件錯(cuò)誤,可能無(wú)法進(jìn)行配置!", System::Windows::Forms::MessageBoxButtons::OK,?System::Windows::Forms::MessageBoxIcon::Error); }
2.對(duì)直接依賴以及引用的DLL進(jìn)行加載。
CLR會(huì)自動(dòng)從運(yùn)行目錄或system32加載DLL,如果沒(méi)有找到就會(huì)觸發(fā)?AssemblyResolve 事件,在此事件中就可以自己去加載需要的DLL文件,返回給CLR.
using?namespace?System::Reflection;
Assembly^?MyResolveEventHandler(Object^?sender,?ResolveEventArgs^?args); //申明 [STAThreadAttribute] int?main(array^args) { AppDomain^?currentDomain?=?AppDomain::CurrentDomain; //?在創(chuàng)建任何控件之前啟用?Windows?XP?可視化效果 Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false);? currentDomain->AssemblyResolve?+=?gcnew?ResolveEventHandler(MyResolveEventHandler); //?創(chuàng)建主窗口并運(yùn)行它 Application::Run(gcnew?Form1()); return?0; } //缺少DLL文件加載的事件 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; if?(dll_name->IndexOf(".resources")?<?0) //一個(gè)DLL文件會(huì)產(chǎn)生2次事件,比如abc.dll??第一次是abc,需要自己添加DLL擴(kuò)展名,第二次會(huì)需要abc.resources,此時(shí)返回為空即可 { dll_name?+=?".DLL"; } else?return?nullptr; //resources返回為空即可 return?Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\"?+?dll_name); }
Assembly::LoadFrom(USER_LIB.GetAppRunningDirectory()?+?"\DLL\"?+?dll_name);
這個(gè)就是從指定的位置加載DLL,可以更換為你自己定義的目錄或者從資源文件中加載。