2009-02-20 18 views
20

Dopo asking about what Visual Studio does to register a COM Library, è diventato chiaro che VS ha fatto due cose per la registrazione COM:Typelib Generazione e installazione con WiX

  1. registrati COM Biblioteca
  2. crea e registra una libreria dei tipi

visiva Studio sembra fare questa registrazione usando regasm.exe. Per la prima parte (la registrazione diretta di COM) utilizzando tallow o heat (WiX 2.0 o WiX 3.0) sembra che tutte le informazioni di base sulla registrazione COM siano corrette.

Tuttavia, ciò che non sembra fare sego/calore è l'installazione di una libreria di tipi. Sarebbe possibile creare un'azione personalizzata per eseguire questa operazione con un programma di installazione Wix e regasm.exe, ma il richiamo di azioni personalizzate non sono le migliori pratiche quando si tratta di programmi di installazione basati su Microsoft Installer.

Dopo ulteriori ricerche, sembra che un msi abbia la possibilità di generare la libreria dei tipi al momento dell'installazione. In effetti, WiX sembra avere un supporto diretto per questo! In un elemento file, è possibile aggiungere un elemento Typelib. Infatti, an article over here on wix ha un esempio di compilazione dell'elemento TypeLib con gli elementi Interface.

Sembra che ci sia almeno due attributi necessari a un elemento di interfaccia:

  1. Id
  2. Nome

Larry Osterman speaks about the other parts of the interface that need to be registered for a TypeLib in general, e questa voce interfaccia sembra prendere cura delle singole parti. Larry dice che dobbiamo specificare ProxyStubClassId32 come "{00020424-0000-0000-C000-000000000046}", così possiamo facilmente aggiungerlo.

Dove andare da lì e cosa compilare per i vari elementi di interfaccia mi ha perplesso. Sono andato avanti e ho aggiunto l'elemento TypeLib al mio file wix, e viene compilato con successo. Sono un po 'incapace di come impostare gli elementi dell'interfaccia però. Cosa dobbiamo fare per compilare correttamente l'elemento TypeLib e quali app o strumenti posso utilizzare per ottenerlo?

La risposta di seguito di wcoenen sembra promettente ... ho intenzione di fare un tentativo.

Aggiornamento: pubblicato la mia soluzione finale sotto come risposta.

+0

+1, vorrei che tutte le domande su questo sito fossero scritte in questo modo ... –

+0

Heh, gli do il mio scatto migliore. :) –

risposta

13

Ecco il modo pigro di risolvere questo problema: Utilizzare heat da WiX 3.0.

Se si dispone di una libreria dei tipi generata automaticamente e installato tramite regasm, heat può prendere il TLB come un argomento a

heat file c:\my\path\to\my.tlb -out tlb.wxs 

Esso genera tutti gli elementi TypeLib e interfaccia, devi essere registrato. Questo non risolverà il problema di doverli conoscere prima del tempo e non risolverà il problema dei GUID che cambiano quando la versione dell'assembly cambia (anche se l'interfaccia non lo fa - che è l'unica volta che si " supponendo di cambiarlo) ma ti porterà a metà strada lì.

+2

+1 Non sapevo che poteste raccogliere file tlb con heat.exe –

+1

Anche se non penso ci siano GUID variabili se li dichiarate nel vostro codice .NET con un GUID [assembly: Guid ("... ")] attributo per il typelib e un attributo [Guid (" ... ")] per le interfacce e le classi COM –

+1

Per i COM guid, penso che tu sia corretto. Sfortunatamente la libreria dei tipi ha diversi strumenti. : | Mi chiedo se c'è un attributo per impostare anche quei guidi ... –

7

Il seguente trucco può aiutare a raccogliere le modifiche del registro e trasformarle in un file wxs, incluso l'elemento typelib che si sta cercando.

  1. In primo luogo, portare il Registro di tornare in uno stato in cui la libreria di tipo non è stato registrato:

    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb /u mylib.dll 
    
  2. Esporta questo stato pulito del Registro di sistema a HKLM-prima.reg:

    c:\WINDOWS\system32\reg.exe export HKLM hklm-before.reg 
    
  3. registrare la libreria di tipo nuovo:

    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb mylib.dll 
    
  4. Esportare il nuovo stato del registro HKLM-after.reg:

    c:\WINDOWS\system32\reg.exe export HKLM hklm-after.reg 
    
  5. ora abbiamo due file di testo, hklm-before.reg e hklm-after.reg. Creare un file diff.reg che contiene solo le differenze rilevanti tra questi. È possibile trovare facilmente le differenze con uno strumento diverso. Mi piace usare lo strumento diff incluso in TortoiseSVN poiché lo uso già tutti i giorni. (WinDiff non sembra funzionare bene in questo caso a causa di problemi di testo-codifica.)

  6. Ora possiamo convertire diff.reg in un .wxs chiamando heat.exe con il comando reg. (Richiede Wix 3.5 o più recente.)

    heat reg diff.reg -out typelib.wxs 
    
+2

Ouch. Non c'è da stupirsi che affermano che l'authoring WiX in questo momento è un processo manuale, euch! –

+1

Questo perché WIX è per lo più solo un formato XML che si associa a un database di installazione di Windows (msi/msm/mst/pcp). Ad esempio, esiste un elemento "typelib" perché esiste anche una tabella "typelib". Lo strumento di raccolta heat.exe è utile valore aggiunto ma ha bisogno di esperti per completarlo. –

+0

A partire da WiX 3.10 il calore ha un parametro specifico dedicato alla raccolta dei file di registro. –

3

Sembra registrare una libreria dei tipi, il miglior modo sarebbe quello di generare il proprio file IDL o ODL, che conterrà i tuoi GUID. I Typelib generati direttamente dall'Assembly sono [i] dipendenti [/ i] sui numeri di versione dell'assembly: i GUID vengono generati in base a tali informazioni, anche se l'interfaccia non è stata modificata. Visual Studio utilizza il regasm per registrare e generare il typelib. Al di sotto, utilizza RegisterTypeLib, una chiamata win32. L'uso dell'elemento typelib sembra fare qualcosa di simile. Non buono.

Tuttavia! Creare la libreria dei tipi a mano è doloroso. È possibile ottenere quei GUID in un altro modo: scavarli dal typelib e creare gli elementi da soli.

Larry Osterman ha le informazioni necessarie: alcune chiavi del Registro di sistema devono essere impostate. Puoi fare quelli con la tabella di registro (e in Wix3, che significa elementi di RegistryValue.) Il trucco qui è ottenere i GUID: qualsiasi vecchio GUID non funzionerà. Normalmente, ottenere i GUID è semplicemente una questione di cercare nell'IDL della tua libreria (hai scritto il tuo IDL, giusto? :)).

Se non è stato scritto un file IDL o ODL per la compilazione in una libreria dei tipi, esistono ancora, nel file. Microsoft fornisce diversi strumenti pratici: LoadTypeLibEx e l'interfaccia ITypeLib. Con queste interfacce, è possibile sfogliare la libreria dei tipi e ottenere tutti i tipi di informazioni. Come navighiamo nella biblioteca?

Ho semplicemente dato un'occhiata a come ha fatto Regasm! Un rapido disassemblaggio più tardi, e scopriamo che il regramma è scritto anche in C#. Giorno di gloria. Ho iniziato un progetto, e con pochi utilizzando le istruzioni e un PInvoke tardi, abbiamo:

using System.Runtime.InteropServices;   // for struct marshaling 
using System.Runtime.InteropServices.ComTypes; // for the ITypeLib + related types 

// TYPELIBATTR lives in two places: Interop and ComTypes, but the one 
// in Interop is deprecated. 
using TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR; 

/// <summary> 
/// The registry kind enumeration for LoadTypeLibEx. This must be made 
/// here, since it doesn't exist anywhere else in C# afaik. This is found 
/// here: http://msdn.microsoft.com/en-us/library/ms221159.aspx 
/// </summary> 
enum REGKIND 
{ 
    REGKIND_DEFAULT, 
    REGKIND_REGISTER, 
    REGKIND_NONE 
} 

// and this is how we get the library. 
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false)] 
    private static extern void LoadTypeLibEx(string strTypeLibName, REGKIND regKind, out ITypeLib TypeLib); 

Accidenti! Una volta che abbiamo questo, dobbiamo navigare nella struttura. Questo sta interagendo con le risorse non gestite, quindi preparatevi ad essere roba da fare Marshal.

ITypeLib lib = null; 
LoadTypeLibEx(Value, REGKIND.REGKIND_NONE, out lib); 
IntPtr libInfoPtr = IntPtr.Zero; 
lib.GetLibAttr(out libInfoPtr); 
TYPELIBATTR libInfo = 
    (TYPELIBATTR) Marshal.PtrToStructure(libInfoPtr, typeof(TYPELIBATTR)); 
int typeCount = lib.GetTypeInfoCount(); 
for (int i = 0; i < typeCount; ++i) 
{ 
    ITypeInfo info; 
    lib.GetTypeInfo(i, out info); 
    IntPtr typeDescrPtr = IntPtr.Zero; 
    info.GetTypeAttr(out typeDescrPtr); 
    TYPELIBATTR type = 
     (TYPELIBATTR)Marshal.PtrToStructure(typeDescrPtr, typeof(TYPELIBATTR)); 
    // get GUID, other info from the specific type 
} 

lib.ReleaseTLibAttr(libInfoPtr); 
libInfoPtr = IntPtr.Zero; 

Whew. Quindi, devi scrivere del codice per estrarre le informazioni. Una volta fatto, è necessario inserire tali informazioni in Registy Entries, come specificato By Larry Osterman.

Ovviamente, è possibile evitare questo passaggio semplicemente scrivendo il proprio file IDL per iniziare.La scelta nel dolore: tocca a voi!

+0

L'ho riletto un paio di volte, ma sono molto confuso. Non ho idea di cosa hai ottenuto qui. –

+0

Il codice non è la soluzione. Visual Studio genera tutte le informazioni che dovresti fare tu stesso in un file IDL come parte del regasma. Questo ti permette di capire cosa ha fatto il regasma a tuo nome. Quello che dovresti fare è creare un file IDL. –

+1

Se stavi cercando di capire cosa regham inserisce nel tlb, allora perché non aprire il file tlb generato dal regasm con oleview.exe? –

Problemi correlati