How to handle dll dependency that may not be present? [duplicate] - c#

I am not sure the best way to explain this so please leave comments if you do not understand.
Basically, I have a few libraries for various tasks to work with different programs - notification is just one example.
Now, I am building a new program, and I want it to be as lightweight as possible. Whilst I would like to include my notification engine, I do not think many people would actually use its functionality, so, I would rather not include it by default - just as an optional download.
How would I program this?
With unmanaged Dlls and P/Invoke, I can basically wrap the whole lot in a try/catch loop, but I am not sure about the managed version.
So far, the best way I can think of is to check if the DLL file exists upon startup then set a field bool or similar, and every time I would like a notification to be fired, I could do an if/check the bool and fire...
I have seen from the debug window that DLL files are only loaded as they are needed. The program would obviously compile as all components will be visible to the project, but would it run on the end users machine without the DLL?
More importantly, is there a better way of doing this?
I would ideally like to have nothing about notifications in my application and somehow have it so that if the DLL file is downloaded, it adds this functionality externally. It really is not the end of the world to have a few extra bytes calling notification("blabla"); (or similar), but I am thinking a lot further down the line when I have much bigger intentions and just want to know best practices for this sort of thing.

I do not think many people would
actually use its functionality, so, I
would rather not include it by default
- just as an optional download.
Such things are typically described as plugins (or add-ons, or extensions).
Since .NET 4, the standard way to do that is with the Managed Exensibility Framework. It is included in the framework as the System.ComponentModel.Composition assembly and namespace. To get started, it is best to read the MSDN article and the MEF programming guide.

You can use System.Reflection.Assembly and its LoadFile method to dynamically load a DLL. You can then use the methods in Assembly to get Classes, types etc. embedded in the DLL and call them.
If you just check if the .dll exists or load every .dll in a plugin directory you can get what you want.

To your question if the program will run on the user's machine without the dlls already being present - yes , the program would run. As long as you dont do something that needs the runtime to load the classes defined in the dll , it does not matter if the dll is missing from the machine. To the aspect you are looking for regarding loading the dll on demand , I think you are well of using some sort of a configuration and Reflection ( either directly or by some IoC strategy. )

Try to load the plugin at startup.
Instead of checking a boolean all over the place, you can create a delegate field for the notification and initialize it to a no-op function. If loading the plugin succeeds, assign the delegate to the plugin implementation. Then everywhere the event occurs can just call the delegate, without worrying about the fact that the plugin might or might not be available.

Related

Can you use a class library if you don't reference all of it's dependencies?

Let me clarify:
I have built a class library to be used in several projects. As part of this DLL I want to add a few different custom providers for Owin Cookies by extending CookieAuthenticationProvider so I need to include a reference to Microsoft.Owin.Security.Cookies. This is safe because the newer projects that will use my library also use Microsoft.Owin.Security.Cookies.
However some of the projects are older and dont use Owin etc... Will they blow up if I include the library for other use? Or will they only blow up if I try to use the provider (which I wouldn't since they cant use it).
I want to put some commonly used things in my library without having to reference every one of it's dependent DLL's to every project that uses them. I'm pretty sure what I'm doing is ok but I was hoping somone could tell me before I waste many hours going forward with this. Also if there is a better way I'm all ears.
The rules:
All types which are visible to a given assembly must be declared in assemblies referenced by that assembly.As long as your class library does not actually expose in its public API the types found in the Microsoft.Owin.Security.Cookies assembly, then other assemblies can safely compile with your DLL without referencing that assembly.
A referenced assembly need not be present at runtime, except when code in that assembly is actually needed, i.e. some other code attempts to call that code.
In general, this means that as long as other assemblies which are referencing your assembly and which don't reference Microsoft.Owin.Security.Cookies also don't call any code in your assembly that would then in turn attempt to call code in Microsoft.Owin.Security.Cookies, that assembly need not be present at runtime.
The tricky part on that second point is that what constitutes "calling code in Microsoft.Owin.Security.Cookies" is not always clear. Typically, as long as you don't access the types in the assembly at all, .NET won't try to execute any code in that assembly. But it's not hard to accidently access the types even when they are not necessarily needed (e.g. in initializers, static or otherwise, code that checks for interface implementations, etc.).
If you really want your clients to be able to use your DLL, which references Microsoft.Owin.Security.Cookies, without necessarily needing that DLL to be present at runtime, you will need to be very careful to ensure you've fully supported that scenario. It is possible to do, but it's also not hard to make a mistake.
(I have to admit, I'm surprised that this useful question hasn't already been addressed on Stack Overflow. Seems like it would have come up before by now. But I was unable to find a duplicate, hence the answer above. If anyone is aware of a duplicate I've overlooked, I welcome any suitable notice of that.)

protect dll from use outside application

I have a dll library that I use in one of my projects. I don't want others to be able to link and access the methods in the library. Is it possible to protect it? Thanks!
EDIT: Is there a way to 'hide' method names or make them random inside dll?
You can attempt to limit its use by requireing a key. If a wrong key is passed, your library will not work.
This however can be easily circumvented by decompiling your application and check what key you supply and simply use the same key.
Another possibility would be to add a check to every public method on every public class. That check would verify that the calling assembly is one of yours.
Depending on the implementation of this check, it is easily circumvented by creating a small proxy assembly that is named the same as one of yours.
In general: It is not possible to prevent it. Just like with copy protection, everything can be circumvented if the other party has access to your assembly - and I mean the compiled assembly, not the source code.
Short answer is no. If somebody wants access to your library they will find a way.
You can obfuscate your library to make things harder for them however, but there is no sure-fire way of preventing them.
One way is Friend Assemblies
You can mark your assembly internal and only specified assemblies can access your library.
But it just forbids to use your library in "easy way".
You can protect your libraries and executables from anuthorized using with help of third party products like Sentinel Hasp, but it will cost to your application in performance, cost to you some money and it is not garanteed that nobody will break it.
But to break protection pirates should work hard.

ReflectionOnlyLoad can it be garbage collected?

I want to "hot" load some pre-packaged assembli(es) into a separate AppDomain, the thing however is I do not know the name of the entry point class or even the assembly file. I need to find this entry point so I can run some initialization routine.
So what I intend to do is to run ReflectionOnlyLoad on all the files and find the one that follows a certain convention ie. annotated/implements a certain interface etc.
Question is, will I start leaking memory if I were to run ReflectionOnlyLoad from the main AppDomain over and over? If this can't be run from the main app domain, what are my options, because again I do not know where the entry point is.
Also any additional information about the subtleties in using ReflectionOnlyLoad is appreciated.
I recommend Mono.Cecil. It's a simple assembly you can use on .net (it doesn't require the Mono runtime). It offers an API to load assemblies as data, and works pretty well. I found the API easy to work with, and it suffered from none of the problems I experienced when using reflection-only-load.
You can also use CCI, which is an open source project by MS that offers an assembly reader.
See also: CCI vs. Mono.Cecil -- advantages and disadvantages
ReflectionOnlyLoad won't solve your problem, see docs
Why don't you execute the code for finding the entry point etc. in the new AppDomain?
Cannot reflect through the dlls. Even with reflection only load, the type sticks to the main AppDomain.
2 Solutions:
Put the entry point in an xml somewhere and parse that.
Use a
2 stage AppDomain, one for the reflector, and then another for the
actual object.
I picked (1) since it's the most sensible.
(2) I have to pass through 2 separate proxies in order to issue command to the actual remote object, that or I need to couple the interfaces much more closely than I like. Not to mention being a pain to code.

Merging DLL's and changing managing namespaces

I want to create a single dll that is merged with a 3rd party dll. This means end consumers will only have to deal with 1 dll instead of 2.
For augments sake lets say that the 3rd party dll is nLog. How do I deal with cases where the consumer of the merged dll already has NLog as a reference in their project?
Ideally what I would like to be able to do is change NLog namespace within my project to "XyzNLog", meaning that the user wouldn't need to do any aliasing... Any idea how I might do this?
Now I know I can add aliases to my project for NLog so that I have to refer to it as XyzNLog, but I want the same to carry over to consumers of the merged dll so that there is never a conflict.
UPDATE - Solution
http://blog.mattbrailsford.com/2010/12/10/avoiding-dependency-conflicts-using-ilmerge/
Bingo! So by using ILMerge, it becomes
possible to merge the third-party
libraries DLLs in with the Providers
own DLL, meaning we will only have one
DLL to deploy. But that’s not all, we
can actually go one step further, and
tell ILMerge to internalize all
dependencies. What this does it
converts all the third party classes
to be declared as internal, meaning
they can only be used from within the
final DLL. Woo hoo! problem solved =)
Given this the problem where the consumer of my dll could also have NLog goes away... as my referenced NLog shifts to being all internal! This is exactly what I want.
Does anyone have any feedback or thoughts on this?
I agree with Hans, I would strongly suggest releasing with registering the DLLs separately.
Otherwise, you could be in DLL hell which would drive your consumers away.
You could then devise some clever deploy methods to detect if the DLL is already registered, etc.
I have to agree with #Hans Passant (and here's some info about the oft-discussed DLL hell), but since you've asked the question, I'll try to answer it.
You can bundle the third-party DLL as a resource. Please see this question for details.
As far as your other questions, I'd just expose the relevant classes from a third-party DLL under your own namespace, and maybe use extension methods to provide whatever additional functionality you want.
For instance, you can provide access to NLog's Log() method using a static method in your class, say XyzNLog.Logger.Log(), taking care of initialization, and whatever else internally, inside your code (static constructor or whatever else you fancy up).
Since you load the NLog assembly using the method above, you'll be the only one having access to the embedded NLog assembly directly and the user won't be able to access it. Now, you don't get the benefit of having all classes autoexposed from NLog, you still have to expose them manually in this case.
EDIT: Another approach would be to try to use ILMerge with /internalize flag as described here. You may not be able to completely resolve the issue, but look at this article to see if you can avoid the pitfalls the author described. Spoiler alert: it's not all peaches'n'cream on this one either, but it may work, with enough extra effort.

Sharing dll without adding reference

I have got a dll placed in a shared folder over development server. Is there any way to use that dll without adding reference in my application and without installing the same in GAC.
Thanks in advance.
Assembly asm = Assembly.LoadFrom(path);
See MSDN for late binding, reflection etc.
Small edit: A variable with the keyword "as" is asking for trouble. So "Assembly as" changed to "Assembly asm" should be safer.
You may want to look at the Managed Extensibility Framework or at Assembly.Load... in the base framework.
Why would you want to do this, though? You'd need to call any code within the Assembly via reflection (hence the suggestion that the MEF may be what you're really after).
Yes, it is possible...somehow. Have a look at the Assembly-Class. With it you can load assemblies from a file without knowing what you exactly load.
Using Assembly.LoadFrom would be the only way to have zero references, but you'd still need to share contracts.
What's the problem with adding a reference?
What are you going to do when someone wants to work on a laptop and the WiFi goes down?
Yes,
you can call Assembly.Load() and then make use of Reflection to call into the public interface (lowercase "interface" - what I mean is the methods, fields and properties) exposed by the assembbly.
But in order to do that you need to know what methods to call. It helps if you can be certain that the assembly includes classes that do conform to a known .NET interface.
This idea is the basis for "plug-in" architectures in many tools, where the tool loads any assembly in its "plugin" directory, instantiates classes, casts the result to an ISomething, and then invokes methods via that interface.
I also would read Suzanne Cook's .NET CLR Notes.
http://blogs.msdn.com/suzcook/default.aspx
If this assembly is in a shared folder, you may find that .NET security restrictions stop you working with classes in that assembly in quite the way you'd expect.
Rather than storing on a shared folder, you may want to consider checking in the assembly to your source code repository. (I've seen a "/lib" folder used to good effect for this). Then you can reference the assembly directly.
(There are also repository solutions such as Maven that can more properly control this. However, they don't play well with .NET, unfortunately.)

Categories

Resources