Programing

InternalsVisibleTo 속성이 작동하지 않습니다.

crosscheck 2020. 10. 31. 09:21
반응형

InternalsVisibleTo 속성이 작동하지 않습니다.


내가 사용하려고 InternalsVisibleTo내 단위 테스트 프로젝트에 보이는 .NET 클래스 라이브러리 내 내부 클래스를 만들기 위해 어셈블리 특성을. 어떤 이유로 다음과 같은 오류 메시지가 계속 표시됩니다.

보호 수준으로 인해 'MyClassName'에 액세스 할 수 없습니다.

두 어셈블리 모두 서명되었으며 특성 선언에 올바른 키가 나열되어 있습니다. 어떤 아이디어?


속성에 올바른 공개 키를 지정 했습니까? 공개 키 토큰뿐만 아니라 전체 공개 키를 지정해야합니다. 다음과 같이 보입니다.

[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]

320 자리 정도의 16 진수입니다. 전체 공개 키를 지정해야하는 이유가 확실하지 않습니다. 다른 어셈블리 참조에서 사용되는 공개 키 토큰 만 있으면 누군가 친구 어셈블리의 ID를 스푸핑하는 것이 더 쉬울 수 있습니다.


또 다른 가능한 "gotcha":에 지정하는 friend 어셈블리 의 이름은 친구의 프로젝트 속성 (응용 프로그램 탭에 있음)에 표시된대로 friend 어셈블리의 이름과 정확히 일치 InternalsVisibleToAttribute해야합니다 .

제 경우에는 둘 다 서명되지 않은 어셈블리를 생성 하는 프로젝트 Thingamajig와 동반 프로젝트 ThingamajigAutoTests(유죄를 보호하기 위해 이름이 변경됨)가있었습니다. [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )]Thingamajig \ AssemblyInfo.cs 파일에 속성 정식으로 추가하고 위에서 언급 한대로 AssemblyKeyFileAssemblyKeyName속성을 주석 처리했습니다 . Thingamajig프로젝트는 잘 구축하지만, 내부 구성원은 고집 자동 측정 프로젝트에 표시하지 않았다.

머리를 많이 긁은 후 ThingamajigAutoTests프로젝트 속성을 다시 확인한 결과 어셈블리 이름이 "ThingamajigAutoTests.dll"로 지정되어 있음을 발견했습니다. 빙고- InternalsVisibleTo속성 의 어셈블리 이름에 ".dll"확장자를 추가 했고 조각이 제자리에 놓였습니다.

때때로 그것은 가장 작은 것들 ...


어셈블리가 서명되지 않았지만 여전히 동일한 오류가 발생하는 경우 AssemblyInfo.cs 파일에서 다음 줄 중 하나를 확인하십시오.

[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

속성 탭에는 이러한 줄 중 하나 (또는 ​​둘 다)가있는 경우 어셈블리가 서명되지 않은 것으로 표시되지만 InternalsVisibleTo 특성은 이러한 줄이있는 어셈블리를 강력하게 서명 된 것으로 처리합니다. 이 행을 삭제 (또는 주석 처리)하면 잘 작동합니다.


"친구"(테스트) 어셈블리가 C # / VB.Net이 아닌 C ++ / CLI로 작성된 경우 다음을 사용해야합니다.

#using "AssemblyUnderTest.dll" as_friend

프로젝트 참조 또는 일반적인 #using진술 대신 . 어떤 이유로 프로젝트 참조 UI에서이 작업을 수행 할 수있는 방법이 없습니다.


InternalsVisibleTo 구문을 생성 하는 AssemblyHelper 도구사용할 수 있습니다 . 다음 은 최신 버전에 대한 링크 입니다. 강력한 이름의 어셈블리에서만 작동합니다.


다음은이 속성을 빠르게 생성하는 데 사용하는 매크로입니다. 약간 해키하지만 작동합니다. 내 컴퓨터에서. 최신 서명 된 바이너리가 /bin/debug. Etc equivocation etc. 어쨌든, 당신은 그것이 당신에게 힌트를 줄 것입니다. 시간이 허락하는대로 수정 / 개선하십시오.

Sub GetInternalsVisibleToForCurrentProject()
    Dim temp = "[assembly:  global::System.Runtime.CompilerServices." + _
               "InternalsVisibleTo(""{0}, publickey={1}"")]"
    Dim projs As System.Array
    Dim proj As Project
    projs = DTE.ActiveSolutionProjects()
    If projs.Length < 1 Then
        Return
    End If

    proj = CType(projs.GetValue(0), EnvDTE.Project)
    Dim path, dir, filename As String
    path = proj.FullName
    dir = System.IO.Path.GetDirectoryName(path)
    filename = System.IO.Path.GetFileNameWithoutExtension(path)
    filename = System.IO.Path.ChangeExtension(filename, "dll")
    dir += "\bin\debug\"
    filename = System.IO.Path.Combine(dir, filename)
    If Not System.IO.File.Exists(filename) Then
        MsgBox("Cannot load file " + filename)
        Return
    End If
    Dim assy As System.Reflection.Assembly
    assy = System.Reflection.Assembly.Load(filename)
    Dim pk As Byte() = assy.GetName().GetPublicKey()
    Dim hex As String = BitConverter.ToString(pk).Replace("-", "")
    System.Windows.Forms.Clipboard.SetText(String.Format(temp, assy.GetName().Name, hex))
    MsgBox("InternalsVisibleTo attribute copied to the clipboard.")
End Sub

friend 어셈블리 (InternalsVisibleTo 특성을 포함하지 않는 어셈블리)를 컴파일 할 때 / out : 컴파일러 스위치를 사용해야합니다.

컴파일러는 결과 어셈블리를 친구 어셈블리로 간주해야하는지 여부를 결정하기 위해 컴파일되는 어셈블리의 이름을 알아야합니다.


위의 모든 것 외에도 모든 것이 옳은 것처럼 보이지만 friend 어셈블리는 내부 정보를 고집스럽게 거부 하고 솔루션을 다시로드하거나 Visual Studio를 다시 시작 하면 문제를 해결할 수 있습니다.


VS.Net 2015를 사용하는 경우에는 두 어셈블리 모두 에 서명 해야했습니다 (최소 하나의 어셈블리에 서명해야하거나 어셈블리의 공개 키를 참조하려는 경우).

내 프로젝트는 서명을 전혀 사용하지 않았습니다. 그래서 내 테스트 라이브러리에 서명 키를 추가하고 프로젝트의 기본 라이브러리에서 InternalsVisibleTo-Attribute를 사용하기 시작했습니다. 그러나 VS.Net은 항상 friend 메서드에 액세스 할 수 없다고 설명했습니다.

기본 라이브러리에 서명하기 시작했을 때 (기본 라이브러리에 서명하는 한 동일하거나 다른 서명 키일 수 있음) VS.Net은 즉시 예상대로 작동 할 수있었습니다.


PublicKey를 사용한 이전 답변 : (Visual Studio 2015 : 한 줄에 있어야합니다. 그렇지 않으면 어셈블리 참조가 잘못되었거나 참조 할 수 없다고 불평합니다. PublicKeyToken이 작동하지 않았습니다.)

[assembly: InternalsVisibleTo("NameSpace.MyFriendAssembly, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C1406E2F553073FF557D2DB6C5")]

@Joe 덕분에

friend 어셈블리의 공개 키를 얻으려면 :

sn -Tp path\to\assembly\MyFriendAssembly.dll

개발자 명령 프롬프트 내부 (시작> 프로그램> Visual Studio 2015> Visual Studio 도구> VS2015 용 개발자 명령 프롬프트). @Ian G에게 감사합니다.

Although, the final touch that made it work for me after the above was to sign my friend library project the same way the project of the library to share is signed. Since it was a new Test library, it wasn't signed yet.


You are required to generate an new full public key for the assembly and then specify the attribute to assembly.

[assembly: InternalsVisibleTo("assemblyname,
PublicKey="Full Public Key")]

Follow the below MSDN steps to generate new full public key for the assembly from visual studio.

To add a Get Assembly Public Key item to the Tools menu

In Visual Studio, click External Tools on the Tools menu.

In the External Tools dialog box, click Add and enter Get Assembly Public Key in the Title box.

Fill the Command box by browsing to sn.exe. It is typically installed at the following location: C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0a\Bin\x64\sn.exe.

In the Arguments box, type the following (case sensitive): -Tp $(TargetPath). Select the Use Output window check box.

Click OK. The new command is added to the Tools menu.

Whenever you need the Public Key Token of the assembly you are developing, click the Get Assembly Public Key command on the Tools menu, and the public key token appears in the Output window.


Another possibility that may be tricky to track down, depending on how your code is written.

  1. You're invoking an internal method defined in X from another assembly Y
  2. The method signature uses internal types defined in Z
  3. You then have to add [InternalsVisibleTo] in X AND in Z

For example:

// In X
internal static class XType
{
    internal static ZType GetZ() { ... }
}

// In Y:
object someUntypedValue = XType.GetZ();

// In Z:
internal class ZType { ... }

If you have it written like above, where you're not referring to ZType directly in Y, after having added Y as a friend of X, you may be mystified why your code still doesn't compile.

The compilation error could definitely be more helpful in this case.


I'm writing this out of frustration. Make sure the assembly you are granting access to is named as you expect.

I renamed my project but this does not automatically update the Assembly Name. Right click your project and click Properties. Under Application, ensure that the Assembly Name and Default Namespace are what you expect.


Applies only if you like to keep unsigned assemblies as unsigned assembly (and don't want to sign it for several reasons):

There is still another point: if you compile your base library from VS.Net to a local directory, it may work as expected.

BUT: As soon as you compile your base library to a network drive, security policies apply and the assembly can't be successfully loaded. This again causes VS.NET or the compiler to fail when checking for the PublicKey match.

FINALLY, it's possible to use unsigned assemblies: https://msdn.microsoft.com/en-us/library/bb384966.aspx You must ensure that BOTH assemblies are NOT SIGNED And the Assembly attribute must be without PublicKey information:

<Assembly: InternalsVisibleTo("friend_unsigned_B")>


I had the same problem. None of the solutions worked.

Eventually discovered the issue was due to class X explicitly implementing interface Y, which is internal.

the method X.InterfaceMethod was unavailable, though I have no idea why.

The solution was to cast (X as YourInterface).InterfaceMethod in the test library, and then things worked.


As a side note, if you want to easily get the public key without having to use sn and figure out its options you can download the handy program here. It not only determines the public key but also creates the "assembly: InternalsVisibleTo..." line ready to be copied to the clipboard and pasted into your code.


I just resolved a similar problem with the InternalsVisibleTo Attribute. Everything seemed right and I couldn't figure out why the internal class I was aiming still wasn't accessible.

Changing the case of the key from upper to lower case fixed the problem.


If you have more than 1 referenced assembly - check that all necessary assemblies have InternalsVisibleTo attribute. Sometimes it's not obviously, and no message that you have to add this attribute into else one assembly.


1- Sign the test project: In Visual Studio go to the properties window of the test project and Sign the assembly by checking the checkbox with the same phrase in the Signing tab.

2- Create a PublicKey for the test project: Open Visual Studio Command Prompt (e.g. Developer Command Prompt for VS 2017). Go to the folder where the .dll file of the test project exists. Create a Public Key via sn.exe:

sn -Tp TestProject.dll

Note that the argument is -Tp, but not -tp.

3- Introduce the PublicKey to the project to be tested: Go to the AssemblyInfo.cs file in the project to be tested and add this line with the PublicKey created in the previous step:

[assembly: InternalsVisibleTo("TestProjectAssemblyName, PublicKey=2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb002400000480000094000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b1e28d6bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075")]

Don't forget to replace the above PublicKey with yours.

4- Make the private method internal: In the project to be tested change the access modifier of the method to internal.

internal static void DoSomething(){...}

참고URL : https://stackoverflow.com/questions/106880/internalsvisibleto-attribute-isnt-working

반응형