CoCreateInstance返回“类未注册”

7

我已经做了几个小时了,现在开始感到沮丧。

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

运行以下内容:

RegAsm ProtracFunctions.dll /codebase

gacutil /i ProtracFunctions.dll

它们都是成功的。

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

我在RegEdit中注意到我的DLL似乎已经注册了。这时我进行了一些研究,下载了ProcMon,并意识到它正在查看不同的位置。 CLSID略有不同,如果我尝试修改ProtracFunctions.reg文件(使用ProcMon捕获的GUID),RegAsm会给我,它确实会影响ProcMon(至少更多的"SUCCESS"消息而不是"NAME NOT FOUND"消息),但似乎我错过了大量的注册表位置,例如键"TreatAs"、"InprocServerX86"等。

如果有人可以告诉我:

A)我一开始做错了什么

或者

B)当您“注册”COM DLL时添加了哪些注册表值的列表,这样我就可以进去手动执行它(我意识到这并不理想)。

感谢您!

我的代码:

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进行注册。 - Adam Gritt
你的机器是64位的吗?也许这个链接能帮到你。 - Joost Sannen
全面采用32位,不幸的是。 - kogh
是的,我的C#类看起来像这样: [Guid("DA8FA26B-D07F-40D0-ACB2-40B6665F1A11"), ComVisible(true), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IDockingStation))] public class DockingStation : IDockingStation - kogh
如果您在注册表(regedit)中搜索,是否可以在注册表中找到您的IID和CLSID? - TCS
显示剩余2条评论
2个回答

3
我认为你需要在你的程序集中嵌入一个清单。 请查看此链接: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);
}

1

MSDN上Regasm.exe的文章指出,如果您的程序集在GAC中,则不应使用/codebase选项。


1
我在将/codebase开关添加到GAC后尝试了它,但仍然无法正常工作(我有97%的把握是按照这个顺序,但如果我错了,会导致“类未注册”的消息吗?) - kogh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接