How the assembly version matching works exactly? - c#

Let's say I have assemblies in GAC with versions, 1.1.1.5, 1.1.5.1, 1.1.6.2, 1.2.1.1 and 2.1.2.1. My application have a reference of 1.1.3.0 version. Which assembly will be matched at runtime? and what are the actual rules for assembly matching?

If your reference requires a specific version, by default, it will fail on assembly load, as that version doesn't exist.
This can be configured, however, via Assembly Binding Redirection. There are various options of what will happen here, including:
The reference can say that it doesn't care about versioning, in which case the newest is loaded.
You can configure your application in a way that you specify how to redirect the binding.
The assembly in the GAC can be setup with a publisher policy that specifies how to handle this.

Which assembly will be matched at runtime?
None will be matched, your program will bomb.
The documentation for the Version class talks generically about how you pick version numbers. And yes, you normally consider a change in the build number to be a non-breaking change. And a change in the revision to be low risk. Things you consider when you pick an [AssemblyFileVersion].
However, the default CLR policy does not implement this kind of interpretation of the [AssemblyVersion], it insists on an exact match. It is only happy when it find the exact same DLL that you compiled your program with. This is not normally difficult to ensure. You can override this policy and make it weaker, although you should always think twice about that. There is a very long history of well intended minor changes in source code that just did not pan out that well in practice. Something that Microsoft knows too well, having to maintain code that lasts for decades. The default counter-measures against DLL Hell in the CLR are hard as a rock. As they should be. Ratcheting it down up to you.

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.)

Should I strong name my assembly for remoting?

I have read this excellent blog entry on the woes of strong naming and remoting, all of which I am experiencing.
Basically, the client app will always need to load the same version of the strong named common assembly the server is using when the server returns a custom type from the common assembly to the client. I.e.:
The problem one encounters is this: as soon as there is a difference
between the strong name of the common type library on the client, and
the strong name of the common type library on the server, everything
breaks. Remoting throws exceptions as soon as any notable
client/server communication starts.
This is rather annoying since we update the version number when we build, even if no changes have been made to the common assembly. The implementation may not have changed, just the version number.
I am currently getting round this by applying binding redirection/publisher policy - however this seems a lot of engineering just to conform to the strong name rules regarding assembly resolution.
I have tried not strong naming the common assembly as recommended in the blog, which works fine/I don't get any remoting exceptions - however, is this recommended?
I am not adding the common assembly (which just contains interfaces) to the GAC, nor am I too worried about tampering, and as long as I update interfaces carefully in order to maintain backward compatibility/not break existing clients is this enough, hence no need for strong naming?
Thanks in advance.
PS: I'm aware of WCF, but I still need to maintain a remoting interface.
Avoid strong naming if at all possible! Strong naming is painful.
As you probably already know, as soon as you strong name an assembly, everything that it references has to be strong named as well. In a simple application, no big deal. If you have to deal with COM interop libraries, other projects, etc the problem becomes a maintenance nightmare.

.NET 4, AllowPartiallyTrustedCallers attribute, and security markings like SecurityCritical

I'm new C# and am trying to understand the new security features of .NET-4.
To fill in some details, I'm currently trying to update AutofacContrib.Moq to work with the latest Moq. I had no problems doing this for .NET-3.5 and under. But in .NET-4 the security restrictions result in numerous security exceptions.
Moq has a a single method, GetObjectData, that's marked with the SecurityCritical attribute. AutofacContrib.Moq has the AllowPartiallyTrustedCallers attribute set which is the source of the exceptions. It seems that rather than adding the SecurityRules attribute with a SecurityLevel of 1, I'd be better off removing AllowPartiallyTrustedCallers attribute. I believe this makes the assembly SecurityTransparent by default, which may not be sufficient (though the AutofacContrib.Moq unit tests pass).
My main question at the moment is whether assemblies targeting .NET-4 should ever use the AllowPartiallyTrustedCallers attribute? But, given that I definitely don't understand everything yet, what details should be considered when working with assemblies that are security marked? Do I need to explicitly mark my assembly with security attributes in those places it uses, directly or indirectly, something that's marked SecurityCritical?
You are correct: in .NET 4, leaving the APTCA on there makes the assembly SecurityTransparent, and that may be what's causing you grief.
The MSDN article Migrating an APTCA Assembly to the .NET Framework 4 has a good discussion and explanation of the changes to the AllowPartiallyTrustedCallersAttribute in .NET 4.
Specifically:
The AllowPartiallyTrustedCallers attribute has changed. In v4, it no longer has anything to do with link demands. In fact, the implicit link demand that was present on signed libraries in v2 is gone. Instead, all fully trusted assemblies in v4 are, by default, SecurityCritical.
[snip /]
In v4, the effect of APTCA is to remove the automatic SecurityCritical behavior from the assembly to which it’s applied.
And...
Because the AllowPartiallyTrustedCallers attribute causes the entire assembly to be SecurityTransparent by default, the assembly’s author must specifically mark methods needing to perform privileged operations as SecurityCritical or SecuritySafeCritical.
(It's really a good article that author Mike Rousos did a great job with. I encourage you to read it in its entirety.)
If you're starting a new .NET 4 library, it's probably best to stick with the .NET 4 security model and use the appropriate SecurityCritical, SecuritySafeCritical, and SecurityTransparent attributes where needed. They're far easier to manage and understand than old code access security.
If you're migrating an old library to the new model, there's a good example in the article of how to do that... but basically it amounts to removing old LinkDemands and adding [SecurityCritical] in their place.
In your particular case, the fastest way to get going would be to add the SecurityRules attribute so you get the old behavior, but I'm not sure I'd consider that the right way. The right way would probably be to lose the APTCA and add SecurityCritical on the assembly because the assembly may contain SecurityCritical code, then mark the various types that call SecurityCritical code (e.g., stuff that references GetObjectData) with SecuritySafeCritical so your SecurityTransparent code can call it. Of course, that second approach will be a lot more work, so you'll probably want to run SecAnnotate.exe and get some automated tips.
Looking at the Moq trunk, a search for GetObjectData shows that the method in question is the override for an exception serialization mechanism (ISerializable.GetObjectData on System.Exception), which only SecurityCritical code will be calling anyway, so you may not even run into any trouble if you just lose APTCA and mark the assembly SecurityCritical.
There is an issue filed on Autofac to update it to the latest security model. If you like the idea, go vote/comment on it.
Sorry that wasn't a short answer. Security is, unfortunately, never easy. :S

How can I prevent the referencing of a certain assembly when running in Mono

I know how to branch the code based on Mono (Type.GetType("Mono.Runtime") != null) but even when the Mono code path is taken, Mono is attempting to load assemblies that would be required by the non-Mono code path. This is not all that surprising, but how do I get around the problem? I have tried putting the call to the non-Mono assembly in a different class, but that didn't help.
The only option to do it directly is Reflection all the way, so far as I can see.
I'd suggest a more roundabout approach: refactor all your code that is dependent on Mono or .NET into separate assemblies, one for each platform - let's call them MA and NA. Make sure that the entire API surface of your classes there is covered by common interfaces, which should be in the 3rd assembly, IA. After that, your main application references IA for interfaces, and uses Reflection just once to load either MA or NA depending on whether it's running on Mono or .NET, and obtain the instance of "top-level factory class". Once there, it just uses normal calls via IA interfaces to instantiate all other objects via that factory and work with them.
Expanding on Pavel's answer you can use a plugin framework to help with the conditionality of loading bits of code that are specific to a platform. You can use Mono.Addins or MS' own open sourced Managed Extensibility Framework known as MEF (http://www.codeplex.com/MEF)
Don't add the reference in the command-line compiler options. If you are using a high level IDE tool then you might have to play with its project settings to effect the same thing.
There are other files that come into play too like AssemblyInfo.cs and might contain instructions about assemblies that you are considering. Also the program might be using types from App.Config (Configuration file) or Web.Config (ASP.NET) / dynamic type loading.
Don't rely for your dependencies on the fact that your code is JITted and that only called code is JITted.
Best is always to assume, that whatever is referenced will be loaded and has to be available.
You user might choose to use AOT, which is Mono's counterpart of NGEN.
Or subtle differences in how newer runtime versions handle things like serialization, remoting, security, reflection, etc. can lead to your references being loaded even your code does not use anything directly. (But the serializer might have pulled all types, which then loaded other assemblies)
Use interfaces or classic inheritance, or maybe events or other means of indirection to load the .Net parts only when they are appropriate. And by hat I mean an assembly that you don't reference but load dynamically.

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