2012-03-21 13 views
10

Sto cercando di ottenere la COM senza registrazione che funziona con Excel come client e una DLL .NET come server. Attualmente sto semplicemente cercando di ottenere un proof-of-concept funzionante ma sto avendo problemi.COM RegFree che funziona da C#, NON funziona da VBA

Ovviamente, come sto usando Excel, non posso semplicemente utilizzare un soggiorno manifesta cliente a fianco l'eseguibile, quindi sto usando Microsoft.Windows.ActCtx (link)

ho il cliente manifesta, assemblaggio manifesti, e dll tutto nella stessa posizione.

Sfortunatamente, ciò che funziona in C# non sembra funzionare in Excel/VBA e sono perplesso sul motivo. Mentre il client di test C# funziona perfettamente, VBA fornisce un errore , con il messaggio Metodo 'CreateObject' dell'oggetto "IActCtx" non riuscito.

ho una dll .NET (COMTestService.dll) esponendo una singola classe/interfaccia COM (COMTestObject/ICOMTestObject), come in questo caso:

[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
[Guid("EEE50CDF-D8EC-4F38-B986-C231EC45171E")] 
public interface ICOMTestObject 
{ 
    [ComVisible(true)] 
    string GetString(int number); 
} 

[ComVisible(true), ClassInterfaceAttribute(ClassInterfaceType.None), ComDefaultInterface(typeof(ICOMTestObject))] 
[Guid("6E54611B-8B56-49E0-9415-E59B0774A4BE")] 
public class COMTestObject : ICOMTestObject 
{ 
    public COMTestObject() 
    { 
    } 

    public string GetString(int number) 
    { 
     return string.Format("The number is: {0}", number); 
    } 
} 

Il cliente manifesta (COMTestService_Client.manifest):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly 
    manifestVersion="1.0" 
    xmlns="urn:schemas-microsoft-com:asm.v1" > 
    <assemblyIdentity 
     name="client" 
     version="1.0.0.0" /> 
    <dependency> 
     <dependentAssembly> 
      <assemblyIdentity 
       name="COMTestService" 
       version="1.0.0.0" 
       processorArchitecture="msil" /> 
     </dependentAssembly> 
    </dependency> 
</assembly> 

Il manifesto di montaggio (COMTestService.manifest):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly 
    manifestVersion="1.0" 
    xmlns="urn:schemas-microsoft-com:asm.v1" > 
    <assemblyIdentity 
     name="COMTestService" 
     version="1.0.0.0" 
     processorArchitecture="msil" /> 
    <clrClass 
     clsid="{6E54611B-8B56-49E0-9415-E59B0774A4BE}" 
     progid="COMTestService.COMTestObject" 
     threadingModel="Both" 
     name="COMTestService.COMTestObject" 
     runtimeVersion="v4.0.30319"> 
    </clrClass> 
    <file 
     name="COMTestService.dll" 
     hashalg="SHA1">   
    </file> 
</assembly> 

Il codice client VBA:

Dim actCtx As Object 
Set actCtx = CreateObject("Microsoft.Windows.ActCtx") 
actCtx.Manifest = "...\COMTestService_Client.manifest" 

Dim testObject As Object 
Set testObject = actCtx.CreateObject("COMTestService.COMTestObject") 'This line throws... 

Dim text As String 
text = thing.GetString(42) 

Debug.Print text 

Il codice C# client:

var actCtxType = System.Type.GetTypeFromProgID("Microsoft.Windows.ActCtx"); 
dynamic actCtx = System.Activator.CreateInstance(actCtxType); 
actCtx.Manifest = @"...\COMTestService_Client.manifest"; 

var type = System.Type.GetTypeFromProgID("COMTestService.COMTestObject"); 
dynamic obj = System.Activator.CreateInstance(type); 
dynamic s = obj.GetString(42); 

EDIT

La trama si infittisce ... Solo per divertimento, ho scritto un rapido COM-visibile, Classe helper registrata per eseguire la creazione dell'oggetto in C#, quindi passarla indietro, utilizzando un metodo lungo le righe di public object CreateObject(string manifestPath, string typeName) Ora, chiamare questo da un exe C# funziona correttamente, ma la chiamata da VBA non riesce (80070002 di nuovo, messaggio: Il sistema non riesce a trovare il file specificato.). Ora sono ancora più confuso ...

Grazie in anticipo per qualsiasi aiuto, e se ho bisogno di fornire ulteriori informazioni fammelo sapere e sarò lieto di rendere omaggio!

+0

Il percorso Manifesto che si supera non è valido, non è possibile utilizzare tre punti. E hai sicuramente bisogno di un percorso completo, non puoi prevedere quale sarà la directory di lavoro corrente. –

+0

Mi dispiace confondere, era solo un segnaposto. Il percorso è lì per intero, ed è corretto. –

risposta

0

Non posso dire di aver mai provato a utilizzare questa tecnica e ho fatto molte installazioni nel corso degli anni. Devo chiedermi, perché non registrare solo il tuo server .NET COM Visible? Regasm tende a creare una registrazione COM molto pulita e leggera nel registro. Molto più pulito quindi il vecchio DllRegisterServer() non gestito.

+0

Purtroppo questo viene distribuito senza la possibilità di diritti di amministratore, quindi il regasmo è fuori dalla finestra ... –

+0

I progetti InstallShield MSI hanno un attributo "COM visibile COM" che richiama RegAsm al momento della compilazione per estrarre i meta dati COM. Nel caso di un'installazione per utente, le chiavi COM vengono scritte in HKCU \ Software \ Classes anziché in HKLM \ Software \ Classes. Non vedo come la registrazione COM in stile RegAsm sia fuori questione. –

2

Utilizzando Process Monitor, ho scoperto che la dll era stata cercata in C:/Programmi/Microsoft Office/Office11 /. Ho spostato tutte le mie DLL sopra e l'errore era sparito.

Su un sidenote, se qualcuno sa come dire a Excel di non cercare i miei file ma invece dove è stato trovato .tlb, sono interessato. (Ho già provato ad aggiungere il percorso alla variabile d'ambiente PATH)