private int InternalMenuHandler(String windowName, String objName, ref ArrayList menuList, String actionType = "Select") { if (String.IsNullOrEmpty(windowName) || String.IsNullOrEmpty(objName)) { throw new XmlRpcFaultException(123, "Argument cannot be empty."); } Object pattern = null; String currObjName = null; AutomationElementCollection c = null; ControlType[] type = new ControlType[3] { ControlType.Menu, ControlType.MenuBar, ControlType.MenuItem }; ControlType[] controlType = new ControlType[3] { ControlType.Menu, ControlType.MenuItem, ControlType.MenuBar }; AutomationElement tmpContextHandle = null; AutomationElement windowHandle, childHandle; AutomationElement prevObjHandle = null, firstObjHandle = null; InternalTreeWalker w = new InternalTreeWalker(); try { windowHandle = utils.GetWindowHandle(windowName); if (windowHandle == null) { throw new XmlRpcFaultException(123, "Unable to find window: " + windowName); } processId = windowHandle.Current.ProcessId; windowHandle.SetFocus(); LogMessage("Window name: " + windowHandle + " : " + windowHandle.Current.Name + " : " + windowHandle.Current.ControlType.ProgrammaticName); childHandle = windowHandle; /* * // element is an AutomationElement. * AutomationPattern[] patterns = childHandle.GetSupportedPatterns(); * foreach (AutomationPattern pattern1 in patterns) * { * Console.WriteLine("ProgrammaticName: " + pattern1.ProgrammaticName); * Console.WriteLine("PatternName: " + Automation.PatternName(pattern1)); * } * /**/ while (true) { if (objName.Contains(";")) { int index = objName.IndexOf(";", StringComparison.CurrentCulture); currObjName = objName.Substring(0, index); objName = objName.Substring(index + 1); } else { currObjName = objName; } LogMessage("childHandle: " + childHandle.Current.Name + " : " + currObjName + " : " + childHandle.Current.ControlType.ProgrammaticName); childHandle = utils.GetObjectHandle(childHandle, currObjName, type, false); if (childHandle == null) { if (currObjName == objName) { throw new XmlRpcFaultException(123, "Unable to find Object: " + objName); } else { throw new XmlRpcFaultException(123, "Unable to find Object: " + currObjName); } } // Store previous handle for later use prevObjHandle = childHandle; if (firstObjHandle == null) { // Save it for later use firstObjHandle = childHandle; } if ((actionType == "Select" || actionType == "SubMenu" || actionType == "Check" || actionType == "UnCheck" || actionType == "VerifyCheck" || actionType == "Window") && !utils.IsEnabled(childHandle, false)) { throw new XmlRpcFaultException(123, "Object state is disabled"); } try { if (actionType == "Window") { utils.InternalXYClick(childHandle); } else { // SetFocus() fails on Windows Explorer childHandle.SetFocus(); } } catch (Exception ex) { LogMessage(ex); } if (childHandle.TryGetCurrentPattern(InvokePattern.Pattern, out pattern) || childHandle.TryGetCurrentPattern( ExpandCollapsePattern.Pattern, out pattern)) { if (actionType == "Select" || currObjName != objName || actionType == "SubMenu" || actionType == "VerifyCheck" || actionType == "Window") { try { LogMessage("Invoking menu item: " + currObjName + " : " + objName + " : " + childHandle.Current.ControlType.ProgrammaticName + " : " + childHandle.Current.Name); } catch (Exception ex) { // Noticed with closewindow() to close Notepad // System.UnauthorizedAccessException: Access is denied // Exception from HRESULT: 0x80070005 (E_ACCESSDENIED) LogMessage(ex); } if (actionType != "Window") { try { // SetFocus() fails on Windows Explorer childHandle.SetFocus(); } catch (Exception ex) { LogMessage(ex); } } if (!(actionType == "VerifyCheck" && currObjName == objName) && (actionType != "Window")) { utils.InternalClick(childHandle); } try { // Invoke doesn't work for VMware Workstation // But they work for Notepad // MoveToAndClick works for VMware Workstation // But not for Notepad (on first time) // Requires 2 clicks ! //((InvokePattern)pattern).Invoke(); utils.InternalWait(1); c = childHandle.FindAll(TreeScope.Children, Condition.TrueCondition); } catch (System.NotImplementedException ex) { // Noticed with VMware Workstation // System.Runtime.InteropServices.COMException (0x80040200): // Exception from HRESULT: 0x80040200 LogMessage("NotImplementedException"); LogMessage(ex); } catch (System.Windows.Automation.ElementNotEnabledException ex) { // Noticed with VMware Workstation // System.Runtime.InteropServices.COMException (0x80040200): // Exception from HRESULT: 0x80040200 LogMessage("Element not enabled"); LogMessage(ex); } catch (Exception ex) { LogMessage(ex); } } } if (currObjName == objName && actionType != "SubMenu") { int state; switch (actionType) { case "Select": case "Window": // No child menu item to be processed return(1); case "Check": case "UnCheck": state = IsMenuChecked(childHandle); LogMessage("IsMenuChecked(childHandle): " + childHandle.Current.ControlType.ProgrammaticName); LogMessage("actionType: " + actionType); // Don't process the last item if (actionType == "Check") { if (state == 1) { // Already checked, just click back the main menu utils.InternalClick(firstObjHandle); } else { // Check menu utils.InternalClick(childHandle); } return(1); } else if (actionType == "UnCheck") { if (state == 0) { // Already unchecked, just click back the main menu utils.InternalClick(firstObjHandle); } else { // Uncheck menu utils.InternalClick(childHandle); } return(1); } break; case "Exist": case "Enabled": state = utils.IsEnabled(childHandle) == true ? 1 : 0; LogMessage("IsEnabled(childHandle): " + childHandle.Current.Name + " : " + state); LogMessage("IsEnabled(childHandle): " + childHandle.Current.ControlType.ProgrammaticName); // Set it back to old state, else the menu selection left there utils.InternalClick(firstObjHandle); // Don't process the last item if (actionType == "Enabled") { return(state); } else if (actionType == "Exist") { return(1); } break; case "SubMenu": int status = HandleSubMenu(w.walker.GetFirstChild(childHandle), firstObjHandle, ref menuList); if (status == 1) { return(1); } break; case "VerifyCheck": state = IsMenuChecked(childHandle); utils.InternalClick(firstObjHandle); return(state); default: break; } } else if ((tmpContextHandle = utils.InternalWaitTillControlTypeExist( ControlType.Menu, processId, 3)) != null) { LogMessage("InternalWaitTillControlTypeExist"); // Find object from current handle, rather than navigating // the complete window childHandle = tmpContextHandle; if (actionType != "SubMenu") { continue; } else if (currObjName == objName) { switch (actionType) { case "SubMenu": int status = HandleSubMenu(w.walker.GetFirstChild(childHandle), firstObjHandle, ref menuList); if (status == 1) { return(1); } break; } } } else if (c != null && c.Count > 0) { if (currObjName == objName) { switch (actionType) { case "SubMenu": int status = HandleSubMenu(w.walker.GetFirstChild(childHandle), firstObjHandle, ref menuList); if (status == 1) { return(1); } break; } } LogMessage("c != null && c.Count > 0"); childHandle = windowHandle; continue; } // Required for Notepad like app if ((c == null || c.Count == 0)) { LogMessage("Work around for Windows application"); LogMessage(windowHandle.Current.Name + " : " + objName); AutomationElement tmpChildHandle = utils.GetObjectHandle( windowHandle, objName, type, false); // Work around for Notepad, as it doesn't find the menuitem // on clicking any menu if (tmpChildHandle != null) { LogMessage("Work around: tmpChildHandle != null"); if (actionType == "SubMenu" && currObjName == objName) { // Work around for Notepad like app childHandle = tmpChildHandle; } else { // Work around for Notepad like app, // but for actionType other than SubMenu childHandle = windowHandle; } } } if (currObjName == objName) { switch (actionType) { case "SubMenu": int status = HandleSubMenu(w.walker.GetFirstChild(childHandle), firstObjHandle, ref menuList); if (status == 1) { return(1); } break; } } } } catch (Exception ex) { LogMessage(ex); if (firstObjHandle != null && actionType != "Window") { // Set it back to old state, else the menu selection left there utils.InternalXYClick(firstObjHandle); } if (((ex is ElementNotAvailableException) || (ex is UnauthorizedAccessException)) && actionType == "Window") { // API closewindow() can close Windows Explorer on XP, but: // ----------------------------------------------------------- // if (childHandle.TryGetCurrentPattern(InvokePattern.Pattern, // out pattern) || childHandle.TryGetCurrentPattern( // ExpandCollapsePattern.Pattern, out pattern)) // ----------------------------------------------------------- // Sometimes above code will throw exception, sometimes not: // System.Runtime.InteropServices.COMException (0x80040201): // Exception from HRESULT: 0x80040201 // System.UnauthorizedAccessException, Access is denied: // Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) // So use this if block as workaround return(1); } if (ex is XmlRpcFaultException) { throw; } else { throw new XmlRpcFaultException(123, "Unhandled exception: " + ex.Message); } } finally { c = null; w = null; pattern = null; windowHandle = childHandle = null; prevObjHandle = firstObjHandle = null; } }