问题
I have a C# application (project A) that requires X.dll. I have added the project that produces X.dll to A as a reference in visual studio. I have also added the release build of X.dll to a resource file in A as a binary. I have told project A not to copy X.dll to the output directory.
Now I want A.exe to load, say "hey I can't find this file", then look in the resource file and use Assembly.Load(byte[]) get X.dll back. I have the code that re-magicifies the DLL back, however this code never get called.
Currently I have a bone simple project, just trying to get it to work. It compile OK. When I run it, I get a FileNotFoundException on X.dll.
I have:
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
But the breakpoint in *CurrentDomain_AssemblyResolve* never gets hit. I get a FileNotFoundException immediately. Surely there is something I a missing?
回答1:
This question seems to be very similar to what you are trying to achieve, and it worked for the asker.
Merge .dll into C# Assembly?
Are you doing something differently? Specifically, if you're targetting an older version of the .NET Framework, maybe that's a hint for understanding why your application is behaving differently.
Another direction, use a tool such as Fusion Log Viewer to analyze what was going on when you tried to load the assembly. This may give some more hints. If you manage to get log information, posting it in the question may help someone figure it out.
EDIT: Another explanation, following your comment.
Well, now I think I know what the problem is.
In your Main
method, you are refering to the type in the other dll. But you are doing it in static code, i.e. you use the type explicitly in the code (as opposed to loading it dynamically by its name).
Why is this a problem? The CLR tries to load your assembly in order to JIT Main
itself.
Your FileNotFoundException
was thrown while Main
was being compiled. Main
didn't even start running, and therefore your event handler wasn't registered.
A simple way to check if I'm right is to change the code to something like this:
static public void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += MyEventHandler;
MyMain();
}
// The CLR will actually try to load your assembly before even starting the execution
// of this method. It needs the assembly in order to JIT the method because it has to
// know the Thing type.
static public void MyMain()
{
using(var thing = new Thing())
{
// ...
}
}
The important difference is that Main
has no dependency on another assembly, so there will be no problem to JIT and run it.
By the time MyMain
is being JIT'ed, your event handler is already in place so you can manually load the assembly.
By the way, to avoid another possible similar pitfall, make sure that the class in which Main
is defined doesn't have any field with a type from the other assembly, because in this case also, the CLR will try loading the assembly before Main
starts, in order to compile it.
来源:https://stackoverflow.com/questions/4494366/c-how-to-embed-dll-into-resourcefile-no-dll-copy-in-program-directory