it-swarm-eu.dev

Atribut InternalsVisibleTo nefunguje

Snažím se použít atribut InternalsVisibleTo Assembly, aby se moje interní třídy v knihovně třídy. Z nějakého důvodu se stále zobrazuje chybová zpráva, která říká:

„MyClassName“ je nepřístupné kvůli své úrovni ochrany

Obě sestavy jsou podepsány a mám správný klíč uvedený v deklaraci atributů. Nějaké nápady?

68
skb

Jste si zcela jisti, že máte v atributu zadán správný veřejný klíč? Všimněte si, že musíte zadat úplný veřejný klíč, nikoli pouze token veřejného klíče. Vypadá to něco jako:

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

Je to 320 nebo více hexadecimálních číslic. Nejste si jisti, proč je třeba zadat úplný veřejný klíč - možná jen s tokenem veřejného klíče, který se používá v jiných odkazech na shromáždění, by bylo pro někoho snazší spoofovat identitu přítele shromáždění.

91
Joe

Další možné "gotcha": Jméno přítele shromáždění, které zadáte v InternalsVisibleToAttribute, musí přesně odpovídat jménu vašeho přítele Assembly, jak je uvedeno ve vlastnostech projektu přítele (na kartě Aplikace).

V mém případě jsem měl projekt Thingamajig a doprovodný projekt ThingamajigAutoTests (jména změněna tak, aby chránily vinného), že oba vytvořili nepodepsané sestavy. Správně jsem přidal atribut [Assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] do souboru Thingamajig AssemblyInfo.cs a komentoval atributy AssemblyKeyFile a AssemblyKeyName, jak je uvedeno výše. Projekt Thingamajig postavený v pořádku, ale jeho interní členové tvrdohlavě odmítli ukázat se v projektu autotestu.

Po mnoha škrábancích hlavy jsem znovu zkontroloval vlastnosti projektu ThingamajigAutoTests a zjistil, že název sestavy byl zadán jako "ThingamajigAutoTests.dll". Bingo - Přidal jsem rozšíření ".dll" do názvu sestavy v atributu InternalsVisibleTo a kusy padly na místo.

Někdy je to nejmenší věc ...

39
John Beyer

Pokud vaše sestavy nejsou podepsány, ale stále se zobrazuje stejná chyba, zkontrolujte soubor AssemblyInfo.cs pro některý z následujících řádků:

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

Karta vlastností bude stále zobrazovat sestavení jako nepodepsané, pokud je přítomen jeden nebo oba tyto řádky, ale atribut InternalsVisibleTo zachází se sestavou s těmito řádky jako silně podepsané. Jednoduše vymažte (nebo komentujte) tyto řádky a mělo by to fungovat dobře.

35
Skimedic

Stojí za zmínku, že pokud je "přítel" (testy) shromáždění napsáno v C++/CLI, spíše než C #/VB.Net pak musíte použít následující:

#using "AssemblyUnderTest.dll" as_friend

místo reference projektu nebo obvyklého příkazu #using. Z nějakého důvodu neexistuje žádný způsob, jak to provést v referenčním uživatelském rozhraní projektu.

11
Colin Desmond

Můžete použít AssemblyHelper nástroj , který bude generovat InternalsVisibleTo syntaxi pro vás. Zde je odkaz na nejnovější verzi . Všimněte si, že funguje pouze pro silně pojmenované sestavy.

9
Vadim

Zde je makro, které používám k rychlému generování tohoto atributu. Je to trochu hacky, ale funguje to. Na mém stroji. Když je poslední podepsaný binární soubor v /bin/debug. Etc vyrovnání atd. V každém případě můžete vidět, jak to dostane klíč, takže vám dá nápovědu. Opravte/zlepšete, jak to čas dovolí.

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
5
Will

Při kompilaci přítele Assembly (shromáždění, které Neobsahuje atribut InternalsVisibleTo) musíte použít přepínač/out: kompilátor. 

Překladatel musí znát název shromáždění, které bylo sestaveno, aby zjistil, zda by výsledné shromáždění mělo být považováno za přítele shromáždění. 

4
Ash

Kromě všeho výše uvedeného, ​​kdy se vše zdá být správné, ale kamarádské shromáždění tvrdohlavě odmítá vidět nějaké interiéry, znovu naložit řešení nebo restartovat Visual Studio může problém vyřešit.

3
Alex J

V mém případě používajícím VS.Net 2015 jsem potřeboval podepsatOBAshromáždění (pokud má být podepsáno alespoň 1 shromáždění nebo chcete odkazovat na veřejný klíč vašeho shromáždění).

Můj projekt vůbec nepoužíval podepisování. Začal jsem tedy přidávat znakový klíč do mé testovací knihovny a používat InternalsVisibleTo-Atribut v základní knihovně svého projektu. Ale VS.Net vždy vysvětlil, že nemá přístup k metodám přítele.

Když jsem začal podepisovat základní knihovnu (může to být stejné nebo jiné znaménko - pokud podepisujete základní knihovnu), VS.Net byl okamžitě schopen pracovat podle očekávání.

3
Jochen

Další možností, která může být složitá sledovat, záleží na tom, jak je váš kód napsán.

  1. Vyvoláváte vnitřní metodu definovanou v X z jiného shromáždění Y
  2. Podpis metody používá interní typy definované v Z
  3. Potom musíte přidat [InternalsVisibleTo] v X A v Z

Například:

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

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

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

Pokud ho máte napsaný jako nahoře, kde se nevztahuje na ZType přímo v Y, poté, co jste Y přidali jako přítele X, můžete být mystifikováni, proč váš kód ještě není kompilován.

Chyba kompilace by v tomto případě určitě mohla být užitečnější.

2
Tatiana Racheva

Jste povinni vygenerovat nový úplný veřejný klíč pro sestavení a poté zadat atribut Assembly.

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

Postupujte podle níže uvedených kroků MSDN a vytvořte nový úplný veřejný klíč pro shromáždění z vizuálního studia.

Přidání položky Získat veřejný klíč shromáždění do nabídky Nástroje

V aplikaci Visual Studio klepněte v nabídce Nástroje na příkaz Externí nástroje.

V dialogovém okně Externí nástroje klepněte na tlačítko Přidat a do pole Název zadejte klíč Veřejný klíč shromáždění.

Vyplňte příkazové pole procházením sn.exe. Obvykle se instaluje v následujícím umístění: C: Program Files (x86) Microsoft SDK Windows v7.0a Bin x64 sn.exe.

Do pole Argumenty zadejte následující (rozlišují velká a malá písmena): -Tp $ (TargetPath). Zaškrtněte políčko Použít výstup.

Klikněte na OK. Nový příkaz je přidán do nabídky Nástroje.

Kdykoli potřebujete veřejný klíč Token shromáždění, který vyvíjíte, klepněte na příkaz Získat veřejný klíč shromáždění v nabídce Nástroje a token veřejného klíče se zobrazí v okně Výstup.

Předchozí odpovědi s PublicKey pracovaly: (Visual Studio 2015: POTŘEBUJÍ být na jednom řádku, jinak si stěžuje, že odkaz na shromáždění je neplatný nebo nemůže odkazovat. PublicKeyToken nefungoval)

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

Díky @ Joe

Chcete-li získat veřejný klíč přítele shromáždění:

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

Uvnitř příkazu příkazový řádek Vývojář (Po spuštění> Programy> Visual Studio 2015> Nástroje Visual Studio> Příkazový řádek pro vývojáře pro VS2015). Děkujeme uživateli @Ian G.

Ačkoliv konečný dotek, který pro mě fungoval po výše uvedeném, bylo podepsat projekt mojí kamarádské knihovny stejným způsobem, jakým je podepsán projekt knihovny ke sdílení. Vzhledem k tomu, že se jednalo o novou testovací knihovnu, ještě nebyla podepsána.

2
Micaël

Píšu to z frustrace. Ujistěte se, že shromáždění, které udělujete přístup, je pojmenováno podle očekávání.

Přejmenoval jsem projekt, ale to automaticky neaktualizuje název sestavy. Klepněte pravým tlačítkem myši na projekt a klepněte na příkaz Vlastnosti. V části Aplikace se ujistěte, že Název sestavy a Výchozí jmenný prostor jsou to, co očekáváte.

1
Kameron Kincade

Platí pouze v případě, že chcete zachovat nepodepsané sestavy jako nepodepsané sestavení (a nechcete jej podepisovat z několika důvodů):

Je ještě další bod: Pokud kompilovat základní knihovny z VS.Net do místního adresáře, může fungovat podle očekávání.

BUT: Jakmile kompilujete základní knihovnu do síťové jednotky, platí zásady zabezpečení a sestavení nelze úspěšně načíst. To opět způsobí selhání VS.NET nebo kompilátoru při kontrole shody PublicKey.

KONEČNÉ je možné použít nepodepsané sestavy: https://msdn.Microsoft.com/en-us/library/bb384966.aspx Musíte zajistit, aby obě sestavy nebyly NOT SIGNED A atribut Assembly musí být bez informací PublicKey: 

<Assembly: InternalsVisibleTo("friend_unsigned_B")>

1
Jochen

Měl jsem stejný problém. Žádná z řešení nefungovala.

Nakonec objevil problém byl kvůli třídě X explicitně implementaci rozhraní Y, což je interní.

metoda X.InterfaceMethod nebyla k dispozici, i když nemám ponětí, proč.

Řešení bylo obsazení (X jako YourInterface). InterfaceMethod v testovací knihovně, a pak věci fungovaly. 

1
Sentinel

Pokud máte více než 1 odkazované sestavy - zkontrolujte, zda všechny potřebné sestavy mají atribut InternalsVisibleTo. Někdy to není zjevné, a žádná zpráva, že musíte přidat tento atribut do jiného shromáždění.

0
VladExL

Jako vedlejší poznámka, pokud chcete snadno získat veřejný klíč, aniž byste museli používat sn a zjistit jeho možnosti, můžete si stáhnout praktický program zde . Nejenže určuje veřejný klíč, ale také vytvoří řádek "Assembly: InternalsVisibleTo ...", který bude připraven ke kopírování do schránky a vložen do kódu.

0
Bill W

1- Podepsat projekt testu: Ve Visual Studiu přejděte do okna vlastností testovacího projektu a Podepište shromáždění zaškrtnutím políčka se stejnou frází v Podpis kartu.

2- Vytvořte PublicKey pro testovací projekt: Otevřete příkazový řádek Visual Studio (např. Příkazový řádek vývojáře pro VS 2017). Přejděte do složky, kde je soubor DLL souboru testovací projekt existuje. Vytvořit veřejný klíč pomocí sn.exe:

sn -Tp TestProject.dll

Všimněte si, že argument je -Tp, ale ne -tp.

3- Zavést PublicKey do projektu, který má být testován: Přejděte do souboru AssemblyInfo.cs v projektu, který má být testován a přidejte tento řádek s PublicKey vytvořeným v předchozím kroku:

[Montáž: InternalsVisibleTo ( " TestProjectAssemblyName , PublicKey = 2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb002400000480000094000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b1e28d6bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075")]

Nezapomeňte nahradit výše uvedený PublicKey vaším.

4- Proveďte interní interní metodu: V testovaném projektu změňte modifikátor přístupu metody na interní.

interní statický void DoSomething () {...}

0
user3029066

Právě jsem vyřešil podobný problém s atributem InternalsVisibleTo. Všechno se zdálo být správné a nemohl jsem přijít na to, proč vnitřní třída, na kterou jsem mířil, ještě není dostupná.

Problém byl vyřešen změnou případu klíče z horního na malá písmena. 

0
Keysharpener