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
Related
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.
I have two DLLs, app1.dll and app2.dll, that use the same third dll, util.dll, which might have slightly different behavior when built for a specific app.
I want to achieve that app1.dll and app2.dll are isolated concerning the versions of util.dll that they use. On MSDN, I read that assigning a strong name to util.dll is the solution, i.e. that this strong name contains the name and version of the dll as well as the fingerprint due to signing.
I currently build util.dll...
for app1 with KeyFileApp1.snk and version 1.0.0.1
for app2 with KeyFileApp2.snk and version 1.0.0.2
and this seams to work on the target machine when deploying the apps with the respective util.dll build.
However, I have some ambiguities:
Would it be enough to build util.dll always with version 1.0.0.0 but different key files for both apps and having both apps using the right dll in the end?
Are the strong names only considered when putting a dll in the global assembly cache or also when having it as private assembly?
yes you can have both with the same name and version, but different public key. Is it good/maintainable solution - up to you. Will likely confuse more people than you want. I.e. no regular person will be able to tell you "public key" used by DLL, but most people can right click and check details to see version (if you set it properly on your assemblies).
strong name is always considered. Note that if you have local and GAC copy GAC one will always be used if version in GAC is acceptable.
Notes:
strong names are "viral" as you can't have strongly named assembly depend on one without strong name. Be careful as you'd need many for your assemblies to be strongly signed (not a bad thing by itself) and have good versioning plan.
you may eventually endup with multiple versions of the same assembly loaded into process - either prepare for it or use publisher policy to map all versions to latest.
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.
I have a project where I simultaneously must use reports built in ActiveReports 2 and ActiveReports 6. Overall, it works ok, but some of the helper assemblies use the same name. For instance, to be able to export to PDF, both versions use an assembly called ActiveReports.PdfExport.dll. The corresponding assemblies are different, of course.
Note that I don't access the ActiveReports.PdfExport.dll directly - this is handled by the ActiveReports runtime.
I can't find a way to include both of them into the project. Is there a way? Is GAC the answer?
Creating separate external aliases for each assembly will help if you have type name collisions. For assembly name collisions, take a look at ILMerge; you can combine all related assemblies together. You'd create an assembly for ActiveReports 2 that combines all its required assemblies and another for ActiveReports 6.
GAC is one way, but Fusion resolution has a lot of flexibility in it that might suffice. Fusion will probe in the BaseDirectory for the assembly name .[DLL|EXE]. If not found it will probe BaseDirectory\Name.[DLL|EXE]\Name.[DLL|EXE]. So you might be able to get away with creating a folder named ActiveReports.PdfExport.DLL in your Bin folder and dumping the older version of the file in there.
Yes, you have to put both into GAC (this is what it's made for, in case of client assemblies).
My idea: create two libraries-helpers, reference each to appropriate assembly, register them into some kind of factory or manager and call specific one when you need.
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.