-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathica_runner.py
100 lines (84 loc) · 3.78 KB
/
ica_runner.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
import asyncio
import logging
import shutil
import subprocess
import tempfile
import time
from pathlib import Path
from typing import Union, Tuple
import pywinauto
import rich.console
from pywinauto import Desktop
from context import Context
logger = logging.getLogger(__name__)
def run_ica(ica_file: Union[Path, str], runner):
logger.debug('Runner path: {}'.format(runner))
ica_file = Path(ica_file)
with tempfile.TemporaryDirectory() as tempdir:
tmp_ica = Path(tempdir) / 'temp.ica'
shutil.copy(ica_file, tmp_ica)
# The return code seems always to be 0
try:
_ = subprocess.call([str(runner), str(tmp_ica)], timeout=5)
except subprocess.TimeoutExpired:
# Sometimes, by double-clicking the .lnk to launch makes the process stuck forever. Not sure why.
logger.warning('Timeout while waiting for runner process has not exited. But assume nothing.')
async def _check_rdm(ctx: Context, timeout=120) -> Tuple[bool, str]:
"""Check if there's any positive or negative rules matching"""
with ctx.console.status("Looking for matching rules...", spinner='line'):
_start = time.time()
while time.time() - _start < timeout:
has_failure = False
for w in Desktop(backend="uia").windows(class_name='#32770', top_level_only=True):
# "#32770" is either the opening dialog, or the dialog that reports connection error.
try:
_text = ''.join(w.children_texts())
logger.debug(f'Found title="{w.window_text()}"'
f' className="{w.class_name()}" '
f' allText="{_text[:30]}"')
if 'did not launch successfully' in _text or 'resource is not available' in _text:
# Try to close the dialog
for c in filter(lambda i: 'button' in str(i.class_name()).lower(), w.children()):
if c.class_name and c.texts() == ['Close']:
c.click()
break
has_failure = True
except pywinauto.findwindows.ElementNotFoundError:
# Not found the error dialog
pass
if has_failure:
return False, 'Failed due to detecting the error dialog(s)'
w = Desktop(backend="uia").window(
title_re=r'^Remote Desktop Manager.*',
class_name='Transparent Windows Client')
try:
logger.debug(f'Found title="{w.window_text()}" (className="{w.class_name()}")')
return True, 'OK'
except pywinauto.findwindows.ElementNotFoundError:
# Not found the opened app
pass
await asyncio.sleep(1)
return False, 'Failed due to time out'
async def check(ctx: Context, key: str, timeout=120) -> Tuple[bool, str]:
# windows = Desktop(backend="uia").windows()
# pprint([w.window_text() for w in windows])
logger.info(f'Checking launch rules for {key} (timeout={timeout}s)')
try:
if key == 'Remote Desktop Manager':
return await _check_rdm(ctx, timeout)
else:
logger.warning(f'No checking rules for "{key}". Assuming successful.')
return True, 'No checking rules'
except Exception as e:
ctx.console.print_exception(show_locals=True)
return False, str(e)
if __name__ == '__main__':
from rich.logging import RichHandler
logging.basicConfig(
level=logging.NOTSET,
format='[%(name)s] %(message)s',
handlers=[RichHandler(rich_tracebacks=True)]
)
asyncio.run(
check(Context(rich.console.Console()), 'Remote Desktop Manager')
)