Magazine

Sviluppare un Add-In per Reflector

Davide Senatore

21/11/2006

Sviluppare un Add-In con interfaccia integrato in Reflector, IL decompilatore per .net

0%100%
per esprimere un voto รจ necessario registrarsi al sito

Concetti di programmazione ad oggetti, Visual Basic.net

CodeSapiens.Reflector.ClassDumper.zip (9,00 Kb)

Introduzione

Reflector è IL tool che ogni sviluppatore .net deve avere installato nella propria macchina. E' stato sviluppato da Lutz Roeder e permette di decompilare eseguibili e dll .net per poter comprendere il codice scritto all'interno. Usato per scopi di studio, è uno strumento formidabile, in quanto permette di rendersi conto di come è stata implementata una caratteristica del Framework, oppure di come potrebbe essere realizzata una funzionalità particolare molto simile ad un'altra già presente in qualche assembly del Framework .net.

L'applicazione si presenta con un'interfaccia explorer-like, con l'insieme degli assembly "indagati" in una treeview sulla sinistra e con un'area adibita a ricerca e browser di codice sulla destra. Non vado oltre nella descrizione delle funzionalità di questa perla di programmazione, invitando chiunque (ma credo siano pochissimi) non conosca Reflector a scaricarlo a questo indirizzo. Non resterete delusi.

Estendibilità ed Add-Ins

Una delle features più interessanti, e forse più "segrete" di Reflector, è la sua espandibilità. Il creatore del programma ha infatti previsto la possibilità di creare nuove funzionalità che possono essere integrate all'interno dell'interfaccia di Reflector in modo abbastanza semplice. In questo articolo andremo a realizzare un Add-In minimo, ovvero una semplice finestra che visualizzi un pulsante all'interno dell'interfaccia di Reflector.

Creazione del progetto

Per prima cosa creiamo una soluzione di Visual Studio 2002 di tipo Library. Avete capito bene: Visual Studio 2002...infatti reflector è ancora compilato con il .net Framework 1.0 ed il riferimento a mscorlib.dll è alla versione 1.0.3300.0, potete controllare utilizzando Reflector per decompilare... Reflector.exe!!! Una volta creata la soluzione ed il progetto di tipo dll, è il momento di creare il riferimento all'assembly Reflector.exe, che contiene le interfacce che dovremo andare ad implementare e gli oggetti che dovremo creare per gestire il nostro add-in. Qui nasce il primo problema, solitamente, in quanto con VS2002 non è possibile creare un riferimento ad un file eseguibile. La soluzione potete trovarla in un mio precedente tip, e consiste nella modifica "a mano" del file di progetto della nostra library. Una volta aggiunto il riferimento, è possibile cominciare ad esplorare ed utilizzare le interfacce e le classi che ci mette a disposizione Reflector. Non è scopo di questo articolo elencare le classi e le interfacce, bensì vedremo come creare un semplice add-in, e per crearlo dobbiamo, come prima cosa, aggiungere una classe che chiameremo ClassDumperPackage al nostro progetto.

Questa classe dovrà implementare l'interfaccia IPackage che è fondamentale per l'integrazione all'interno di Reflector. L'interfaccia IPackage contiene 2 metodi Load(ByVal serviceProvider As System.IServiceProvider) e Unload() che vengono invocati al caricamento del plugin. L'informazione più importante sta in quell'oggetto serviceProvider che viene passato alla funzione Load. Esso espone infatti il metodo GetService() che permette di referenziare servizi base del motore di reflector all'interno del nostro plugin.

Tra i servizi più importanti possiamo ricordare:

  • IWindowManager: si occupa della parte di interfaccia di reflector e permette di aggiungere una nuova finestra alla collection delle finestre visibili.
  • ICommandBarManager: si occupa della gestione delle toolbar e dei menù di Reflector. Utilizzando tale servizio è possibile aggiungere un pulsante in un menu o in una toolbar
  • IAssemblyBrowser: permette di conoscere l'elemento selezionato nella TreeView
  • IAssemblyManager: permette tra le altre cose, di caricare, scaricare ed elencare gli assembly caricati nella TreeView principale
  • ILanguageManager: gestisce i linguaggi disponibili per effettuare le decompilazioni. Solitamente sono VB.net e C#, ma nelle ultime versione di Reflector sono stati aggiunti l'IL, Delphi e C++
  • ITranslatorManager: è il servizio di traduzione che permette di disassemblare classi, metodi e namespaces.

Nel nostro caso, per semplificare il template d'esempio, non andremo a complicare ulteriormente il codice e ci limiteremo ad utilizzare i servizi per lasciare ad un altro articolo l'approfondimento relativo alla decompilazione.

Prima di scrivere qualsiasi riga di codice, consideriamo anche il fatto che il nostro plugin dovrà avere un'interfaccia. Questa viene implementata attraverso l'uso di uno UserControl che andremo a battezzare ClassDumperWindow. E' da notare che tale controllo non deve obbligatoriamente implementare alcuna interfaccia, ma sarà bene creare al suo interno una serie di proprietà pubbliche atte a mantenere i riferimenti ai servizi che dovranno essere utilizzati dalle funzionalità che andremo a sviluppare.

Vediamo a questo punto il codice minimo della classe ClassDumperWindow che permette di caricare il nostro usercontrol all'interno dell'interfaccia di Reflector, dandoci la possibilità di utilizzare tutti i servizi che quest'ultimo espone.

Imports Reflector

Public Class ClassDumperPackage
    
Implements IPackage

    
Private _button As ICommandBarButton             'Pulsante per richiamare il plugin
    
Private _commandBarManager As ICommandBarManager 'Toolbar nella quale inserire il pulsante
    
Private _separator As ICommandBarSeparator       'Separatore (per chiarezza)
    
Private _windowManager As IWindowManager         'Servizio di gestione interfaccia di Reflector

    '''Codice da eseguire al caricamento del plugin
    
Public Sub Load(ByVal serviceProvider As System.IServiceProvider) Implements IPackage.Load
        
'Creazione interfaccia
        
Dim _classDumperWindow As New ClassDumperWindow()
        
'ottengo un riferimento al servizio di interfaccia
        
_windowManager = DirectCast(serviceProvider.GetService(GetType(IWindowManager)), IWindowManager)
        
'aggiungo il mio usercontrol alla collection delle finestre di Reflector
        
_windowManager.Windows.Add("ClassDumperWindow", _classDumperWindow, "Class Dumper")
        
'ottengo un riferimento al servizio di toolbar
        
_commandBarManager = DirectCast(serviceProvider.GetService(GetType(ICommandBarManager)), ICommandBarManager)
        
'Aggiungo un separatore
        
_separator = _commandBarManager.CommandBars.Item("Tools").Items.AddSeparator
        
'Aggiungo un pulsante per attivare il plugin
        
_button = _commandBarManager.CommandBars.Item("Tools").Items.AddButton("&Class Dumper", New EventHandler(AddressOf ClassDumperButtonHandler))
    
End Sub

    
'''Codice da eseguire allo scaricamento del plugin
    
Public Sub Unload() Implements IPackage.Unload
        
'Rimuovo la finstra il pulsante ed il separatore che ho creato nella fase di caricamento
        
_windowManager.Windows.Remove("ClassDumperWindow")
        _commandBarManager.CommandBars.Item("Tools").Items.Remove(_button)
        _commandBarManager.CommandBars.Item("Tools").Items.Remove(_separator)
    
End Sub

    
''' Gestore del click del pulsante
    
Private Sub ClassDumperButtonHandler(ByVal sender As ObjectByVal As EventArgs)
        
'rendo visibile l'interfaccia del mio plugin
        
_windowManager.Windows.Item("ClassDumperWindow").Visible = True
    End Sub

End Class

Lo UserControl includerà solo un pulsante che al click farà comparire una messagebox con un saluto, quindi non riporto il codice relativo...

A questo punto, compilato l'assembly, è possibile registrarlo all'interno degli Add-In di Reflector seguendo i passi:

  • Copiare l'assembly nella directory di Reflector
  • Aprire Reflector
  • Selezionare il menu View>Add-Ins...
  • Scegliere Add... e selezionare l'assembly che abbiamo appena compilato.

Se tutto è stato fatto nel modo corretto, nel menù tools dovrebbe comparire una voce "Class Dumper" che permetterà, una volta cliccata, di visualizzare il nostro UserControl incorporato nell'interfaccia di Reflector.

Conclusioni

In questo articolo abbiamo visto come scrivere il codice "minimo" per far partire un Add-In con Interfaccia all'interno di .net Reflector. In un successivo articolo approfondiremo l'uso dei servizi esposti da Reflector. Nel frattempo, scaricate il codice sorgente e buoni Add-Ins a tutti!!

Commenti
Nome

Sito web
Commento


indietro