L’atsortingbut InternalsVisibleTo ne fonctionne pas

J’essaie d’utiliser l’atsortingbut d’assemblage InternalsVisibleTo pour rendre mes classes internes dans une bibliothèque de classes .NET visibles par mon projet de test unitaire. Pour une raison quelconque, je continue à recevoir un message d’erreur indiquant:

“MyClassName” est inaccessible en raison de son niveau de protection

Les deux assemblages sont signés et la clé correcte est répertoriée dans la déclaration d’atsortingbut. Des idées?

Êtes-vous absolument certain d’avoir la clé publique correcte spécifiée dans l’atsortingbut? Notez que vous devez spécifier la clé publique complète, pas seulement le jeton de clé publique. Il ressemble à quelque chose comme:

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

C’est environ 320 chiffres hexadécimaux. Vous ne savez pas pourquoi vous devez spécifier la clé publique complète – peut-être qu’avec le seul jeton de clé publique utilisé dans d’autres références d’assembly, il serait plus facile pour quelqu’un de usurper l’identité de l’assembly de l’ami.

Un autre possible “gotcha”: Le nom de l’assembly friend que vous spécifiez dans InternalsVisibleToAtsortingbute doit correspondre exactement au nom de votre assembly ami, comme indiqué dans les propriétés du projet de cet ami (dans l’onglet Application).

Dans mon cas, j’ai eu un projet Thingamajig et un projet compagnon ThingamajigAutoTests (noms modifiés pour protéger les coupables) qui ont tous deux produit des assemblages non signés. J’ai dûment ajouté l’atsortingbut [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] au fichier Thingamajig \ AssemblyInfo.cs et mis en commentaire les atsortingbuts AssemblyKeyFile et AssemblyKeyName comme indiqué ci-dessus. Le projet Thingamajig s’est bien Thingamajig , mais ses membres internes ont obstinément refusé de se présenter dans le projet d’autotest.

Après beaucoup de travail, j’ai revérifié les propriétés du projet ThingamajigAutoTests et découvert que le nom de l’assembly était “ThingamajigAutoTests.dll”. Bingo – J’ai ajouté l’extension “.dll” au nom de l’assembly dans l’atsortingbut InternalsVisibleTo et les morceaux sont tombés en place.

Parfois, ce sont les petites choses …

Si vos assemblys ne sont pas signés, mais que vous obtenez toujours la même erreur, vérifiez votre fichier AssemblyInfo.cs pour l’une des lignes suivantes:

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

L’onglet Propriétés affichera toujours votre assembly comme non signé si l’une des lignes (ou les deux) sont présentes, mais l’atsortingbut InternalsVisibleTo traite un assembly avec ces lignes comme fortement signé. Supprimez simplement (ou mettez en commentaire) ces lignes, et cela devrait fonctionner pour vous.

Il convient de noter que si l’assembly “friend” (tests) est écrit en C ++ / CLI, plutôt que C # / VB.Net, vous devez utiliser les éléments suivants:

 #using "AssemblyUnderTest.dll" as_friend 

au lieu d’une référence de projet ou de l’énoncé habituel #using. Pour une raison quelconque, il n’y a aucun moyen de le faire dans l’interface utilisateur de référence du projet.

Colin

Vous pouvez utiliser l’outil AssemblyHelper pour générer la syntaxe InternalsVisibleTo. Voici le lien vers la dernière version . Notez simplement que cela ne fonctionne que pour les assemblys à nom fort.

Voici une macro que j’utilise pour générer rapidement cet atsortingbut. C’est un peu pirate, mais ça marche. Sur ma machine Lorsque le dernier binary signé est dans /bin/debug . Etc équivoque, etc. En tout cas, vous pouvez voir comment vous obtenez la clé, alors cela vous donnera un indice. Corrigez / améliorez selon votre temps.

 Sub GetInternalsVisibleToForCurrentProject() Dim temp = "[assembly: global::System.Runtime.ComstackrServices." + _ "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 

Vous devez utiliser le commutateur / out: comstackr lors de la compilation de l’assembly friend (l’assembly ne contenant pas l’atsortingbut InternalsVisibleTo).

Le compilateur doit connaître le nom de l’assembly en cours de compilation afin de déterminer si l’assembly résultant doit être considéré comme un assembly ami.

En plus de tout ce qui précède, lorsque tout semble correct, mais que l’assemblée refuse obstinément de voir des éléments internes, le rechargement de la solution ou le redémarrage de Visual Studio peut résoudre le problème.

Dans mon cas, en utilisant VS.Net 2015, je devais signer les deux assemblées (si au moins un assemblage devait être signé ou si vous souhaitez faire référence à la clé publique de votre assemblage).

Mon projet n’a pas utilisé la signature du tout. J’ai donc commencé à append une clé de signe à ma bibliothèque de tests et à utiliser l’atsortingbut InternalsVisibleTo dans la bibliothèque de base de mon projet. Mais VS.Net a toujours expliqué qu’il ne pouvait pas accéder aux méthodes des amis.

Lorsque j’ai commencé à signer la bibliothèque de base (cela peut être la même ou une autre clé de signe – tant que vous signez la bibliothèque de base), VS.Net a immédiatement pu fonctionner comme prévu.

Les réponses précédentes avec PublicKey fonctionnaient: (Visual Studio 2015: NEED doit être sur une seule ligne, sinon il se plaint que la référence de l’assembly n’est pas valide ou ne peut pas être référencée. PublicKeyToken n’a pas fonctionné)

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

Merci à @Joe

Pour obtenir la clé publique de l’assembly friend:

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

À l’intérieur d’une invite de commandes Developper (Démarrage> Programmes> Visual Studio 2015> Outils Visual Studio> Invite de commande du développeur pour VS2015). Merci à @Ian G.

Cependant, la touche finale qui a fait en sorte que cela a fonctionné après ce qui précède était de signer le projet de bibliothèque de mon ami de la même manière que le projet de la bibliothèque à partager est signé. Comme il s’agissait d’une nouvelle bibliothèque de test, elle n’était pas encore signée.

Vous devez générer une nouvelle clé publique complète pour l’assembly, puis spécifier l’atsortingbut à l’assembly.

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

Suivez les étapes MSDN ci-dessous pour générer une nouvelle clé publique complète pour l’assembly à partir de Visual Studio.

Pour append un élément Obtenir une clé publique d’assemblage au menu Outils

Dans Visual Studio, cliquez sur Outils externes dans le menu Outils.

Dans la boîte de dialog Outils externes, cliquez sur Ajouter et entrez Obtenir la clé publique de l’assembly dans la zone Titre.

Remplissez la zone de commande en naviguant jusqu’à sn.exe. Il est généralement installé à l’emplacement suivant: C: \ Program Files (x86) \ Kit de développement Microsoft \ Windows \ v7.0a \ Bin \ x64 \ sn.exe .

Dans la zone Arguments, tapez ce qui suit (sensible à la casse): -Tp $ (TargetPath) . Cochez la case Utiliser la fenêtre de sortie.

Cliquez sur OK . La nouvelle commande est ajoutée au menu Outils.

Chaque fois que vous avez besoin du jeton de clé publique de l’assembly que vous développez, cliquez sur la commande Obtenir la clé publique d’assemblage dans le menu Outils, et le jeton de clé publique apparaît dans la fenêtre Sortie.

Une autre possibilité peut être délicate à suivre, selon la manière dont votre code est écrit.

  1. Vous invoquez une méthode interne définie dans X à partir d’un autre assemblage Y
  2. La signature de la méthode utilise les types internes définis dans Z
  3. Vous devez ensuite append [InternalsVisibleTo] dans X ET dans Z

Par exemple:

 // In X internal static class XType { internal static ZType GetZ() { ... } } // In Y: object someUntypedValue = XType.GetZ(); // In Z: internal class ZType { ... } 

Si vous l’avez écrit comme ci-dessus, où vous ne faites pas directement référence à ZType dans Y, après avoir ajouté Y en tant qu’ami de X, il se peut que vous ne compreniez pas pourquoi votre code ne comstack toujours pas.

L’erreur de compilation pourrait certainement être plus utile dans ce cas.

S’applique uniquement si vous souhaitez conserver les assemblys non signés en tant que assembly non signé (et ne souhaitez pas le signer pour plusieurs raisons):

Il y a encore un autre point: si vous comstackz votre bibliothèque de base depuis VS.Net vers un répertoire local, cela peut fonctionner comme prévu.

MAIS: Dès que vous comstackz votre bibliothèque de base sur un lecteur réseau, les stratégies de sécurité s’appliquent et l’assembly ne peut pas être chargé avec succès. Ceci provoque à nouveau l’échec de VS.NET ou du compilateur lors de la vérification de la correspondance PublicKey.

Enfin, il est possible d’utiliser des assemblys non signés: https://msdn.microsoft.com/en-us/library/bb384966.aspx Vous devez vous assurer que les deux assemblys NE SONT PAS SIGNÉS Et que l’atsortingbut Assembly doit être sans informations PublicKey:

En outre, si vous souhaitez obtenir facilement la clé publique sans avoir à utiliser sn et à trouver ses options, vous pouvez télécharger le programme pratique ici . Il détermine non seulement la clé publique, mais crée également la ligne “assembly: InternalsVisibleTo …” prête à être copiée dans le presse-papiers et collée dans votre code.

Je viens de résoudre un problème similaire avec l’atsortingbut InternalsVisibleTo . Tout semblait correct et je n’arrivais pas à comprendre pourquoi le cours interne que je visais n’était toujours pas accessible.

La modification de la casse de la clé de la majuscule à la minuscule a résolu le problème.

J’écris ceci par frustration. Assurez-vous que l’assembly auquel vous accordez l’access est nommé comme prévu.

J’ai renommé mon projet, mais celui-ci n’est pas automatiquement mis à jour. Cliquez avec le bouton droit sur votre projet et cliquez sur Propriétés . Sous Application , vérifiez que le nom de l’ assembly et l’ espace de noms par défaut sont ceux que vous attendez.

Si vous avez plus d’un assemblage référencé – vérifiez que tous les assemblys nécessaires possèdent un atsortingbut InternalsVisibleTo. Parfois, ce n’est pas évident, et aucun message ne vous oblige à append cet atsortingbut à un autre ensemble.

J’ai eu le même problème. Aucune des solutions n’a fonctionné.

Finalement découvert que le problème était dû à la classe X implémentant explicitement l’interface Y, qui est interne.

la méthode X.InterfaceMethod n’était pas disponible, bien que je ne sache pas pourquoi.

La solution consistait à convertir (X en YourInterface) .InterfaceMethod dans la bibliothèque de tests, puis les choses ont fonctionné.