2013-10-10 12 views
11

TL; DR Tutte le voci di registro prodotte da regsvr32 devono essere presenti in un manifest SxS reg-free-COM e viceversa?Quali tag sono richiesti nel manifest per la registrazione senza COM?


Sto cercando di ottenere la registrazione COM libera per un componente di terze parti.

Readingupon il soggetto, trovo che ci sono diversi elementi menzionati, che possono essere messi in un manifesto:

From the docs, possiamo aggiungere le seguenti tag a un manifesto per descrivere un componente COM:

  • assemblyIdentity - che in realtà solo descrive il "astratto assembly" per quanto mi riguarda posso dire
  • comClass - descrive la classe COM (IID In terface). Sembrerebbe, questo è sempre necessario.
  • typelib - quando?
  • comInterfaceExternalProxyStub - quando?
  • comInterfaceProxyStub - quando?

From the other docs for HKEY_LOCAL_MACHINE\SOFTWARE\Classes possiamo osservare che ci sono alcune categorie per le voci di registro COM:

Utilizzando regsvr42 per estrarre la roba la dll che sto cercando di regfree cede un manifesto che contiene solo comClass voci, nessuna libreria dei tipi o le voci ProxyStub. (E ho incrociato le chiavi scritte, la DLL in questione, pdm.dll, MS Process Debug Manager scrive solo quelle chiavi, cioè non c'è nessuna libreria di tipi o informazioni di stub proxy apparenti nel registro.)

Se il registro contiene solo le informazioni relative a comClass ciò significa che queste informazioni saranno sufficienti nel manifest SxS o potrebbero essere necessarie ulteriori informazioni nel manifest?


Per inciso ho notato che il registro contiene un VersionIndependentProgId e ProgId che ha un numero di versione aggiunto alla fine. Il manifesto ha solo una voce di ProgId, e lo Stato docs:

progid: identificatore programmatico Versione-dipendente associato al componente COM . Il formato di un ProgID è <vendor>.<component>.<version>.

Ma i documenti affermare anche

Il ComClass elemento può avere <progid>...</progid> elementi come bambini, che elencano la versione ProgID dipendenti.

e they say che l'attributo progid dovrebbe essere quello indipendente dalla versione.

Quindi, cosa mettere qui? E importa anche quando il client non richiede una versione specifica?

+0

PDM non avrà una libreria di tipi, non ha interfacce IDispatch ed è necessario utilizzare CoCreateInstance(). E si comporta come un componente in-process a thread libero quindi non ha bisogno di un proxy/stub. Cosa va veramente storto qui? –

+0

@ Ciao, grazie. Niente va storto in quanto tale, ma non ero sicuro se ci fossero potenziali insidie. (COM mi fa sempre sentire come se mi mancasse qualcosa.) Se tu potessi aiutare a svelare le mie divagazioni di cui sopra in due o tre domande davvero utili, lo apprezzerei. Altrimenti sono contento che tu sembri pensare che tutto sia ordinato :-) –

risposta

11

L'elemento assemblyIdentity è sempre richiesto, parte dell'impianto idraulico manifest. È sempre necessario fornire l'elemento comClass, sostituisce la chiave di registro HKLM\Software\Classes\CLSID e viene utilizzato per far funzionare la chiamata CoCreateInstance() del client. L'elemento file nomina il file eseguibile del server COM.

Il resto dei tasti è facoltativo, sono necessari per eseguire il marshalling. Il marshalling si verifica quando la chiamata del client deve essere eseguita su un thread diverso. Questo sarà sempre accade quando il server e il client sono in processi diversi, il caso per un server fuori processo o quando il server viene eseguito su un altro computer. E può succedere quando il ThreadingModel specificato nell'elemento comClass lo richiede. In altre parole, quando l'oggetto COM è stato creato su un thread ma viene chiamato su un altro e il server non è thread-safe.

RPC implementa il marshaling ma ha un lavoro per farlo con cui ha bisogno di aiuto. Ha bisogno di sapere quali sono gli argomenti per la funzione, così come il tipo di ritorno. In modo che possa serializzare correttamente i loro valori in un pacchetto di dati che può essere trasmesso attraverso una rete o passato al codice in un altro thread che effettua la chiamata. Questo è il lavoro del proxy. Lo stub viene eseguito all'estremità ricevente e deserializza gli argomenti per creare lo stack frame e effettua la chiamata. Il valore restituito dalla funzione, così come i valori degli argomenti passati per riferimento, tornano al chiamante. Il codice che rende la chiamata altrimenti non ha consapevolezza che non ha chiamato direttamente la funzione.

ci sono quattro casi fondamentali:

  • Il server COM non supporta essere chiamato in quel modo a tutti e deve sempre essere utilizzato dallo stesso filo è stato creato su. Fermati lì, non c'è bisogno di aggiungere nulla al manifest.

  • Il server COM implementa IMarshal interface. Interrogato automaticamente da COM quando non riesce a trovare un altro modo per eseguire il marshalling della chiamata. Questo è abbastanza raro, ad eccezione di un caso in cui il server COM aggrega il marshaller a thread libero. In altre parole, è completamente sicuro per i thread da solo, senza bisogno di aiuto e funziona sempre in-process. PDM è probabile che funzioni in questo modo. Fermati lì, non c'è bisogno di aggiungere nulla al manifest.

  • L'autore del server COM ha iniziato il suo progetto scrivendo la descrizione dell'interfaccia del server nel linguaggio IDL. Che è stato poi compilato da MIDL. Un'opzione disponibile è quella di generare automaticamente il codice dalle dichiarazioni IDL, codice che può essere utilizzato per creare una DLL separata che implementa il proxy e lo stub. IDL è sufficientemente ricco per descrivere i dettagli dei tipi di argomenti della funzione e dell'utilizzo per consentire al marshalling di essere eseguito da questo codice generato automaticamente. A volte gli attributi IDL non sono sufficienti, l'autore COM scrive quindi un marshaller personalizzato. La COM carica la DLL in fase di runtime per creare automaticamente gli oggetti proxy e stub.

  • Specifico per il sottogruppo COM Automation (interfaccia IDispatch), Windows ha un marshaller integrato che sa come effettuare il marshalling delle chiamate che soddisfano i requisiti dei sottoinsiemi. Molto comune. Usa la libreria dei tipi per scoprire la dichiarazione della funzione.

Gli ultimi due proiettili richiedere l'uso HKLM\Software\Classes\Interface, ha voci per l'IID per ogni interfaccia. Ecco come la COM scopre come creare il proxy e lo stub per l'interfaccia. Se non riesce a trovare la chiave, torna a IMarshal. È necessario utilizzare l'elemento comInterfaceExternalProxyStub per sostituire la chiave di registro. L'utilizzo di comInterfaceProxyStub è un caso speciale, ovvero quando il codice proxy e stub è incluso nell'eseguibile del server COM invece di essere un file separato. Un'opzione nei progetti ATL, ad esempio, attivata con la selezione della procedura guidata "Permetti l'unione di proxy/stub".

L'ultimo punto richiede inoltre l'utilizzo dell'elemento typelib, richiesto in modo che il marshaller integrato possa trovare la libreria dei tipi di cui ha bisogno.

Il progID è necessario quando il client COM utilizza l'associazione tardiva tramite IDispatch, la funzione helper di CreateObject() nella libreria di supporto del runtime del client è boilerplate. Ad esempio, utilizzato in qualsiasi host di scripting.

Avere una certa conoscenza interna di come il server COM è stato creato aiuta sicuramente, contattare sempre il fornitore o l'autore per un consiglio. Tuttavia, può essere decodificato osservando quali chiavi del registro vengono scritte quando il server è registrato, lo strumento ProcMon di SysInternals è il modo migliore per vederlo. cose di base da cercare:

  • Se lo vedete scrivere la chiave HKLM\Software\Classes\Interface allora si può supporre che è necessario fornire il comInterface | esterno | elemento ProxyStub

  • Se lo vedi scrivere {00.020.420-0.000 -0000-C000-000000000046} per la chiave ProxyStubClsid32, quindi è possibile assumere che stia utilizzando il marshaller standard e che sia necessario utilizzare l'elemento comInterfaceExternalProxyStub e l'elemento typelib. Dovresti anche vederlo scrivere la chiave di registro TypeLib dell'IID e la voce nella chiave di registro HKLM \ Software \ Classes \ Typelib. Quest'ultimo dà il percorso della libreria dei tipi. Quasi sempre uguale al server COM, l'incorporamento della libreria dei tipi come risorsa è molto comune. Se è separato (un file .tlb), devi distribuirlo.

  • Se il valore della chiave ProxyStubClsid32 è un altro guid, è possibile assumere che utilizzi la propria DLL proxy/stub. Dovresti anche vederlo scrivere la chiave CLSID per il proxy, la sua chiave InProcServer32 ti dà il percorso della DLL. Se il nome del file corrisponde al nome del file del server, allora si può supporre che il codice proxy/stub sia stato unito e che sia invece necessario utilizzare l'elemento comInterfaceProxyStub. Se non è necessario comInterfaceExternalProxyStub, è necessario distribuire la DLL

  • Se si vede scrivere il ProgID in HKLM\Software\Classes quindi utilizzare l'elemento progid, esattamente come mostrato nella traccia.

+0

Incredibile. Grazie. :-) pdm.dll è un caso interessante in quanto esiste una seconda DLL, msdbg2.dll che * sembra * includere ProxyStubs per le interfacce di debug. (msdbg2.dll è, ad esempio, richiesto da Visual Studio per essere in grado di collegarsi a un processo) Tuttavia, il modo in cui usiamo pdm.dll (per eseguire il debug di vbscript) non sembra richiedere i ProxStub da msdbg2.dll, come il nostro codice funziona felicemente senza msdbg2.dll. (Anche se, se registrato, msdbg2.dll verrà caricato tramite pdm.dll - non ha idea di cosa faccia esattamente.) Meh. Questo è tutto un casino. –