2012-03-21 35 views
10

Actualmente estoy tratando de obtener un COM libre de registro que trabaje con Excel como cliente y un .NET dll como servidor. Actualmente estoy tratando de hacer funcionar una prueba de concepto pero estoy teniendo problemas.RegFree COM trabajando desde C#, NO trabajando desde VBA

Obviamente, como estoy usando Excel, no puedo simplemente usar la vida manifiesta cliente junto con el ejecutable, por lo que estoy usando Microsoft.Windows.ActCtx (link)

hago que el cliente manifiesta, manifiesto del ensamblado, y DLL todos en el mismo lugar

Desafortunadamente, lo que funciona en C# no parece funcionar en Excel/VBA y no estoy seguro del motivo. Mientras que el cliente de prueba C# funciona perfectamente, VBA da un error , con el mensaje El método 'CreateObject' del objeto 'IActCtx' falló.

Tengo una DLL .NET (COMTestService.dll) la exposición de una sola clase/interfaz de COM (COMTestObject/ICOMTestObject), como en este 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); 
    } 
} 

El cliente manifiesta (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> 

El manifiesto de ensamblado (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> 

El código de cliente 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 

El código C# cliente:

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); 

EDITAR

La trama se complica ... Sólo por diversión, me escribió una rápida COM-visible, Clase de ayudante REGISTRADO para hacer la creación de objetos en C#, luego pasarla de nuevo, usando un método como public object CreateObject(string manifestPath, string typeName) Ahora, llamar a esto desde un C# exe funciona bien, pero llamarlo desde VBA falla (80070002 otra vez, mensaje: El sistema no puede encontrar el archivo especificado.). Ahora estoy aún más confundido ...

Gracias de antemano por cualquier ayuda, y si necesito proporcionar más información solo házmelo saber y estaré encantado de complacerlo!

+0

La ruta de manifiesto que pasa no es válida, no puede usar tres puntos. Y definitivamente necesita una ruta completa, no puede predecir cuál será el directorio de trabajo actual. –

+0

Perdón por confundir, eso era solo un marcador de posición. El camino está ahí completo, y es correcto. –

Respuesta

0

No puedo decir que alguna vez haya intentado usar esa técnica y he hecho muchas instalaciones a lo largo de los años. Tengo que preguntarme, ¿por qué no simplemente registrar su servidor .NET COM Visible? Regasm tiende a crear un registro COM muy limpio y ligero en el registro. Mucho más limpio que el viejo DllRegisterServer() no gestionado.

+0

Lamentablemente, esto se implementa sin la posibilidad de derechos de administrador, por lo que regasm está fuera de la ventana ... –

+0

Los proyectos de InstallShield MSI tienen un atributo ".NET COM Visible" que invoca RegAsm en tiempo de compilación para extraer los metadatos COM. En el caso de una instalación por usuario, las claves COM se escriben en HKCU \ Software \ Classes en lugar de HKLM \ Software \ Classes. No veo cómo el registro COM de estilo RegAsm está fuera de discusión. –

2

Utilizando Process Monitor, descubrí que se estaba buscando la dll en C:/Archivos de programa/Microsoft Office/Office11 /. Moví todos mis dlls allí y el error desapareció.

En una nota al margen, si alguien sabe cómo decirle a Excel que no busque mis archivos, pero en su lugar donde se encontró .tlb, estoy interesado. (Ya intenté agregar la ruta a la variable de entorno PATH)

Cuestiones relacionadas