如何编辑COM库以提供方法访问

时间:2014-04-03 14:20:48

标签: c++ com interop

在我们的头文件中,我们有GroupInitEditInitprotected的类定义。我希望能够通过从C#解决方案添加对生成的GrpSvr.tlb文件的引用来访问这些方法,因此我将这些更改为公共...

#if !defined(AFX_GRPCALL_H__FFB54BC3_B15E_11D1_99BC_0000E803C444__INCLUDED_)
#define AFX_GRPCALL_H__FFB54BC3_B15E_11D1_99BC_0000E803C444__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif
class CGrpCall : public CCmdTarget
{
    DECLARE_DYNCREATE(CGrpCall)
    CGrpCall(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
    public:
    virtual void OnFinalRelease();
    DECLARE_MESSAGE_MAP()
    DECLARE_OLECREATE(CGrpCall)
    afx_msg BSTR GroupInit(LPCTSTR bstrIniFile, BOOL bDiagErr, BOOL bProcErr);
    afx_msg BSTR EditInit(LPCTSTR bstrIniFile);
    DECLARE_DISPATCH_MAP()
    DECLARE_INTERFACE_MAP()
   // Implementation
protected:
   virtual ~CGrpCall();
};
#endif // !defined(AFX_GRPCALL_H__FFB54BC3_B15E_11D1_99BC_0000E803C444__INCLUDED_)

GrpSvr.cpp代码是

IMPLEMENT_DYNCREATE(CGrpCall, CCmdTarget)
CGrpCall::CGrpCall() {
    EnableAutomation();
    AfxOleLockApp();
    Initialize(FALSE);
}

CGrpCall::~CGrpCall() {
    AfxOleUnlockApp();
    GroupTerm();
}

void CGrpCall::OnFinalRelease() {
    CCmdTarget::OnFinalRelease();
}

BEGIN_MESSAGE_MAP(CGrpCall, CCmdTarget)
END_MESSAGE_MAP()

BEGIN_DISPATCH_MAP(CGrpCall, CCmdTarget)
    DISP_FUNCTION(CGrpCall, "GroupInit", GroupInit, VT_BSTR, VTS_BSTR VTS_BOOL VTS_BOOL)
    DISP_FUNCTION(CGrpCall, "EditInit", EditInit, VT_BSTR, VTS_BSTR)
END_DISPATCH_MAP()

static const IID IID_IGrpCall =
{ 0xffb54bc2, 0xb15e, 0x11d1, { 0x99, 0xbc, 0x0, 0x0, 0xe8, 0x3, 0xc4, 0x44 } };

BEGIN_INTERFACE_MAP(CGrpCall, CCmdTarget)
    INTERFACE_PART(CGrpCall, IID_IGrpCall, Dispatch)
END_INTERFACE_MAP()

IMPLEMENT_OLECREATE(CGrpCall, "GrpSvr.GrpCall", 0xffb54bc2, 0xb15e, 0x11d1, 
   0x99, 0xbc, 0x0, 0x0, 0xe8, 0x3, 0xc4, 0x44)

BSTR CGrpCall::GroupInit(LPCTSTR bstrIniFile, BOOL bDiagErr, BOOL bProcErr) { /* Some Code */ }
BSTR CGrpCall::EditInit(LPCTSTR bstrIniFile) { /* Some Code */ }

我现在可以通过在C#中添加引用并执行

来查看这些方法
GrpSvr.GrpCall g = new GrpSvr.GrpCall();
g.GroupInit(this.strCommandFilePath, true, true);

然而,这是给予

  

未处理的类型' System.Runtime.InteropServices.COMException'发生在mscorlib.dll中。 ......班级未注册......

为了能够直接调用这些方法,我该怎么办?

感谢您的时间。


编辑。在评论后我打开OLEView中的.tlb文件,得到以下输出

// Generated .IDL file (by the OLE/COM Object Viewer)
// 
// typelib filename: GrpSvr.tlb

[
  uuid(FFB54BB5-B15E-11D1-99BC-0000E803C444),
  version(1.0),
  custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 134218331),
  custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1396349854),
  custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, "Created by MIDL version 8.00.0603 at Tue Apr 01 11:57:34 2014
")

]
library GrpSvr
{
    // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    dispinterface IGrpCall;

    [
      uuid(FFB54BC2-B15E-11D1-99BC-0000E803C444)
    ]
    dispinterface IGrpCall {
        properties:
        methods:
            [id(0x00000001)]
            BSTR GroupInit(
                            BSTR bstrIniFile, 
                            VARIANT_BOOL bDiagErr, 
                            VARIANT_BOOL bProcErr);
            [id(0x00000002)]
            BSTR EditInit(BSTR bstrIniFile);
            [id(0x00000003)]
            BSTR GroupTerm();
            [id(0x00000004)]
            BSTR GetVars(
                            short* sNumInp, 
                            short* sLastOP, 
                            short* sLenDiag, 
                            short* sLenProc, 
                            short* sNumDiag, 
                            short* sNumProc, 
                            BSTR* bstrInpFile, 
                            BSTR* bstrOutFile, 
                            BSTR* bstrDbFile);
            [id(0x00000005)]
            BSTR GetFldDets(
                            short sIndex, 
                            BSTR* bstrFldName, 
                            short* sNumFld, 
                            short* sFldNum, 
                            short* sFldLen, 
                            short* sFldType, 
                            short* sFldPos);
            [id(0x00000006)]
            long SetVersionDate(BSTR bstrDate);
            [id(0x00000007)]
            BSTR GetLabel(
                            short sFldNum, 
                            BSTR bstrCode);
            [id(0x00000008)]
            BSTR BatchProcess(long* lNRecs);
            [id(0x00000009)]
            BSTR FldEdit(
                            short sFld, 
                            BSTR bstrVal);
            [id(0x0000000a)]
            BSTR GroupRecord(BSTR bstrRec);
            [id(0x0000000b)]
            BSTR GetReport();
            [id(0x0000000c)]
            BSTR GetFldVal(
                            short sFld, 
                            long sOcc, 
                            BSTR* bstrVal);
            [id(0x0000000d)]
            BSTR EditRec(BSTR bstrRec);
            [id(0x0000000e)]
            BSTR MakeRec(
                            short sFld, 
                            short sOcc, 
                            BSTR bstrVal);
            [id(0x0000000f)]
            BSTR GetRecord();
            [id(0x00000010)]
            BSTR GetCount(long* lRecs);
            [id(0x00000011)]
            BSTR WriteReport();
            [id(0x00000012)]
            BSTR Test(VARIANT_BOOL bTest);
            [id(0x00000013)]
            BSTR GetFldVal2(
                            short sFld, 
                            short sOcc);
    };

    [
      uuid(FFB54BC4-B15E-11D1-99BC-0000E803C444)
    ]
    coclass GrpCall {
        [default] dispinterface IGrpCall;
    };
};

1 个答案:

答案 0 :(得分:1)

由于这是一个MFC项目,因此必须在类声明/实现中提供DECLARE_OLETYPELIB / IMPLEMENT_OLETYPELIB。正确注册类型库需要一些其他步骤:

TN065: Dual-Interface Support for OLE Automation Servers

我建议使用 OleView 工具进行故障排除。在树中找到您的"GrpSvr.GrpCall"对象,右键单击它并尝试从那里创建。检查相应的注册表项是否指向正确的.DLL(和.TLB,如果单独注册)。