2012-03-21 16 views
10

Obecnie staram się uzyskać wolny od rejestracji COM pracujący z programem Excel jako klientem i biblioteką .NET dll jako serwerem. Obecnie staram się po prostu uruchomić proof-of-concept, ale mam problem.RegFree COM działające z C#, NIE działające z VBA

Oczywiście, jak używam Excela, nie mogę po prostu użyć klienta oczywistego życia obok pliku wykonywalnego, więc używam Microsoft.Windows.ActCtx (link)

Mam klienta manifest, montaż oczywisty i dll wszystko w tej samej lokalizacji.

Niestety, to, co działa w języku C#, nie działa w programie Excel/VBA i nie jestem pewien co do przyczyny. Podczas gdy klient testowy C# działa idealnie, VBA daje błąd z komunikatem Metoda "CreateObject" obiektu "IActCtx" nie powiodła się.

Mam dll .NET (COMTestService.dll) wystawienie jednej klasy/interfejsu COM (COMTestObject/ICOMTestObject), jak tutaj:

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

Klient manifest (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> 

manifestu zespół (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> 

VBA kod klienta:

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 

C# Kod klienta:

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

Fabuła się zagęszcza ... Po prostu dla zabawy, napisałem krótki COM-widzialne, ZAREJESTROWANA klasa pomocnika, aby utworzyć obiekt w języku C#, a następnie przekazać go z powrotem, przy użyciu metody wzdłuż linii public object CreateObject(string manifestPath, string typeName) Teraz wywoływanie tego z C# exe działa poprawnie, ale wywoływanie go z VBA nie działa (80070002 ponownie, wiadomość: System nie może odnaleźć określonego pliku.). Teraz jestem jeszcze bardziej zdezorientowany ...

Z góry dziękuję za wszelką pomoc, a jeśli potrzebuję dostarczyć więcej informacji, daj mi znać, a ja z przyjemnością Cię zobowiązam!

+0

Przekazana ścieżka jest niepoprawna, nie można użyć trzech kropek. I zdecydowanie potrzebujesz pełnej ścieżki, nie możesz przewidzieć, jaki będzie bieżący katalog roboczy. –

+0

Przepraszam za pomylenie, to był tylko symbol zastępczy. Ścieżka jest tam w całości i jest poprawna. –

Odpowiedz

0

Nie mogę powiedzieć, że kiedykolwiek próbowałem użyć tej techniki i zrobiłem wiele instalacji na przestrzeni lat. Zastanawiam się, dlaczego nie zarejestrować swojego serwera .NET COM Visible? Regasm ma tendencję do tworzenia bardzo czystej i lekkiej rejestracji COM w rejestrze. Znacznie czystszy niż stary niezarządzany program DllRegisterServer().

+0

Niestety jest to wdrażane bez możliwości uprawnień administratora, więc regresja jest niedostępna w oknie ... –

+0

Projekty InstallShield MSI mają atrybut ".NET COM Visible", który wywołuje RegAsm w czasie kompilacji, aby wyodrębnić dane meta COM. W przypadku instalacji na użytkownika klucze COM są zapisywane w HKCU \ Software \ Classes zamiast w HKLM \ Software \ Classes. Nie widzę, jak rejestracja w stylu RegAsm w stylu COM nie wchodzi w rachubę. –

2

Za pomocą Monitora procesu odkryłem, że biblioteka dll była poszukiwana w C:/Program Files/Microsoft Office/Office11 /. Przeniosłem wszystkie moje biblioteki DLL tam i błąd zniknął.

W sidenote, jeśli ktoś wie, jak powiedzieć programowi Excel, aby nie szukał tam plików, ale zamiast tego, gdzie został znaleziony plik .tlb, jestem zainteresowany. (Próbowałem już dodać ścieżkę do zmiennej środowiskowej PATH)