C# - How to make my assembly strongly named? - c#

I'm trying to create unit tests for some of my private methods and I read that you can access them from your unit tests via [assembly: InternalsVisibleTo("DLLName")].
However, mine's not working and another solution was to add the Public Key. I tried to get the Public Key of my unit test project via sn -Tp DLLName but it is complaining that it isn't strongly named.
How can I make it so that it is strongly named? Am I using the InternalsVisibleTo the wrong way?

I think if you go to the properties of your project, on the side bar there should be a navigation link called "Signing". There should be an option to sign the assembly. If that is not there, then I don't think you can give it a strong name?

Chances are your unit test assembly isn't strongly named at the moment - after all, it's a relatively unusual requirement, as the reasons for strong naming don't often apply to test assemblies.
However, the use of InternalsVisibleTo does necessitate this - because it's a bit like you're adding a reference from the strongly-named production assembly to the test assembly, and you can't refer to a non-strongly-named assembly from a strongly-named one.
So just make the test assembly strongly named in the same way as you have for the production assembly (Project Properties, Signing), give it a key (e.g. the same one as your production assembly) and then use sn -Tp to get the public key.
All this is assuming that the reason your original InternalsVisibleTo attempt didn't work because the production assembly is strongly-named. If it isn't, then signing the test assembly won't help at all, and you need to give us more information about the problem you're seeing.

To create and sign an assembly with a strong name using the Assembly Linker
At the command prompt, type the following command:
al /out:<assembly name> <module name> /keyfile:<file name>
In this command, assembly name is the name of the assembly to sign with a strong name, module name is the name of the code module used to create the assembly, and file name is the name of the container or file that contains the key pair.
The following example signs the assembly MyAssembly.dll with a strong name using the key file sgKey.snk.
al /out:MyAssembly.dll MyModule.netmodule /keyfile:sgKey.snk

Related

Assembly generation failed -- Referenced assembly 'XXXX' does not have a strong name

In my solution, there have one C# class library project(A project). I would like to add the strongly named assembly in that project. But (A project) has include another DLL (B.dll).
I generate the "a.snk" using VS2012 x86 Native Tools Command Prompt.
Like this
sn.exe -k C:\A.snk
And I add the following code in "AssemblyInfo.cs" of (A project). Then build the project.
[assembly: ComVisible(true)]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("C:\A.snk")]
After build (A project), it has a error "Assembly generation failed -- Referenced assembly 'B' does not have a strong name". But (B.DLL) is created by third party.
How to fix it? Many Thanks.
You have a problem. Your only option is to ask the third party to provide a strong name otherwise you won't be able to do it for your application.
The point of these strong names is to create some kind of accountability are you going to be accountable for your app if the third party dll is failing or doing things that are not 'normal' ?
This question has been asked before I found something on msdn :
https://social.msdn.microsoft.com/Forums/vstudio/en-US/35930958-9775-4e56-bd38-0362d124ffc4/assign-strong-name-to-third-part-dll
You don't have to create a strong name for your assembly (A project) just because it references an assembly with a strong name. Simply don't do that and you will be able to compile your assembly without problems. In fact, all the BCL assemblies have strong names and could otherwise not be referenced.
But as Philip Stuyck is telling in the answer above, if you need to create a strong name, you will have to ask your third-party vendor for a signed version of B.DLL.

.net - Added a strong named assembly, but it is looking for unsigned assembly

So, I have two projects... One is a big class library, and the other is a big simulator project.
Originally during testing the assemblies were not strong-named, but now that I need COM visibility, I need to strong name them (I need this quick, and it is easier to make them COM visible rather than deal with the CLI).
I generated a .snk and added it to the properties of each of the projects, the class library compiles just fine and outputs the .dll just fine. I added this .dll as a reference in the simulator project, but now the simulator project is giving me the following error:
The type "DynamicsControl" is defined in an assembly that is not
referenced. You must add a reference to assembly "DynamicsControl,
Version=0.4.3.0, Culture=neutral, PublicKeyToken=null"
The type DynamicsControl does exist in the class library (I verified), but it is claiming I am not loading the correct assembly. I believe it is the PublicKeyToken=null that is causing the issue (as my assembly would have a public key).
When I do sn -Tp DynamicsControl.dll (the one in the location I am referencing), it outputs the private and public key, so I know it has a proper signature.
What step am I missing? Do I have to add the assembly to the GAC? Do I manually have to add the public key?
Yes you need to specify the publicKeyToken for a strong named assembly otherwise it will look for unsigned version of the assembly. You can find out the public key token either by adding the assembly to GAC (and you will see it there) or by using the steps mentioned in the this link
If you want to read more about strong name and dll hell you can go to this URL .
Strong name prevents from dll hell which means you can have multiple versions of same assembly.
To your other question you don't have to add the assembly to GAC but CLR will look for the assembly first in GAC and then other places. Also, you don't have to add the key manually. If you remove the reference and add it back using the signed assembly it should automatically take the key.

InternalsVisibleTo does not work

I insert the line:
[assembly: InternalsVisibleTo("MyTests")]
inside my project under test( Properties/AssemblyInfo.cs) where MyTests is the name of the Unit Test project. But for some reason I still cannot access the internal methods from the unit test project.
Any ideas about what I am doing wrong ?
If your assembly is signed with a strong name look at this answer.
Otherwise check that the name of your test assembly really is "MyTests.dll" (it doesn't have to match the project name, though it will by default).
Let's break it down a bit as many of us have experienced this slight mix-up in the past...
Assembly A has your internal class.
Assembly B has your unit tests.
You wish to grant the internals of assembly A visibility in assembly B.
You need to put the InternalsVisibleTo assembly attribute inside assembly A and grant access to assembly B.
You still need your test project to reference your main project.
This can be easy to overlook and if you have no existing test code this may appear like the InternalsVisibleTo is not functioning.
I had the same issue after renaming a namespace. Basically the in .cs files was the new namespace but in the .csproj and AssemblyInfo.cs it was the old namespace.
namespace newNamespace {
....
}
So, I changed in .csproj the following to the new namespace:
<RootNamespace>oldnamespace</RootNamespace>
<AssemblyName>oldnamespace</AssemblyName>
And in AssemblyInfo.cs:
[assembly: AssemblyTitle("oldnamespace")]
[assembly: AssemblyProduct("oldnamespace")]
In my case I was coding to an Interface. As interfaces can only specify public properties the internal properties were not present on the interface.
Make sure you're not doing the same thing as I was!
I changed:
Assert.IsNotNull((exportFileManager)?.ThumbnailFileExporter);
To:
Assert.IsNotNull((exportFileManager as ExportFileManager)?.ThumbnailFileExporter);
I made the incorrect assumption that InternalsVisibleTo will help in accessing Private methods too.
Here are some other aspects that can lead to this error:
Your class is either internal or public
Your method is internal
The InternalsVisibleTo property contains the full namespace of your test project.
You can expose internals from strong named assembly to another strong named friend assembly only. But non-strong named assembly can expose internals to strong named friend assembly.

Reference to assembly without strong name

Is there a way to reference a library without a strong name?
When I add a reference to the assembly in references and rebuild solution everything is fine, but when I call the class from this assembly solution it doesn't build.
Output says that referenced assembly should have strong name. What is the best solution? Strong naming library is not preferable.
I think the problem you have here is that the assembly you are trying to add the reference from is being signed with a strong name but the assembly you are trying to reference is not signed. A strong-named assembly can only reference other strong-named assemblies.
Either sign the assembly you are referencing or don't sign the assembly that is referencing it.
The reason why the error only appears when you actually call the class is because the compiler will strip out the reference in the compiled output if there is no code actually invoking the referenced assembly.
If it's the case that you really can't either add a strong name to the one being referenced, or remove the strong name from the one doing the referencing (sorry long-winded) then you are going to have to look at binding the class at runtime via reflection and then accessing it via a common base or interface - not ideal at all; or even worse actually invoking it via reflection, or dynamic.
The whole point of a strong name is that you know what dlls are getting loaded. You can't add a strong-name to your dll if you reference something that isn't strong-named, as anything could be loaded in place of the dll you are thinking of (as long as the name matches). This entirely defeats the guarantees that a strong name is intended to provide.
So (one of):
don't add a strong-name to your dll (for most internal things, you just don't need one)
or; rebuild the dll you are referencing with a strong-name
or; load the additional dll only through reflection (yuck)

How to declare a friend assembly?

I have 2 projects in my solution:
Assembly (Basic Library)
Test Assembly (NUnit)
I had declared the test assembly as friends assembly in first project:
[assembly: InternalsVisibleTo ("Company.Product.Tests")]
Everything was working fine till I realised that I have forgot to setup the solution to sign my assemblies. So created a snk file and setup the visual studio project to sign the first assembly (Basic Library). Now when I compile the first project, I get following error:
Friend assembly reference
'Company.Product.Tests' is invalid.
Strong-name signed assemblies must
specify a public key in their
InternalsVisibleTo declarations.
I tried to extract the public key from my snk file using sn utility but it generates a wired binary file which I am unsure how to use. How can I fix the problem?
You need to sign both assemblies, because effectively both assemblies reference each other.
You have to put the public key in the InternalsVisibleTo attribute. For example, in Protocol Buffers I use:
[assembly:InternalsVisibleTo("Google.ProtocolBuffers.Test,PublicKey="+
"00240000048000009400000006020000002400005253413100040000010001008179f2dd31a648"+
"2a2359dbe33e53701167a888e7c369a9ae3210b64f93861d8a7d286447e58bc167e3d99483beda"+
"72f738140072bb69990bc4f98a21365de2c105e848974a3d210e938b0a56103c0662901efd6b78"+
"0ee6dbe977923d46a8fda18fb25c65dd73b149a5cd9f3100668b56649932dadd8cf5be52eb1dce"+
"ad5cedbf")]
The public key is retrieved by running
sn -Tp path\to\test\assembly.dll
Alternatively, get it from the .snk file:
sn -p MyStrongnameKey.snk public.pk
sn -tp public.pk
You can directrly get publicKey from assembly which you interest,
without magic with sn.exe
<!-- language: c# -->
var assemblyName = Assembly.GetExecutingAssembly().GetName();
Console.WriteLine("{0}, PublicKey={1}",
assemblyName.Name,
string.Join("", assemblyName.GetPublicKey().Select(m => string.Format("{0:x2}", m))));
I think you need to put in the strong name, which would be something like "Company.Product.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=17135d9fcba0119f". I assume Company.Product.Tests is your assembly name and 17135d9fcba0119f is the public key.
Another way to resolve this problem would be not to use separate assemblies. I usually put the source code and the testing code in the same assembly. I don't know if you have any special concern that you must separate them.

Categories

Resources