C#如何将Excel.workbook转换为IntPtr以传递给导出的dll函数

时间:2016-07-29 20:04:22

标签: c# c++ .net excel com

所以我有一个用于excel的VSTO插件,我想调用我编写的代码,利用一些自动化。我在c ++中使用导入的lib文件方法编写了这里:

C++ app automates Excel (CppAutomateExcel)

所以我有一个扩展方法:

public static bool isEmbeded(this Excel.Workbook Book)
    {
        return dllFuncs.IsEmbeded(Book);
    }

一个dll导入函数:

namespace dllFuncs
{
    #region IsEmbeded
    [DllImport("test.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    public static extern bool IsEmbeded(Excel.Workbook Book);
    #endregion
}

这对应于导出的函数,该函数接收IUnknown指针并在其上执行查询接口以确定它是excel工作簿,word文档还是powerpoint演示文稿。

c ++代码标题:

bool WINAPI IsEmbeded(IUnknown* pOfficeDocument);

class EmbededHelperFunctions
{
public:
    static bool isEmbeded(IUnknown* pOfficeDocument);
private:
    static bool isEmbededHelper(IUnknown* pOfficeDocument);
    EmbededHelperFunctions() = delete;
}

c ++ cpp代码:

bool WINAPI IsEmbeded(IUnknown* pOfficeDocument)
{
    return EmbededHelperFunctions::isEmbeded(pOfficeDocument);
}

bool EmbededHelperFunctions::isEmbededHelper(IUnknown* pOfficeDocument)
{
    Excel::_WorkbookPtr spXlBook = nullptr;
    HRESULT  hResult = pOfficeDocument->QueryInterface(&spXlBook);

    if(hResult == S_OK)
    {
        _bstr_t path = spXlBook->Path;

        return (path.GetAddress() == nullptr || path.length() == 0);
    }

    return false;
}

bool EmbededHelperFunctions::isEmbeded(IUnknown* pOfficeDocument)
{
    if (isEmbededHelper(pOfficeDocument))
    {
        IOleObject *LobjOleObject = nullptr;
        IOleClientSite *LobjPpClientSite = nullptr;
        if (pOfficeDocument->QueryInterface(&LobjOleObject) == S_OK)
        {
            // get the client site
            LobjOleObject->GetClientSite(&LobjPpClientSite);

            if (LobjPpClientSite != nullptr)
            {
                // if there is one - we are embedded
                return true;
            }
        }
    }

    // not embedded
    return false;
}

现在我遇到的第一个问题是尽管工作簿是一个COM对象。没有简洁的方法可以从中获取指针。

我尝试了此处描述的方法:C# - How To Convert Object To IntPtr And Back?

但是创建工作簿的GCHandle会在alloc调用上崩溃。

如果我只是传递对象原始的东西似乎工作,直到我关闭时,我得到一个rpc服务器不可用错误

我将pinvoke更改为

#region IsEmbeded
        [DllImport("test.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern bool IsEmbeded([MarshalAs(UnmanagedType.IUnknown)] object Book);
#endregion
事情似乎正在起作用......但现在关机时的RPC错误是不确定的。

有没有办法去除远程可调用包装器.net封装所有这些com对象并只传递原始指针?有谁知道我怎么能这样做?

0 个答案:

没有答案