Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InternalsVisibleTo not working for Managed C++

InternalsVisibleTo is not working for my managed C++ projects, but it is for my C# projects. Any help would be appreciated. Here is a simplified layout.

Project A - C#, has an internal property I want to access from B/C.
Project B - Managed C++. References A.
Project C - C#, references A.

All projects are signed with the same key. Looking at the compiled assemblies with ILDASM or Reflector show that they are all signed correctly (when I comment out the internal property usage).

In AssemblyInfo.cs in Project A, I have the following InternalsVisibleTo;

[assembly: InternalsVisibleTo( "B, " +
   "PublicKey=00240000048000009400000006020000002400005253413100040000010001007" +
   "50098646D1C04C2A041FAAF801521A769535DE9A04CD3B4DEDCCBF73D1A6456BF4FE5881451" +
   "0E84983C72D0460B8BA85C52A9CACDC4A0785A08E247C335884C2049ECFE6B2C5E20A18FE4B" +
   "9BFF009ADA232E980D220B3C9586C9C5EE29C29AEE8853DB7BB90CF5A4C704F5244E1A1085C" +
   "4306008535049A0EBB00FE47E78DCB" )]

[assembly: InternalsVisibleTo( "C, " +
   "PublicKey=00240000048000009400000006020000002400005253413100040000010001007" +
   "50098646D1C04C2A041FAAF801521A769535DE9A04CD3B4DEDCCBF73D1A6456BF4FE5881451" +
   "0E84983C72D0460B8BA85C52A9CACDC4A0785A08E247C335884C2049ECFE6B2C5E20A18FE4B" +
   "9BFF009ADA232E980D220B3C9586C9C5EE29C29AEE8853DB7BB90CF5A4C704F5244E1A1085C" +
   "4306008535049A0EBB00FE47E78DCB" )]

The keys are cut'n'pasted, so I know they are correct.

When I try to compile, A & C compile fine, but project B fails with

Error 1 error C3767: 'A::MyClass::MyProperty::get': candidate function(s) not accessible c:\Users\<snip>\CppClass.cpp 201 B

The MSDN docs say this works with C++. Is there a bug or something else I need to do?

Is there another way that I can protect a property so that it can only be used by assemblies signed by me? I know I can protect all of my assembly, but can I do it on a granular level like this?

EDIT

Based on comments in MSDN, I changed the attribute to the following, but that still doesn't work.

[assembly: InternalsVisibleTo( "B, " +
   "PublicKey=00240000048000009400000006020000002400005253413100040000010001007" +
   "50098646D1C04C2A041FAAF801521A769535DE9A04CD3B4DEDCCBF73D1A6456BF4FE5881451" +
   "0E84983C72D0460B8BA85C52A9CACDC4A0785A08E247C335884C2049ECFE6B2C5E20A18FE4B" +
   "9BFF009ADA232E980D220B3C9586C9C5EE29C29AEE8853DB7BB90CF5A4C704F5244E1A1085C" +
   "4306008535049A0EBB00FE47E78DCB" ),
InternalsVisibleTo( "C, " +
   "PublicKey=00240000048000009400000006020000002400005253413100040000010001007" +
   "50098646D1C04C2A041FAAF801521A769535DE9A04CD3B4DEDCCBF73D1A6456BF4FE5881451" +
   "0E84983C72D0460B8BA85C52A9CACDC4A0785A08E247C335884C2049ECFE6B2C5E20A18FE4B" +
   "9BFF009ADA232E980D220B3C9586C9C5EE29C29AEE8853DB7BB90CF5A4C704F5244E1A1085C" +
   "4306008535049A0EBB00FE47E78DCB" )]
like image 530
Rob Prouse Avatar asked Jan 06 '09 19:01

Rob Prouse


1 Answers

I found the answer to this. C++ works differently than the other languages. In addition to the InternalsVisibleTo, you must reference assembly A with the as_friend keyword. Since as_friend is not an option in the Add References dialog, you cannot add a project reference, instead, you need to add a reference in each CPP file that you needs it.

#using <A.dll> as_friend

You then also need to change your assembly search path to include the build directory of project A.

IMHO, this is broken and typical of managed C++ being a second class language. Without the ability to do project references, you end up referencing the assembly in the build debug or release directory. This breaks dependencies and the only way you can get it to reference the correct DLL when you change your configuration from debug to release is with ugly #IFDEF DEBUG and relative paths for the #using.

I was also disappointed that this wasn't mentioned in the InternalsVisibleToAttribute documentation. I needed to dig around in the C++ documentation to find the information.

Edit: The documentation for InternalsVisisbleTo has since been updated with a link to the Friend Assemblies (C++) document.

like image 187
Rob Prouse Avatar answered Sep 24 '22 10:09

Rob Prouse