Skip to content

Instantly share code, notes, and snippets.

@statik
Last active September 24, 2020 04:43
Show Gist options
  • Save statik/0c16fcc216a55ae556640ef5c17fd9d8 to your computer and use it in GitHub Desktop.
Save statik/0c16fcc216a55ae556640ef5c17fd9d8 to your computer and use it in GitHub Desktop.
uiautomation.py dump of zoom.exe application controls.
# Credit for initial script: https://github.com/oldjohngalt
#
# Martijn Smit <[email protected] / @smitmartijn>
import os
import sys
import time
import argparse
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import uiautomation as automation
debug = False
zoomMeetingOpen = False
zoomToolbarOpen = False
toggleMute = False
toggleVideo = False
toggleShare = False
def DetectZoomMeeting():
global zoomToolbarOpen
global zoomMeetingOpen
if debug == True:
global start
start = time.time()
zoomMeetingInProgress = False
def GetFirstChild(control):
return control.GetFirstChildControl()
def GetNextSibling(control):
return control.GetNextSiblingControl()
desktop = automation.GetRootControl()
zoomMeetingOpen = False
zoomToolbarOpen = False
for control, depth in automation.WalkTree(desktop, getFirstChild=GetFirstChild, getNextSibling=GetNextSibling, includeTop=False, maxDepth=2):
if debug == True:
print(str(depth) + ' ' * depth * 4 + str(control))
if str(control).find("ZPContentViewWndClass") > 0:
zoomMeetingInProgress = True
zoomMeetingOpen = True
if str(control).find("ZPFloatToolbarClass") > 0:
zoomMeetingInProgress = True
zoomToolbarOpen = True
return zoomMeetingInProgress
def GetFirstChild(control):
return control.GetFirstChildControl()
def GetNextSibling(control):
return control.GetNextSiblingControl()
def GetZoomStatus():
global debug
global zoomToolbarOpen
global zoomMeetingOpen
global toggleMute
global toggleVideo
global toggleView
global toggleShare
statusMute = "unknown"
statusVideo = "unknown"
statusShare = "unknown"
statusView = "unknown"
statusRecord = "unknown"
desktop = automation.GetRootControl()
if zoomToolbarOpen == True:
window = automation.WindowControl(searchDepth=1, ClassName='ZPFloatToolbarClass')
toolsMenu = window
else:
window = automation.WindowControl(searchDepth=1, ClassName='ZPContentViewWndClass')
toolsMenu = window.WindowControl(searchDepth=3, ClassName='ZPControlPanelClass')
if debug == True:
print ("desktop="+str(desktop))
print ("window="+str(window))
print ("toolsMenu="+str(toolsMenu))
if window != toolsMenu:
for control, depth in automation.WalkTree(window, getFirstChild=GetFirstChild, getNextSibling=GetNextSibling, includeTop=False, maxDepth=3):
if str(control).find("Gallery View (Alt+F2)") > 0:
statusView = "speaker"
print(str(control))
if toggleView == True:
print("sending keys f2")
automation.SendKeys('{Alt}{F2}')
statusView = "gallery"
break
elif str(control).find("Speaker View") > 0:
statusView = "gallery"
if toggleView == True:
automation.SendKeys('{Alt}{F1}')
statusView = "speaker"
break
for control, depth in automation.WalkTree(toolsMenu, getFirstChild=GetFirstChild, getNextSibling=GetNextSibling, includeTop=False, maxDepth=2):
if debug == True:
print(str(depth) + ' ' * depth * 4 + str(control))
if str(control).find("currently muted") > 0:
statusMute = "muted"
if toggleMute == True:
automation.SendKeys('{Alt}a')
statusMute = "unmuted"
elif str(control).find("currently unmuted") > 0:
statusMute = "unmuted"
if toggleMute == True:
automation.SendKeys('{Alt}a')
statusMute = "muted"
elif str(control).find("start my video") > 0:
statusVideo = "stopped"
if toggleVideo == True:
automation.SendKeys('{Alt}v')
statusVideo = "started"
elif str(control).find("stop my video") > 0:
statusVideo = "started"
if toggleVideo == True:
automation.SendKeys('{Alt}v')
statusVideo = "stopped"
elif str(control).find("Share Screen") > 0:
statusShare = "stopped"
if toggleShare == True:
automation.SendKeys('{Alt}s')
statusShare = "started"
elif str(control).find("Stop Share") > 0:
statusShare = "started"
if toggleShare == True:
automation.SendKeys('{Alt}s')
statusShare = "stopped"
elif str(control).find("Resume Share") > 0:
statusShare = "disabled"
# Toolbar
elif str(control).find("Start Video") > 0:
statusVideo = "stopped"
if toggleVideo == True:
automation.SendKeys('{Alt}v')
statusVideo = "started"
elif str(control).find("Stop Video") > 0:
statusVideo = "started"
if toggleVideo == True:
automation.SendKeys('{Alt}v')
statusVideo = "stopped"
# The maxDepth needs to be increased if you want to add recording status. However, it doubles the processing time.
# elif str(control).find("Name: Record") > 0:
# statusRecord = "stopped"
# elif str(control).find("Pause/Stop Recording") > 0:
# statusRecord = "started"
# elif str(control).find("Resume Share") > 0:
# statusRecord = "paused"
if debug == True:
stop = time.time()
print("Elapsed Time:", stop-start)
statusZoom = "call"
status = "zoomStatus:"+statusZoom+",zoomMute:"+statusMute+",zoomVideo:"+statusVideo+",zoomShare:"+statusShare+",zoomView:"+statusView
print (status)
def end_meeting():
automation.SendKeys('{Alt}q')
time.sleep(1)
window = automation.WindowControl(searchDepth=1, ClassName='zLeaveWndClass')
for control, depth in automation.WalkTree(window, getFirstChild=GetFirstChild, getNextSibling=GetNextSibling, includeTop=False, maxDepth=2):
if str(control).find("End Meeting for All") > 0:
control.Click(simulateMove = False)
exit(0)
def main():
if DetectZoomMeeting() == True:
# Zoom Meeting in Progress
GetZoomStatus()
else:
# No Zoom Meeting Detected
status = "zoomStatus:closed,zoomMute:disabled,zoomVideo:disabled,zoomShare:disabled,zoomView:disabled"
print (status)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", help = "Debug", action='store_true')
parser.add_argument("-m", "--toggle_mute", help = "Toggle Mute", action='store_true')
parser.add_argument("-v", "--toggle_video", help = "Toggle Video", action='store_true')
parser.add_argument("-s", "--toggle_share", help = "Toggle Share", action='store_true')
parser.add_argument("-t", "--toggle_view", help = "Toggle Speaker View", action='store_true')
parser.add_argument("-e", "--end_meeting", help = "End Meeting", action='store_true')
args = parser.parse_args()
if args.end_meeting:
end_meeting()
exit(0)
if args.debug:
debug = True
if args.toggle_mute:
toggleMute = True
if args.toggle_video:
toggleVideo = True
if args.toggle_share:
toggleShare = True
if args.toggle_view:
toggleView = True
main()
if window != toolsMenu:
for control, depth in automation.WalkTree(window, getFirstChild=GetFirstChild, getNextSibling=GetNextSibling, includeTop=False, maxDepth=3):
if str(control).find("Gallery View") > 0:
statusView = "speaker"
elif str(control).find("Speaker View") > 0:
statusView = "gallery"
status = "zoomStatus:"+statusZoom+",zoomMute:"+statusMute+",zoomVideo:"+statusVideo+",zoomShare:"+statusShare+",zoomView:"+statusView
UIAutomation 2.0.6 (Python 3.7.1, 64 bit)
please wait for 3 seconds
2020-09-23 23:57:49.005 automation.py[75] main -> Starts, Current Cursor Position: (970, 785)
ControlType: PaneControl ClassName: #32769 AutomationId: Rect: (0,0,1536,864)[1536x864] Name: Desktop 1 Handle: 0x10010(65552) Depth: 0 SupportedPattern: LegacyIAccessiblePattern
ControlType: WindowControl ClassName: ZPContentViewWndClass AutomationId: Rect: (478,75,1504,811)[1026x736] Name: Zoom Meeting Handle: 0x5045C(328796) Depth: 1 SupportedPattern: LegacyIAccessiblePattern TransformPattern WindowPattern
ControlType: ToolTipControl ClassName: tooltips_class32 AutomationId: Rect: (970,799,1051,819)[81x20] Name: Share (Alt+S) Handle: 0x803AE(525230) Depth: 2 SupportedPattern: LegacyIAccessiblePattern
ControlType: WindowControl ClassName: ATL:77FACB78 AutomationId: 49697336 Rect: (486,106,1498,804)[1012x698] Name: ContentLeftPanel Handle: 0x80464(525412) Depth: 2 SupportedPattern: LegacyIAccessiblePattern
ControlType: WindowControl ClassName: ZPControlPanelClass AutomationId: Rect: (486,751,1498,804)[1012x53] Name: Meeting Tools Handle: 0x203B0(132016) Depth: 3 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (486,751,1498,804)[1012x53] Name: Handle: 0x0(0) Depth: 4 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (486,751,488,804)[2x53] Name: Handle: 0x0(0) Depth: 5 SupportedPattern: LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (488,754,576,802)[88x48] Name: Unmute, currently muted, Alt+A Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (488,754,576,802)[88x48] Name: Handle: 0x0(0) Depth: 6 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (488,754,554,802)[66x48] Name: Handle: 0x0(0) Depth: 7 SupportedPattern: LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (554,756,574,782)[20x26] Name: Audio Settings Handle: 0x0(0) Depth: 7 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (576,754,674,802)[98x48] Name: stop my video, Alt+V Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (576,754,674,802)[98x48] Name: Handle: 0x0(0) Depth: 6 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (576,754,652,802)[76x48] Name: Handle: 0x0(0) Depth: 7 SupportedPattern: LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (652,756,672,782)[20x26] Name: Video Settingsà Handle: 0x0(0) Depth: 7 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (674,751,692,804)[18x53] Name: Handle: 0x0(0) Depth: 5 SupportedPattern: LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (692,754,772,802)[80x48] Name: Security Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (772,754,862,802)[90x48] Name: Closed, open participants pane... Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (862,754,942,802)[80x48] Name: Polls Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (942,754,1040,802)[98x48] Name: Share Screen, Alt+S Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (942,754,1040,802)[98x48] Name: Handle: 0x0(0) Depth: 6 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (942,754,1018,802)[76x48] Name: Handle: 0x0(0) Depth: 7 SupportedPattern: LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (1018,756,1038,782)[20x26] Name: Share Option Handle: 0x0(0) Depth: 7 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (1041,754,1121,802)[80x48] Name: Record Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1121,754,1219,802)[98x48] Name: Closed Caption Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (1121,754,1219,802)[98x48] Name: Handle: 0x0(0) Depth: 6 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (1121,754,1219,802)[98x48] Name: Handle: 0x0(0) Depth: 7 SupportedPattern: LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1218,754,1298,802)[80x48] Name: Reactions Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (1298,754,1378,802)[80x48] Name: More meeting controls Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: AutomationId: Rect: (1378,751,1396,804)[18x53] Name: Handle: 0x0(0) Depth: 5 SupportedPattern: LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1423,763,1485,791)[62x28] Name: End, Alt+Q Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: PaneControl ClassName: ATL:77FACB78 AutomationId: 49734568 Rect: (910,108,1072,200)[162x92] Name: VideoContainer Handle: 0x203BA(132026) Depth: 3 SupportedPattern: LegacyIAccessiblePattern
ControlType: PaneControl ClassName: VideoContainerWndClass AutomationId: 49697624 Rect: (505,202,1479,750)[974x548] Name: VideoContainerWnd Handle: 0x4046E(263278) Depth: 3 SupportedPattern: LegacyIAccessiblePattern
ControlType: WindowControl ClassName: VideoRenderWndClass AutomationId: 49698208 Rect: (505,202,1479,750)[974x548] Name: Video Content Handle: 0x701B4(459188) Depth: 4 SupportedPattern: LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (0,0,0,0)[0x0] Name: Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (0,0,0,0)[0x0] Name: Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (513,210,537,234)[24x24] Name: Meeting Information Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1410,209,1471,235)[61x26] Name: Show my connected time, 00:34:... Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (545,210,569,234)[24x24] Name: You are using enhanced encrypt... Handle: 0x0(0) Depth: 5 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1463,113,1489,139)[26x26] Name: Enter Full Screen (Alt+F) Handle: 0x0(0) Depth: 3 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1354,112,1455,138)[101x26] Name: Gallery View (Alt+F2) Handle: 0x0(0) Depth: 3 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: TitleBarControl ClassName: AutomationId: Rect: (502,78,1498,106)[996x28] Name: Handle: 0x0(0) Depth: 2 ValuePattern.Value: Zoom Meeting SupportedPattern: LegacyIAccessiblePattern ValuePattern
ControlType: MenuBarControl ClassName: AutomationId: MenuBar Rect: (486,82,508,104)[22x22] Name: System Handle: 0x0(0) Depth: 3 SupportedPattern: LegacyIAccessiblePattern
ControlType: MenuItemControl ClassName: AutomationId: Rect: (486,82,508,104)[22x22] Name: System Handle: 0x0(0) Depth: 4 ExpandCollapsePattern.ExpandCollapseState: ExpandCollapseState.Collapsed SupportedPattern: ExpandCollapsePattern InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1355,76,1403,106)[48x30] Name: Minimize Handle: 0x0(0) Depth: 3 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1403,76,1450,106)[47x30] Name: Maximize Handle: 0x0(0) Depth: 3 SupportedPattern: InvokePattern LegacyIAccessiblePattern
ControlType: ButtonControl ClassName: AutomationId: Rect: (1450,76,1498,106)[48x30] Name: Close Handle: 0x0(0) Depth: 3 SupportedPattern: InvokePattern LegacyIAccessiblePattern
2020-09-23 23:58:05.960 automation.py[110] main -> Ends
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment