Robert McLaws: FunWithCoding.NET

Public Shared Function BrainDump(ByVal dotNet As String) As [Value]

News

<script type="text/javascript"><!-- google_ad_client = "pub-4330602465258980"; google_hints = "ASP.NET, VB.NET, C#, C#.NET, WindowsForms, .NET Framework, VS2005, Visual Studio, XAML, WinFX, Windows Workflow, WPF, WCF, Atlas, NetFX3, Visual Studio Orcas"; google_ad_width = 120; google_ad_height = 240; google_ad_format = "120x240_as"; google_ad_type = "text_image"; google_ad_channel ="4997399242"; google_color_border = "B6C9E7"; google_color_bg = "EFEFEF"; google_color_link = "0000FF"; google_color_text = "000000"; google_color_url = "002C99"; //--></script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<!--
-->

You should feel free to challenge me, disagree with me, or tell me I'm completely nuts in the comments section of each blog entry, but I reserve the right to delete any comment for any reason whatsoever. That said, I will most likely only delete abusive, profane, rude, or annonymous comments, so keep it polite, please.

Blogroll

Cool .NET Articles

My .NET Tools

My Builder.com Articles

My MSKB Articles

Getting an Assembly's Public Key the Programmatic way

I have been struggling with the dumbest problem all day. I have been working with extending the XHEO|Licensing system with a new licensing limit for a new product that I'm working on. Basically, it limits the assembly to be used only by a specific calling assembly. Anyways, I was looking for a way to get the public key and public key token of an assembly programmatically, and after some hunting through the System.Reflection namespace, I found it. It really sucks though, because I went through the MSDN docs for the AssemblyName.GetPublicKeyToken, and it had an example of almost exactly what I needed The problem is, it didn't work

Here is the code I used, and the output that followed.

Function Test2() As String
    ' Get the assemblies loaded in the current application domain.
    ' Get the dynamic assembly named 'MyAssembly'.
    Dim myAssembly As
[Assembly] = [Assembly].GetCallingAssembly
    Dim sb As New
StringBuilder
    Dim i As
Integer
    If Not (myAssembly Is Nothing)
Then
        sb.Append("AssemblyName: ")
        sb.Append(myAssembly.GetName.FullName)
        sb.Append("<br>Public Key: ")
        Dim pk As Byte
() = myAssembly.GetName().GetPublicKey()
        For i = 0 To
(pk.Length - 1)
            sb.Append("{0:x}", pk(i))
        Next
i
        sb.Append("<br>")
        sb.Append("<br>Public Key Token: ")
        Dim pt As Byte
() = myAssembly.GetName().GetPublicKeyToken()
        For i = 0 To
(pt.Length - 1)
            sb.Append("{0:x}", pt(i))
        Next
i
    End
If
    Return
sb.ToString
End Function

AssemblyName: myAssemblyTest, Version=1.0.1524.22437, Culture=neutral, PublicKeyToken=f925674905014eec
Public Key: {{{{{{{{{{{{{{{{{{{{{{{{{{{{.....etc.
Public Key Token: {{{{{{{{{{{{{{{{....etc.

I wasn't sure why the MS-given sample didn't work. With about an hour of experimentation (should have been less, but oh well), I finally stumbled upon the answer. It seems that they were using the ASP.NET syntax for formatting. The correct code for cycling through the byte arrays is as follows:

Function Test2() As String
    ' Get the assemblies loaded in the current application domain.
    ' Get the dynamic assembly named 'MyAssembly'.
    Dim myAssembly As
[Assembly] = [Assembly].GetCallingAssembly
    Dim sb As New
StringBuilder
    Dim i As
Integer
    If Not (myAssembly Is Nothing)
Then
        sb.Append("AssemblyName: ")
        sb.Append(myAssembly.GetName.FullName)
        sb.Append("<br>Public Key: ")
        Dim pk As Byte
() = myAssembly.GetName().GetPublicKey()
        For i = 0 To
(pk.Length - 1)
            sb.Append(pk(i).ToString("x"))
        Next
i
        sb.Append("<br>")
        sb.Append("<br>Public Key Token: ")
        Dim pt As Byte
() = myAssembly.GetName().GetPublicKeyToken()
        For i = 0 To
(pt.Length - 1)
            sb.Append(pt(i).ToString("x"))
        Next i
    End
If
    Return
sb.ToString
End Function

This function had slightly better results:

AssemblyName: myAssemblyTest, Version=1.0.1524.22437, Culture=neutral, PublicKeyToken=f925674905014eec
Public Key: 02400480009400062000240052534131040010.... etc.
Public Key Token: f9256749514eec

As you can see, the Public Key Tokens match. The “x” formatting string makes the ToString method kick out hexadecimal code instead of normal text. In case you didn't know, you can use lots of other formatting tokens as well. The documentation on the subject kinda sucks, so I'm working on an article on the subject, publish date TBD.

There you have it. Hope that code comes in handy for someone. Speaking of publishing, Builder.com has put all their new content on hold for a little while, so I'm shopping around for a new publisher. If any of you know of any sites that pay for articles, please let me know. I have 4 that just need a final polish up and they are good to go. Builder has been great, but they've been slipping ever since they merged with TechRepublic. It took nearly seven weeks to get my last paycheck.

Comments

Udi Dahan - The Software Simplist said:

Have you considered the linkdemand part of the security attribute ?
# March 5, 2004 1:46 AM

Robert McLaws said:

No, because I have no idea what that is. Can you explain?
# March 5, 2004 6:27 AM

Udi Dahan - The Software Simplist said:

This does exactly what you need - "it limits the assembly to be used only by a specific calling assembly"
# March 5, 2004 3:35 PM

Robert McLaws said:

Yeah, but that is done programmatically. The XHEO|Licensing system is a run-time licensing thing, and I won't know at compilation time what assembly is going to be calling it.
# March 6, 2004 12:40 PM

Daren said:

Robert , does the built in Xheo limit "Publisher" not already do what your looking for ?
# March 6, 2004 6:58 PM

Robert McLaws said:

No, the Publicher Limit only limits it to an assembly with a given Strong Name Key. I want a publisher to be able to use it on a certain control, but not necessarily all of their controls.
# March 6, 2004 9:07 PM

Carlos Barichello said:

The format string should be "x2" instead of just "x". This makes sure that the resulting string has two characters. That is important in this scenario. For example, if "pt(i)" shows up as "10" in the debugger, notice that the converted value will be "a" if the format string is "x", but it will correctly be "0a" if the format string is "x2".

Having said the above, lots of thanks for your example: it saved me hours of my time.

Carlos Barichello
CBarichello@Epicor.com


# August 10, 2004 6:41 PM