如下用GetActiveObject只能得到一个Excle的接口.   HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
   if(SUCCEEDED(hr)) 
       hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);如果想得到所有打开的Excel实例接口该怎么做?谢谢!!

解决方案 »

  1.   

    一个自动化应用程序可能存在两种工作模式:
    一种是单实例模式,在这种模式下即使有多个EXCEL文档被打开了,但它以类似于MDI的方式工作,体现为一个Application对象打开了多个Document对象。
    另一种是多实例模式,每个进程或者每个主窗口代表一个实例,此时通过GetActiveObject将只能获得一个实例。要获得多个实例,必须访问ROT,通过GetRunningObjectTable获得ROT,然后调用EnumRunning获得IEnumMoniker,再通过Next方法获得每一个打开的Moniker的指针(每个Moniker代表一个唯一的打开文档的实例)。有了Moniker,你能获取当前文档的显示名称(通常是文件路径),也能获得文档对象。
      

  2.   

    谢谢jameshooo!
    通过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;
    }
      

  3.   

    #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)==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; 

      

  4.   

    弱弱的问下LS那个for (;;) 干嘛用的?
      

  5.   

    还是不行,hRes = pROT->GetObject(pMoniker,&pUnk);永远返回的是第一个同名接口.