.NET Development

How to Find the Public Key Token for a Strongly-Named Assembly

Posted on Updated on

In another post, we discussed why you should strongly name assemblies and how to do it via the Strong Name Tool (sn.exe). In this quick post we will consider another scenario – how to get the public key token string value of a strongly named assembly (dll).

This is easily accomplished by using the Strong Name Tool as well by simply using the -T switch and specifying the path and name of the dll for which to retrieve the public key token. It can also be done in code using the System.Reflection.Assembly class. We will take a quick look at each approach.

Using the Strong Name Tool

To use the Strong Name Tool (sn.exe), simply open the Microsoft Visual Studio Developer Command Prompt and use the following syntax:

sn.exe -T <assembly path and name>

For this example, we will retrieve the public key token for an assembly named SampleClassLibrary.dll that is located in the c:\Temp folder.

Get Public Key Token of Strongly Named Assembly using Strong Name Tool

For this example, the public key token is ba27e13c07659075.

Using the System.Reflection.Assembly Class – Getting the Public Key Token in Code

The manner in which we get the public key token for an assembly depends upon our point of reference. For example, we can do it for the currently executing assembly, do it for a specific assembly based on a file path, or do it for one or all assemblies that have been loaded within the current AppDomain.

Let’s consider two of these scenarios:

Getting the Public Key Token for the Currently Executing Assembly

To demonstrate this approach, I have created a simple method in a sample class:

public void GetPublicKeyTokenForThisAssembly()
{
    byte[] token = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();
}

Now, if we execute this code, and place a breakpoint on the line that gets the byte array, we can use Visual Studio debugging to view the results of our token retrieval.

PublicKeyTokenDebuggerView

Since the return type is a byte array, the results are exactly as we would expect. So how do we convert that to the same string that we saw when we did it through the Strong Name Tool?

We write a little bit of C# code to do this as shown below:

byte[] token = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();

StringBuilder sb = new StringBuilder();

for (int i = 0; i < token.GetLength(0); i++)
{
     sb.Append(String.Format("{0:x2}", token[i]));
}

string publicKeyToken = sb.ToString();

The result of this is the public key token that we retrieved using the Strong Name Tool above.

If you are wondering what the “{0:x2}” formatter does, this is something known as Composite Formatting. The hexadecimal format specifier (X) converts a number to a string of hexadecimal digits. The “2” instructs the runtime to produce a string with a length of 2.

Getting the Public Key Token for Assemblies in the Current AppDomain

Though the point of this post is not to discuss Reflection or how to use the methods of the Assembly class, it is beneficial to take a look at how this same logic could be applied to all assemblies loaded within the current AppDomain.

To do this, we merely have to change our code to get the assemblies and iterate through them to retrieve the public key tokens.

byte[] token;

StringBuilder publicKeyTokens = new StringBuilder();
Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();

foreach (Assembly assembly in loadedAssemblies)
{
    token = assembly.GetName().GetPublicKeyToken();
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < token.GetLength(0); i++)
    {
        sb.Append(String.Format("{0:x2}", token[i]));
    }

    publicKeyTokens.AppendLine("The public key token for assembly " + assembly.FullName + " is:  " + sb.ToString());
}

string allPublicKeyTokens = publicKeyTokens.ToString();

The output of our StringBuilder is as follows:

The public key token for assembly mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly Microsoft.VisualStudio.HostingProcess.Utilities, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly Microsoft.VisualStudio.Debugger.Runtime, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly vshost32, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly System.Deployment, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a is:  b03f5f7f11d50a3a
The public key token for assembly System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is:  b77a5c561934e089
The public key token for assembly WindowsFormsApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null is:
The public key token for assembly SampleClassLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ba27e13c08759075 is:  ba27e13c08759075

If you notice the assembly for my sample WinForms assembly shows a PublicKeyToken that is null. Why is this? Because I did not strongly name that assembly! Also, notice that in our code we extracted the FullName value for each assembly. This is an important point when talking about strong naming because the FullName shows us the name, version, public key token, and culture information.

In this simple little sample, I utilized a solution with two projects: a WinForms project and a class library that is referenced by the WinForms project. In this sample, the class library is strongly named and the WinForms project is not. This is okay, but the opposite scenario is not. Suppose that we strongly name the WinForms assembly but remove the strong name from the class library. The compiler will bark at us then we try to build the solution because as we said before, a strongly named assembly requires all referenced assemblies to be strongly named as well. The output below is generated when we try to build under the second scenario:

strongnamedcompilererror

 

 

Strong-Named Assemblies – Why and How

Posted on Updated on

Overview

In this short post, I will discuss strong-named assemblies in .NET and cover why and how you should use strong naming within your .NET projects.

First, there seems to be a misconception among many developers with whom I’ve worked that strong naming is a security measure. That is not the intent of strong naming! Instead, strong naming provides a means of uniquely identifying assemblies and providing evidence that the assembly to be loaded is indeed the one intended. A strong name consists of the following things:

  • The assembly’s simple text name
  • The assembly’s full version number
  • The assembly’s culture information
  • A Public Key
  • A Digital Signature

Why Use Strong-Named Assemblies?

Based on your scenario, there are some distinct reasons why assemblies should be strongly named.

  • If you plan to deploy your assembly to the Global Assembly Cache (GAC), the assembly MUST be strongly named. This is necessary because the GAC allows multiple versions of the same assembly to coexist simultaneously. Anyone who has been around long enough to remember Windows development in the past, especially prior to .NET remember the term “DLL Hell”. I know this term all too well and learned very quickly a long time ago what a pain it can be. Those are bad memories, so I will move on! I will discuss the Global Assembly Cache in another article.
  • Strong names protect the version lineage of an assembly. If an assembly is strongly named, the assemblies it references must also be strongly named.

Strong naming relies upon asymmetric cryptography. Although the purpose of this article is strong naming, a very quick discussion of asymmetric cryptography is warranted. I will only take a shallow dive into asymmetric cryptography because this purpose of this article is to briefly discuss strong-named assemblies and not encryption.

Asymmetric Cryptography (Public Key Cryptography)

Public Key Cryptography (PKC) is a form of cryptography that requires two “keys” – a public key and a private key. The public key is known to all and the private key is only known to the individual. In a very simple example of PKC, if I decide to send an encrypted message to one of my friends, I use my friend’s public key to encrypt the message, then he uses his private key to decrypt it. If he then decides to send me an encrypted message, he uses my public key to encrypt it then I use my private key to decrypt. Makes sense, right? It is important to note that with PKC, only the public key can be used to encrypt, and only the corresponding private key can be used to decrypt.

How to Create a Strong Name Key Pair

Before strongly naming an assembly, you must first have a public/private key pair file. The key pair is used by the compiler to create the strong-named assembly.

Creating a strong name key pair is made very simple by Microsoft through use of the Strong Name Tool (sn.exe). To create a key pair using this tool, simply follow these steps:

  1. From the Start menu, select your version of Visual Studio in the All Programs menu, click Visual Studio Tools, then select the Visual Studio Developer Command Prompt menu. See the following image.
  2. When the Visual Studio Command Prompt window opens, invoke the Strong Name Tool using the following syntax: sn -k KeyFileName.snk. The Strong Name Tool has numerous switches that can be used with its invocation. The -k switch instructs the tool to create the public/private key pair with the name that you specify. You can specify the path to which the .snk file should be created. In the example below, I create a key pair named MyKeyPair and I write it to the c:\Temp folder.sn_result
  3. When the key pair has been created, the next step is to use it to strongly-name an assembly. This is easily accomplished within Visual Studio by right-clicking the project to be signed and selecting the Properties menu. The example below shows the Properties window for a sample class library that I have created.SigningTabBrowse
  4. Browse to the .snk file and click Ok. The .snk is then associated with the project and when built, the resulting assembly will be strongly-named.

That’s it! Pretty simple. In the next article we take a look at how to extract the PublicKeyToken from a strongly-named assembly.

 

New Features in WCF 4.5

Posted on Updated on

With the release of Windows Communication Foundation (WCF) in version 3.0 of the .NET Framework in 2006, Microsoft set the stage for a unified framework for developing service-oriented applications in .NET. Since then, I have personally become quite a fan of WCF and have created countless services and service clients. WCF is flexible and robust, and with .NET 4.5 has become even better!

Though we won’t dive into detail, I would like to take a quick moment to briefly discuss some of the highlights of the new features in WCF 4.5. These are the new features that I have found to be most exciting:

Generated Configuration Files have been Simplified

When we Add a Service Reference via Visual Studio or use the svcutil.exe, a client config file is generated for us. In earlier versions, this file contained every binding present, including those that just had default values. Now the config files only contain those with non-default bindings.

Configuration Validation

When we build our project(s) via Visual Studio, the attributes that we implement within our project classes are validated against the values in the config files. This allows us to discover issues at built-time without having to wait for run-time.

ASP.NET Compabibility Mode Default

Through use of the aspNetCompatibilityEnabled attribute in the <serviceHostingEnvironment> node, WCF now gives developers access to the functionality of the HTTP pipeline when writing WCF services. Setting this to true enables us to access the HttpContext.

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

Support for Asynchronous Streaming

WCF now truly supports asynchronous streaming – this is a significant scalability enhancement!

IIS HTTPS Simplification

A new HTTPS protocol mapping which greatly simplifies implementing a WCF server over HTTPS when using IIS. I remember this being a slight pain in the past.

<system.serviceModel>
    <services>
         <service name="SampleService">
               <endpoint address=""
                     binding="basicHttpsBinding"
                     contract="ISampleService">
              </endpoint>
         </service>
    </services>
 </system.serviceModel>

Prior to WCF 4.5, we would have had a <basicHttpBinding> node and a <security> node with the mode attribute set to “Transport”. Now we just set a basicHttpsBinding attribute within the endpoint. Pretty cool!

Easier Configuration of WCF Services in Code

In the pre-4.5 days, we had to create a ServiceHostFactory that created the ServiceHost. in WCF 4.5, you merely create a public static method named Configure that accepts a ServiceConfiguration object.

public class MyService : IMyService
{
    public static void Configure(ServiceConfiguration config)
    {
        ServiceEndpoint serviceEndpoint = new ServiceEndpoint(new ContractDescription(&quot;IMyService1&quot;),
                new BasicHttpBinding(), new EndpointAddress(&quot;basic&quot;));
        serviceEndpoint.Behaviors.Add(new MyEndpointBehavior());
        config.AddServiceEndpoint(serviceEndpoint);

        ServiceDebugBehavior sdb = new ServiceDebugBehavior();
        sdb.HttpGetEnabled = true;
        config.Description.Behaviors.Add(sdb);

        ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
        smb.IncludeExceptionDetailInDefaults = true;
        config.Description.Behaviors.Add(smb);
    }
}

Multiple Authentication Types via a Single Binding

You read that right! Beginning with WCF 4.5, multiple authentication types can be used via a single endpoint if you are using HTTP with Transport security. Because IIS allows multiple authentication methods on a virtual directory, these same authentication types can be used by WCF for the virtual directory in which the web service is hosted.

WebSocket Support via Two New Bindings

Two new bindings, NetHttpBinding and NetHttpsBinding provide TCP-like performance over the standard HTTP and HTTPS ports (80 and 443) bidirectionally. The HTTP paradigm that we all know and love has been built based on the concepts of requests and responses. The WebSocket specification defines socket connections between a web browser and a server over HTTP. This is a wonderful enhancement because what we have is a connection between the client and the server and both parties can start sending information any time. A discussion of WebSockets is beyond the scope of this short feature overview, but it is a topic worth discussing at a later date.

UDP Support

Anyone familiar with UDP knows that it is a great way to very quickly send messages in one direction. WCF 4.5 now supports UDP!

Conclusion

Though there are other exciting enhancements in WCF 4.5, these are my favorites and in my mind some of the most interesting.

8004E00F – COM+ was unable to talk to Microsoft Distributed Transaction Coordinator

Posted on Updated on

Problem Overview

When you open the Windows Component Services Configuration Console (dcomcnfg), you see a red, downward-pointing arrow on the My Computer icon under Component Services as shown below.

MSDTC 8004E00F - COM+ was unable to talk to the Microsoft Distributed Transaction Coordinator

This error is commonly caused by the MSDTC service being set to run under the local system account instead of NT Authority\NetworkService.

If you check the MSDTC service and discover that this is indeed the problem, follow these steps to change the identity:

  1. Open the Registry Editor (regedit.exe).
  2. Find the following registry key: HKEY_LOCAL_MACHINE\Software\Microsoft\MSDTC
  3. Right-click TurnOffRpcSecurity, then select Modify. Add a value of 1.
  4. Open the Services Console and stop the MSDTC service.
  5. Right-click the service and select Properties on the popup menu.
  6. When the Properties dialog opens, click the Log On tab and change the identity to NT Authority\NetworkService (the password is blank).
  7. Click Apply then click OK.
  8. Return to the Services management console and restart the MSDTC service.

If the problem persists, check the Application Log within the Event Viewer and look for errors (red icons). The Event Viewer is a great resource for finding out what is really going on.

One possible solution is to stop the service, uninstall and then reinstall MSDTC. To do this, follow these steps:

  1. Stop the MSDTC service.
  2. Open a command prompt (cmd).
  3. Type “msdtc -uninstall”.
  4. Type “msdtc -install”
  5. Close the command prompt.