C# - Assembly-t aláíró Macro készítése

forráskód letöltése
A Visual Studio.NET keretrendszer kitűnő támogatást nyújt ahhoz, hogy makróinkat eddig soha nem tapasztalt képességekkel ruházzuk fel. Lehetővé teszi, hogy elérjük az IDE objektumait, valamint a betöltött projekteket. Ezt kihasználva elkészítünk egy makrót, mely generál egy .SNK állományt, a projekthez adja azt, majd a hivatkozást beszúrja az AssemblyInfo.cs állomány megfelelő helyére. Ezzel a művelettel fölöslegessé válik az SN.EXE segédprogram parancssorból történő használata. A projektet ezt követően már csak le kell fordítani, és kész az aláírt assembly.
A mellékelt makró használata előtt be kell azt töltenie a keretrendszer makrói közé. Ennek módjáról a cikk „Kezdeti lépések” című szakaszában olvashat.
A mellékelt projekt egy Windows-os alkalmazást generál a fordítás után, melyet a makró segítségével Strong Name assembly-vé alakítunk, vagyis aláírunk egy, a SN.EXE segédprogram által generált kulcs-állománnyal.
Kezdeti lépések
A keretrendszer Macro Explorer ablakában találunk egy Macros csomópontot, mely alapértelmezésben már tartalmaz betöltött makró projekteket. Ezekhez fűzzük a saját projektünket, melyet a mellékelt példa Macro mappájában helyeztünk el.
A Macros csomópont gyorsmenüjében válasszuk a „Load Macro Project” feliratú menüpontot, majd a felbukkanó keresőablakban keressük meg a saját makró-projektünket.

Miután a projektet megtaláltuk és betöltöttük, megjelenik egy SNKeyToProjectMacro csomópont, melynek Module1 nevű modulja tartalmazza az aláírást generáló AddSNKeyToProject metódust.
Makró elkészítése
A makró Modul1 modulja tartalmazza tehát a metódust, melynek meghívásával futtatjuk a SN.EXE segédprogramot, generálunk egy TestKey.snk állományt, az állományt a projekt egy erőforrásává tesszük, majd az AssemblyInfo.cs állományba szúrjuk úgy, hogy a fordító képes legyen megtalálni, és assembly aláírást kapjon.
A megoldás lényege, hogy a Rendszerleíró adatbázis HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework kulcsának SDKINSTALLROOT bejegyzésének értékét kiolvassuk, amely a .NET Framework telepítési mappájának elérési útvonalát tartalmazza. Ennek segítségével már meghatározható a SN.EXE segédprogram helye, így futtatható. A segédprogram alapértelmezésben tehát a következő elérési útvonalon található:
<meghajtó>:\\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin
A segédprogramot a következő szintaxissal hívjuk meg a TestKey.snk kulcsállomány generálása érdekében:
Sn.exe –k <elérési út>TestKey.snk
A művelet eredményeképpen a kulcsállomány a fenti mappába kerül, és onnan kerül hozzáadásra a projekthez.
A Rendszerleíró adatbázis olvasásához a makróban létre kell hoznunk egy változót.
Dim path As Microsoft.Win32.RegistryKey
Az adatbázisból a következőképpen olvassuk ki a megfelelő kulcs értékét:
path = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("software\microsoft\.NetFramework")
Ha az olvasás eredményes volt, akkor a kapott elérési útvonal végére odaillesztjük a BIN karakterláncot, hogy előálljon a SN.EXE alkalmazás elérési útvonala.
If Not path Is Nothing Then
  temp = path.GetValue("sdkinstallroot", "") & "bin"
End If
A létrehozandó kulcsállomány nevét egy változóban helyezzük el.
filename = "TestKey.snk"
A következő lépés, hogy átlépünk a kapott elérési útvonalon található mappába. Erre a ChDir Visual Basic metódus használható.
Microsoft.VisualBasic.ChDir(temp)
A Shell metódus segítségével lefuttatjuk a SN.EXE segédalkalmazást a fent említett szintaxissal.
Microsoft.VisualBasic.Shell("cmd /c sn.exe -k """ & filename & """", AppWinStyle.NormalFocus, True)
A műveletben megjelenik egy pillanatra a parancssor, de el is tűnik a művelet végeztével.
Létrehozunk egy újabb változót, melyben a most generált TestKey.snk állomány teljes elérési útvonalát tároljuk.
Dim fullName As String
fullName = temp & "\" & filename
A DTE objektum ItemOperations kollekciójának segítségével adhatjuk a létrehozott állományt a projekthez. Ennek érdekében meg kell hívni az AddExistingItem metódust, paraméterként átadva a fenti elérési útvonalat.
DTE.ItemOperations.AddExistingItem(fullName)
A következő, és egyben utolsó lépés annak elérése, hogy a projekt fordításakor a kulcsállomány a megfelelő helyen legyen, és a bejegyzés az AssemblyInfo.cs állományba bekerüljön. A kulcsállományt a SNKeyToProjectMacro.sln állománnyal azonos mappában helyeztük el, és erre az elérési útvonalra kell hivatkoznunk az AssemblyInfo.cs-ben is. A művelet végén a következő bejegyzést kell találnunk az állományban:
[assembly: AssemblyKeyFile(@"TestKey.snk")]
A makróban akkor is be tudjuk írni a fenti hivatkozást, ha az AssemblyInfo.cs állomány nincs megnyitva. Ezt ellenőrizzük a DTE.ItemOperations.IsFileOpen metódussal, majd FALSE érték esetén megnyitjuk az állományt az OpenFile metódussal.
If DTE.ItemOperations.IsFileOpen("AssemblyInfo.cs") = False Then
  DTE.ItemOperations.OpenFile("AssemblyInfo.cs")
End If
A következő lépésben aktívvá tesszük az állományt, ha netán nem volt az, majd kijelöljük a teljes állomány szövegét.
DTE.Windows.Item("AssemblyInfo.cs").Activate()
Dim selection As TextSelection = DTE.ActiveWindow.Selection
selection.SelectAll()
Ezt követően kicseréljük a [assembly: AssemblyKeyFile("""")] karakterláncot a [assembly: AssemblyKeyFile(@" & Chr(34) & filename & Chr(34) & ")] karakterláncra.
snlocation = "[assembly: AssemblyKeyFile(@" & Chr(34) & filename & Chr(34) & ")]"
selection.ReplacePattern("[assembly: AssemblyKeyFile("""")]", snlocation)
A művelet ezennel kész, a betöltött projektek által generált assembly-k most már aláírhatók egy kattintással.