Is there such a thing as delay loading a dll in C#?
I know this is possible to do in C++, but what about managed code?
.NET does that automatically, everything is loaded on demand by default.
This article explains in detail how it works in .NET. Summary of key points:
There are a number of different ways that assemblies are loaded in
.NET. When you create a typical project, assemblies usually come from:
The Assembly reference list of the top level 'executable' project
The Assembly references of referenced projects
Dynamically loaded assemblies, using runtime loading via AppDomain or Reflection loading
and
.NET automatically loads mscorlib (most of the System namespace) as part of the .NET runtime hosting process that hoists up
the .NET runtime in EXE apps, or some other kind of runtime hosting
environment (runtime hosting in servers like IIS, SQL Server or COM
Interop).
and
Dependent Assembly References are not pre-loaded when an application starts (by default)
Dependent Assemblies that are not referenced by executing code are never loaded
Dependent Assemblies are just in time loaded when first referenced in code
Once Assemblies are loaded they can never be unloaded, unless the AppDomain that hosts them is unloaded.
Yes it is. You don't include the DLL as a reference in your project and where you want to load/use it, you call the Assembly.LoadFile method.
This blog post does a pretty good job with code to describe how to do it.
Related
I never understand , What actually happens to the the external DLLs when code is compiled by the compiler and converted to Intermediate code to run on CLR.
Does DLL code added to the Intermediate code and the references are not longer needed on the new machine or just the path of added DLLs are stored and we need those DLLs on our drive to run the program.
Generally (ie. there are some exceptions) the referenced assembly needs to be on the deployment system. All that is included in your assembly is the assembly name (this includes version and possibly signature).
Assembly binding (involving the GAC, config overrides etc.) is applied at runtime to get the right assembly. The rules depend on how the app domain was set up (eg. extra folders can be added, which is why ASP.NET web apps apply different rules).
There are various cases where the reference can be embedded (including referencing ActiveX when the right options are set and use of the assembly binding tool).
Could be a very naive question, but was wondering how this stuff works: Lets assume that we have 10 projects in Visual Studio, and 5 of them have references to an external DLL (say Ext.dll), using a relative path.
Now when my application is deployed an running on client machine, would Ext.dll get loaded 5 times in memory? Or would it just get loaded once and gets used by other referencing projects?
Assembly will be loaded only once in memory.
CLR first check if assembly already loaded in current AppDomain, if not than assembly gets loaded under AppDomain otherwise symbols are resolved from the already loaded assembly.
Ofcourse unless you are manually creating another AppDomain which has its own set of assemblies.
Moreover, assembly with same version cannot be loaded in memory at
same time. CLR doesn't allow that. But you can have different versions
of same assembly to be loaded in memory and that too in case
assemblies are strongly signed. But in your case version is same so CLR won't load same assembly twice anyhow.
If you want to check at certain interval time that what assemblies are loaded in a memory, you can use this piece of code to get all loaded assemblies:
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
Clr load assembly in memory just once.
Note :for each instance of application Clr load assembly again.
You can read Clr via c#.In chapter one you can learn many of these Concepts.
Since version 3.0, .NET installs a bunch of different 'reference assemblies' under C:\Program Files\Reference Assemblies\Microsoft...., to support different profiles (say .NET 3.5 client profile, Silverlight profile). Each of these is a proper .NET assembly that contains only metadata - no IL code - and each assembly is marked with the ReferenceAssemblyAttribute. The metadata is restricted to those types and member available under the applicable profile - that's how intellisense shows a restricted set of types and members. The reference assemblies are not used at runtime.
I learnt a bit about it from this blog post.
I'd like to create and use such a reference assembly for my library.
How do I create a metadata-only assembly - is there some compiler flag or ildasm post-processor?
Are there attributes that control which types are exported to different 'profiles'?
How does the reference assembly resolution at runtime - if I had the reference assembly present in my application directory instead of the 'real' assembly, and not in the GAC at all, would probing continue and my AssemblyResolve event fire so that I can supply the actual assembly at runtime?
Any ideas or pointers to where I could learn more about this would be greatly appreciated.
Update: Looking around a bit, I see the .NET 3.0 'reference assemblies' do seem to have some code, and the Reference Assembly attribute was only added in .NET 4.0. So the behaviour might have changed a bit with the new runtime.
Why? For my Excel-DNA ( http://exceldna.codeplex.com ) add-in library, I create single-file .xll add-in by packing the referenced assemblies into the .xll file as resources. The packed assemblies include the user's add-in code, as well as the Excel-DNA managed library (which might be referenced by the user's assembly).
It sounds rather complicated, but works wonderfully well most of the time - the add-in is a single small file, so no installation of distribution issues. I run into (not unexpected) problems because of different versions - if there is an old version of the Excel-DNA managed library as a file, the runtime will load that instead of the packed one (I never get a chance to interfere with the loading).
I hope to make a reference assembly for my Excel-DNA managed part that users can point to when compiling their add-ins. But if they mistakenly have a version of this assembly at runtime, the runtime should fail to load it, and give me a chance to load the real assembly from resources.
To create a reference assembly, you would add this line to your AssemblyInfo.cs file:
[assembly: ReferenceAssembly]
To load others, you can reference them as usual from your VisualStudio project references, or dynamically at runtime using:
Assembly.ReflectionOnlyLoad()
or
Assembly.ReflectionOnlyLoadFrom()
If you have added a reference to a metadata/reference assembly using VisualStudio, then intellisense and building your project will work just fine, however if you try to execute your application against one, you will get an error:
System.BadImageFormatException: Cannot load a reference assembly for execution.
So the expectation is that at runtime you would substitute in a real assembly that has the same metadata signature.
If you have loaded an assembly dynamically with Assembly.ReflectionOnlyLoad() then you can only do all the reflection operations against it (read the types, methods, properties, attributes, etc, but can not dynamically invoke any of them).
I am curious as to what your use case is for creating a metadata-only assembly. I've never had to do that before, and would love to know if you have found some interesting use for them...
If you are still interested in this possibility, I've made a fork of the il-repack project based on Mono.Cecil which accepts a "/meta" command line argument to generate a metadata only assembly for the public and protected types.
https://github.com/KarimLUCCIN/il-repack/tree/xna
(I tried it on the full XNA Framework and its working afaik ...)
Yes, this is new for .NET 4.0. I'm fairly sure this was done to avoid the nasty versioning problems in the .NET 2.0 service packs. Best example is the WaitHandle.WaitOne(int) overload, added and documented in SP2. A popular overload because it avoids having to guess at the proper value for *exitContext" in the WaitOne(int, bool) overload. Problem is, the program bombs when it is run on a version of 2.0 that's older than SP2. Not a happy diagnostic either. Isolating the reference assemblies ensures that this can't happen again.
I think those reference assemblies were created by starting from a copy of the compiled assemblies (like it was done in previous versions) and running them through a tool that strips the IL from the assembly. That tool is however not available to us, nothing in the bin/netfx 4.0 tools Windows 7.1 SDK subdirectory that could do this. Not exactly a tool that gets used often so it is probably not production quality :)
You might have luck with the Cecil Library (from Mono); I think the implementation allows ILMerge functionality, it might just as well write metadata only assemblies.
I have scanned the code base (documentation is sparse), but haven't found any obvious clues yet...
YYMV
I have a C# .Net 2.0CF application where I would like to load a .NET 'plug-in' DLL at runtime.
As I understand it, I should be able to use the System.Reflection.Assembly.LoadFrom() to load the DLL to an Assembly. Then use Assembly.GetTypes() to get the list of types within the plugin to match them to my expected interfaces.
The problem is that when I call GetTypes(), I get a System.TypeLoadException(). Based on the exception message, I assume this is because this particular plugin references some other assembly that this program knows nothing about. But, that's part of the point of it being a plugin! I don't want my application to have to know anything about these other assemblies.
How can I load this plug-in DLL without having my application reference every assembly used in the plugin?
Thanks,
PaulH
The situation is not that your app should reference every assembly that a plug-in uses. The plug-in references another DLL, not your app, and the plug-in should be "installed" (maybe simply put in a directory) along with everything it needs. This is unavoidable.
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...