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.
Related
I have a signed assembly where I'd like to use InternalsVisibleTo:
[assembly: InternalsVisibleTo("My.Project.Name", PublicKey=002400000...")]
Where I also have a My.Project.Name.csproj in another directory that has My.Project.Name as the AssemblyName. I need to get the PublicKey for this assembly. How do I do that using the command line tools?
Various references indicate I call sn -Tp path-to-assembly but I don't have a path yet. I need the PublicKey first since I can't compile until the internals are visible to this assembly.
I also use a <AssemblyOriginatorKeyFile> in both projects, which I presume is for the signing, but I'm not clear on if, or how, this relates to the PublicKey I need.
Note: I'm doing this on Mac using the Mono CLI toolkit.
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.
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.
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
I have created a test project whose output will be strong named assembly. I have specified the SNK file name in the 'project -> properties - > Signing' section so that assembly will be strong named.
I added reference of the assembly which is NOT signed or strong named. I was expecting that my project will not at all build since it's referencing unsigned assembly. However, it built and i could install the assembly in GAC too! Why is it so? (I'm using .NEt 4.0 and it's gacutil.exe)
Note: I have ensured that the assembly which is being referenced is NOT strong named.
Can i programatically load the 'unsigned' (i.e. non-strong named) assembly in my program whose output is going to be strong named assembly? If yes, why is it allowed to do so when on the other hand, .NET don't allow to add reference to unsigned assemblies?
If I have multiple versions of the same assembly in GAC. In my configuration file, If I specify just the name of the assembly, which version will be loaded from GAC? Will it be latest version everytime? Which API will be useful? I found many methods marked 'deprecated' in Assembly class.
You can reference the unsigned assembly in VS.Net from a signed assembly. But if you call anything from the signed to the unsigned, the build will fail.
There is no problem in signed assembly referencing an unsigned assembly. It can be done and signed assembly can be GACed.
Yes, you can load.
How can you specify assembly by just name ? There is only one API LoadWithPartialName and thats deprecated for many reasons. You need version, culture and public key token to uniquely identify assembly.