InternalsVisibleTo not working for Managed C++
Asked Answered
A

2

12

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" )]
Asoka answered 6/1, 2009 at 19:47 Comment(1)
please retag from "c++" to "c++cli" thanksVaden
A
29

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.

Asoka answered 7/1, 2009 at 15:7 Comment(2)
Have you found a way to let a C# assembly see the internals of another built with C++? As far as I can tell, there's no way to set anything like as_friend in c#.Circumstantial
FWIW, you don't need to use #ifdefs to reference the correct DLL. Instead, you can set the path for #using references in project properties, C/C++, General, Resolve #using references. Here you can use the configuration macros, such as $(ConfigurationName) and others to specify the paths to used assemblies.Canaletto
M
0

Note:

Maybe for someone will help to NOT ADD REFERENCE by hand to the library which is being included by " #using as_friend ", because if it stays in references like that, it may not be compiled.

Let .NET mechanics by itself decide what to do with this library after the #using directive.

And yes, add the library to the list in Properties -> C/C++ -> General -> AdditionalUsingDirectories.

Medwin answered 28/10, 2019 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.