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

所以我有一个VSTO插件为Excel,我想调用我写的代码利用一些自动化。 我用c ++编写了使用import文件中指定的lib文件的方法:

C ++应用程序自动化Excel(CppAutomateExcel)

所以我有一个扩展方法:

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

和一个DLL导入的function:

 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; } 

现在我遇到的第一个问题是,尽pipe工作簿是一个COM对象。 没有简单的方法从它得到指针。

我试过这里描述的方法: C# – 如何将对象转换为IntPtr和返回?

但是在alloc调用中创build一个工作簿的GCHandle会崩溃。

如果我只是通过对象生的东西似乎工作,直到我关机,当我得到一个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对象,只是传递原始指针? 有人知道我能做到吗?