# 1.1.3 is released (Orchestrator RDP Active is realy upgraded+ fixed memory leak (need test))

dev-linux
Ivan Maslov 5 years ago
parent 31e2d1a08c
commit 7ca1c2b6b3

@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pyOpenRPA
Version: 1.1.2
Version: 1.1.3
Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov

@ -1,8 +1,8 @@
pyOpenRPA-1.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.2.dist-info/METADATA,sha256=i36JUYLUfNOz4jax1gu2KxREFioKKXo4g6oS6ZVo-n0,3541
pyOpenRPA-1.1.2.dist-info/RECORD,,
pyOpenRPA-1.1.2.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.2.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA-1.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.3.dist-info/METADATA,sha256=ObJb3J2niW85Wzoh8Uy_TC99RYMif_Ipn-QwE7NSv_8,3541
pyOpenRPA-1.1.3.dist-info/RECORD,,
pyOpenRPA-1.1.3.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.3.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174
pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203
pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277
@ -10,17 +10,14 @@ pyOpenRPA/.idea/pyOpenRPA.iml,sha256=EXh41F8lqRiSBMVg-n2tKaEaHC6_3gGSuKkPJA12Na0
pyOpenRPA/.idea/vcs.xml,sha256=2HygA1oRAwc3VBf-irxHrX5JJG9DXuQwrN0BlubhoKY,191
pyOpenRPA/.idea/workspace.xml,sha256=kcCP7x0iSOAWJdy7YtntGrgsQ04QIq0b6_9w04DKxfg,2555
pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
pyOpenRPA/Orchestrator/HowToUse.txt,sha256=ZcIgNvPUhzN0XFElqDirlm07fUb7QKLVjzvNrTk4a7k,148
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=0Q4VYZPdXV2qmLuowMWD_vERj1GQurQx_VFwfsxuucQ,7076
pyOpenRPA/Orchestrator/Processor.py,sha256=zSsNWZtuKX5Y3q5iYCVdPpv2X7x-XzcTe5_w2CNUJ6E,12780
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=iVp7DlLZHsURBOBegfDG4LanqSrI0A5a6GebP1cBOnI,8301
pyOpenRPA/Orchestrator/Processor.py,sha256=mPSv3xO1ah1BzhQdfltt77_tJrmKP9CAfwqeFAqeTFY,11364
pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=YB5HJL-Qf4IlVrFHyRv_ZMJ0Vo4vjyYqWKjvrTnf1k4,1564
pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=2nm5S_FOfnLkDVdlm2MVag9vL3DlyJ98LnwYNMzFNho,15914
pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=WgGqWoPAnMeXpI_w3iuFX0KUBssvlSk9MuPBuIsNOuY,491
pyOpenRPA/Orchestrator/RobotRDPActive/GlobalDictSessionIndex_Defs.py,sha256=4BbAozLyOlXJxNw0NAlHt38-AyV-B6-Nl1M1AY8CTtk,4212
pyOpenRPA/Orchestrator/RobotRDPActive/Monitor.py,sha256=Y4mhNslK0EBS1LIDfK67j3lkjTZSU5xq-HUl9XNKW-U,10609
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=v-xwXHEbslqCO6QgzQdnw38pyKCQEAKf-GDVhnSyfcU,7649
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=vsISwvRTMbbEtL_u9PU-rP6W71VUhAUBLMblOSGp2BE,9893
pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=8H_7KTUy_9m4FwbXIlDBUdX4-z3RtsaQRmYzSVdpBIU,25171
pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=goBIuwTmpdiAkimhrsqy3Y41BeljUsMQO8TaZgpx0I0,8650
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=_dZQWv1lUMV8VwzeL2GclU4ZodNcYiEF7uKLrsYZjOI,10137
pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144
pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=JEMVYkEmNcfg_p8isdIyvj9E-2ZB5mj-R3MkcNMKxkA,2426
pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077
@ -30,8 +27,6 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/CMDStr.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Clipboard.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/ConnectorExceptions.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/GlobalDictSessionIndex_Defs.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Processor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/RobotRDPActive.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,,
@ -41,7 +36,7 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=gqJO6FRDKTBZytJVdJgPF1PvOf05qYUyKDBJJkEpLzk,22755
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=mpPAxAe6PvmKaZlreaoQAy_5wV80edz_0qc-iFrEmBQ,7123
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=UpIkCcR7cfkbUS0vNiyWpeR2wXg8uFBFJplT4BF0qKI,37145
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=giviLTJ1GJyVayvPski2GkcB6Wd2MFYVw5yK6gSsx84,38272
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -52,7 +47,6 @@ pyOpenRPA/Orchestrator/__pycache__/ServerSettings.cpython-37.pyc,,
pyOpenRPA/Orchestrator/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/todo.txt,sha256=OAjkuE770VZ_w1yXt6qNUT03prhODvQ0ivVoUvFLIps,419
pyOpenRPA/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293
pyOpenRPA/Resources/Web/Google/LatoItalic.css,sha256=pB6OZ6F2VsaqkL-g5hW-wE_T0m9H_NltzmzjX-XAKDk,3112
pyOpenRPA/Resources/Web/Handlebars/handlebars-v4.1.2.js,sha256=h6O4BrhyPtJspLDEQwogC53uHFRozuBpxvN2S4tJHE8,171994
@ -306,6 +300,6 @@ pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=mx0F70tuKb-PzNALCeEZI3ZZcgHLBu8dsv1ILrNNH_s,174
pyOpenRPA/__init__.py,sha256=zLXCLfZm0anOTnxES7ijiJFJqTniSxBCuqjNArOBU5Q,174
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -1,2 +0,0 @@
1. Настроить конфигурацию запуска/остановки robotDaemonConfiguration.json
2. Запустить исполняемый файл демона runProcessOpenRPARobotDaemon_x32.cmd

@ -10,13 +10,13 @@ import pdb
from . import Server
from . import Timer
from . import Processor
import logging
import copy
#from .Settings import Settings
import importlib
from importlib import util
import threading # Multi-threading for RobotRDPActive
from .RobotRDPActive import RobotRDPActive #Start robot rdp active
import uuid # Generate uuid
#Единый глобальный словарь (За основу взять из Settings.py)
global gSettingsDict
@ -34,6 +34,10 @@ if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
#mGlobalDict = Settings.Settings(sys.argv[1])
#Logger alias
lL = gSettingsDict["Logger"]
if lL: lL.info("Link the gSettings in submodules") #Logging
Processor.gSettingsDict = gSettingsDict
Timer.gSettingsDict = gSettingsDict
Timer.Processor.gSettingsDict = gSettingsDict
@ -43,34 +47,56 @@ Server.Processor.gSettingsDict = gSettingsDict
#Инициализация настроечных параметров
lDaemonLoopSeconds=gSettingsDict["Scheduler"]["ActivityTimeCheckLoopSeconds"]
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
lDaemonStartDateTime=datetime.datetime.now()
lDaemonLastDateTime=datetime.datetime.now()
#Инициализация сервера
lThreadServer = Server.RobotDaemonServer("ServerThread", gSettingsDict)
lThreadServer.start()
if lL: lL.info("Web server has been started") #Logging
# Init the RobotRDPActive in another thread
lRobotRDPActiveThread = threading.Thread(target= RobotRDPActive.RobotRDPActive, kwargs={"inGSettings":gSettingsDict})
lRobotRDPActiveThread.daemon = True # Run the thread in daemon mode.
lRobotRDPActiveThread.start() # Start the thread execution.
#Logging
gSettingsDict["Logger"].info("Scheduler loop init")
# Выполнить активности при старте
if lL: lL.info("Robot RDP active has been started") #Logging
# Orchestrator start activity
if lL: lL.info("Orchestrator start activity run") #Logging
for lActivityItem in gSettingsDict["OrchestratorStart"]["ActivityList"]:
Processor.ActivityListOrDict(lActivityItem)
#Вечный цикл
if lL: lL.info("Scheduler loop start") #Logging
gDaemonActivityLogDictRefreshSecInt = 10 # The second period for clear lDaemonActivityLogDict from old items
gDaemonActivityLogDictLastTime = time.time() # The second perioad for clean lDaemonActivityLogDict from old items
while True:
lCurrentDateTime = datetime.datetime.now()
#Циклический обход правил
lFlagSearchActivityType=True
# Periodically clear the lDaemonActivityLogDict
if time.time()-gDaemonActivityLogDictLastTime>=gDaemonActivityLogDictRefreshSecInt:
gDaemonActivityLogDictLastTime = time.time() # Update the time
for lIndex, lItem in enumerate(lDaemonActivityLogDict):
if lItem["ActivityEndDateTime"] and lCurrentDateTime<=lItem["ActivityEndDateTime"]:
pass
# Activity is actual - do not delete now
else:
# remove the activity - not actual
lDaemonActivityLogDict.pop(lIndex,None)
lIterationLastDateTime = lDaemonLastDateTime # Get current datetime before iterator (need for iterate all activities in loop)
# Iterate throught the activity list
for lIndex, lItem in enumerate(gSettingsDict["Scheduler"]["ActivityTimeList"]):
# Prepare GUID of the activity
lGUID = None
if "GUID" in lItem and lItem["GUID"]:
lGUID = lItem["GUID"]
else:
lGUID = str(uuid.uuid4())
lItem["GUID"]=lGUID
#Проверка дней недели, в рамках которых можно запускать активность
lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6])
if lCurrentDateTime.weekday() in lItemWeekdayList:
if lFlagSearchActivityType:
#Лог
lItemCopy = copy.deepcopy(lItem)
lItemCopy["DateTimeUTCStringStart"]=datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f")
gSettingsDict["Scheduler"]["LogList"].append(lItemCopy)
#######################################################################
#Branch 1 - if has TimeHH:MM
#######################################################################
@ -82,16 +108,15 @@ while True:
lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
#Убедиться в том, что время наступило
if (
lActivityDateTime>=lDaemonStartDateTime and
lCurrentDateTime>=lActivityDateTime and
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
#Выполнить операцию
#Запись в массив отработанных активностей
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
#Запустить процесс
lActivityDateTime>=lDaemonLastDateTime and
lCurrentDateTime>=lActivityDateTime):
# Log info about activity
if lL: lL.info(f"Scheduler:: Activity is started. Scheduler item: {lItem}") #Logging
# Do the activity
Processor.ActivityListOrDict(lItem["Activity"])
lIterationLastDateTime = datetime.datetime.now() # Set the new datetime for the new processor activity
#######################################################################
#Banch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
#Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
#######################################################################
if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem:
#Сформировать временной штамп, относительно которого надо будет проверять время
@ -104,10 +129,11 @@ while True:
if (
lCurrentDateTime<lActivityTimeEndDateTime and
lCurrentDateTime>=lActivityDateTime and
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
(lGUID,lActivityDateTime) not in lDaemonActivityLogDict):
#Запись в массив отработанных активностей
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
lDaemonActivityLogDict[(lGUID,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime, "ActivityEndDateTime":lActivityTimeEndDateTime}
#Запуск циклической процедуры
Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"])
lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity
#Уснуть до следующего прогона
time.sleep(lDaemonLoopSeconds)

@ -5,7 +5,6 @@ import pdb
import os
import sys
import subprocess
import copy
import importlib
import psutil
#Input arg
@ -46,14 +45,12 @@ import psutil
# "Type":"ProcessStart",
# "Path":"",
# "ArgList":[]
#
# },
# {
# "Type":"ProcessStartIfTurnedOff",
# "CheckTaskName":"", #Check if current task name is not active (then start process),
# "Path":"",
# "ArgList":[]
#
# },
# {
# "Type":"ProcessStop",
@ -86,8 +83,6 @@ gSettingsDict = None
def Activity(inActivity):
#Глобальная переменная - глобальный словарь унаследованный от Settings.py
global gSettingsDict
#Fill DateTimeUTCStringStart
inActivity["DateTimeUTCStringStart"] = datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f")
#Alias (compatibility)
lItem = inActivity
lCurrentDateTime = datetime.datetime.now()
@ -179,16 +174,12 @@ def Activity(inActivity):
lDict=lDict[lItem2]
#Return value
lItem["Result"]=lDict.get(lItem["KeyList"][-1],None)
#Определить вид активности
lActivityDateTime=inActivity["DateTimeUTCStringStart"]
#####################################
#ProcessStart
#####################################
if lItem["Type"]=="ProcessStart":
#Вид активности - запуск процесса
#Запись в массив отработанных активностей
#Лог
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
#Запустить процесс
lItemArgs=[lItem["Path"]]
lItemArgs.extend(lItem["ArgList"])
@ -209,8 +200,6 @@ def Activity(inActivity):
if not CheckIfProcessRunning(lCheckTaskName):
#Вид активности - запуск процесса
#Запись в массив отработанных активностей
#Лог
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
#Запустить процесс
lItemArgs=[lItem["Path"]]
lItemArgs.extend(lItem["ArgList"])
@ -229,8 +218,6 @@ def Activity(inActivity):
#Завершить процессы только текущего пользоваиеля
if lItem.get('User',"")!="":
lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"'
#Лог
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Name"], "activityStartDateTime":str(lCurrentDateTime)})
#Завершить процесс
os.system(lActivityCloseCommand)
#################################
@ -263,15 +250,6 @@ def Activity(inActivity):
else:
lItem["Result"] = True
###################################
#Set datetime stop
lItem["DateTimeUTCStringStop"] = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")
##################
#Trace activity
##################
#print(mGlobalDict)
if gSettingsDict["Processor"].get(f"LogType_{lItem['Type']}", True):
#Add activity in TransactionList if it is applicable
gSettingsDict["Processor"]["LogList"].append(copy.deepcopy(lItem))
#Вернуть результат
return lItem

@ -10,6 +10,17 @@ import keyboard # Keyboard functions
import time
import random # random integers
from win32api import GetSystemMetrics # Get Screen rect
import pyautogui # for hotkey operations
# System variables for recovery scenario
gRecoveryWindowRDPRetryCountInt = 3 # Retry iteration count is RDP window is not responsible
gRecoveryWindowRDPRetryIntervalSecInt = 3 # Retry interval for reconnect
gRecoveryWindowRUNRetryCountInt = 3 # Retry iteration count is RUN window is not responsible
gRecoveryWindowRUNRetryIntervalSecInt = 3 # Retry interval for retry
gRecoveryCMDResponsibleRetryCountInt = 3 # Retry iteration count is CMD is not responsible
gRecoveryCMDResponsibleRetryIntervalSecInt = 3 # Retry interval for retry
#Connect to RDP session
"""
{
@ -24,7 +35,7 @@ from win32api import GetSystemMetrics # Get Screen rect
}
}
"""
def Session(inRDPSessionConfiguration):
def Session(inRDPSessionConfiguration, inScreenSize550x350Bool = False):
#RDPConnector.SessionConnect(mConfiguration)
#RDPConnector.LoginPassSet("111.222.222.111","ww","dd")
(lRDPFile, lSessionHex) = SessionConfigurationCreate(inRDPSessionConfiguration)
@ -33,7 +44,7 @@ def Session(inRDPSessionConfiguration):
#Set login/password
SessionLoginPasswordSet(inRDPSessionConfiguration["Host"],inRDPSessionConfiguration["Login"],inRDPSessionConfiguration["Password"])
#Start session
SessionRDPStart(lRDPFile)
SessionRDPStart(lRDPFile, inScreenSize550x350Bool= inScreenSize550x350Bool)
#Remove temp file
time.sleep(4) #Delete file after some delay - one way to delete and run the RDP before because RDP is not read file in one moment
os.remove(lRDPFile) # delete the temp rdp
@ -79,7 +90,7 @@ def SessionConfigurationCreate(inConfiguration):
#Return .rdp full path
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart
def SessionRDPStart(inRDPFilePath):
def SessionRDPStart(inRDPFilePath, inScreenSize550x350Bool = False):
#Disable certificate warning
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f'
os.system(lCMDString)
@ -137,24 +148,43 @@ def SessionRDPStart(inRDPFilePath):
# Raise exception if RDP is not active
if len(lWaitResult) == 0:
raise ConnectorExceptions.SessionWindowNotExistError("Error when initialize the RDP session - No RDP windows has appreared!")
# Wait for init
time.sleep(3)
SessionScreenSize_X_Y_W_H(inSessionHex = lRDPFileName, inXInt = 10, inYInt = 10, inWInt = 550, inHInt = 350) #Prepare little window
time.sleep(3) # Wait for init
if inScreenSize550x350Bool: SessionScreenSize_X_Y_W_H(inSessionHex = lRDPFileName, inXInt = 10, inYInt = 10, inWInt = 550, inHInt = 350) #Prepare little window
return None
#Set fullscreen for app
def SessionScreenFull(inSessionHex):
#Prepare little window
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
except Exception as e:
return None
lRDPWindow.set_focus()
lRDPWindow.maximize()
#time.sleep(0.5)
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
def SessionScreenFull(inSessionHex, inLogger = None, inRDPConfigurationItem = None):
########################################
lWindowRDPRetryIterator = 0 # Retry iterator if RDP window is not active
lRDPConfigurationItem = inRDPConfigurationItem # Get the RDP configuration item
lL = inLogger # Get the logger instance
lRDPWindow = None # Init the variable
while lWindowRDPRetryIterator<gRecoveryWindowRDPRetryCountInt: # Loop iteration to connect to RDP
try: # Try to get RDP window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lWindowRDPRetryIterator = gRecoveryWindowRDPRetryCountInt # Set last iterator to turn off the loop
# RDP window has been detected - go to set focus and maximize
lRDPWindow.set_focus()
lRDPWindow.maximize()
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
except Exception as e: # RDP window is not exist - try to reconnect
if lL: lL.warning(f"RDP::SessionScreenFull: RDP window is not exist - try sleep {gRecoveryWindowRDPRetryIntervalSecInt}[s.] and then to reconnect. SessionHex: {inSessionHex}. Current retry iterator is {lWindowRDPRetryIterator}")
if lRDPConfigurationItem:
time.sleep(gRecoveryWindowRDPRetryIntervalSecInt) # Before try to reconnect sleep
# Try to reconnect the RDP
SessionClose(inSessionHexStr=inSessionHex) # Close the
Session(lRDPConfigurationItem) # Create RDP session
inSessionHex = lRDPConfigurationItem["SessionHex"] # Get new session hex after reconnect
SystemRDPWarningClickOk() # Click all warning messages
lWindowRDPRetryIterator = lWindowRDPRetryIterator + 1 # increase the iterator
if lWindowRDPRetryIterator >= gRecoveryWindowRDPRetryCountInt: # Raise the error if retry count is over
if lL: lL.warning(f"RDP::SessionScreenFull: Retry count is over. Raise the error. SessionHex: {inSessionHex}.") # Log the info
raise ConnectorExceptions.SessionWindowNotExistError() # raise the error
else:
if lL: lL.warning(f"RDP::SessionScreenFull: Has no RDP configuration item - don't reconnect. Raise the error. SessionHex: {inSessionHex}") # Log the info
raise ConnectorExceptions.SessionWindowNotExistError() # raise the error
return None
# Set the screen size
@ -202,14 +232,14 @@ def SessionClose(inSessionHexStr):
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5):
def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5, inLogger=None, inRDPConfigurationItem=None):
lL = inLogger # Init the logger
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
# Enter full screen mode
SessionScreenFull(inSessionHex)
SessionScreenFull(inSessionHex, inLogger=lL, inRDPConfigurationItem=inRDPConfigurationItem) # Enter full screen mode with recovery scenario
time.sleep(2)
# Run CMD operations
lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec)
lResult = SystemCMDRun(inSessionHexStr = inRDPConfigurationItem["SessionHex"], inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec, inLogger=lL)
# Exit fullscreen mode
SessionScreenSize_X_Y_W_H(inSessionHex=inSessionHex, inXInt=10, inYInt=10, inWInt=550,
inHInt=350) # Prepare little window
@ -233,6 +263,19 @@ def SessionIsFullScreen(inSessionHexStr):
if lSessionHeight == lHeight and lSessionWeight == lWeight:
lResult = True
return lResult
# Check if session is in minimized screen mode
# Return True - is in minimized
# example print(Connector.SessionIsFullScreen(""))
def SessionIsMinimizedScreen(inSessionHexStr):
#Default result
lResult = False
#Get window screen
try:
lResult = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).is_minimized()
except Exception as e:
pass
return lResult
# Check if RDP session is responsible (check with random combination in cmd)
# Attention - function will be work fine if RDP will be in full screen mode!!! (see def SessionScreenFull)
# Return True - is responsible; False - is not responsible
@ -248,46 +291,90 @@ def SessionIsFullScreen(inSessionHexStr):
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SystemCMDRun(inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5):
# Set random text to clipboard (for check purposes that clipboard text has been changed)
lClipboardTextOld = str(random.randrange(999,9999999))
def SystemCMDRun(inSessionHexStr, inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5, inLogger = None):
lRDPWindow = None # Init the UI object
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}])
except Exception as e:
raise ConnectorExceptions.SessionWindowNotExistError() # Raise error of gui window
lL = inLogger # Alias for logger
lResult = {"OutStr": None,"IsResponsibleBool":True} # Init the result dict
lClipboardTextOld = str(random.randrange(999,9999999)) # Set random text to clipboard (for check purposes that clipboard text has been changed)
Clipboard.TextSet(lClipboardTextOld)
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
lCrosscheckKeyStr = str(random.randrange(999,9999999))
lCMDPostFixStr = "" # Case default "RUN"
if inModeStr == "CROSSCHECK":
lCMDPostFixStr = f"| echo {lCrosscheckKeyStr} | clip"
elif inModeStr == "LISTEN":
lCMDPostFixStr = f"| clip"
keyboard.press_and_release('win+r')
time.sleep(1)
# Remove old text
keyboard.press_and_release("ctrl+a")
keyboard.press_and_release("backspace")
# Write new text
keyboard.write(f"cmd /c {inCMDCommandStr} {lCMDPostFixStr}")
time.sleep(1)
# TODo cross check from clipboard
keyboard.press_and_release('enter')
# Get OutStr (Case CROSSCHECK and LISTEN)
if inModeStr == "CROSSCHECK" or inModeStr == "LISTEN":
lClipboardWaitTimeStartSec = time.time()
lResult["OutStr"] = Clipboard.TextGet() # Get text from clipboard
while lResult["OutStr"] == lClipboardTextOld and (time.time() - lClipboardWaitTimeStartSec) <= inClipboardTimeoutSec:
lRecoveryCMDResponsibleRetryIteratorInt = 0 # Init the retry iterator
while lRecoveryCMDResponsibleRetryIteratorInt<gRecoveryCMDResponsibleRetryCountInt: # loop for retry
# # # # # # # # # # # # # OPEN WINDOW RUN # # # # # # # # # # # # # # #
lRecoveryWindowRUNRetryIteratorInt = 0 # Init the retry iterator
while lRecoveryWindowRUNRetryIteratorInt<gRecoveryWindowRUNRetryCountInt: # loop for retry
lCMDPostFixStr = "" # Case default "RUN"
if inModeStr == "CROSSCHECK":
lCMDPostFixStr = f"& (echo {lCrosscheckKeyStr} | clip)"
elif inModeStr == "LISTEN":
lCMDPostFixStr = f"| clip"
keyboard.press_and_release('win+r')
time.sleep(1) # Wait for RUN window will appear
lRDPWindow.type_keys("^(a)") # Select all
keyboard.press_and_release("backspace") # Delete selected all
time.sleep(0.5) # Wait for RUN window will appear ctrl+a+backspace is async - so we need some timeout...
lInputStr = f"cmd /c ({inCMDCommandStr}) {lCMDPostFixStr}" # Generate the output string for RUN window
keyboard.write(lInputStr) # Write new text
time.sleep(0.5)
lRDPWindow.type_keys("^(a)") # Select all
lRDPWindow.type_keys("^(c)") # Copy data
# Check the clipboard
lClipboardWaitTimeStartSec = time.time()
lClipboardStr = Clipboard.TextGet() # Get text from clipboard
while lClipboardStr != lInputStr and (time.time() - lClipboardWaitTimeStartSec) <= inClipboardTimeoutSec:
lClipboardStr = Clipboard.TextGet() # Get text from clipboard
time.sleep(0.5) # wait some time for the next operation
if lClipboardStr == lInputStr: # Cross check the clipboard data and input string
lRecoveryWindowRUNRetryIteratorInt = gRecoveryWindowRUNRetryCountInt # Set final count to block the loop
else: # Failed - wait and retry
if lL: lL.warning(f"RDP::SystemCMDRun: Window run doesn't appear. Wait for {gRecoveryWindowRUNRetryIntervalSecInt}[s.] and retry. Current retry iterator is {lRecoveryWindowRUNRetryIteratorInt}. CMD Str: {lInputStr}") # Log the error
lRecoveryWindowRUNRetryIteratorInt = lRecoveryWindowRUNRetryIteratorInt + 1 # Increment the iterator
if lRecoveryWindowRUNRetryIteratorInt == gRecoveryWindowRUNRetryCountInt:
if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error. CMD Str: {lInputStr}") # Log the error
raise ConnectorExceptions.RUNExistError() # Raise the error
time.sleep(gRecoveryWindowRUNRetryIntervalSecInt) # wait for some seconds before new iteration
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # RUN CMD # # # # # # # # # # # # # # #
keyboard.press_and_release('enter') # Execute CMD
if inModeStr == "CROSSCHECK" or inModeStr == "LISTEN": # Get OutStr (Case CROSSCHECK and LISTEN)
lClipboardWaitTimeStartSec = time.time()
lResult["OutStr"] = Clipboard.TextGet() # Get text from clipboard
time.sleep(0.5) # wait some time for the next operation
# Do crosscheck
if inModeStr == "CROSSCHECK":
if lResult["OutStr"] == f"{lCrosscheckKeyStr} \r\n\x00\x00\x00\x00\x00":
lResult["IsResponsibleBool"] = True
else:
lResult["IsResponsibleBool"] = False
# return the result
return lResult
while lResult["OutStr"] == lClipboardTextOld and (time.time() - lClipboardWaitTimeStartSec) <= inClipboardTimeoutSec:
lResult["OutStr"] = Clipboard.TextGet() # Get text from clipboard
time.sleep(0.5) # wait some time for the next operation
if lResult["OutStr"] == lClipboardTextOld: # If value hasn't been changed - retry send
lRecoveryCMDResponsibleRetryIteratorInt = lRecoveryCMDResponsibleRetryIteratorInt + 1 # increment the iterator
if lL: lL.warning(f"RDP::SystemCMDRun: CMD command doesn't been executed (no changes in clipboard data). Wait for {gRecoveryCMDResponsibleRetryIntervalSecInt}[s.] and retry from start window RUN. Current retry iterator is {lRecoveryCMDResponsibleRetryIteratorInt}. CMD Str: {lInputStr}, Clipboard data: {lResult['OutStr']}") # Log the error
if lRecoveryCMDResponsibleRetryIteratorInt >= gRecoveryCMDResponsibleRetryCountInt: # raise the error if retry count is exceeded
if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error.") # Log the error
raise ConnectorExceptions.CMDResponsibleError() # Raise the error
time.sleep(gRecoveryCMDResponsibleRetryIntervalSecInt) # wait for some seconds before new iteration
else: # Data was recieved - do crosscheck
if inModeStr == "CROSSCHECK":
if lResult["OutStr"] == f"{lCrosscheckKeyStr} \r\n\x00\x00\x00\x00\x00": # it is ok - do futher check
lResult["IsResponsibleBool"] = True
lRecoveryCMDResponsibleRetryIteratorInt = gRecoveryCMDResponsibleRetryCountInt # turn off the iterator
else:
lResult["IsResponsibleBool"] = False
lRecoveryCMDResponsibleRetryIteratorInt = lRecoveryCMDResponsibleRetryIteratorInt + 1 # increment the iterator
if lL: lL.warning(f"RDP::SystemCMDRun: CMD command doesn't been executed (wrong clipboard data). Wait for {gRecoveryCMDResponsibleRetryIntervalSecInt}[s.] and retry from start window RUN. Current retry iterator is {lRecoveryCMDResponsibleRetryIteratorInt}. CMD Str: {lInputStr}, Clipboard data: {lResult['OutStr']}") # Log the error
if lRecoveryCMDResponsibleRetryIteratorInt >= gRecoveryCMDResponsibleRetryCountInt: # raise the error if retry count is exceeded
if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error.") # Log the error
raise ConnectorExceptions.CMDResponsibleError() # Raise the error
time.sleep(gRecoveryCMDResponsibleRetryIntervalSecInt) # wait for some seconds before new iteration
else: # clipboard data has been changed but mode is not crosscheck - return success from function
lRecoveryCMDResponsibleRetryIteratorInt = gRecoveryCMDResponsibleRetryCountInt # turn off the iterator
else: # Success - no cross validation is aaplicable
lRecoveryCMDResponsibleRetryIteratorInt = gRecoveryCMDResponsibleRetryCountInt # turn off the iterator
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
return lResult # return the result
# Check if current RDP is responsible
def SystemRDPIsResponsible():
return SystemCMDRun(inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK")["IsResponsibleBool"]
def SystemRDPIsResponsible(inSessionHexStr):
return SystemCMDRun(inSessionHexStr = inSessionHexStr, inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK")["IsResponsibleBool"]
# Click OK on error messages
def SystemRDPWarningClickOk():
# Try to click OK Error window in RUS version

@ -2,7 +2,9 @@
# RobotRDPActive Exceptions class
#####################################
class SessionWindowNotExistError(Exception): pass #Error when Window not exists
class SessionWindowNotResponsibleError(Exception): pass # Error when Window not responding
class SessionWindowNotResponsibleError(Exception): pass # Error when Window not responding to delete
class RUNExistError(Exception): pass # Error when RUN window not identified
class CMDResponsibleError(Exception): pass # Error when command is not return
class HostNoGUIError(Exception): pass # Orchestrator session has no GUI
#try:
# raise SessionWindowNotResponsibleError("Test")

@ -1,66 +0,0 @@
# ATTENTION! HERE IS NO Relative import because it will be imported dynamically
# All function check the flag SessionIsWindowResponsibleBool == True else no cammand is processed
# All functions can return None, Bool or Dict { "IsSuccessful": True }
from pyOpenRPA.Tools.RobotRDPActive import CMDStr # Create CMD Strings
from pyOpenRPA.Tools.RobotRDPActive import Connector # RDP API
def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True):
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStartIfNotRunning: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Create CMD str to stop process
def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose):
lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# TODO Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStop: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def FileStoredSend(inGlobalDict, inSessionIndex, inHostFilePath, inRDPFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePath, inRDPFilePath = inRDPFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredSend: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def FileStoredRecieve(inGlobalDict, inSessionIndex, inRDPFilePath, inHostFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePath, inHostFilePath = inHostFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredRecieve: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult

@ -1,158 +0,0 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import time # Time wait operations
import importlib # from dynamic import module
from . import ConnectorExceptions # Exceptions classes
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True
lResponsibilityCheckLastSec = time.time() # Get current time for check interval
while lFlagWhile:
try:
# UIOSelector list init
lUIOSelectorList = []
#Prepare selectors list for check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
#Run wait command
#import pdb
#pdb.set_trace()
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#print(lRDPDissappearList)
###########################################
#Analyze if flag safeturn off is activated
if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
lFlagWhile=False
#Set status disconnected for all RDP List
for lItem in inGlobalDict["RDPList"]:
lItem["SessionIsWindowExistBool"]=False
lItem["SessionIsWindowResponsibleBool"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
###########################################
###########################################
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
#pdb.set_trace()
#Session start if it is not in ignore list
#add check for selector if it is not in ignoreIndexList
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Flag that session is started
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]= True
# Write in logger - info
inGlobalDict["Logger"].info(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session has been initialized!")
# catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not exist!")
# catch ConnectorExceptions.SessionWindowNotResponsibleError
except ConnectorExceptions.SessionWindowNotResponsibleError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not responsible!")
# general exceptions
except Exception as e:
# Write in logger - warning
inGlobalDict["Logger"].exception(f"!!! ATTENTION !!! Unrecognized error")
#######################
# Click all warning messages
Connector.SystemRDPWarningClickOk()
#######################
###########################################
#Check if from Orchestrator full screen session is set
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] != inGlobalDict["FullScreenSessionIndex"]:
#Do some switches
#If full screen mode we have now
if inGlobalDict["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreen100x550(inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionHex"])
#If new session is setted
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"])
#Set one to other equal
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]
###########################################
####################################
##### Block check responsibility interval [ResponsibilityCheckIntervalSec]
if inGlobalDict['ResponsibilityCheckIntervalSec']: # Do check if ResponsibilityCheckIntervalSec is not None
if (time.time - lResponsibilityCheckLastSec()) > inGlobalDict['ResponsibilityCheckIntervalSec']:
# Set new time
lResponsibilityCheckLastSec = time.time()
# Do responsibility check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
# Check RDP responsibility
lDoCheckResponsibilityBool = True
lDoCheckResponsibilityCountMax = 20
lDoCheckResponsibilityCountCurrent = 0
while lDoCheckResponsibilityBool:
# Enter full screen mode
Connector.SessionScreenFull(lItem['SessionHex'])
time.sleep(2)
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
# Check if counter is exceed - raise exception
if lDoCheckResponsibilityCountCurrent >= lDoCheckResponsibilityCountMax:
lItem["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
lItem["SessionIsWindowResponsibleBool"]=False
# Session window is not responsible - restart RDP (close window here - next loop will reconnect)
Connector.SessionClose(lItem['SessionHex'])
# Turn off the loop
lDoCheckResponsibilityBool = False
else:
# Exit fullscreen mode
Connector.SessionScreen100x550(lItem['SessionHex'])
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
# increase the couter
lDoCheckResponsibilityCountCurrent+=1
####################################
# Check ActivityList from orchestrator
lActivityListNew = []
lActivityListOld = inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]+inGlobalDict["ActivityListStart"]
inGlobalDict["ActivityListStart"] = []
for lActivityItem in lActivityListOld:
#################
#Call function from Activity structure
################################################
lSubmoduleFunctionName = lActivityItem["DefName"]
lFileFullPath = lActivityItem["ModulePath"] # "path\\to\\module.py"
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
# Set gSettings in module
lTechModuleFromSpec.gSettings = inGlobalDict
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lActivityItemResult=getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"])
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
if lActivityItemResultType is bool:
if not lActivityItemResult:
# Activity is not done - add to list (retry in future)
lActivityListNew.append(lActivityItem)
#################################################
inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = lActivityListNew # Override the value
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Host session has lost the GUI")
finally:
# Wait for the next iteration
time.sleep(0.7)
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -30,10 +30,9 @@ def RDPSessionConnect(inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPa
"SessionIsWindowResponsibleBool": False, # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False
"SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False
}
# Add item in RDPList
gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem
# Create the RDP session
Connector.Session(lRDPConfigurationItem)
gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem # Add item in RDPList
Connector.Session(lRDPConfigurationItem) # Create the RDP session
Connector.SystemRDPWarningClickOk() # Click all warning messages
return True
# Disconnect the RDP session
@ -43,6 +42,7 @@ def RDPSessionDisconnect(inRDPSessionKeyStr):
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
Connector.SessionClose(inSessionHexStr=lSessionHex)
Connector.SystemRDPWarningClickOk() # Click all warning messages
return True
# RDP Session reconnect
@ -64,18 +64,19 @@ def RDPSessionLogoff(inRDPSessionKeyStr):
# Calculate the session Hex
lSessionHex = gSettings["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="CROSSCHECK", inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None) # Remove item from RDPList
return lResult
# Check RDP Session responsibility TODO NEED DEV + TEST
def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
global gSettings
inGlobalDict = gSettings
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
lRDPConfigurationItem = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] # Get the alias
# set the fullscreen
Connector.SessionScreenFull(inSessionHex=lSessionHex)
# ATTENTION!!! Session hex can be updated!!!
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationItem["SessionHex"], inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
time.sleep(1)
# Check RDP responsibility
lDoCheckResponsibilityBool = True
@ -87,7 +88,7 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
pass
#raise ConnectorExceptions.SessionWindowNotResponsibleError("Error when initialize the RDP session - RDP window is not responding!")
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible(inSessionHexStr = lRDPConfigurationItem["SessionHex"])
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
@ -105,7 +106,7 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr,
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="CROSSCHECK", inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult
# Create CMD str to stop process
def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool):
@ -119,7 +120,7 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="CROSSCHECK", inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr):
@ -132,7 +133,7 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat
#lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120, inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr):
@ -144,5 +145,5 @@ def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFile
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120, inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult

@ -9,9 +9,7 @@ def RobotRDPActive(inGSettings):
# inGSettings = {
# ... "RobotRDPActive": {} ...
# }
#import pdb
#pdb.set_trace()
lLogger = inGSettings["Logger"] # Synonim
lL = inGSettings["Logger"] #Logger alias
Processor.gSettings = inGSettings # Set gSettings in processor module
mGSettingsRDPActiveDict = inGSettings["RobotRDPActive"] # Get configuration from global dict settings
# Global error handler
@ -48,21 +46,17 @@ def RobotRDPActive(inGSettings):
# Check if RDP window is not ignored
if not lRDPConfigurationDict["SessionIsIgnoredBool"]:
try:
Connector.Session(lRDPConfigurationDict)
Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True)
lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started
# Write in logger - info
lLogger.info(
f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!")
if lL: lL.info(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!") #Logging
# catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e:
lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
# Write in logger - warning
lLogger.warning(
f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist!")
if lL: lL.warning(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist!") #Logging
# general exceptions
except Exception as e:
# Write in logger - warning
lLogger.exception(f"!!! ATTENTION !!! Unrecognized error")
if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging
pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Safe turn off the - no need because of Orchestrator control
@ -96,18 +90,17 @@ def RobotRDPActive(inGSettings):
inWInt=550,
inHInt=350) # Prepare little window
# Set full screen for new window
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"])
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"], inLogger= inGSettings["Logger"], inRDPConfigurationItem=inGlobalDict["RDPList"][lRDPSessionKeyStrItem])
else:
# Check all RDP window and minimize it
for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]:
lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem]
if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]):
if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]) or Connector.SessionIsMinimizedScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): # If window is minimized - restore # if window in full screen - resize
Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"],
inXInt=10, inYInt=10,
inWInt=550,
inHInt=350) # Prepare little window
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Iterate the activity list in robot RDP active
lActivityListNew = []
lActivityListOld = inGlobalDict["ActivityList"]
@ -115,10 +108,13 @@ def RobotRDPActive(inGSettings):
for lActivityItem in lActivityListOld:
lSubmoduleFunctionName = lActivityItem["DefNameStr"]
if lSubmoduleFunctionName in dir(Processor):
# Run SettingUpdate function in submodule
# mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"])
lActivityItemResult = None # init the variable
try: # try to run function from Processor.py
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"])
except Exception as e:
if lL: lL.exception(f"RDP::main: Exception when run def in processor.py - activity will be ignored. Activity item: {lActivityItem}") #Logging
lActivityItemResult = True # True - clear from repeat list
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
if lActivityItemResultType is bool:
@ -129,8 +125,7 @@ def RobotRDPActive(inGSettings):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
lLogger.warning(f"Host session has lost the GUI")
if lL: lL.warning(f"Host session has lost the GUI") #Logging
finally:
# Wait for the next iteration
time.sleep(0.7)
@ -138,5 +133,4 @@ def RobotRDPActive(inGSettings):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1)
except Exception as e:
# Write in logger - warning
lLogger.exception(f"!!! ATTENTION !!! Global error handler - look at code")
if lL: lL.exception(f"!!! ATTENTION !!! Global error handler - look at code") #Logging

@ -254,6 +254,34 @@
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Escape onclick
/// RenderRobotList
lResponseJSON["RenderRobotList"].forEach(
function(lItem){
if ('FooterButtonX2List' in lItem) {
/// FooterButtonX2List
lItem["FooterButtonX2List"].forEach(
function(lItem2){
if ('OnClick' in lItem) {
lOnClickEscaped = lItem["OnClick"];
lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
lItem["OnClick"] = lOnClickEscaped;
}
}
);
/// FooterButtonX1List
lItem["FooterButtonX1List"].forEach(
function(lItem2){
if ('OnClick' in lItem) {
lOnClickEscaped = lItem["OnClick"];
lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
lItem["OnClick"] = lOnClickEscaped;
}
}
);
}
}
);
///Сформировать HTML код новой таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-control-panel",lResponseJSON)
//Присвоить ответ в mGlobal.Monitor.mResponseList

@ -1,4 +0,0 @@
1. [+] Убрать префикс orchestrator так как он и так находится в папке Orchestrator/ OrchestratorMain > Orchestrator
2. [+] Консолидировать выполнение всех действий через orchestratorProcessor
3. [+] Свести в планарную структуру inConfiguration. Логи сейчас формируются за предалали этой структуры - возникает двойное трактование
4. [+] Рефакторинг конфигурации до конца вместе с консолидацией orchestratorProcessor

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.1.2'
__version__ = 'v1.1.3'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pyOpenRPA
Version: 1.1.2
Version: 1.1.3
Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov

@ -1,8 +1,8 @@
pyOpenRPA-1.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.2.dist-info/METADATA,sha256=i36JUYLUfNOz4jax1gu2KxREFioKKXo4g6oS6ZVo-n0,3541
pyOpenRPA-1.1.2.dist-info/RECORD,,
pyOpenRPA-1.1.2.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.2.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA-1.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.3.dist-info/METADATA,sha256=ObJb3J2niW85Wzoh8Uy_TC99RYMif_Ipn-QwE7NSv_8,3541
pyOpenRPA-1.1.3.dist-info/RECORD,,
pyOpenRPA-1.1.3.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.3.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174
pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203
pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277
@ -10,17 +10,14 @@ pyOpenRPA/.idea/pyOpenRPA.iml,sha256=EXh41F8lqRiSBMVg-n2tKaEaHC6_3gGSuKkPJA12Na0
pyOpenRPA/.idea/vcs.xml,sha256=2HygA1oRAwc3VBf-irxHrX5JJG9DXuQwrN0BlubhoKY,191
pyOpenRPA/.idea/workspace.xml,sha256=kcCP7x0iSOAWJdy7YtntGrgsQ04QIq0b6_9w04DKxfg,2555
pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
pyOpenRPA/Orchestrator/HowToUse.txt,sha256=ZcIgNvPUhzN0XFElqDirlm07fUb7QKLVjzvNrTk4a7k,148
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=0Q4VYZPdXV2qmLuowMWD_vERj1GQurQx_VFwfsxuucQ,7076
pyOpenRPA/Orchestrator/Processor.py,sha256=zSsNWZtuKX5Y3q5iYCVdPpv2X7x-XzcTe5_w2CNUJ6E,12780
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=iVp7DlLZHsURBOBegfDG4LanqSrI0A5a6GebP1cBOnI,8301
pyOpenRPA/Orchestrator/Processor.py,sha256=mPSv3xO1ah1BzhQdfltt77_tJrmKP9CAfwqeFAqeTFY,11364
pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=YB5HJL-Qf4IlVrFHyRv_ZMJ0Vo4vjyYqWKjvrTnf1k4,1564
pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=2nm5S_FOfnLkDVdlm2MVag9vL3DlyJ98LnwYNMzFNho,15914
pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=WgGqWoPAnMeXpI_w3iuFX0KUBssvlSk9MuPBuIsNOuY,491
pyOpenRPA/Orchestrator/RobotRDPActive/GlobalDictSessionIndex_Defs.py,sha256=4BbAozLyOlXJxNw0NAlHt38-AyV-B6-Nl1M1AY8CTtk,4212
pyOpenRPA/Orchestrator/RobotRDPActive/Monitor.py,sha256=Y4mhNslK0EBS1LIDfK67j3lkjTZSU5xq-HUl9XNKW-U,10609
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=v-xwXHEbslqCO6QgzQdnw38pyKCQEAKf-GDVhnSyfcU,7649
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=vsISwvRTMbbEtL_u9PU-rP6W71VUhAUBLMblOSGp2BE,9893
pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=8H_7KTUy_9m4FwbXIlDBUdX4-z3RtsaQRmYzSVdpBIU,25171
pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=goBIuwTmpdiAkimhrsqy3Y41BeljUsMQO8TaZgpx0I0,8650
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=_dZQWv1lUMV8VwzeL2GclU4ZodNcYiEF7uKLrsYZjOI,10137
pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144
pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=JEMVYkEmNcfg_p8isdIyvj9E-2ZB5mj-R3MkcNMKxkA,2426
pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077
@ -30,8 +27,6 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/CMDStr.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Clipboard.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/ConnectorExceptions.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/GlobalDictSessionIndex_Defs.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Processor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/RobotRDPActive.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,,
@ -41,7 +36,7 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=gqJO6FRDKTBZytJVdJgPF1PvOf05qYUyKDBJJkEpLzk,22755
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=mpPAxAe6PvmKaZlreaoQAy_5wV80edz_0qc-iFrEmBQ,7123
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=UpIkCcR7cfkbUS0vNiyWpeR2wXg8uFBFJplT4BF0qKI,37145
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=giviLTJ1GJyVayvPski2GkcB6Wd2MFYVw5yK6gSsx84,38272
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -52,7 +47,6 @@ pyOpenRPA/Orchestrator/__pycache__/ServerSettings.cpython-37.pyc,,
pyOpenRPA/Orchestrator/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/todo.txt,sha256=OAjkuE770VZ_w1yXt6qNUT03prhODvQ0ivVoUvFLIps,419
pyOpenRPA/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293
pyOpenRPA/Resources/Web/Google/LatoItalic.css,sha256=pB6OZ6F2VsaqkL-g5hW-wE_T0m9H_NltzmzjX-XAKDk,3112
pyOpenRPA/Resources/Web/Handlebars/handlebars-v4.1.2.js,sha256=h6O4BrhyPtJspLDEQwogC53uHFRozuBpxvN2S4tJHE8,171994
@ -306,6 +300,6 @@ pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=mx0F70tuKb-PzNALCeEZI3ZZcgHLBu8dsv1ILrNNH_s,174
pyOpenRPA/__init__.py,sha256=zLXCLfZm0anOTnxES7ijiJFJqTniSxBCuqjNArOBU5Q,174
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -1,2 +0,0 @@
1. Настроить конфигурацию запуска/остановки robotDaemonConfiguration.json
2. Запустить исполняемый файл демона runProcessOpenRPARobotDaemon_x32.cmd

@ -10,13 +10,13 @@ import pdb
from . import Server
from . import Timer
from . import Processor
import logging
import copy
#from .Settings import Settings
import importlib
from importlib import util
import threading # Multi-threading for RobotRDPActive
from .RobotRDPActive import RobotRDPActive #Start robot rdp active
import uuid # Generate uuid
#Единый глобальный словарь (За основу взять из Settings.py)
global gSettingsDict
@ -34,6 +34,10 @@ if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
#mGlobalDict = Settings.Settings(sys.argv[1])
#Logger alias
lL = gSettingsDict["Logger"]
if lL: lL.info("Link the gSettings in submodules") #Logging
Processor.gSettingsDict = gSettingsDict
Timer.gSettingsDict = gSettingsDict
Timer.Processor.gSettingsDict = gSettingsDict
@ -43,34 +47,56 @@ Server.Processor.gSettingsDict = gSettingsDict
#Инициализация настроечных параметров
lDaemonLoopSeconds=gSettingsDict["Scheduler"]["ActivityTimeCheckLoopSeconds"]
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
lDaemonStartDateTime=datetime.datetime.now()
lDaemonLastDateTime=datetime.datetime.now()
#Инициализация сервера
lThreadServer = Server.RobotDaemonServer("ServerThread", gSettingsDict)
lThreadServer.start()
if lL: lL.info("Web server has been started") #Logging
# Init the RobotRDPActive in another thread
lRobotRDPActiveThread = threading.Thread(target= RobotRDPActive.RobotRDPActive, kwargs={"inGSettings":gSettingsDict})
lRobotRDPActiveThread.daemon = True # Run the thread in daemon mode.
lRobotRDPActiveThread.start() # Start the thread execution.
#Logging
gSettingsDict["Logger"].info("Scheduler loop init")
# Выполнить активности при старте
if lL: lL.info("Robot RDP active has been started") #Logging
# Orchestrator start activity
if lL: lL.info("Orchestrator start activity run") #Logging
for lActivityItem in gSettingsDict["OrchestratorStart"]["ActivityList"]:
Processor.ActivityListOrDict(lActivityItem)
#Вечный цикл
if lL: lL.info("Scheduler loop start") #Logging
gDaemonActivityLogDictRefreshSecInt = 10 # The second period for clear lDaemonActivityLogDict from old items
gDaemonActivityLogDictLastTime = time.time() # The second perioad for clean lDaemonActivityLogDict from old items
while True:
lCurrentDateTime = datetime.datetime.now()
#Циклический обход правил
lFlagSearchActivityType=True
# Periodically clear the lDaemonActivityLogDict
if time.time()-gDaemonActivityLogDictLastTime>=gDaemonActivityLogDictRefreshSecInt:
gDaemonActivityLogDictLastTime = time.time() # Update the time
for lIndex, lItem in enumerate(lDaemonActivityLogDict):
if lItem["ActivityEndDateTime"] and lCurrentDateTime<=lItem["ActivityEndDateTime"]:
pass
# Activity is actual - do not delete now
else:
# remove the activity - not actual
lDaemonActivityLogDict.pop(lIndex,None)
lIterationLastDateTime = lDaemonLastDateTime # Get current datetime before iterator (need for iterate all activities in loop)
# Iterate throught the activity list
for lIndex, lItem in enumerate(gSettingsDict["Scheduler"]["ActivityTimeList"]):
# Prepare GUID of the activity
lGUID = None
if "GUID" in lItem and lItem["GUID"]:
lGUID = lItem["GUID"]
else:
lGUID = str(uuid.uuid4())
lItem["GUID"]=lGUID
#Проверка дней недели, в рамках которых можно запускать активность
lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6])
if lCurrentDateTime.weekday() in lItemWeekdayList:
if lFlagSearchActivityType:
#Лог
lItemCopy = copy.deepcopy(lItem)
lItemCopy["DateTimeUTCStringStart"]=datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f")
gSettingsDict["Scheduler"]["LogList"].append(lItemCopy)
#######################################################################
#Branch 1 - if has TimeHH:MM
#######################################################################
@ -82,16 +108,15 @@ while True:
lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
#Убедиться в том, что время наступило
if (
lActivityDateTime>=lDaemonStartDateTime and
lCurrentDateTime>=lActivityDateTime and
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
#Выполнить операцию
#Запись в массив отработанных активностей
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
#Запустить процесс
lActivityDateTime>=lDaemonLastDateTime and
lCurrentDateTime>=lActivityDateTime):
# Log info about activity
if lL: lL.info(f"Scheduler:: Activity is started. Scheduler item: {lItem}") #Logging
# Do the activity
Processor.ActivityListOrDict(lItem["Activity"])
lIterationLastDateTime = datetime.datetime.now() # Set the new datetime for the new processor activity
#######################################################################
#Banch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
#Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
#######################################################################
if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem:
#Сформировать временной штамп, относительно которого надо будет проверять время
@ -104,10 +129,11 @@ while True:
if (
lCurrentDateTime<lActivityTimeEndDateTime and
lCurrentDateTime>=lActivityDateTime and
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
(lGUID,lActivityDateTime) not in lDaemonActivityLogDict):
#Запись в массив отработанных активностей
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
lDaemonActivityLogDict[(lGUID,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime, "ActivityEndDateTime":lActivityTimeEndDateTime}
#Запуск циклической процедуры
Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"])
lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity
#Уснуть до следующего прогона
time.sleep(lDaemonLoopSeconds)

@ -5,7 +5,6 @@ import pdb
import os
import sys
import subprocess
import copy
import importlib
import psutil
#Input arg
@ -46,14 +45,12 @@ import psutil
# "Type":"ProcessStart",
# "Path":"",
# "ArgList":[]
#
# },
# {
# "Type":"ProcessStartIfTurnedOff",
# "CheckTaskName":"", #Check if current task name is not active (then start process),
# "Path":"",
# "ArgList":[]
#
# },
# {
# "Type":"ProcessStop",
@ -86,8 +83,6 @@ gSettingsDict = None
def Activity(inActivity):
#Глобальная переменная - глобальный словарь унаследованный от Settings.py
global gSettingsDict
#Fill DateTimeUTCStringStart
inActivity["DateTimeUTCStringStart"] = datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f")
#Alias (compatibility)
lItem = inActivity
lCurrentDateTime = datetime.datetime.now()
@ -179,16 +174,12 @@ def Activity(inActivity):
lDict=lDict[lItem2]
#Return value
lItem["Result"]=lDict.get(lItem["KeyList"][-1],None)
#Определить вид активности
lActivityDateTime=inActivity["DateTimeUTCStringStart"]
#####################################
#ProcessStart
#####################################
if lItem["Type"]=="ProcessStart":
#Вид активности - запуск процесса
#Запись в массив отработанных активностей
#Лог
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
#Запустить процесс
lItemArgs=[lItem["Path"]]
lItemArgs.extend(lItem["ArgList"])
@ -209,8 +200,6 @@ def Activity(inActivity):
if not CheckIfProcessRunning(lCheckTaskName):
#Вид активности - запуск процесса
#Запись в массив отработанных активностей
#Лог
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
#Запустить процесс
lItemArgs=[lItem["Path"]]
lItemArgs.extend(lItem["ArgList"])
@ -229,8 +218,6 @@ def Activity(inActivity):
#Завершить процессы только текущего пользоваиеля
if lItem.get('User',"")!="":
lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"'
#Лог
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Name"], "activityStartDateTime":str(lCurrentDateTime)})
#Завершить процесс
os.system(lActivityCloseCommand)
#################################
@ -263,15 +250,6 @@ def Activity(inActivity):
else:
lItem["Result"] = True
###################################
#Set datetime stop
lItem["DateTimeUTCStringStop"] = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")
##################
#Trace activity
##################
#print(mGlobalDict)
if gSettingsDict["Processor"].get(f"LogType_{lItem['Type']}", True):
#Add activity in TransactionList if it is applicable
gSettingsDict["Processor"]["LogList"].append(copy.deepcopy(lItem))
#Вернуть результат
return lItem

@ -10,6 +10,17 @@ import keyboard # Keyboard functions
import time
import random # random integers
from win32api import GetSystemMetrics # Get Screen rect
import pyautogui # for hotkey operations
# System variables for recovery scenario
gRecoveryWindowRDPRetryCountInt = 3 # Retry iteration count is RDP window is not responsible
gRecoveryWindowRDPRetryIntervalSecInt = 3 # Retry interval for reconnect
gRecoveryWindowRUNRetryCountInt = 3 # Retry iteration count is RUN window is not responsible
gRecoveryWindowRUNRetryIntervalSecInt = 3 # Retry interval for retry
gRecoveryCMDResponsibleRetryCountInt = 3 # Retry iteration count is CMD is not responsible
gRecoveryCMDResponsibleRetryIntervalSecInt = 3 # Retry interval for retry
#Connect to RDP session
"""
{
@ -24,7 +35,7 @@ from win32api import GetSystemMetrics # Get Screen rect
}
}
"""
def Session(inRDPSessionConfiguration):
def Session(inRDPSessionConfiguration, inScreenSize550x350Bool = False):
#RDPConnector.SessionConnect(mConfiguration)
#RDPConnector.LoginPassSet("111.222.222.111","ww","dd")
(lRDPFile, lSessionHex) = SessionConfigurationCreate(inRDPSessionConfiguration)
@ -33,7 +44,7 @@ def Session(inRDPSessionConfiguration):
#Set login/password
SessionLoginPasswordSet(inRDPSessionConfiguration["Host"],inRDPSessionConfiguration["Login"],inRDPSessionConfiguration["Password"])
#Start session
SessionRDPStart(lRDPFile)
SessionRDPStart(lRDPFile, inScreenSize550x350Bool= inScreenSize550x350Bool)
#Remove temp file
time.sleep(4) #Delete file after some delay - one way to delete and run the RDP before because RDP is not read file in one moment
os.remove(lRDPFile) # delete the temp rdp
@ -79,7 +90,7 @@ def SessionConfigurationCreate(inConfiguration):
#Return .rdp full path
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart
def SessionRDPStart(inRDPFilePath):
def SessionRDPStart(inRDPFilePath, inScreenSize550x350Bool = False):
#Disable certificate warning
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f'
os.system(lCMDString)
@ -137,24 +148,43 @@ def SessionRDPStart(inRDPFilePath):
# Raise exception if RDP is not active
if len(lWaitResult) == 0:
raise ConnectorExceptions.SessionWindowNotExistError("Error when initialize the RDP session - No RDP windows has appreared!")
# Wait for init
time.sleep(3)
SessionScreenSize_X_Y_W_H(inSessionHex = lRDPFileName, inXInt = 10, inYInt = 10, inWInt = 550, inHInt = 350) #Prepare little window
time.sleep(3) # Wait for init
if inScreenSize550x350Bool: SessionScreenSize_X_Y_W_H(inSessionHex = lRDPFileName, inXInt = 10, inYInt = 10, inWInt = 550, inHInt = 350) #Prepare little window
return None
#Set fullscreen for app
def SessionScreenFull(inSessionHex):
#Prepare little window
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
except Exception as e:
return None
lRDPWindow.set_focus()
lRDPWindow.maximize()
#time.sleep(0.5)
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
def SessionScreenFull(inSessionHex, inLogger = None, inRDPConfigurationItem = None):
########################################
lWindowRDPRetryIterator = 0 # Retry iterator if RDP window is not active
lRDPConfigurationItem = inRDPConfigurationItem # Get the RDP configuration item
lL = inLogger # Get the logger instance
lRDPWindow = None # Init the variable
while lWindowRDPRetryIterator<gRecoveryWindowRDPRetryCountInt: # Loop iteration to connect to RDP
try: # Try to get RDP window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lWindowRDPRetryIterator = gRecoveryWindowRDPRetryCountInt # Set last iterator to turn off the loop
# RDP window has been detected - go to set focus and maximize
lRDPWindow.set_focus()
lRDPWindow.maximize()
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
except Exception as e: # RDP window is not exist - try to reconnect
if lL: lL.warning(f"RDP::SessionScreenFull: RDP window is not exist - try sleep {gRecoveryWindowRDPRetryIntervalSecInt}[s.] and then to reconnect. SessionHex: {inSessionHex}. Current retry iterator is {lWindowRDPRetryIterator}")
if lRDPConfigurationItem:
time.sleep(gRecoveryWindowRDPRetryIntervalSecInt) # Before try to reconnect sleep
# Try to reconnect the RDP
SessionClose(inSessionHexStr=inSessionHex) # Close the
Session(lRDPConfigurationItem) # Create RDP session
inSessionHex = lRDPConfigurationItem["SessionHex"] # Get new session hex after reconnect
SystemRDPWarningClickOk() # Click all warning messages
lWindowRDPRetryIterator = lWindowRDPRetryIterator + 1 # increase the iterator
if lWindowRDPRetryIterator >= gRecoveryWindowRDPRetryCountInt: # Raise the error if retry count is over
if lL: lL.warning(f"RDP::SessionScreenFull: Retry count is over. Raise the error. SessionHex: {inSessionHex}.") # Log the info
raise ConnectorExceptions.SessionWindowNotExistError() # raise the error
else:
if lL: lL.warning(f"RDP::SessionScreenFull: Has no RDP configuration item - don't reconnect. Raise the error. SessionHex: {inSessionHex}") # Log the info
raise ConnectorExceptions.SessionWindowNotExistError() # raise the error
return None
# Set the screen size
@ -202,14 +232,14 @@ def SessionClose(inSessionHexStr):
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5):
def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5, inLogger=None, inRDPConfigurationItem=None):
lL = inLogger # Init the logger
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
# Enter full screen mode
SessionScreenFull(inSessionHex)
SessionScreenFull(inSessionHex, inLogger=lL, inRDPConfigurationItem=inRDPConfigurationItem) # Enter full screen mode with recovery scenario
time.sleep(2)
# Run CMD operations
lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec)
lResult = SystemCMDRun(inSessionHexStr = inRDPConfigurationItem["SessionHex"], inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec, inLogger=lL)
# Exit fullscreen mode
SessionScreenSize_X_Y_W_H(inSessionHex=inSessionHex, inXInt=10, inYInt=10, inWInt=550,
inHInt=350) # Prepare little window
@ -233,6 +263,19 @@ def SessionIsFullScreen(inSessionHexStr):
if lSessionHeight == lHeight and lSessionWeight == lWeight:
lResult = True
return lResult
# Check if session is in minimized screen mode
# Return True - is in minimized
# example print(Connector.SessionIsFullScreen(""))
def SessionIsMinimizedScreen(inSessionHexStr):
#Default result
lResult = False
#Get window screen
try:
lResult = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).is_minimized()
except Exception as e:
pass
return lResult
# Check if RDP session is responsible (check with random combination in cmd)
# Attention - function will be work fine if RDP will be in full screen mode!!! (see def SessionScreenFull)
# Return True - is responsible; False - is not responsible
@ -248,46 +291,90 @@ def SessionIsFullScreen(inSessionHexStr):
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SystemCMDRun(inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5):
# Set random text to clipboard (for check purposes that clipboard text has been changed)
lClipboardTextOld = str(random.randrange(999,9999999))
def SystemCMDRun(inSessionHexStr, inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5, inLogger = None):
lRDPWindow = None # Init the UI object
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}])
except Exception as e:
raise ConnectorExceptions.SessionWindowNotExistError() # Raise error of gui window
lL = inLogger # Alias for logger
lResult = {"OutStr": None,"IsResponsibleBool":True} # Init the result dict
lClipboardTextOld = str(random.randrange(999,9999999)) # Set random text to clipboard (for check purposes that clipboard text has been changed)
Clipboard.TextSet(lClipboardTextOld)
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
lCrosscheckKeyStr = str(random.randrange(999,9999999))
lCMDPostFixStr = "" # Case default "RUN"
if inModeStr == "CROSSCHECK":
lCMDPostFixStr = f"| echo {lCrosscheckKeyStr} | clip"
elif inModeStr == "LISTEN":
lCMDPostFixStr = f"| clip"
keyboard.press_and_release('win+r')
time.sleep(1)
# Remove old text
keyboard.press_and_release("ctrl+a")
keyboard.press_and_release("backspace")
# Write new text
keyboard.write(f"cmd /c {inCMDCommandStr} {lCMDPostFixStr}")
time.sleep(1)
# TODo cross check from clipboard
keyboard.press_and_release('enter')
# Get OutStr (Case CROSSCHECK and LISTEN)
if inModeStr == "CROSSCHECK" or inModeStr == "LISTEN":
lClipboardWaitTimeStartSec = time.time()
lResult["OutStr"] = Clipboard.TextGet() # Get text from clipboard
while lResult["OutStr"] == lClipboardTextOld and (time.time() - lClipboardWaitTimeStartSec) <= inClipboardTimeoutSec:
lRecoveryCMDResponsibleRetryIteratorInt = 0 # Init the retry iterator
while lRecoveryCMDResponsibleRetryIteratorInt<gRecoveryCMDResponsibleRetryCountInt: # loop for retry
# # # # # # # # # # # # # OPEN WINDOW RUN # # # # # # # # # # # # # # #
lRecoveryWindowRUNRetryIteratorInt = 0 # Init the retry iterator
while lRecoveryWindowRUNRetryIteratorInt<gRecoveryWindowRUNRetryCountInt: # loop for retry
lCMDPostFixStr = "" # Case default "RUN"
if inModeStr == "CROSSCHECK":
lCMDPostFixStr = f"& (echo {lCrosscheckKeyStr} | clip)"
elif inModeStr == "LISTEN":
lCMDPostFixStr = f"| clip"
keyboard.press_and_release('win+r')
time.sleep(1) # Wait for RUN window will appear
lRDPWindow.type_keys("^(a)") # Select all
keyboard.press_and_release("backspace") # Delete selected all
time.sleep(0.5) # Wait for RUN window will appear ctrl+a+backspace is async - so we need some timeout...
lInputStr = f"cmd /c ({inCMDCommandStr}) {lCMDPostFixStr}" # Generate the output string for RUN window
keyboard.write(lInputStr) # Write new text
time.sleep(0.5)
lRDPWindow.type_keys("^(a)") # Select all
lRDPWindow.type_keys("^(c)") # Copy data
# Check the clipboard
lClipboardWaitTimeStartSec = time.time()
lClipboardStr = Clipboard.TextGet() # Get text from clipboard
while lClipboardStr != lInputStr and (time.time() - lClipboardWaitTimeStartSec) <= inClipboardTimeoutSec:
lClipboardStr = Clipboard.TextGet() # Get text from clipboard
time.sleep(0.5) # wait some time for the next operation
if lClipboardStr == lInputStr: # Cross check the clipboard data and input string
lRecoveryWindowRUNRetryIteratorInt = gRecoveryWindowRUNRetryCountInt # Set final count to block the loop
else: # Failed - wait and retry
if lL: lL.warning(f"RDP::SystemCMDRun: Window run doesn't appear. Wait for {gRecoveryWindowRUNRetryIntervalSecInt}[s.] and retry. Current retry iterator is {lRecoveryWindowRUNRetryIteratorInt}. CMD Str: {lInputStr}") # Log the error
lRecoveryWindowRUNRetryIteratorInt = lRecoveryWindowRUNRetryIteratorInt + 1 # Increment the iterator
if lRecoveryWindowRUNRetryIteratorInt == gRecoveryWindowRUNRetryCountInt:
if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error. CMD Str: {lInputStr}") # Log the error
raise ConnectorExceptions.RUNExistError() # Raise the error
time.sleep(gRecoveryWindowRUNRetryIntervalSecInt) # wait for some seconds before new iteration
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # RUN CMD # # # # # # # # # # # # # # #
keyboard.press_and_release('enter') # Execute CMD
if inModeStr == "CROSSCHECK" or inModeStr == "LISTEN": # Get OutStr (Case CROSSCHECK and LISTEN)
lClipboardWaitTimeStartSec = time.time()
lResult["OutStr"] = Clipboard.TextGet() # Get text from clipboard
time.sleep(0.5) # wait some time for the next operation
# Do crosscheck
if inModeStr == "CROSSCHECK":
if lResult["OutStr"] == f"{lCrosscheckKeyStr} \r\n\x00\x00\x00\x00\x00":
lResult["IsResponsibleBool"] = True
else:
lResult["IsResponsibleBool"] = False
# return the result
return lResult
while lResult["OutStr"] == lClipboardTextOld and (time.time() - lClipboardWaitTimeStartSec) <= inClipboardTimeoutSec:
lResult["OutStr"] = Clipboard.TextGet() # Get text from clipboard
time.sleep(0.5) # wait some time for the next operation
if lResult["OutStr"] == lClipboardTextOld: # If value hasn't been changed - retry send
lRecoveryCMDResponsibleRetryIteratorInt = lRecoveryCMDResponsibleRetryIteratorInt + 1 # increment the iterator
if lL: lL.warning(f"RDP::SystemCMDRun: CMD command doesn't been executed (no changes in clipboard data). Wait for {gRecoveryCMDResponsibleRetryIntervalSecInt}[s.] and retry from start window RUN. Current retry iterator is {lRecoveryCMDResponsibleRetryIteratorInt}. CMD Str: {lInputStr}, Clipboard data: {lResult['OutStr']}") # Log the error
if lRecoveryCMDResponsibleRetryIteratorInt >= gRecoveryCMDResponsibleRetryCountInt: # raise the error if retry count is exceeded
if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error.") # Log the error
raise ConnectorExceptions.CMDResponsibleError() # Raise the error
time.sleep(gRecoveryCMDResponsibleRetryIntervalSecInt) # wait for some seconds before new iteration
else: # Data was recieved - do crosscheck
if inModeStr == "CROSSCHECK":
if lResult["OutStr"] == f"{lCrosscheckKeyStr} \r\n\x00\x00\x00\x00\x00": # it is ok - do futher check
lResult["IsResponsibleBool"] = True
lRecoveryCMDResponsibleRetryIteratorInt = gRecoveryCMDResponsibleRetryCountInt # turn off the iterator
else:
lResult["IsResponsibleBool"] = False
lRecoveryCMDResponsibleRetryIteratorInt = lRecoveryCMDResponsibleRetryIteratorInt + 1 # increment the iterator
if lL: lL.warning(f"RDP::SystemCMDRun: CMD command doesn't been executed (wrong clipboard data). Wait for {gRecoveryCMDResponsibleRetryIntervalSecInt}[s.] and retry from start window RUN. Current retry iterator is {lRecoveryCMDResponsibleRetryIteratorInt}. CMD Str: {lInputStr}, Clipboard data: {lResult['OutStr']}") # Log the error
if lRecoveryCMDResponsibleRetryIteratorInt >= gRecoveryCMDResponsibleRetryCountInt: # raise the error if retry count is exceeded
if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error.") # Log the error
raise ConnectorExceptions.CMDResponsibleError() # Raise the error
time.sleep(gRecoveryCMDResponsibleRetryIntervalSecInt) # wait for some seconds before new iteration
else: # clipboard data has been changed but mode is not crosscheck - return success from function
lRecoveryCMDResponsibleRetryIteratorInt = gRecoveryCMDResponsibleRetryCountInt # turn off the iterator
else: # Success - no cross validation is aaplicable
lRecoveryCMDResponsibleRetryIteratorInt = gRecoveryCMDResponsibleRetryCountInt # turn off the iterator
# # # # # # # # # # # # # # # # # # # # # # # # # # # #
return lResult # return the result
# Check if current RDP is responsible
def SystemRDPIsResponsible():
return SystemCMDRun(inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK")["IsResponsibleBool"]
def SystemRDPIsResponsible(inSessionHexStr):
return SystemCMDRun(inSessionHexStr = inSessionHexStr, inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK")["IsResponsibleBool"]
# Click OK on error messages
def SystemRDPWarningClickOk():
# Try to click OK Error window in RUS version

@ -2,7 +2,9 @@
# RobotRDPActive Exceptions class
#####################################
class SessionWindowNotExistError(Exception): pass #Error when Window not exists
class SessionWindowNotResponsibleError(Exception): pass # Error when Window not responding
class SessionWindowNotResponsibleError(Exception): pass # Error when Window not responding to delete
class RUNExistError(Exception): pass # Error when RUN window not identified
class CMDResponsibleError(Exception): pass # Error when command is not return
class HostNoGUIError(Exception): pass # Orchestrator session has no GUI
#try:
# raise SessionWindowNotResponsibleError("Test")

@ -1,66 +0,0 @@
# ATTENTION! HERE IS NO Relative import because it will be imported dynamically
# All function check the flag SessionIsWindowResponsibleBool == True else no cammand is processed
# All functions can return None, Bool or Dict { "IsSuccessful": True }
from pyOpenRPA.Tools.RobotRDPActive import CMDStr # Create CMD Strings
from pyOpenRPA.Tools.RobotRDPActive import Connector # RDP API
def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True):
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStartIfNotRunning: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Create CMD str to stop process
def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose):
lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# TODO Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStop: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def FileStoredSend(inGlobalDict, inSessionIndex, inHostFilePath, inRDPFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePath, inRDPFilePath = inRDPFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredSend: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def FileStoredRecieve(inGlobalDict, inSessionIndex, inRDPFilePath, inHostFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePath, inHostFilePath = inHostFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredRecieve: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult

@ -1,158 +0,0 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import time # Time wait operations
import importlib # from dynamic import module
from . import ConnectorExceptions # Exceptions classes
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True
lResponsibilityCheckLastSec = time.time() # Get current time for check interval
while lFlagWhile:
try:
# UIOSelector list init
lUIOSelectorList = []
#Prepare selectors list for check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
#Run wait command
#import pdb
#pdb.set_trace()
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#print(lRDPDissappearList)
###########################################
#Analyze if flag safeturn off is activated
if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
lFlagWhile=False
#Set status disconnected for all RDP List
for lItem in inGlobalDict["RDPList"]:
lItem["SessionIsWindowExistBool"]=False
lItem["SessionIsWindowResponsibleBool"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
###########################################
###########################################
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
#pdb.set_trace()
#Session start if it is not in ignore list
#add check for selector if it is not in ignoreIndexList
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Flag that session is started
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]= True
# Write in logger - info
inGlobalDict["Logger"].info(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session has been initialized!")
# catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not exist!")
# catch ConnectorExceptions.SessionWindowNotResponsibleError
except ConnectorExceptions.SessionWindowNotResponsibleError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not responsible!")
# general exceptions
except Exception as e:
# Write in logger - warning
inGlobalDict["Logger"].exception(f"!!! ATTENTION !!! Unrecognized error")
#######################
# Click all warning messages
Connector.SystemRDPWarningClickOk()
#######################
###########################################
#Check if from Orchestrator full screen session is set
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] != inGlobalDict["FullScreenSessionIndex"]:
#Do some switches
#If full screen mode we have now
if inGlobalDict["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreen100x550(inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionHex"])
#If new session is setted
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"])
#Set one to other equal
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]
###########################################
####################################
##### Block check responsibility interval [ResponsibilityCheckIntervalSec]
if inGlobalDict['ResponsibilityCheckIntervalSec']: # Do check if ResponsibilityCheckIntervalSec is not None
if (time.time - lResponsibilityCheckLastSec()) > inGlobalDict['ResponsibilityCheckIntervalSec']:
# Set new time
lResponsibilityCheckLastSec = time.time()
# Do responsibility check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
# Check RDP responsibility
lDoCheckResponsibilityBool = True
lDoCheckResponsibilityCountMax = 20
lDoCheckResponsibilityCountCurrent = 0
while lDoCheckResponsibilityBool:
# Enter full screen mode
Connector.SessionScreenFull(lItem['SessionHex'])
time.sleep(2)
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
# Check if counter is exceed - raise exception
if lDoCheckResponsibilityCountCurrent >= lDoCheckResponsibilityCountMax:
lItem["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
lItem["SessionIsWindowResponsibleBool"]=False
# Session window is not responsible - restart RDP (close window here - next loop will reconnect)
Connector.SessionClose(lItem['SessionHex'])
# Turn off the loop
lDoCheckResponsibilityBool = False
else:
# Exit fullscreen mode
Connector.SessionScreen100x550(lItem['SessionHex'])
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
# increase the couter
lDoCheckResponsibilityCountCurrent+=1
####################################
# Check ActivityList from orchestrator
lActivityListNew = []
lActivityListOld = inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]+inGlobalDict["ActivityListStart"]
inGlobalDict["ActivityListStart"] = []
for lActivityItem in lActivityListOld:
#################
#Call function from Activity structure
################################################
lSubmoduleFunctionName = lActivityItem["DefName"]
lFileFullPath = lActivityItem["ModulePath"] # "path\\to\\module.py"
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
# Set gSettings in module
lTechModuleFromSpec.gSettings = inGlobalDict
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lActivityItemResult=getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"])
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
if lActivityItemResultType is bool:
if not lActivityItemResult:
# Activity is not done - add to list (retry in future)
lActivityListNew.append(lActivityItem)
#################################################
inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = lActivityListNew # Override the value
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Host session has lost the GUI")
finally:
# Wait for the next iteration
time.sleep(0.7)
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -30,10 +30,9 @@ def RDPSessionConnect(inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPa
"SessionIsWindowResponsibleBool": False, # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False
"SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False
}
# Add item in RDPList
gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem
# Create the RDP session
Connector.Session(lRDPConfigurationItem)
gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem # Add item in RDPList
Connector.Session(lRDPConfigurationItem) # Create the RDP session
Connector.SystemRDPWarningClickOk() # Click all warning messages
return True
# Disconnect the RDP session
@ -43,6 +42,7 @@ def RDPSessionDisconnect(inRDPSessionKeyStr):
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
Connector.SessionClose(inSessionHexStr=lSessionHex)
Connector.SystemRDPWarningClickOk() # Click all warning messages
return True
# RDP Session reconnect
@ -64,18 +64,19 @@ def RDPSessionLogoff(inRDPSessionKeyStr):
# Calculate the session Hex
lSessionHex = gSettings["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="CROSSCHECK", inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None) # Remove item from RDPList
return lResult
# Check RDP Session responsibility TODO NEED DEV + TEST
def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
global gSettings
inGlobalDict = gSettings
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
lRDPConfigurationItem = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] # Get the alias
# set the fullscreen
Connector.SessionScreenFull(inSessionHex=lSessionHex)
# ATTENTION!!! Session hex can be updated!!!
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationItem["SessionHex"], inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
time.sleep(1)
# Check RDP responsibility
lDoCheckResponsibilityBool = True
@ -87,7 +88,7 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
pass
#raise ConnectorExceptions.SessionWindowNotResponsibleError("Error when initialize the RDP session - RDP window is not responding!")
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible(inSessionHexStr = lRDPConfigurationItem["SessionHex"])
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
@ -105,7 +106,7 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr,
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="CROSSCHECK", inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult
# Create CMD str to stop process
def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool):
@ -119,7 +120,7 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="CROSSCHECK", inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr):
@ -132,7 +133,7 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat
#lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120, inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr):
@ -144,5 +145,5 @@ def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFile
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120, inLogger=gSettings["Logger"], inRDPConfigurationItem=gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr])
return lResult

@ -9,9 +9,7 @@ def RobotRDPActive(inGSettings):
# inGSettings = {
# ... "RobotRDPActive": {} ...
# }
#import pdb
#pdb.set_trace()
lLogger = inGSettings["Logger"] # Synonim
lL = inGSettings["Logger"] #Logger alias
Processor.gSettings = inGSettings # Set gSettings in processor module
mGSettingsRDPActiveDict = inGSettings["RobotRDPActive"] # Get configuration from global dict settings
# Global error handler
@ -48,21 +46,17 @@ def RobotRDPActive(inGSettings):
# Check if RDP window is not ignored
if not lRDPConfigurationDict["SessionIsIgnoredBool"]:
try:
Connector.Session(lRDPConfigurationDict)
Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True)
lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started
# Write in logger - info
lLogger.info(
f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!")
if lL: lL.info(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!") #Logging
# catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e:
lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
# Write in logger - warning
lLogger.warning(
f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist!")
if lL: lL.warning(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist!") #Logging
# general exceptions
except Exception as e:
# Write in logger - warning
lLogger.exception(f"!!! ATTENTION !!! Unrecognized error")
if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging
pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Safe turn off the - no need because of Orchestrator control
@ -96,18 +90,17 @@ def RobotRDPActive(inGSettings):
inWInt=550,
inHInt=350) # Prepare little window
# Set full screen for new window
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"])
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"], inLogger= inGSettings["Logger"], inRDPConfigurationItem=inGlobalDict["RDPList"][lRDPSessionKeyStrItem])
else:
# Check all RDP window and minimize it
for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]:
lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem]
if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]):
if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]) or Connector.SessionIsMinimizedScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): # If window is minimized - restore # if window in full screen - resize
Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"],
inXInt=10, inYInt=10,
inWInt=550,
inHInt=350) # Prepare little window
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Iterate the activity list in robot RDP active
lActivityListNew = []
lActivityListOld = inGlobalDict["ActivityList"]
@ -115,10 +108,13 @@ def RobotRDPActive(inGSettings):
for lActivityItem in lActivityListOld:
lSubmoduleFunctionName = lActivityItem["DefNameStr"]
if lSubmoduleFunctionName in dir(Processor):
# Run SettingUpdate function in submodule
# mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"])
lActivityItemResult = None # init the variable
try: # try to run function from Processor.py
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"])
except Exception as e:
if lL: lL.exception(f"RDP::main: Exception when run def in processor.py - activity will be ignored. Activity item: {lActivityItem}") #Logging
lActivityItemResult = True # True - clear from repeat list
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
if lActivityItemResultType is bool:
@ -129,8 +125,7 @@ def RobotRDPActive(inGSettings):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
lLogger.warning(f"Host session has lost the GUI")
if lL: lL.warning(f"Host session has lost the GUI") #Logging
finally:
# Wait for the next iteration
time.sleep(0.7)
@ -138,5 +133,4 @@ def RobotRDPActive(inGSettings):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1)
except Exception as e:
# Write in logger - warning
lLogger.exception(f"!!! ATTENTION !!! Global error handler - look at code")
if lL: lL.exception(f"!!! ATTENTION !!! Global error handler - look at code") #Logging

@ -254,6 +254,34 @@
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Escape onclick
/// RenderRobotList
lResponseJSON["RenderRobotList"].forEach(
function(lItem){
if ('FooterButtonX2List' in lItem) {
/// FooterButtonX2List
lItem["FooterButtonX2List"].forEach(
function(lItem2){
if ('OnClick' in lItem) {
lOnClickEscaped = lItem["OnClick"];
lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
lItem["OnClick"] = lOnClickEscaped;
}
}
);
/// FooterButtonX1List
lItem["FooterButtonX1List"].forEach(
function(lItem2){
if ('OnClick' in lItem) {
lOnClickEscaped = lItem["OnClick"];
lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
lItem["OnClick"] = lOnClickEscaped;
}
}
);
}
}
);
///Сформировать HTML код новой таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-control-panel",lResponseJSON)
//Присвоить ответ в mGlobal.Monitor.mResponseList

@ -1,4 +0,0 @@
1. [+] Убрать префикс orchestrator так как он и так находится в папке Orchestrator/ OrchestratorMain > Orchestrator
2. [+] Консолидировать выполнение всех действий через orchestratorProcessor
3. [+] Свести в планарную структуру inConfiguration. Логи сейчас формируются за предалали этой структуры - возникает двойное трактование
4. [+] Рефакторинг конфигурации до конца вместе с консолидацией orchestratorProcessor

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.1.2'
__version__ = 'v1.1.3'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.1.2'
__version__ = 'v1.1.3'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot
Loading…
Cancel
Save