# 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

dev-linux
Ivan Maslov 4 years ago
parent 608c0c680c
commit 4dde6d1501

@ -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_<Type>: <bool> 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")

@ -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,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<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
except Exception as e: # RDP window is not exist - try to reconnect
if inLogger: inLogger.warning(f"RDP::SessionScreenFull: RDP window is not exist - try sleep {gRecoveryWindowRDPRetryIntervalSecInt}[s.] and then to reconnect. SessionHex: {inSessionHex}")
time.sleep(gRecoveryWindowRDPRetryIntervalSecInt) # Before try to reconnect sleep
if lRDPConfigurationItem:
# Try to reconnect the RDP
Connector.SessionClose(inSessionHexStr=lSessionHex) # Close the
Connector.Session(lRDPConfigurationItem) # Create RDP session
lWindowRDPRetryIterator = lWindowRDPRetryIterator + 1 # increase the iterator
else:
if inLogger: inLogger.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 errors
# RDP window has been detected - go to set focus and maximize
lRDPWindow.set_focus()
lRDPWindow.maximize()
#time.sleep(0.5)
@ -202,11 +230,11 @@ 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, inGSettings = None):
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
# Enter full screen mode
SessionScreenFull(inSessionHex)
SessionScreenFull(inSessionHex, inGSettings = inGSettings)
time.sleep(2)
# Run CMD operations
lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec)
@ -233,6 +261,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

@ -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)

@ -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

@ -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")
if lL: lL.exception(f"!!! ATTENTION !!! Global error handler - look at code") #Logging

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