2011-04-14 18 views
9

Nel mio programma creo oggetti COM + dynamicly (associazione tardiva) utilizzandoCom + tardiva C# 4.0

Type comObjectType = Type.GetTypeFromProgID(progId, true); 
object comObject = Activator.CreateInstance(comObjectType); 

e quindi chiamare uno dei metodi utilizzando la riflessione

object result = comObjectType.InvokeMember(MethodToActivate, BindingFlags.InvokeMethod, null, comObjec, new object[] {....}); 

Funziona greate in .Net 1,1/2,0/3,5

Ora sto cercando di eseguire lo stesso codicesulla stessa macchina (Windows XP) compilato per .Net 4.0, ma ho un

Exception: Method 'System.__ComObject.{MethodName}' not found. 

Ho l'eccezione per la maggior parte degli oggetti Com + (non per tutti). Qualcuno sa qual è il problema? Perché ottengo l'eccezione nell'ambiente FW 4.0? Cosa devo fare per evitarlo?

Grazie mille, Daniel

Dopo un po 'di più indagini ho scoperto che alcuni dei COM + proxy vengono creati come System._ComObject (questi sono quelli nativi, suppongo), e alcuni sono creati come System.Runtime.Remoting.Proxies._TransparentProxy (I pensa che quelli siano. Com + oggetti). L'invocazione del metodo funziona correttamente per quelli creati come System._ComObject e non funziona per System.Runtime.Remoting.Proxies._TransparentProxy. Il fatto più interessante è che in .Net 2.0 tutti gli oggetti sono creati allo stesso modo (_ComObject e _TransparentProxy) ma l'invocazione del metodo funziona correttamente. Un altro fatto interessante è che posso vedere il metodo "mancante" nel debugger utilizzando reflecton

((System.EnterpriseServices.RemoteServicedComponentProxy)((((System.Runtime.Remoting.Proxies.__TransparentProxy)(ObjectToActivate)))._rp)).ProxiedType.GetMethods()

ho pensato per qualche momento che potrebbe essere un problema di sicurezza, ma eseguire il codice come servizio di windows connesso come utente con privilegi di amministratore

+0

Hai controllato qualche problema 32/64-bit? Forse il tuo processo è a 64-bit e quindi il registro COM a 64-bit (dove nessuno vive :-)? –

+0

Non penso che sia un problema 32/34-bit, la mia macchina locale è a 32 bit, quindi è il server remoto –

+0

ok per 32/64-bit. Ora, sembra che il tuo server COM non sia in-process o abbia uno specifico modello di threading (da qui i proxy). Puoi dare maggiori dettagli su questo? sono ospitati fuori processo? Nei servizi componenti? E che dire degli argomenti Invoke? sei sicuro che non ci siano ambiguità? Che mi dici di BindingFlags? non hai bisogno di Public | Instance? –

risposta

6

Ho scoperto che esiste una differenza tra .NET FW nella creazione del tipo COM e, per quanto ne so, la differenza esiste solo per gli oggetti COM .NET. Quando il tipo di oggetto COM viene creato con

Type comObjectType = Type.GetTypeFromProgID(progId, true); 

il tipo che viene restituito in .NET 1.1/2.0/3.5 è il tipo .NET effettivo dell'oggetto, quindi non c'è nessun problema nel metodo la sua invocazione, ma in NET 4.0 del tipo System.__ComObject viene restituito in modo che il codice di

result = comObjectType.InvokeMember(
    MethodToActivate, BindingFlags.InvokeMethod, null, ObjectToActivate, InputParams); 

fallisce con un metodo non trovato eccezione.

La soluzione che ho trovato è il seguente:

Type comObjectType = Type.GetTypeFromProgID(progId, true);   
object comObject = Activator.CreateInstance(comObjectType); 

// here the real object type is returned 
Type acctualObjectType = comObject.GetType(); 
result = acctualObjectType.InvokeMember(
    "MethodToActivate", BindingFlags.InvokeMethod, null, comObject, InputParams); 

Questo codice funziona bene per tutti gli ambienti.

+0

Interessante - In realtà ho postato una risposta precedente che sospetto avrebbe aiutato cancellandola ironicamente dopo aver letto un'altra domanda che mi ha convinto In ogni caso, sono felice di aver risolto il problema – Justin

+0

Nel tuo codice soluzione, 'comObject' dovrebbe essere uguale a' ObjectToActivate'? –

+0

Sì, ObjectToActivate è una proprietà che restituisce comObject. –

1

Non sono sicuro del motivo per cui il codice in esecuzione non funziona più, tuttavia credo che in .Net 4.0 sia possibile chiamare i metodi COM utilizzando IDispatch/late binding tramite il tipo dynamic - vedere Does C# .NET support IDispatch late binding?.

+0

Ho pensato a questo tipo di soluzione, ma non è accettabile per me, perché ho bisogno dello stesso codice per tutte le versioni .Net FW. Fa parte di una libreria principale le esecuzioni in diversi ambienti –

+0

@Daniel: Indipendentemente dal fatto che sia soddisfacente, l'uso di 'dynamic' mostra ancora l'errore? – Gabe

+0

Ho provato un po 'di esempio con la' dinamica ', funziona (ma non è utile per me (:) –

Problemi correlati