Weak assembly changed to strong assembly - c#

I have a plugin structure which all is compiled using weak assemblies. I want to change this now but running into some difficulties.
interface.dll contains my interface for my plugins (IPlugin)
Load.exe will load all the plugin implementations which implements IPlugin
pluginA.dll contains a implementation of IPlugin
All assemblies is original weak assemblies.
I now want to change the assemblies to strong name assemblies.
After I have made the interface.dll and load.exe strong name assemblies I am unable to create an instance of the pluginA.dll IPlugin implementation, unless I have recompiled pluginA.dll to reference the new strong name interface.dll
Is there a way for me to set strong name on interface.dll and load.exe without being forced to recompile all plugins implementing IPlugin?
The reason I ask this, is that I have a lot of plugins and I don't have control of all of them. So I want to avoid breaking the plugin functionallity when I updated the interface.dll with a strong name.
I hope you can help me, and please do not hesitate to ask for further details if something is unclear.
Thanks

Giving an assembly a strong name is a hard breaking change. You cannot patch it up with a config file or publisher policy. So rebuilding the plug-ins is a hard requirement you cannot skip.
You didn't otherwise state the reason for deciding to do so. There is no compelling one in a plug-in scenario. A strong name provides a way to verify that an assembly is an exact match with the reference assembly that your program was built with. But, by design, you don't have a reference assembly for a plug-in. So there's nothing to verify.

There is no way around this, unfortunately. The benefits you derive from strong-naming an assembly (most likely the reasons you are converting yours) are lost if you can reference simple named assemblies.
From Microsoft's documentation:
When you reference a strong-named assembly, you expect to get certain benefits, such as versioning and naming protection. If the strong-named assembly then references an assembly with a simple name, which does not have these benefits, you lose the benefits you would derive from using a strong-named assembly and revert to DLL conflicts. Therefore, strong-named assemblies can only reference other strong-named assemblies.

Related

strong name assembly - having to change thousands of assemblies

according to https://learn.microsoft.com/en-us/dotnet/framework/app-domains/create-and-use-strong-named-assemblies
A strong-named assembly can only use types from other strong-named assemblies. Otherwise, the integrity of the strong-named assembly would be compromised.
This is an issue because I would need to change all my thousands of assemblies, from weakly-named to strongly-named. This would take a long time, is there any way around this.
My use case:
I am building an application which will allow users to write C#, and execute it. I am doing this through an application domain. The application domain will compile the user code, in a partially trusted assembly. The user will be able to call a utilities assembly library. This utilities library, will be fully-trusted, and hence must be strongly named. This utilities library must be able to access the thousands of assemblies. The only way to do that now, is by changing all the assemblies to be strongly-named. which means I would need to add a AssemblyKeyFile attribute to each one.
Thanks
Dan
Yes, you are right strongly typed assembly can not have weakly-named assemblies in the reference.
There is a cool nuget package which signs unsigned libraries in the references:
https://www.nuget.org/packages/strongnamer

Load an assembly from another location not in the GAC

I have several applications which are required to use the same assembly. This assembly may be changed regularly, and can be installed by different MSIs. For this reason, I do not want to put it in the GAC, it can become a deployment nightmare over time.
If I turn the CopyLocal attribute for this assembly to NO in the application, how do I tell the runtime where to look for the assembly?
E.g. the application is loaded in C:/Program Files/<some directory>/bin
The DLL is in C:/<some other directory>
Is it thus possible to load the assembly in this way?
I've had a look at <codebase>, but I'm not sure the assembly can be strongly signed. And probing seems to work only for the private paths specified as subdirectories of the application?
Please let me know. Thank you.
Use Assembly.LoadFrom to load the assembly into memory, then you can use Activator.CreateInstance to create an instance of your preferred type. You need to user reflection for this:
Assembly assembly = Assembly.LoadFrom("c:\\path\\MyDll.dll");
Type type = assembly.GetType("MyClass");
object instanceOfMyType = Activator.CreateInstance(type);
Take a look on reflection in order to create instances with parameters.
Why do you want to set CopyLocal to "No"? The usual way to avoid "DLL hell" (aka "deployment nightmare") is to ensure that DLL dependencies are copied into the same directory with your program. IMHO, this is the simplest, most straightforward way to guarantee you are loading the DLL you want.
Note also that if you sign the DLL, install it in the GAC, and then in your own program require a specific version (or a minimum version, depending on your needs), that should also address the "DLL hell" scenarios. I.e. the presence of other versions of the DLL won't conflict, because you've required a specific version and .NET can reliably distinguish the correct version from an incorrect one.
Barring those approaches...
It's not clear what your exact requirements are. However, if you are trying to provide a way to identify an assembly that's not in the usual assembly-loading paths, there are at least a couple of mechanisms you can use.
One way is to use ApplicationBase and PrivateBinPath to control how .NET searches for your assemblies.
Another way is to handle the System.AppDomain.AssemblyResolve event.
That event will be raised any time .NET tries to load a referenced assembly and can't find it. Your handler can then perform whatever search it needs to (or just use a fixed path for that matter), load the assembly itself (e.g. using Assembly.LoadFrom()), and then return that via the event's arguments object.
Note that the AssemblyResolve event is only raised if .NET can't find a DLL to load. So that would not be an appropriate solution if it's not tolerable to have a different instance of the DLL that satisfies the reference requirements for the program of that DLL.

Is using Assembly.Load a static reference or dynamic reference?

What are the implications and suggested scenarios to use either?
Assembly.Load is a dynamic reference since you're dynamically loading an external DLL at run-time. You would consider a static reference more like when you're adding a reference to a .NET project and building the project with that reference in place.
EDIT:
From the MSDN Doc:
The compiler records static references
in the assembly manifest's metadata at
build time.
Hmmm, not sure about this one myself. I'll keep my answer here for now, in the hope of getting more correction comments or seeing better answers.
In reference to:
What are the implications and
suggested scenarios to use either?
Usually, if I use Assembly.Load(), it is because I am developing a pluggable system. Dynamic references facilitate inclusion of assemblies that are not necessarily part of my build.
Instantiating types from a dynamically loaded assembly requires at least some reflection. The amount of reflection necessary can be mitigated by ensuring that dynamically-loaded types implement some known interface or base class (from a statically-loaded assembly).
In short, it's a lot of work to use dynamically loaded assemblies; however, doing so can make an application more flexible by allowing users to develop plug-ins. Just weigh the trade-offs of the anticipated flexibility of dynamic references (which may not be a requirement), and design-time support from Visual Studio for static references.
A practice worth consideration if building a plug-in architecture is to load assemblies in their own AppDomains. Doing so permits you to have finer-grained control over the security permissions of assemblies you may not entirely trust, and provides the added benefit that the assemblies can be unloaded at run-time. Personally, I found working with AppDomains to be labor-intensive; however, if the benefits are required, it's good to know that AppDomains are there.
A dyanamic reference as stated in the MSDN(http://msdn.microsoft.com/en-us/library/yx7xezcf(VS.71).aspx) references dynamic referencing as loading a reference with only enough information that the runtime has to search for the assembly being loaded. With static references, the location of assemblies(GAC, application direcotry, etc) are known and can be still accomplished using Assembly.load.

When should we not create Assembly's strong name? What are the disadvantages of "strong named assembly"?

I have a project, i.e. library.exe. In this I have referenced an assembly (logging.dll ver 1.0.3.0) and I have given this assembly a strong name.
Now suppose I changed a method in logging.dll and made version 1.0.4.0.
Now when I copy/replaced the old DLL with this new one I got an exception.
I know that exception is because I have changed version number of the DLL. As it was a strong name DLL it's not allowed unless I rebuilt library.exe.
What I want to say with above story is
Use strong name with assembly only when we have to add it to GAC.
If we have an application where individual assemblies requires updating do not use strong named assemblies.
Am I correct with point 1 and 2?
When should strong named assemblies not be used?
What are the disadvantages of "strong named assembly"?
It is only really needed if you want to place your assemblies in the GAC, but it also helps against tampering. It is fairly easy to change the code in an assembly so this gives bad people an advantage. When you are using strong named assemblies you are signing it with a private key only you have. People could still change your assembly, but they can't give it the same strong name, because they do not have your private key. In that case .Net refuses the assemly tamperd with. When they sign your assembly with a new private key the .Net still refuses to load it since the identity of the assembly has changed.
There are several ways to solve the versioning problem. When your application wants to load a v1 assembly you could tell it to look voor a v2 anyway. See here for more information. The other option would be not to change the Assembly Version at all, but to change the File Version of the assembly only. For .Net the assemblies are the same, but you and your installer can still see which one is newer. See the AssemblyFileVersion attribute.
Both correct.
You don't need a StrongName if your signing the assembly afterwards, like with a real certificate.
In my oppinion strong naming is not realy worth anything, see this link for example. Well you need it for placing an assembly into the GAC but that's it.

C# Plugin Architecture with Strong Names: A Misunderstanding

I have a server executable that talks to Active Directory to retrieve user information. In addition to AD, this exe allows customers to write their own plugins to talk to custom user directories.
This executable is strongly named.
Is the following a true statement:
In order for a strongly named
assembly to load another assembly, the
loaded assembly must also be signed
with the same key.
The following code returns null, if the assembly is not strongly signed, with no error indicating the assembly was not properly signed. Note, that if I do sign the assembly, I get an instance of IService. Which leads me to believe that loaded assemblies must be strongly signed.
Assembly assembly = Assembly.LoadFrom(path);
foreach (Type t in assembly.GetTypes())
{
if (t.GetInterface(typeof(IService).FullName) != null)
{
return (Activator.CreateInstance(t) as IService);
}
}
So, does this mean if you have a strongly signed assembly, and support assembly plugins, they must also be signed--plugin writers must sign them with the same key? That doesn't sound right.
Finally, Say I have an assembly that implements the IService interface, but also references an assembly, that references yet another assembly, each signed with a different key. What happens when I try to load? Should they all be signed by the same key?
The following statement is correct:
In order for a strongly named assembly
to load another assembly, the loaded
assembly must also be signed with the same key.
From MSDN:
If the strong-named assembly then
references an assembly with a simple
name, which does not have these
benefits, you lose the benefits you
would derive from using a strong-named
assembly and revert to DLL conflicts.
Therefore, strong-named assemblies can
only reference other strong-named
assemblies.
Edit: D'oh! Though my answer is true, as P Daddy points out, it's irrelevant!
Using reflection to Load a weakly-named assembly is not the same thing as referencing one, and is not restricted the same way.
I recreated your code (or at least a close approximation), with the following assemblies:
Interface.dll (signed, contains IService)
Loader.exe (signed, a console app that takes a path, uses your code to load and return the first IService it finds in the assembly specified by that path, then calls an IService method)
Plugin.dll (not signed, contains an IService implementation)
Next I added a Plugin.dll reference to Loaded.exe and tried to access its IService implementation, which failed as expected with the following message: "Assembly generation failed -- Referenced assembly 'Plugin' does not have a strong name."
Finally, I ran the console app, passed it the name of the weakly-named Plugin.dll, and it worked just fine.
There seems to be something else afoot. Scott Hanselman has blogged about the vagaries of
dynamic assembly loading on several occasions, and he points to Suzanne Cook's blog for authoritative details about the topic.
If your assembly is strongly typed signed, I think any assembly you load must also be strongly typed signed...but not necessarily signed with the same key.
The statement is wrong - referenced assemblies must be signed, but not necessarily with the same key.
When you reference a strong-named assembly, you expect to get certain benefits, such as versioning and naming protection. If the strong-named assembly then references an assembly with a simple name, which does not have these benefits, you lose the benefits you would derive from using a strong-named assembly and revert to DLL conflicts. Therefore, strong-named assemblies can only reference other strong-named assemblies.
(Taken from MSDN Library)

Categories