从 C++/CLI 加载相互依赖的程序集
我想从 C++/CLI 加载两个程序集;程序集 A 依赖于程序集 B,并且两者都是 VB.Net 项目 (3.5)。我希望它们从字节数组加载,所以我使用 Assembly::Load(),但是当我尝试从程序集 A 实例化一个类时,框架会忽略先前加载的程序集 B 并尝试再次加载它,这会失败,因为它不在搜索路径中。程序集的“名称”是相同的,所以我不知道为什么会失败。出于测试目的,我的程序直接从编译的图像加载字节,但实际代码的加载方式会有所不同。这是我的测试代码:
#include "stdafx.h"
using namespace System;
using namespace System::Windows::Forms;
using namespace System::IO;
using namespace System::Reflection;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
array<unsigned char>^ bytes;
FileStream^ f;
f = gcnew FileStream(L"c:\\...\\AssemblyB.dll", FileMode::Open);
bytes = gcnew array<unsigned char>((int)f->Length);
f->Read( bytes, 0, (int) f->Length );
f->Close();
f = nullptr;
Assembly^ assemblyb = Assembly::Load(bytes);
f = gcnew FileStream(L"c:\\...\\AssemblyA.dll", FileMode::Open);
bytes = gcnew array<unsigned char>((int)f->Length);
f->Read( bytes, 0, (int) f->Length );
f->Close();
f = nullptr;
Assembly^ assemblya = Assembly::Load(bytes);
bytes = nullptr;
// Here I get the file not found exception!
Object^ mf = assemblya->CreateInstance(L"AssemblyA.MainForm");
// This line is not reached unless I copy assemblyb.dll to my app's folder:
mf->GetType()->InvokeMember(L"ShowDialog",BindingFlags::Default | BindingFlags::InvokeMethod,
mf->GetType()->DefaultBinder, mf, nullptr );
return 0;
}
错误是:
无法加载文件或程序集“AssemblyB,Version=1.0.3650.39903,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到指定的文件。
当我检查 assemblyb->FullName 时,它准确地显示“AssemblyB, Version=1.0.3650.39903, Culture=neutral, PublicKeyToken=null”。
当然,如果我将 AssemblyB.dll 复制到测试程序的文件夹中,代码就可以正常工作,但这不是我想要的。
有什么想法吗?
(顺便说一句,我的第二步将尝试使 AssemblyA 使用我的 C++/CLI exe 将公开的类。)
I want to load two assemblies from C++/CLI; assembly A depends on assembly B, and both are VB.Net projects (3.5). I want them to load from a byte array, so I use Assembly::Load(), but when I try to instantiate a class from assembly A, the framework ignores the previously loaded assembly B and attempts to load it again, which fails because it is not in the search path. The "Name" of the assembly is the same, so I don't know why it fails. For testing purposes, my program loads the bytes directly from the compiled image, but the real code will be loaded differently. This is my test code:
#include "stdafx.h"
using namespace System;
using namespace System::Windows::Forms;
using namespace System::IO;
using namespace System::Reflection;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
array<unsigned char>^ bytes;
FileStream^ f;
f = gcnew FileStream(L"c:\\...\\AssemblyB.dll", FileMode::Open);
bytes = gcnew array<unsigned char>((int)f->Length);
f->Read( bytes, 0, (int) f->Length );
f->Close();
f = nullptr;
Assembly^ assemblyb = Assembly::Load(bytes);
f = gcnew FileStream(L"c:\\...\\AssemblyA.dll", FileMode::Open);
bytes = gcnew array<unsigned char>((int)f->Length);
f->Read( bytes, 0, (int) f->Length );
f->Close();
f = nullptr;
Assembly^ assemblya = Assembly::Load(bytes);
bytes = nullptr;
// Here I get the file not found exception!
Object^ mf = assemblya->CreateInstance(L"AssemblyA.MainForm");
// This line is not reached unless I copy assemblyb.dll to my app's folder:
mf->GetType()->InvokeMember(L"ShowDialog",BindingFlags::Default | BindingFlags::InvokeMethod,
mf->GetType()->DefaultBinder, mf, nullptr );
return 0;
}
The error is:
Could not load file or assembly 'AssemblyB, Version=1.0.3650.39903, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
When I check assemblyb->FullName, it says exactly 'AssemblyB, Version=1.0.3650.39903, Culture=neutral, PublicKeyToken=null'.
Of course, if I copy AssemblyB.dll to my test program's folder the code works just fine, but that's not what I want.
Any ideas?
(By the way, my second step will be attempt to make AssemblyA use classes that my C++/CLI exe will expose.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我只是让自己感到尴尬。这一切都在文档中。
我希望有人觉得这很有用。 :)
OK, I just embarrased myself. It's all in the docs.
I hope someone finds this useful. :)