Pages

Monday, January 14, 2008

Macro to Add Strong Names to VS.NET Projects

When writing class libraries in Visual Studio .NET that are going to be placed into the GAC you will need to add strong name to the assembly. This is normally done by dropping out to a dos prompt and running the .NET utility sn.exe and then updating the assembly to reference the newly created.snk file. This looked like a great place for a macro to be able to do this all within the IDE. Below is a macro that when run opens up a standard windows dialog box allowing you to navigate to the assembly you would like to add the strong name too. Next, the sn.exe utility will be run on this assembly and added to the current project in the IDE.

There are a couple of things to keep in mind when using this macro. First is that if you have a solution open with several projects in it make sure that the project that you want to add the snk file too has focus. Next, you are required to compile the project before using the macro do to the fact that you must navigate to the assembly in order to run sn.exe on it. Finally, the sn.exe utility is currently set to run with the -k option, if you want other options then you will need to change this.

To use this macro navigate to Tool/Macros/Macro IDE. Next, navigate to the File / Add New Item and choose a Module. Finally, take all the code listed below and paste it inside the newly create module and save the project. The macro should now show up in the Macro explorer and you should be able
to run it from right inside the IDE.

Imports EnvDTE
Imports System.Diagnostics
Imports Microsoft.VisualBasic
Imports Microsoft.VisualBasic.ControlChars
Imports System.Windows
Imports System.Windows.Forms
Imports System
Public Module Module1
Public Class WinWrapper
Implements System.Windows.Forms.IWin32Window
Overridable ReadOnly Property Handle() As System.IntPtr Implements
System.Windows.Forms.IWin32Window.Handle
Get
Dim iptr As New System.IntPtr(DTE.MainWindow.HWnd)
Return iptr
End Get
End Property
End Class
Sub AddStrongNameToProject()
Dim init_dir, outfile_name, outdirectory As String
Dim stemp, Macroprojname As String
Dim prjSolution As EnvDTE.Project
Dim prjVSProject As VSLangProj.VSProject
Dim openfile As Forms.FileDialog
Dim result As Forms.DialogResult
Dim snPath As Microsoft.Win32.RegistryKey
Dim winptr As WinWrapper
Dim myProj As EnvDTE.Project
Try
winptr = New WinWrapper
openfile = New Forms.OpenFileDialog
' set the initial directory to SystemDrive
init_dir = System.Environment.SystemDirectory()
init_dir = Left(init_dir, InStr(init_dir, "\",
CompareMethod.Text))
openfile.InitialDirectory = init_dir
If openfile.ShowDialog(winptr) = result.OK Then
' create the output filename
outfile_name = Right(openfile.FileName,
Len(openfile.FileName) - Len(System.Environment.CurrentDirectory) - 1)
outfile_name = Left(outfile_name, InStr(outfile_name, ".",
CompareMethod.Text) - 1)
outfile_name = outfile_name & ".dll"
' set the output directory to the VsMacros dir
outdirectory = Left(DTE.FullName, InStr(DTE.FullName,
"devenv.exe", CompareMethod.Text) - 1)
outdirectory = outdirectory & "PublicAssemblies\"
snPath =Microsoft.Win32.Registry.LocalMachine.OpenSubKey("software\microsoft\.NetFramework(")")
If Not snPath Is Nothing Then
stemp = snPath.GetValue("sdkinstallroot", "") & "bin"
End If
If stemp = "bin" Then
MsgBox("Unable to get sn.exe location from registry")
Exit Sub
End If
Dim strsnkFileName As String
strsnkFileName = openfile.FileName.Replace(".dll", ".snk")
Microsoft.VisualBasic.ChDir(stemp)
' Shell out to the CMD sn.exe file
Microsoft.VisualBasic.Shell("cmd /c sn.exe -k """ &
strsnkFileName & """", AppWinStyle.NormalFocus, True)
' Add the snk file to the project
DTE.ItemOperations.AddExistingItem(strsnkFileName)
' Navigate to the AssemblyInfo file
DTE.Windows.Item("AssemblyInfo.cs").Activate()
'Update the Assembly file with the location here
Dim ts As TextSelection = DTE.ActiveWindow.Selection
ts.SelectAll()
Dim strNewStrongNameLoc As String
strNewStrongNameLoc = "[assembly: AssemblyKeyFile(@" &
Chr(34) & strsnkFileName & Chr(34) & ")]"
ts.ReplacePattern("[assembly: AssemblyKeyFile("""")]",
strNewStrongNameLoc)
End If
Catch err As System.Exception
MsgBox(err.Message)
End Try
End Sub
End Module

No comments: