CoCreateInstance 返回“类未注册”

Posted

技术标签:

【中文标题】CoCreateInstance 返回“类未注册”【英文标题】:CoCreateInstance returns "Class not registered" 【发布时间】:2012-03-19 19:57:20 【问题描述】:

我已经在这玩了好几个小时了,现在开始感到不安。 :(

我有一个在 .NET 4.0 中创建的 COM DLL,我希望能够使用 VC++ 6 中制作的旧版应用程序来访问它。它对 COM 可见,我已经成功创建了 TLB 和 SNK 文件,并移动了它使用旧的 C++ 代码,#imported TLB 到机器上,一切都编译得很好。

运行以下:

RegAsm ProtracFunctions.dll /codebase

gacutil /i ProtracFunctions.dll

他们都成功了。

当我启动我的应用程序时,只要我点击 CoCreateInstance,就会收到消息“类未注册”。

我在 RegEdit 中注意到我的 DLL 似乎已注册。那时我做了一些研究,下载了 ProcMon,并意识到它正在寻找不同的位置。 CLSID 略有不同,如果我尝试修改 RegAsm 给我的 ProtracFunctions.reg 文件(以使用 ProcMon 获取的 GUID),它确实会对 ProcMon 产生影响(更多的“SUCCESS”消息而不是“NAME至少没有找到”消息),但我似乎错过了很多注册表位置。如键“TreatAs”、“InprocServerX86”等

如果有人可以告诉我:

A)首先我做错了什么

B) 当您“注册”一个 COM DLL 时添加的注册表值的确切列表,这样我就可以进入那里并自己手动进行操作。 (不理想,我意识到)。

TIA!

我的代码:

CoInitialize(NULL);
CComQIPtr <ProtracFunctions::IDockingStation> spTestCom;
HRESULT hRes = spTestCom.CoCreateInstance(CLSID_ProtracDCS, 0, CLSCTX_ALL);

if (SUCCEEDED (hRes))

    printf("Created the instance");

    unsigned char Ret;
    unsigned char ErrCode;
    SAFEARRAY *pSA;

    spTestCom->DockConnect(3, 19200, &Ret);
    spTestCom->GetTagReads(1, &ErrCode, &pSA); 

    spTestCom->PowerOffReader(1, &Ret);
    spTestCom->DockDisconnect();

    spTestCom.Release ();

else

   _com_error error(hRes);
   LPCTSTR errorText = error.ErrorMessage();

   AfxMessageBox(errorText);

   //automatic cleanup when error goes out of scope

添加注释:

开发机器运行 Win XP 32 位,而带有旧版应用程序的“机器”实际上是开发计算机上的虚拟机,也运行 XP。

另外,当我运行我的应用程序并选择触发上述代码的测试菜单项时,我第一次收到错误“未注册类”,如果我再次单击它,我会看到:“不支持这样的接口”......很奇怪。

【问题讨论】:

您是在 64 位操作系统上运行它吗?如果是这样,那么当您注册在 .NET 4 中创建的 COM 程序集时,它将在 System32 中,但 VC++ 6 将在 SysWOW64 中寻找它,注册表也是如此。尝试构建为 x86 并使用位于 SysWOW64 文件夹中的 regsvr32.exe 进行注册。 您使用的是 64 位计算机吗?也许this 会帮助你。 32 位,不幸的是。 您是否为该类指定了 Guid 属性?例如:[Guid("00001111-2222-3333-4444-555566667777"), ComVisible(true)] public class ProtracDCS 是的,我的 C# 类看起来像:[Guid("DA8FA26B-D07F-40D0-ACB2-40B6665F1A11"), ComVisible(true), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IDockingStation) )] 公共类 DockingStation : IDockingStation 【参考方案1】:

我认为您需要在程序集中嵌入清单。 请参阅此网址。 http://blogs.msdn.com/b/cheller/archive/2006/08/24/718757.aspx

您也可以使其工作,而无需使用此代码注册程序集 (Regasm.exe)。


    DWORD cookie;
    ACTCTX actctx = sizeof(actctx);
    actctx.lpSource = L"YOUR ASSEMBLY FULL PATH";
    actctx.lpResourceName = MAKEINTRESOURCE(1); //MAYBE 2 FOR DLL
    actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;   
    HANDLE hActCtx = CreateActCtx(&actctx);
    BOOL fOK = ActivateActCtx(hActCtx, &cookie);
    if (!fOK)
        return E_FAIL;

    CComPtr<CSharpComInterface::ITestCSharpInterface> spCSharpTest;
    HRESULT hr = spCSharpTest.CoCreateInstance(__uuidof(CSharpComInterface::CoClass));

    if (hr != S_OK)
    
        cout << "Failed to create instance CSharpComInterface::CoClass" <<endl;
    
    else
    
        cout << "Load Successfully : CSharpComInterface::CoClass" << endl;
        spCSharpTest->TestMethod();
    

    DeactivateActCtx(0, cookie);
    ReleaseActCtx(hActCtx);

【讨论】:

【参考方案2】:

MSDN 中的 entry on Regasm.exe 表示,如果您的程序集在 GAC 中,则不应使用 /codebase 选项。

【讨论】:

我在将 /codebase 开关添加到 GAC 后尝试了它,但发现它仍然无法正常工作(97% 肯定按此顺序,但如果我错了,它会导致“课程未注册”消息?)

以上是关于CoCreateInstance 返回“类未注册”的主要内容,如果未能解决你的问题,请参考以下文章

VBA Selenium“类未注册”- 80040154

类未注册错误

Metro Style App MFT“类未注册”错误

即使找到接口,CoCreateInstance 也会返回 E_NOINTERFACE

类未注册 sql server management studio

COM 异常:尝试创建 ADOX.Catalog 时出现“类未注册”