From 4dde6d1501c44a980967303ca053ff75eccd709b Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Sun, 31 May 2020 00:28:17 +0300 Subject: [PATCH] # Memory leak fix, recovery scenarion in progress, maximize RDP if minimized, minor fixes - remove old files from repo, add GUID in Scheduler item for detect unique item --- .../Settings/SettingsOrchestratorExample.py | 15 +- Sources/pyOpenRPA/Orchestrator/HowToUse.txt | 2 - .../pyOpenRPA/Orchestrator/Orchestrator.py | 68 +++++--- Sources/pyOpenRPA/Orchestrator/Processor.py | 22 --- .../Orchestrator/RobotRDPActive/Connector.py | 57 ++++++- .../RobotRDPActive/ConnectorExceptions.py | 4 +- .../GlobalDictSessionIndex_Defs.py | 66 -------- .../Orchestrator/RobotRDPActive/Monitor.py | 158 ------------------ .../Orchestrator/RobotRDPActive/Processor.py | 12 +- .../RobotRDPActive/RobotRDPActive.py | 38 ++--- Sources/pyOpenRPA/Orchestrator/todo.txt | 4 - 11 files changed, 129 insertions(+), 317 deletions(-) delete mode 100644 Sources/pyOpenRPA/Orchestrator/HowToUse.txt delete mode 100644 Sources/pyOpenRPA/Orchestrator/RobotRDPActive/GlobalDictSessionIndex_Defs.py delete mode 100644 Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Monitor.py delete mode 100644 Sources/pyOpenRPA/Orchestrator/todo.txt diff --git a/Orchestrator/Settings/SettingsOrchestratorExample.py b/Orchestrator/Settings/SettingsOrchestratorExample.py index 3eb37f8a..f023aebc 100644 --- a/Orchestrator/Settings/SettingsOrchestratorExample.py +++ b/Orchestrator/Settings/SettingsOrchestratorExample.py @@ -2,6 +2,7 @@ import psutil import datetime import logging import sys # stdout fro logging +import os # Init variables gControlPanelPyFilePathList = [ # .py file path list for call SettingsUpdate r"" @@ -188,7 +189,8 @@ def Settings(): "Type": "ProcessStart", #Activity type "Path": "start", #Executable file path "ArgList": ["cmd.exe","/c","PIPUpgrade.cmd"] #List of the arguments - } + }, + "GUID": None #Will be fied in Orchestrator automatically - is needed for detect activity completion }, { "TimeHH:MM": "19:20", #Time [HH:MM] to trigger activity @@ -198,7 +200,8 @@ def Settings(): "Name": "OpenRPARobotDaemon.exe", #Process name "FlagForce": True, #Force process close "User": "%username%" #Empty, user or %username% - } + }, + "GUID": None #Will be fied in Orchestrator automatically - is needed for detect activity completion }, { "TimeHH:MMStart": "12:40", #Time [HH:MM] to trigger activity @@ -210,10 +213,10 @@ def Settings(): "CheckTaskName": "notepad.exe", #Python function module name "Path": "notepad", #Python function name "ArgList": [] #Input python function args - } + }, + "GUID": None #Will be fied in Orchestrator automatically - is needed for detect activity completion } - ], - "LogList": [] + ] }, "Processor": { "LogType_CMDStart": True, #LogType_: if Trace for command is selected for False, the tracing will be off for such activity type. Default True @@ -316,8 +319,6 @@ def Settings(): #Init .py files from Settings folder #################################### #Get file list from Settings folder - import os - import pdb #lFunction to call in subfiles lSubmoduleFunctionName = "SettingsUpdate" #lSettingsPath = os.path.join(inSettingsFolderPath, "Settings") diff --git a/Sources/pyOpenRPA/Orchestrator/HowToUse.txt b/Sources/pyOpenRPA/Orchestrator/HowToUse.txt deleted file mode 100644 index ed2833d1..00000000 --- a/Sources/pyOpenRPA/Orchestrator/HowToUse.txt +++ /dev/null @@ -1,2 +0,0 @@ -1. / robotDaemonConfiguration.json -2. runProcessOpenRPARobotDaemon_x32.cmd \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py index 93d99081..f60809c4 100644 --- a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py +++ b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py @@ -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={} #Словарь отработанных активностей, ключ - кортеж (, , , ) -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=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) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/Processor.py b/Sources/pyOpenRPA/Orchestrator/Processor.py index fd09b3b3..b1800f58 100644 --- a/Sources/pyOpenRPA/Orchestrator/Processor.py +++ b/Sources/pyOpenRPA/Orchestrator/Processor.py @@ -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 diff --git a/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py b/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py index 61fdc4e7..f49d2adb 100644 --- a/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py +++ b/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py @@ -10,6 +10,16 @@ import keyboard # Keyboard functions import time import random # random integers from win32api import GetSystemMetrics # Get Screen rect +# 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 reconnect + +gRecoveryCMDResponsibleRetryCountInt = 3 # Retry iteration count is CMD is not responsible +gRecoveryCMDResponsibleRetryIntervalSecInt = 3 # Retry interval for reconnect + #Connect to RDP session """ { @@ -143,12 +153,30 @@ def SessionRDPStart(inRDPFilePath): 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 +def SessionScreenFull(inSessionHex, inGSettings = None): + ######################################## + lWindowRDPRetryIterator = 0 # Retry iterator if RDP window is not active + lRDPConfigurationItem = None + lL = None + if inGSettings: # Get the values from gSettings + lRDPConfigurationItem = inGSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] # Get the RDP configuration item + lL = inGSettings["Logger"] # Get the logger instance + while lWindowRDPRetryIterator 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) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py b/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py index 17059745..0f204ef1 100644 --- a/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py +++ b/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py @@ -66,7 +66,7 @@ def RDPSessionLogoff(inRDPSessionKeyStr): 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="RUN", inGSettings = gSettings) return lResult # Check RDP Session responsibility TODO NEED DEV + TEST @@ -75,7 +75,7 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr): inGlobalDict = gSettings lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"] # set the fullscreen - Connector.SessionScreenFull(inSessionHex=lSessionHex) + Connector.SessionScreenFull(inSessionHex=lSessionHex, inGSettings = gSettings) time.sleep(1) # Check RDP responsibility lDoCheckResponsibilityBool = True @@ -105,7 +105,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="RUN", inGSettings = gSettings) return lResult # Create CMD str to stop process def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool): @@ -119,7 +119,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="RUN", inGSettings = gSettings) return lResult # Send file from Host to Session RDP using shared drive in RDP def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr): @@ -132,7 +132,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, inGSettings = gSettings) return lResult # Recieve file from Session RDP to Host using shared drive in RDP def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr): @@ -144,5 +144,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, inGSettings = gSettings) return lResult \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py b/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py index bcb3e76f..e24db40c 100644 --- a/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py +++ b/Sources/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py @@ -9,9 +9,7 @@ def RobotRDPActive(inGSettings): # inGSettings = { # ... "RobotRDPActive": {} ... # } - #import pdb - #pdb.set_trace() - lLogger = inGSettings["Logger"] # Synonim + lL = gSettingsDict["Logger"] #Logger alias Processor.gSettings = inGSettings # Set gSettings in processor module mGSettingsRDPActiveDict = inGSettings["RobotRDPActive"] # Get configuration from global dict settings # Global error handler @@ -50,19 +48,15 @@ def RobotRDPActive(inGSettings): try: Connector.Session(lRDPConfigurationDict) 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,18 @@ 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"], inGSettings = inGSettings) 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 # if window in full screen - resize + Connector.SessionIsMinimizedScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): # If window is minimized - restore 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 +109,12 @@ 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"]) + 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 + lActivityItemResultType = 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") \ No newline at end of file + if lL: lL.exception(f"!!! ATTENTION !!! Global error handler - look at code") #Logging \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/todo.txt b/Sources/pyOpenRPA/Orchestrator/todo.txt deleted file mode 100644 index 5ff6b92d..00000000 --- a/Sources/pyOpenRPA/Orchestrator/todo.txt +++ /dev/null @@ -1,4 +0,0 @@ -1. [+] orchestrator Orchestrator/ OrchestratorMain > Orchestrator -2. [+] orchestratorProcessor -3. [+] inConfiguration. - -4. [+] orchestratorProcessor