How to get all instances of Excel.exe
-
Hi, I am working on Excel Automation Project. using GetActiveobject , getting one instance of Excel.exe. But need to track/access any number of instances which are opened. Initally I am checking all the processes in task manager, if Excel.exe is running, then I will loop through to get the active Excel object using GetActiveObject. But only one instance I am able to access. How to track other instance of Excel.exe's. Regards, KTTransfer.
-
Hi, I am working on Excel Automation Project. using GetActiveobject , getting one instance of Excel.exe. But need to track/access any number of instances which are opened. Initally I am checking all the processes in task manager, if Excel.exe is running, then I will loop through to get the active Excel object using GetActiveObject. But only one instance I am able to access. How to track other instance of Excel.exe's. Regards, KTTransfer.
This code by a coder dude called NarVish gets the Windows Handles from process id of excel instance instances.
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
DWORD dwThreadId, dwProcessId;
HINSTANCE hInstance;
char String[255];
HANDLE hProcess;
dwThreadId = GetWindowThreadProcessId(hWnd, &dwProcessId);
}
int _tmain(int argc, _TCHAR* argv[])
{
HWND hwnd = (HWND)FindWindow(_T("XLMAIN"), NULL);
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;if( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) return 1; cProcesses = cbNeeded / sizeof(DWORD); for (i=0; i<cProcesses; i++ ) { if( aProcesses\[i\] != 0 ) { TCHAR szProcessName\[MAX\_PATH\] = \_T("<unknown>"); HANDLE hProcess = OpenProcess( PROCESS\_QUERY\_INFORMATION | PROCESS\_VM\_READ, FALSE, aProcesses\[i\] ); if ( NULL != hProcess ) { HMODULE hMod; DWORD cbNeeded; if( EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded) ) { GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) ); if(\_wcsicmp(szProcessName,L"EXCEL.EXE") == 0) //if(strcmp((const char\*)szProcessName,(const char\*)excelProcName)==0) { cout<< szProcessName << "--" << aProcesses\[i\] <<endl; Excel::Window\* pWindow = NULL; pid = aProcesses\[i\]; EnumWindows( EnumWindowsProc, NULL); HRESULT hr = AccessibleObjectFromWindow(hwnd, OBJID\_NATIVEOM, \_\_uuidof(Excel::Window), (void\*\*)&pWindow); if (hr == S\_OK) { } } } } // Print the process name and identifier. \_tprintf( TEXT("%s (PID: %u)\\n"), szProcessName, aProcesses\[i\] ); CloseHandle( hProcess ); } } return 0;
}
-
Hi, I am working on Excel Automation Project. using GetActiveobject , getting one instance of Excel.exe. But need to track/access any number of instances which are opened. Initally I am checking all the processes in task manager, if Excel.exe is running, then I will loop through to get the active Excel object using GetActiveObject. But only one instance I am able to access. How to track other instance of Excel.exe's. Regards, KTTransfer.
-
Do you need the COM instances or just the process handles?
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition. Blaise Pascal
I need COM instance. Excel::_ApplicationPtr.
-
I need COM instance. Excel::_ApplicationPtr.
This code might help you. Call get_Application function of the obtained document IDispatch to get its application's IDispatch.
void COffCntrDispCtrl::GetDocDispatch() { // No need, if we already have it. if(m\_pDocDisp != NULL) return; // Get a BindCtx. IBindCtx \*pbc; HRESULT hr = CreateBindCtx(0, &pbc); if(FAILED(hr)) { DoErr("CreateBindCtx()", hr); return; } // Get running-object table. IRunningObjectTable \*prot; hr = pbc->GetRunningObjectTable(&prot); if(FAILED(hr)) { DoErr("GetRunningObjectTable()", hr); pbc->Release(); return; } // Get enumeration interface. IEnumMoniker \*pem; hr = prot->EnumRunning(&pem); if(FAILED(hr)) { DoErr("EnumRunning()", hr); prot->Release(); pbc->Release(); return; } // Start at the beginning. pem->Reset(); // Churn through enumeration. ULONG fetched; IMoniker \*pmon; int n = 0; while(pem->Next(1, &pmon, &fetched) == S\_OK) { // Get DisplayName. LPOLESTR pName; pmon->GetDisplayName(pbc, NULL, &pName); // Convert it to ASCII. char szName\[512\]; WideCharToMultiByte(CP\_ACP, 0, pName, -1, szName, 512, NULL, NULL); // Compare it against the name we got in SetHostNames(). if(!strcmp(szName, m\_szDocName)) { DoMsg("Found document in ROT!"); // Bind to this ROT entry. IDispatch \*pDisp; hr = pmon->BindToObject(pbc, NULL, IID\_IDispatch, (void \*\*)&pDisp); if(!FAILED(hr)) { // Remember IDispatch. m\_pDocDisp = pDisp; // Notice... sprintf(buf, "Document IDispatch = %08lx", m\_pDocDisp); DoMsg(buf); } else { DoErr("BindToObject()", hr); } } // Release interfaces. pmon->Release(); // Break out if
-
This code might help you. Call get_Application function of the obtained document IDispatch to get its application's IDispatch.
void COffCntrDispCtrl::GetDocDispatch() { // No need, if we already have it. if(m\_pDocDisp != NULL) return; // Get a BindCtx. IBindCtx \*pbc; HRESULT hr = CreateBindCtx(0, &pbc); if(FAILED(hr)) { DoErr("CreateBindCtx()", hr); return; } // Get running-object table. IRunningObjectTable \*prot; hr = pbc->GetRunningObjectTable(&prot); if(FAILED(hr)) { DoErr("GetRunningObjectTable()", hr); pbc->Release(); return; } // Get enumeration interface. IEnumMoniker \*pem; hr = prot->EnumRunning(&pem); if(FAILED(hr)) { DoErr("EnumRunning()", hr); prot->Release(); pbc->Release(); return; } // Start at the beginning. pem->Reset(); // Churn through enumeration. ULONG fetched; IMoniker \*pmon; int n = 0; while(pem->Next(1, &pmon, &fetched) == S\_OK) { // Get DisplayName. LPOLESTR pName; pmon->GetDisplayName(pbc, NULL, &pName); // Convert it to ASCII. char szName\[512\]; WideCharToMultiByte(CP\_ACP, 0, pName, -1, szName, 512, NULL, NULL); // Compare it against the name we got in SetHostNames(). if(!strcmp(szName, m\_szDocName)) { DoMsg("Found document in ROT!"); // Bind to this ROT entry. IDispatch \*pDisp; hr = pmon->BindToObject(pbc, NULL, IID\_IDispatch, (void \*\*)&pDisp); if(!FAILED(hr)) { // Remember IDispatch. m\_pDocDisp = pDisp; // Notice... sprintf(buf, "Document IDispatch = %08lx", m\_pDocDisp); DoMsg(buf); } else { DoErr("BindToObject()", hr); } } // Release interfaces. pmon->Release(); // Break out if
I am working on a similar problem. I know the HWND for each Excel instance and implemented the MFC ActiveX control you mention above. However, I have not used an ActiveX control in C++ before. Do you know how I can get m_pDocDisp? I tried putting just the code above in my native C++ / Excel C API application and it doesn't find it. http://www.codeproject.com/Messages/3730176/Get-Document-IDispatch-in-native-Cplusplus-possibl.aspx