-
Notifications
You must be signed in to change notification settings - Fork 0
/
window_properties.py
123 lines (97 loc) · 4.55 KB
/
window_properties.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import log
import win32api, win32con, win32process, win32gui, win32con
import psutil
def getFileProperties(fname):
"""
Read all properties of the given file return them as a dictionary.
"""
propNames = ('Comments', 'InternalName', 'ProductName',
'CompanyName', 'LegalCopyright', 'ProductVersion',
'FileDescription', 'LegalTrademarks', 'PrivateBuild',
'FileVersion', 'OriginalFilename', 'SpecialBuild')
props = {'FixedFileInfo': None, 'StringFileInfo': None, 'FileVersion': None}
try:
# backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc
fixedInfo = win32api.GetFileVersionInfo(fname, '\\')
props['FixedFileInfo'] = fixedInfo
props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536,
fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536,
fixedInfo['FileVersionLS'] % 65536)
# \VarFileInfo\Translation returns list of available (language, codepage)
# pairs that can be used to retreive string info. We are using only the first pair.
lang, codepage = win32api.GetFileVersionInfo(fname, '\\VarFileInfo\\Translation')[0]
# any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle
# two are language/codepage pair returned from above
strInfo = {}
for propName in propNames:
strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName)
## print str_info
strInfo[propName] = win32api.GetFileVersionInfo(fname, strInfoPath)
props['StringFileInfo'] = strInfo
except:
pass
return props
def getApplicationName(hwnd):
(_threadId, processId) = win32process.GetWindowThreadProcessId(hwnd)
pHandle = win32api.OpenProcess(
win32con.PROCESS_QUERY_INFORMATION |
win32con.PROCESS_VM_READ, 0, processId)
pExeName = win32process.GetModuleFileNameEx(pHandle, 0)
props = getFileProperties(pExeName)
return props['StringFileInfo']['FileDescription']
def currentApp():
return getApplicationName(win32gui.GetForegroundWindow())
# https://stackoverflow.com/questions/44735798/pywin32-how-to-get-window-handle-from-process-handle-and-vice-versa
def getMainWindowHandles(process_name, expect_one=False):
"""Return a list of handles for visible windows with a given process name"""
# find all processes with process_name
pids = []
for process in psutil.process_iter():
if process.name() == process_name:
pids.append(process.pid)
# find all window handles with process_name
whandles = []
def windowFilter(handle, extra):
if win32process.GetWindowThreadProcessId(handle)[1] in pids:
whandles.append(handle)
# debug_window(handle)
return True
win32gui.EnumWindows(windowFilter, None)
# find all visible/primary windows with process_name
main_handles = []
for handle in whandles:
# debug_window(handle)
if not win32gui.IsWindowVisible(handle):
continue
parent_handle = win32gui.GetParent(handle)
if parent_handle == 0:
main_handles.append(handle)
continue
extended_style = win32api.GetWindowLong(handle, win32con.GWL_EXSTYLE)
if extended_style & win32con.WS_EX_APPWINDOW:
main_handles.append(handle)
continue
if expect_one:
if not main_handles:
log.warn("Expected exactly one main window for app '{}'. Found 0".format(process_name))
elif len(main_handles) > 1:
log.warn("Expected exactly one main window for app '{}'. Found {}"
.format(process_name, len(main_handles)))
for handle in main_handles:
debug_window(handle)
return main_handles
def debug_window(whandle):
extended_style = win32api.GetWindowLong(whandle, win32con.GWL_EXSTYLE)
log.debug('window handle:', str(whandle))
try:
win_text = win32gui.GetWindowText(whandle)
log.debug(' - text:', win_text)
except UnicodeEncodeError as e:
log.error(str(e))
log.debug(' - text: <cannot print: contains undefined character>')
log.debug(' - placement:', win32gui.GetWindowPlacement(whandle))
log.debug(' - visibility:', win32gui.IsWindowVisible(whandle))
log.debug(' - parent:', win32gui.GetParent(whandle))
log.debug(' - extended style:', extended_style)
log.debug(' - pid: {}'.format(
win32process.GetWindowThreadProcessId(whandle)[1]))