Debugging a dynamically-loaded DLL from another AppDomain at Runtime - c#

Ok, after resolving how to Hot-Load a DLL in a running App at Runtime (See my previous post), I have noticed that breakpoints inserted in the freshly loaded DLL are not hit.
Situation
I have a server Application that I want to avoid terminating/re-running every time I make a change to a Dynamically loaded DLL (by Reflection)
Goal
Here is what I am trying to do (I am aware this may not be possible per se) :
Run Application.exe
Load into it Process.dll in newAppDomain and run Process
Debug Process.dll
Unload Process.dll
Edit Process code, recompile Process.dll
Dynamically reload it in Application.exe
Debug Process.dll
etc...
Problem
I have noticed that when Application.exe is launched in Debug mode, code that is loaded from another AppDomain is unreachable by the debugger attached to Application.exe
(I guess If i just launch Application.exe directly from executable file, there is no way to get VS debugger to debug anything, inluding the newly loaded DLL)
Prossible workaround
A workaround (ugly) solution is to separate the "injection" of the DLL into the running App in a separate executable, that would be, then, monitorable by the VS Debugger
I mus admit I am a bit confused.
Any efficient, clean ideas ?

Since it may help others (as this was a top search result for me), I found that adding a reference to the DLL to the "other" project made it possible to debug the assembly being "injected." While I won't deploy my solution like this, it did allow me to at least debug the code being injected to resolve a problem with otherwise stable code. This suggests the IDE looks at references when determining assembly identity (or similar.)
In this scenario a DebugBreak() does nothing, the VS debugger will not be signaled without the reference being added. I did not test, but would imagine any other debugger would have been signaled just fine, so again this suggests the IDE is explicitly ignoring the signal (other DebugBreak()s work just fine.)
As a veteran .NET developer I have to say this problem is new for me, ie. I would say it's a safe bet that if we load Windows 2000, VS.NET 2001-2002 and this same test code that the breaks signal just fine.
Based on the OPs prior post it's most likely that the assembly being loaded is actually being loaded with a distinct identity, even if it's the same assembly but loaded from a different location/mechanism (for example) the CLR will identify it as a unique assembly, consequently so will the IDE.
Some readers may or may not find LoaderOptimization of value in certain scenarios where they are loading the same assembly between appdomains and notice the same assembly is being loaded multiple times.
HTH someone, I was stumped for about an hour. Thanks.

Does putting System.Diagnostics.Debugger.Break() in your DLL where currently you have breakpoints, throw a break correctly?
http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break.aspx
If not I'm inclined to agree with Sam, that unload is failing, or you're loading a different library than you think.

Related

Accessing assemblies at design time in Blend 4

I am getting an exception from my code while designing in Blend 4.
I have narrowed the issue down to loading a specific library. Other libraries can be loaded fine, just this one fails. So, for this code:
var a = Assembly.Load("lib1");
var b = Assembly.Load("lib2");
Line two will throw an exception: Could not load file or assembly 'lib2' or one of its dependencies. The system cannot find the file specified.
If the same code is run outside of Blend, it does not throw. Both assemblies appear to be referenced the same way in the project, and both are marked Copy Local.
Any suggestions on how to troubleshoot this issue?
At design time Blend copies your assemblies to a temporary folder other than your output folder so things can behave differently than when you run the program normally. Blend also requires the "Any CPU" configuration for design time so if you run "x86" normally you can get different results simply because of that.
But Blend itself is a managed program like any other and to diagnose the problem in detail you can crack open the Fusion Log Viewer to see assembly binding errors to try to find out what is going wrong. Presumably the library itself is where it ought to be (in Blend's temporary folder) but one of its indirect dependencies is not being found. By using the log viewer with sufficient detail, you should be able to see the specific binding failure that is causing the problem.
Here is a link:
Fuslogvw.exe (Assembly Binding Log Viewer)

Why can't my .NET CF application find a DLL In the same directory as the executable?

I have a .NET CF 1.1 application that has been running perfectly fine for years. Occasionally, I get a help desk ticket with the following error message (generic):
Method not found:
MethodName
AssemblyNamespace.Class
The DLL is there, and it's the same version as my other devices. What could change that would make it not find the method. Does this error imply that the assembly was loaded, or did it break before that even happened?
Does it matter how I added the reference in Visual Studio (2003, btw)? I have Copy Local set to true, and therefore I made the assumption that it needs to be in the same directory as my executable.
Any help you can offer is appreciated. Thanks.
EDIT: I believe this DLL is also in the windows directory of the device, possibly a different version. It contains a lot of hardware specific functions (i.e. backlight, keyboard state, etc.)
No it does not matter how you add the reference in Visual studio 2003. (100% sure)
Now for the not so sure : I think that someone else has the same assembly in the GAC of the phone. So the GAC assembly gets called rather than the one you deployed and that version of the assembly lacks the requested function.
Depends on how you reference the file in your code. You could be relying on the current working directory which depending on how the app is launched or what they do after, it might not be what you expect it to be.
Sometimes .NetCf throws this exception when the device is running out of memory, instead of the expected "Out of Memory" exception. I have observed this behaviour more often when loading native dlls using P/Invoke than loading pure netcf dlls.

Why are referenced assemblies locked?

I have 2 assemblies. Assembly2 is referenced by Assembly1.
Why is Assembly2 locked?
I thought the whole assembly is loaded into the RAM by the JIT-Compiler, isn't it?
How does the machinism work when a referenced assembly is called?
(yes, the question could have been better, still...)
Referenced assemblies are loaded into the process and are thus locked. You can get around this with shadow copying, or just make sure you close every process that uses your assemblies before you attempt to modify them.
I ran into a situation when writing a .NET componenet to be consumed in a VB6 app where I couldn't deploy my recompiled .NET assembly while the VB6 editor was open. This really frustrated me because I wanted to be able to just make a quick change and then have the change show up in my VB6 editor. I was getting an error message that the assembly was locked by another process or thread.
I later realized that this made a lot of sense. If the referencing application (in my case, the VB6 IDE) is trusting that library to be the same each time it goes to consume it, it's going to run into serious problems if the dll changes while the application is in memory.
In my case, closing the VB6 IDE, updating the dll, and reopening the VB6 IDE worked just fine. It was a little bit of a hindrance in my workflow, but once I realized why it was happening, I got over it.

C# .NET Application Crashes Immediately After Starting

I was experimenting with the Assembly and File version number. Though my program runs well from the IDE, but after creating a Setup file and installing the application crashes with InvalidDeploymentException.
What should I do to resolve the matter?
The [AssemblyVersion] and [AssemblyFileVersion] attributes play different roles. [AssemblyVersion] is only visible to managed code and is important for the GAC. Whenever a make a breaking change in the assembly's public interface you should bump this number up.
The compiler embeds an unmanaged resource in an assembly with the /win32res command line option. This includes the VERSIONINFO resource, readable by all unmanaged code, including the shell. It determines what you see when you right-click the assembly in Explorer and look at the Details property page. The "File version" value shown there is set by the [AssemblyFileVersion] attribute. The [AssemblyVersion] value isn't visible there, Explorer doesn't (yet) know how to read that.
It is up to you to decide how to use this attribute. The crash indicates that there's some minimum sanity checking going on in the deployment code, never tried to get it wrong myself to see what would happen. Making them the same would however make a lot of sense.
Microsoft uses [AssemblyFileVersion] a different way, they automatically increment it for each build and nail [AssemblyVersion] down. That's a good idea and the strategy I use. What is however quite ironic is that the automatic version increment feature works exactly backwards, it can only auto-increment [AssemblyVersion]. Sigh.
Try using the fusion log viewer to see what's not being loaded in your deployed app.

Why are some .Net assemblies not available via an AppDomain's GetAssemblies() method?

I have a little bit of code that loops through the types currently loaded into an AppDomain that runs in an ASP.NET application. Here's how I get the assemblies:
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
When the application first starts up there is no problem and all the types I expect are present. But when I update the Web.config or kill the w3p.exe process (or the process gets recycled for whatever reason) only some of the types I'm expecting are available. When I step through with a debugger I notice that certain assemblies from the private search path (the bin directory of my application) haven't been loaded. I was under the assumption that all assemblies were loaded at application start and restart whether or not they were immediately required. But in the case of restarting this doesn't seem to be happening unless those assembly files have been updated.
What I require is to collect type information at start-up for use later. But since during a restart the types aren't available it reeks havoc later on when the type information needs to be used. So with that in mind how can I solve or work around this deficiency?
Assemblies are loaded on demand, so it could be that you did not used any type contained in these assemblies yet.
You can use
AssemblyName[] assemblies = Assembly.GetCallingAssembly().GetReferencedAssemblies();
This way, you get all assemblies that are referenced from the assembly from which you are calling these method.
As a part of startup, can you explicitly load the assemblies you care about?
You would have to know ahead of time which assemblies you would need.
Scanning the filesystem to find out which assemblies have been shipped along with your app may be a useful idea, but it won't help for GAC loaded assemblies...

Categories

Resources