How to: Create Signed Friend Assemblies (C# and Visual Basic)

This example shows how to use friend assemblies with assemblies that have strong names. Both assemblies must be strong named. Although both assemblies in this example use the same keys, you could use different keys for two assemblies.

To create a signed assembly and a friend assembly in Visual Studio

  1. Open a Visual Studio command prompt.

  2. Use the following sequence of commands with the Strong Name tool to generate a keyfile and to display its public key. For more information, see Sn.exe (Strong Name Tool).

    1. Generate a strong-name key for this example and store it in the file FriendAssemblies.snk:

      sn -k FriendAssemblies.snk

    2. Extract the public key from FriendAssemblies.snk and put it into FriendAssemblies.publickey:

      sn -p FriendAssemblies.snk FriendAssemblies.publickey

    3. Display the public key stored in the file FriendAssemblies.publickey:

      sn -tp FriendAssemblies.publickey

  3. Create a Visual Basic or C# file named friend_signed_A that contains the following code. The code uses the InternalsVisibleToAttribute attribute to declare friend_signed_B as a friend assembly.

    The Strong Name tool generates a new public key every time it runs. Therefore, you must replace the public key in the following code with the public key you just generated, as shown in the following example.

    ' friend_signed_A.vb
    ' Compile with: 
    ' Vbc /target:library /keyfile:FriendAssemblies.snk friend_signed_A.vb
    Imports System.Runtime.CompilerServices
    
    <Assembly: InternalsVisibleTo("friend_signed_B, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e3aedce99b7e10823920206f8e46cd5558b4ec7345bd1a5b201ffe71660625dcb8f9a08687d881c8f65a0dcf042f81475d2e88f3e3e273c8311ee40f952db306c02fbfc5d8bc6ee1e924e6ec8fe8c01932e0648a0d3e5695134af3bb7fab370d3012d083fa6b83179dd3d031053f72fc1f7da8459140b0af5afc4d2804deccb6")> 
    Public Class Class1
        Public Sub Test()
            System.Console.WriteLine("Class1.Test")
            System.Console.ReadLine()
        End Sub
    End Class
    
    // friend_signed_A.cs
    // Compile with: 
    // csc /target:library /keyfile:FriendAssemblies.snk friend_signed_A.cs
    using System.Runtime.CompilerServices;
    
    [assembly: InternalsVisibleTo("friend_signed_B, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e3aedce99b7e10823920206f8e46cd5558b4ec7345bd1a5b201ffe71660625dcb8f9a08687d881c8f65a0dcf042f81475d2e88f3e3e273c8311ee40f952db306c02fbfc5d8bc6ee1e924e6ec8fe8c01932e0648a0d3e5695134af3bb7fab370d3012d083fa6b83179dd3d031053f72fc1f7da8459140b0af5afc4d2804deccb6")]
    class Class1
    {
        public void Test()
        {
            System.Console.WriteLine("Class1.Test");
            System.Console.ReadLine();
        }
    }
    
  4. Compile and sign friend_signed_A by using the following command.

    Vbc /target:library /keyfile:FriendAssemblies.snk friend_signed_A.vb
    
    csc /target:library /keyfile:FriendAssemblies.snk friend_signed_A.cs
    
  5. Create a Visual Basic or C# file that is named friend_signed_B and contains the following code. Because friend_signed_A specifies friend_signed_B as a friend assembly, the code in friend_signed_B can access Friend (Visual Basic) or internal (C#) types and members from friend_signed_A. The file contains the following code.

    ' friend_signed_B.vb
    ' Compile with: 
    ' Vbc /keyfile:FriendAssemblies.snk /r:friend_signed_A.dll friend_signed_B.vb
    Module Sample
        Public Sub Main()
            Dim inst As New Class1
            inst.Test()
        End Sub
    End Module
    
    // friend_signed_B.cs
    // Compile with: 
    // csc /keyfile:FriendAssemblies.snk /r:friend_signed_A.dll /out:friend_signed_B.exe friend_signed_B.cs
    public class Program
    {
        static void Main()
        {
            Class1 inst = new Class1();
            inst.Test();
        }
    }
    
  6. Compile and sign friend_signed_B by using the following command.

    Vbc /keyfile:FriendAssemblies.snk /r:friend_signed_A.dll friend_signed_B.vb
    
    csc /keyfile:FriendAssemblies.snk /r:friend_signed_A.dll /out:friend_signed_B.exe friend_signed_B.cs
    

    The name of the assembly generated by the compiler must match the friend assembly name passed to the InternalsVisibleToAttribute attribute. You can explicitly set the assembly by using the /out compiler option.

    In C#, you must explicitly specify the name of the output assembly (.exe or .dll) by using the /out compiler option. In Visual Basic, this is optional. For more information, see /out (Visual Basic) and /out (C# Compiler Options).

  7. Run the friend_signed_B.exe file.

    The program prints the string "Class1.Test".

Security

There are similarities between the InternalsVisibleToAttribute attribute and the StrongNameIdentityPermission class. The main difference is that StrongNameIdentityPermission can demand security permissions to run a particular section of code, whereas the InternalsVisibleToAttribute attribute controls the visibility of Friend (Visual Basic) or internal (C#) types and members.

See Also

Tasks

How to: Create Unsigned Friend Assemblies (C# and Visual Basic)

Reference

InternalsVisibleToAttribute

/keyfile

Sn.exe (Strong Name Tool)

Concepts

Assemblies and the Global Assembly Cache (C# and Visual Basic)

Friend Assemblies (C# and Visual Basic)

C# Programming Guide

Other Resources

Creating and Using Strong-Named Assemblies

Visual Basic Programming Guide