.net - 在 .Net 中实现 MSSCCI 提供程序

标签 .net msscci

我想实现一个 MSSCCI 提供程序,但是如果可能的话,我想在 .Net 中实现它(所以我的 MSSCCI 提供程序实际上是 .Net 实现的一个薄包装器)

  • 这可能吗?
  • 这是个好主意吗?

我知道在 .Net 中实现它意味着任何使用我的 MSSCCI 提供程序的人都将被迫在其进程内托管 .Net 框架 - 这是一个不合理的请求吗?如果我要在 .Net 中实现它,我还需要考虑哪些其他限制?

最佳答案

这是可能的,而且相对容易。我前段时间开发了一个,效果很好。我使用了从C++C#的COM互操作性。

因此,您将创建两个 dll。 C++ 只是一个包装器,它实现 API,将调用传递给 C# 中的 COM。 C# 组件必须使用 regasm/codebase mycomlibrary.dll 注册为 COM 组件

以下是一些实现指南。在代码示例中,我仅实现 SccInitialize 函数作为示例。希望对您有所帮助。

这是C++组件:

#include <comutil.h>

/**********************************************************************************************************/
// Imports the COM object that implements the SCC API in .NET
/**********************************************************************************************************/
#import "SccCOMServer.tlb" no_namespace named_guids

static int s_nInitializedCount = 0;

/**********************************************************************************************************/
// Starting point of the dll
/**********************************************************************************************************/
BOOL APIENTRY DllMain( 
                      HANDLE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved
                      )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

/**********************************************************************************************************/
// Variable with a instance of the COM object
/**********************************************************************************************************/

ISccCOMServer *mCpi = NULL;


/**********************************************************************************************************/
// Utility functions
/**********************************************************************************************************/

void BSTR2T(BSTR s1, LPSTR s2)
{
    _bstr_t s(s1, false);
    strcpy(s2, s);
}

char* ConvertBSTRToLPSTR (BSTR bstrIn)
{
    LPSTR pszOut = NULL;
    if (bstrIn != NULL)
    {
        int nInputStrLen = SysStringLen (bstrIn);

        // Double NULL Termination
        int nOutputStrLen = WideCharToMultiByte(CP_ACP, 0, bstrIn, nInputStrLen, NULL, 0, 0, 0) + 2; 
        pszOut = new char [nOutputStrLen];

        if (pszOut)
        {
            memset (pszOut, 0x00, sizeof (char)*nOutputStrLen);
            WideCharToMultiByte (CP_ACP, 0, bstrIn, nInputStrLen, pszOut, nOutputStrLen, 0, 0);
        }
    }
    return pszOut;
}

 /**********************************************************************************************************/
//                                      IMPLEMENTATION OF THE FUNCTIONS
/**********************************************************************************************************/


/**********************************************************************************************************/
// Initialization and Housekeepeng Functions
/**********************************************************************************************************/

SCCEXTERNC SCCRTN EXTFUN __cdecl SccInitialize(
    LPVOID * ppContext, 
    HWND hWnd, 
    LPCSTR lpCallerName,
    LPSTR lpSccName, // [In, out]
    LPLONG lpSccCaps, // [Out]
    LPSTR lpAuxPathLabel, // [In, out]
    LPLONG pnCheckoutCommentLen, // [Out]
    LPLONG pnCommentLen //[Out]
    )
{

    // Initialize COM the first time the function is called
    CoInitialize(0);
    s_nInitializedCount++;
    HRESULT hr = CoCreateInstance(CLSID_ISccCOMServerImpl,
        NULL, CLSCTX_INPROC_SERVER,
        IID_ISccCOMServer, reinterpret_cast<void**>(&mCpi));

    long response;

    // We need auxiliar strings because out string in COM are BSTR *  
    BSTR bstrSccName;
    BSTR bstrAuxPathLabel;

    bstrSccName = T2BSTR(lpSccName);
    bstrAuxPathLabel = T2BSTR(lpAuxPathLabel);

    Context *CC = new Context;
    // Calling to the COM equivalent Function

    response = mCpi->Initialize(CC, (long) hWnd, lpCallerName, &bstrSccName, lpSccCaps, &bstrAuxPathLabel, 
        pnCheckoutCommentLen, pnCommentLen);

    *ppContext = (void *)CC;

    // Converting the strings
    BSTR2T(bstrSccName, lpSccName);
    BSTR2T(bstrAuxPathLabel, lpAuxPathLabel);
    return response;

}

然后C#部分就更简单了:

[Guid("C6659361-1625-4746-931C-36014B146679")]
public class ISccCOMServerImpl : ISccCOMServer
{
    public int Initialize(
        out Context ppContext,
        IntPtr hWnd,
        string lpCallerName,
        ref string lpSccName, // out
        out int lpSccCaps, // out
        ref string lpAuxPathLabel, // out
        out int pnCheckoutCommentLen, // out
        out int pnCommentLen //out
        )
    {
       //your manage code here!
    }

}

关于.net - 在 .Net 中实现 MSSCCI 提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3184228/

相关文章:

Azure 上的 .NET 4.5 RTM?

c# - 如何在方法设置中为数组起订 It.IsAny?

c# - P/调用第三方弹窗

c# - 我如何在 LINQ 中写这个?

c# - 无法启动红隼。无法绑定(bind)到已在使用的地址

带有 Visual Fox Pro 9 SP2 的 TFS MSSCCI 提供程序 - 无法从项目元文件更新项目