如下用GetActiveObject只能得到一个Excle的接口. HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
if(SUCCEEDED(hr))
hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);如果想得到所有打开的Excel实例接口该怎么做?谢谢!!
if(SUCCEEDED(hr))
hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);如果想得到所有打开的Excel实例接口该怎么做?谢谢!!
一种是单实例模式,在这种模式下即使有多个EXCEL文档被打开了,但它以类似于MDI的方式工作,体现为一个Application对象打开了多个Document对象。
另一种是多实例模式,每个进程或者每个主窗口代表一个实例,此时通过GetActiveObject将只能获得一个实例。要获得多个实例,必须访问ROT,通过GetRunningObjectTable获得ROT,然后调用EnumRunning获得IEnumMoniker,再通过Next方法获得每一个打开的Moniker的指针(每个Moniker代表一个唯一的打开文档的实例)。有了Moniker,你能获取当前文档的显示名称(通常是文件路径),也能获得文档对象。
通过jameshooo的提示我找到了一些代码.
发现多个实例也确实有两种模式,
一个是通过双击多个xls文件而产生的多个Excel实例,
另一个是通过Excel的快捷方式开启的多个空的Excel实例.第一种ROT里面的是一个Excel的CLSID和多个文档的路径,通过IMoniker::GetDisplayName显示如下:
C:\Documents and Settings\Administrator\??\Book1.xls
!{00024500-0000-0000-C000-000000000046}
C:\Documents and Settings\Administrator\??\Book2.xls第二种ROT里面是多个实例Excel的CLSID,通过IMoniker::GetDisplayName显示如下:
!{00024500-0000-0000-C000-000000000046}
!{00024500-0000-0000-C000-000000000046}第一种通过文档路径的那个IMoniker应该可以得到Excel的实例指针(我没有对Excel进行测试,对另外一种类似的自动化对象进行了测试).我现在想在第二种情况下用CLSID的那个IMoniker来获得Excel的实例指针,却不知该如何操作.刚刚接触COM不久.希望各位大侠不要见笑.下面我贴出我的代码,代码本身比较简单.可以方便地建立一个win32工程就可以进行测试了.
#include "stdafx.h"
#include <windows.h>
const TCHAR szExcel[] = _T("!{00024500-0000-0000-C000-000000000046}");
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hRes;
CLSID clsid;
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL; hRes = OleInitialize(NULL);
if (FAILED(hRes))
{
_tprintf(_T("OleInitialize failed (0x%08X)\n"), hRes);
return -1;
}
CLSIDFromProgID(_T("Excel.Application"), &clsid); IRunningObjectTable * pROT = NULL;
IEnumMoniker * pEnum = NULL;
IMoniker * pMoniker = NULL;
IBindCtx * pBindCtx = NULL;
PWSTR pszName = NULL;
ULONG cElt; for (;;)
{
// get interface pointer of the running object table
hRes = GetRunningObjectTable(NULL, &pROT);
if (FAILED(hRes))
{
_tprintf(_T("GetRunningObjectTable failed (0x%08X)\n"), hRes);
break;
} // create binding context object
hRes = CreateBindCtx(0, &pBindCtx);
if (FAILED(hRes))
{
_tprintf(_T("CreateBindCtx failed (0x%08X)\n"), hRes);
break;
} // enumerate running objects
hRes = pROT->EnumRunning(&pEnum);
if (FAILED(hRes))
{
_tprintf(_T("IRunningObjectTable::EnumRunning failed (0x%08X)\n"),
hRes);
break;
}
// go through all monikers in the table and display moniker name
while (pEnum->Next(1, &pMoniker, &cElt) == S_OK)
{
hRes = pMoniker->GetDisplayName(pBindCtx, NULL, &pszName);
if (FAILED(hRes))
{
_tprintf(_T("IMoniker::GetDisplayName failed (0x%08X)\n"), hRes);
break;
}
_tprintf(_T("%ls\n"), pszName);
//利用pszName来判断是否Excel
if(lstrcmp(pszName,szExcel))
{
//我想在这里取得Excel的实例接口指针,可是不知道怎么操作.*********************************
//下面这句一直出错
hRes = pMoniker->BindToObject(pBindCtx,NULL,IID_IUnknown/*clsid*/,(VOID**)&pDisp);
if (SUCCEEDED(hRes))
{
}
} CoTaskMemFree(pszName);
pMoniker->Release(); pszName = NULL;
pMoniker = NULL;
} break;
} if (pszName != NULL)
CoTaskMemFree(pszName);
if (pMoniker != NULL)
pMoniker->Release();
if (pEnum != NULL)
pEnum->Release();
if (pBindCtx != NULL)
pBindCtx->Release();
if (pROT != NULL)
pROT->Release(); OleUninitialize();
return 0;
}
#include <windows.h>
const TCHAR szExcel[] = _T("!{00024500-0000-0000-C000-000000000046}");
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hRes;
CLSID clsid;
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL; hRes = OleInitialize(NULL);
if (FAILED(hRes))
{
_tprintf(_T("OleInitialize failed (0x%08X)\n"), hRes);
return -1;
}
CLSIDFromProgID(_T("Excel.Application"), &clsid); IRunningObjectTable * pROT = NULL;
IEnumMoniker * pEnum = NULL;
IMoniker * pMoniker = NULL;
IBindCtx * pBindCtx = NULL;
PWSTR pszName = NULL;
ULONG cElt; for (;;)
{
// get interface pointer of the running object table
hRes = GetRunningObjectTable(NULL, &pROT);
if (FAILED(hRes))
{
_tprintf(_T("GetRunningObjectTable failed (0x%08X)\n"), hRes);
break;
} // create binding context object
hRes = CreateBindCtx(0, &pBindCtx);
if (FAILED(hRes))
{
_tprintf(_T("CreateBindCtx failed (0x%08X)\n"), hRes);
break;
} // enumerate running objects
hRes = pROT->EnumRunning(&pEnum);
if (FAILED(hRes))
{
_tprintf(_T("IRunningObjectTable::EnumRunning failed (0x%08X)\n"),
hRes);
break;
}
// go through all monikers in the table and display moniker name
while (pEnum->Next(1, &pMoniker, &cElt) == S_OK)
{
hRes = pMoniker->GetDisplayName(pBindCtx, NULL, &pszName);
if (FAILED(hRes))
{
_tprintf(_T("IMoniker::GetDisplayName failed (0x%08X)\n"), hRes);
break;
}
_tprintf(_T("%ls\n"), pszName);
//利用pszName来判断是否Excel
if(lstrcmp(pszName,szExcel)==0)
{
//我想在这里取得Excel的实例接口指针,可是不知道怎么操作.*********************************
//下面这句一直出错
//hRes = pMoniker->BindToObject(pBindCtx,NULL,IID_IUnknown/*clsid*/,(VOID**)&pDisp);
//if (SUCCEEDED(hRes))
//{
// _tprintf(_T("%ls\n"), _T("goooooooooooooooooooooood"));
//}
hRes = pROT->GetObject(pMoniker,&pUnk);
if (SUCCEEDED(hRes))
{
_tprintf(_T("%ls\n"), _T("goooooooooooooooooooooood"));
}
} CoTaskMemFree(pszName);
pMoniker->Release(); pszName = NULL;
pMoniker = NULL;
} break;
} if (pszName != NULL)
CoTaskMemFree(pszName);
if (pMoniker != NULL)
pMoniker->Release();
if (pEnum != NULL)
pEnum->Release();
if (pBindCtx != NULL)
pBindCtx->Release();
if (pROT != NULL)
pROT->Release(); OleUninitialize();
return 0;
}