托管的无Reg COM服务器将无法激活

时间:2015-11-25 21:31:30

标签: c# c++ com vb6 regfreecom

我从一个非常复杂的客户端和服务器系统开始使用COM引用和其他东西,我一直在减少直到我意识到我甚至无法获得Microsoft示例代码来免费注册COM激活用C#编写的托管COM服务器。

服务器代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace ClassLibrary1
{
   [Guid("A7AC6D8C-FF17-4D2C-A3B1-2C8690A8EA04")
   ,ComVisible(true)]
   public interface IClass1
   {
      [DispId(1)]
      string DummyFunction(string inputValue);
   }

   [Guid("81723475-B5E3-4FA0-A3FE-6DE66CEE211C"),
   ClassInterface(ClassInterfaceType.None),
   ComDefaultInterface(typeof(IClass1)),
   ComVisible(true)]
   public class Class1 : IClass1
   {
      public string DummyFunction(string inputValue)
      {
         return inputValue.Substring(0, 1) + " Inserted " + inputValue.Substring(1);
      }
   }
}

客户端VB6代码:

Dim c As ClassLibrary1.Class1
Set c = New Class1
MsgBox c.DummyFunction("Ben")

客户端C ++代码:

#include "stdafx.h"

#import <ClassLibrary1.tlb> raw_interfaces_only

using namespace ClassLibrary1;

int _tmain(int argc, _TCHAR* argv[])
{
   IClass1Ptr p;

   HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
   hr = CoCreateInstance(__uuidof(Class1), NULL, CLSCTX_INPROC_SERVER, __uuidof(IClass1), (void **)&p);
   if (FAILED(hr))
   {
      _tprintf_s(_T("Error %x\n"), hr);
      CoUninitialize();
      return 1;
   }
   _bstr_t b = _T("Bobby");
   BSTR b2;
   p->DummyFunction(b, &b2);
   wprintf_s(L"%s\n", b2);
   p->Release();
   CoUninitialize();
    return 0;
}

当我删除所有Reg-Free COM代码并使用regasm / codebase注册ClassLibrary1.dll时,两个客户端都正常工作。

然后我取消注册ClassLibrary1,并尝试使用文件Project1.exe.manifest为VB6客户端引入Reg-Free COM:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <assemblyIdentity type="win32" name="Project1" version="1.0.0.0" />
   <dependency>
   <dependentAssembly>
   <assemblyIdentity name="ClassLibrary1" version="1.0.0.0" />
   </dependentAssembly>
   </dependency>
</assembly>

和ClassLibrary1.manifest:

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
   <assemblyIdentity version="1.0.0.0" name="ClassLibrary1" />
   <clrClass clsid="{81723475-B5E3-4FA0-A3FE-6DE66CEE211C}" name="ClassLibrary1.Class1" tlbid="{F8A2D334-5BBB-4007-8308-A1417052E6D6}"></clrClass>
   <file name="ClassLibrary1.dll" ></file>
</assembly>

现在我有时会得到错误429(ActiveX组件无法创建对象),并且(莫名其妙地)有时会出现自动化错误:

  

运行时错误'-2146234304(80131040)':   自动化错误

然后我尝试将COM Isolation引入C ++客户端: Isolated COM Type Library=F:\Lib\ClassLibrary1.tlb - Component File Name=ClassLibrary1.dll

现在,当我运行C ++客户端时,输出只是

  

错误800401f9

1 个答案:

答案 0 :(得分:1)

令我感到沮丧的是,BlueMonkMN的解释非常有用,但我遇到了Class not registered消息。

我有一个.NET 4.6 COM互操作Dll和一个C ++客户端,它通过Windows SxS技术使用免注册COM。程序集清单嵌入在COM Dll中,应用程序清单放在外面,作为单独的.manifest文件。

所有内容都按宣传的方式运行,但在Class not registered期间发生CreateInstance消息时,会发生以下任何一种情况。

  • 复制互操作COM Dll以及C ++客户端可执行文件和 清单文件到其他目录。
  • 对C ++客户端进行非COM相关的更改,然后重建 应用

在这种情况下,为了加重伤害,sxstrace日志为空,应用程序事件日志(eventvwr)没有报告任何SideBySide错误和程序集绑定日志查看器({{ 1}})没有显示C ++客户端应用程序中的任何内容。

让我在BlueMonkMN的回答中添加另一个附录。

附录6

我从目前为止的实验中了解到,在这种情况下,C ++客户端应用程序的激活上下文未被创建。

在这种情况下,需要自己创建激活上下文。

在调用FUSLOGVW.exe之后和拨打CoInitialize(0);之前,将以下代码放入C ++客户端应用程序中。

CreateInstance

作为一种清理措施,在调用ACTCTX context; memset(&context, 0, sizeof(context)); context.cbSize = sizeof(context); context.lpSource = L"CPPClient.exe.manifest"; context.lpAssemblyDirectory = L"D:\\code\\vs2017\\CPPClient\\Debug"; context.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID; HANDLE hActCtx = CreateActCtx(&context); ULONG_PTR cookie = 0; BOOL result = ActivateActCtx(hActCtx, &cookie); //Rest of the code goes here.

之前放入以下代码
CoUninitialize();

现在听起来不错。 Side by Side工作得非常好。如果出现任何问题,可以在sxstrace或应用程序事件日志或程序集绑定日志查看器中看到它。