views:

487

answers:

2

I have 2 projects in my solution:

  1. Assembly (Basic Library)
  2. 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?

+1  A: 

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.

I dont think we need to specify the version number and culture (see http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx). I havent really tried putting the test code in the assembly itself. Will try and see how it works (+1 for the tip).
Hemant
For InternalsVisibleTo, PublicKeToken is not enough. You need the entire public key :-(
Sean Reilly
+11  A: 

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
Jon Skeet
Don't multiple assemblies signed with the same key end up with the same public key? Would this provide an "end-run" around the problem, perhaps?
Bevan
@Bevan: Yes, quite possibly. Just compiling a dummy file with the key is probably a faster way to go - will edit.
Jon Skeet
If both assemblies are being signed with different keys, I assume I need to specify public key of friend assembly (inside InternalsVisibleTo attribute). Is that right?
Hemant
And it is damn irritating to see the MSDN documentation (http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx) mention ridiculously short public key which almost look like public key **token** to me.
Hemant
Hemant: I think at one stage the docs actually claimed it *did* need to be the token. Doh.
Jon Skeet
You can extract the public key directly from a .snk file: sn -k MyStrongnameKey.snk // sn -p MyStrongnameKey.snk public.pk //sn -tp public.pk //
Tim Long
@Tim: Thanks, I seem to remember this being corrected in another answer, but not this one. Will edit now.
Jon Skeet