RegFree COM работает с C#, НЕ работает с VBA
Я в настоящее время пытаюсь получить COM без регистрации, работающий с Excel в качестве клиента и.NET dll в качестве сервера. В настоящее время я просто пытаюсь получить подтверждение концепции, но у меня проблемы.
Очевидно, что, поскольку я использую Excel, я не могу просто использовать манифест клиента, находящийся рядом с исполняемым файлом, поэтому я использую Microsoft.Windows.ActCtx
( ссылка)
У меня есть манифест клиента, манифест сборки и DLL все в том же месте.
К сожалению, то, что работает в C#, похоже, не работает в Excel / VBA, и я озадачен причиной. В то время как тестовый клиент C# работает отлично, VBA выдает ошибку 80070002 с ошибкой метода сообщения "CreateObject" объекта "IActCtx".
У меня есть.NET dll (COMTestService.dll), выставляющий один класс / интерфейс для COM (COMTestObject
/ ICOMTestObject
), как здесь:
[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);
}
}
Манифест клиента (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>
Манифест сборки (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:
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#:
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);
РЕДАКТИРОВАТЬ
Сюжет утолщается... Ради интереса я написал быстрый COM-видимый вспомогательный класс для создания объекта в C#, а затем передал его обратно, используя метод, аналогичный public object CreateObject(string manifestPath, string typeName)
Теперь вызов этого из C# exe работает нормально, но вызвать его из VBA не удается (снова 80070002, сообщение: система не может найти указанный файл.). Теперь я еще больше запутался...
Заранее благодарю за любую помощь, и если мне нужно предоставить больше информации, просто дайте мне знать, и я буду рад обязать вас!
2 ответа
Используя Process Monitor, я обнаружил, что dll ищется в C:/Program Files/Microsoft Office/Office11/. Я перенес все свои библиотеки туда, и ошибка исчезла.
Что касается текста, если кто-нибудь знает, как сказать Excel не искать там мои файлы, а вместо этого, где был найден.tlb, мне интересно. (Я уже пытался добавить путь к переменной окружения PATH)
Я не могу сказать, что когда-либо пытался использовать эту технику, и я сделал много установок за эти годы. Я должен задаться вопросом, почему бы просто не зарегистрировать свой.NET COM Visible сервер? Regasm имеет тенденцию создавать очень чистую и легкую регистрацию COM в реестре. Гораздо чище, чем старые неуправляемые вещи DllRegisterServer().