This is in regards to the selected answer for this question:
How to iterate through instance of Excel c#
This code works great for getting all instances of Excel unless one of these instances has the VBA Editor open. The code breaks when it tries to find the class for EXCEL7
. This is the class for the workbook subwindow. While debugging I determined that when enumerating the child windows, the EXCEL7 child window can not be located. Classes like VbaWindow
instead show up. I even tried to get the Excel.Window with the window handle for this vba window class but it failed. How can I still get the method AccessibleObjectFromWindow
to reference the Excel.Window, which I can then use to reference the application. Here is my modified method (I already have the Excel Process ID... all other declarations were omitted for readability):
internal static Excel.Application GetExcelInstance(int procID)
{
EnumChildCallback cb;
Process p = Process.GetProcessById(procID);
if (p != null)
{
if ((int)p.MainWindowHandle > 0)
{
int childWindow = 0;
cb = new EnumChildCallback(EnumChildProc);
EnumChildWindows((int)p.MainWindowHandle, cb, ref childWindow);
if (childWindow > 0)
{
const uint OBJID_NATIVEOM = 0xFFFFFFF0;
// GUIDs used by the OLE Automation Protocol:
// https://msdn.microsoft.com/en-us/library/cc237842.aspx
Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
Excel.Window window = null;
int res = AccessibleObjectFromWindow
(
childWindow,
OBJID_NATIVEOM,
IID_IDispatch.ToByteArray(),
ref window
);
if (res >= 0)
{
return window.Application;
}
}
}
}
return null;
}
// If VBA is open this method will fail when enumerating
// all child windows of the excel process
// EXCEL7 will not be found in child windows but other windows
// will be found like the window for class "VbaWindow"
private static bool EnumChildProc(int hwndChild, ref int lParam)
{
StringBuilder buf = new StringBuilder(128);
GetClassName(hwndChild, buf, 128);
// More info on excel classes:
// http://www.mrexcel.com/forum/excel-questions/54007-worksheet-class-findwindow-api.html
if (buf.ToString() == "EXCEL7")
{
lParam = hwndChild;
return false;
}
return true;
}