RegFree COM работает с C #, НЕ работает с VBA

Я сейчас пытаюсь заставить COM без регистрации работать с Excel в качестве клиента и .NET dll в качестве сервера. В настоящее время я просто пытаюсь заставить работать доказательство концепции, но у меня проблемы.

Очевидно, что, поскольку я использую Excel, я не могу просто использовать клиентский манифест, расположенный рядом с исполняемым файлом, поэтому я использую Microsoft.Windows.ActCtx (ссылка)

У меня есть манифест клиента, манифест сборки и dll в одном месте.

К сожалению, то, что работает в C #, не работает в Excel / VBA, и я не понимаю, в чем причина. Хотя тестовый клиент C # работает отлично, VBA выдает ошибку 80070002 с сообщением Method 'CreateObject' объекта 'IActCtx' failed.

У меня есть .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) Now, вызывая это из C # exe. работает нормально, но вызов из VBA завершается ошибкой (снова 80070002, сообщение: Система не может найти указанный файл.). Теперь я еще больше запуталась ...

Заранее благодарим за любую помощь, и если мне нужно предоставить дополнительную информацию, просто дайте мне знать, и я буду рад помочь!


person Simon Cowen    schedule 21.03.2012    source источник
comment
Путь манифеста, который вы передаете, недействителен, нельзя использовать три точки. И вам обязательно нужен полный путь, вы не можете предсказать, какой будет текущий рабочий каталог.   -  person Hans Passant    schedule 21.03.2012
comment
Извините за путаницу, это просто заполнитель. Путь там полностью, и он правильный.   -  person Simon Cowen    schedule 21.03.2012


Ответы (2)


Используя Process Monitor, я обнаружил, что dll ищется в C: / Program Files / Microsoft Office / Office11 /. Я переместил туда все свои библиотеки, и ошибка исчезла.

Кстати, если кто-нибудь знает, как сказать Excel, чтобы он не искал мои файлы там, а где был найден .tlb, меня это интересует. (Я уже пробовал добавить путь к переменной окружения PATH)

person sean.net    schedule 19.02.2013

Не могу сказать, что когда-либо пробовал использовать эту технику, и за эти годы я сделал много установок. Я должен задаться вопросом, почему бы просто не зарегистрировать свой .NET COM Visible сервер? Regasm имеет тенденцию создавать очень чистую и легкую регистрацию COM в реестре. Намного чище, чем старый неуправляемый материал DllRegisterServer ().

person Christopher Painter    schedule 26.03.2012
comment
К сожалению, это развертывается без прав администратора, так что регазм не подходит ... - person Simon Cowen; 27.03.2012
comment
У проектов InstallShield MSI есть атрибут .NET COM Visible, который вызывает RegAsm во время сборки для извлечения метаданных COM. В случае установки на одного пользователя ключи COM записываются в HKCU \ Software \ Classes вместо HKLM \ Software \ Classes. Я не понимаю, почему о регистрации COM в стиле RegAsm не может быть и речи. - person Christopher Painter; 27.03.2012