# Prefinal RobotRDPActive OpenRPA test

dev-linux
Ivan Maslov 5 years ago
parent b02acc1a14
commit e4863d89ca

@ -0,0 +1,12 @@
import os # Get abs path of the file
# Create CMD str to run file if process.exe is not running
def ProcessStartIfNotRunning(inProcessName, inFilePath):
lFileAbsPath = os.abspath(inFilePath)
lResult = f'tasklist /nh /fi "imagename eq {inProcessName}" | find /i "{inProcessName}" > nul || (start {lFileAbsPath})'
return lResult
# Create CMD str to stop process
def ProcessStop(inProcessName, inFlagForceClose)
lResult = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lResult+= " /F"
return lResult

@ -6,6 +6,10 @@ import tempfile #Temporary location
import time import time
import subprocess import subprocess
from . import Clipboard # Clipboard functions get/set from . import Clipboard # Clipboard functions get/set
import keyboard
import time
import random # random integers
from win32api import GetSystemMetrics # Get Screen rect
#Connect to RDP session #Connect to RDP session
""" """
{ {
@ -118,40 +122,71 @@ def SessionRDPStart(inRDPFilePath):
], ],
30 30
) )
# Raise exception if RDP is not active
if len(lWaitResult) == 0:
raise Exception("Error when initialize the RDP session!")
#Prepare little window #Prepare little window
SessionScreen100x550(lRDPFileName) SessionScreen100x550(lRDPFileName)
return None return None
#Set fullscreen for app #Set fullscreen for app
def SessionScreenFull(inSessionHex): def SessionScreenFull(inSessionHex):
#Prepare little window #Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "uia"}]) #Hotfix uia is needed to set focus in RDP lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.maximize()
lRDPWindow.set_focus() lRDPWindow.set_focus()
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
return None return None
#Set Little window of the session #Set Little window of the session
def SessionScreen100x550(inSessionHex): def SessionScreen100x550(inSessionHex):
#Prepare little window #Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
#lRDPWindow.minimize() lRDPWindow.set_focus()
#lRDPWindow.restore() if SessionIsFullScreen(inSessionHex):
lRDPWindow.maximize() lRDPWindow.type_keys("^%{BREAK}")
lRDPWindow.type_keys("^%{BREAK}") # Ctrl + alt + creak to return window from full screen correctly time.sleep(0.5)
lRDPWindow.restore()
time.sleep(0.5)
lRDPWindow.move_window(10,10,550,100) lRDPWindow.move_window(10,10,550,100)
return None return None
import keyboard
import time
#Type command in CMD #Type command in CMD
def SessionCMDRun(inSessionHex,inCMDCommandStr): # inFlagDoCrossCheck: True - Do check that CMD is executed (the text response will not be available)
# inModeStr "LISTEN", "CROSSCHECK", "RUN"
# "LISTEN" - Get result of the cmd command in result TODO get home script
# "CROSSCHECK" - Check if the command was successufully sent TODO get home script
# "RUN" - Run without crosscheck and get clipboard
# return ...
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SessionCMDRun(inSessionHex,inCMDCommandStr, inModeStr="RUN"):
lCMDPostFixStr = "" # Case default "RUN"
if inModeStr == "CROSSCHECK":
lCMDPostFixStr = f"| echo {str(random.randrange(999,9999999))} | clip"
elif inModeStr == "LISTEN":
lCMDPostFixStr = f"| clip"
SessionScreenFull(inSessionHex) SessionScreenFull(inSessionHex)
time.sleep(2) # High priority
keyboard.press_and_release('win+r')
time.sleep(2) time.sleep(2)
print(Clipboard.InputIsFocused()) UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
keyboard.write(f"cmd") keyboard.press_and_release('win+r')
keyboard.press_and_release('enter') time.sleep(1)
time.sleep(2) # Only time wait we can set here :( keyboard.write(f"cmd /c {inCMDCommandStr} {lCMDPostFixStr}")
print(Clipboard.CMDIsOpen()) time.sleep(1)
keyboard.write(f"{inCMDCommandStr} && exit") # Run CMD command and close CMD console # TODo cross check from clipboard
keyboard.press_and_release('enter') keyboard.press_and_release('enter')
time.sleep(2)
SessionScreen100x550(inSessionHex) SessionScreen100x550(inSessionHex)
# Check if session is in Full screen mode
# Return True - is in fullscreen
# example print(Connector.SessionIsFullScreen(""))
def SessionIsFullScreen(inSessionHexStr):
#Default resul
lResult = False
lWeight = GetSystemMetrics(0)
lHeight = GetSystemMetrics(1)
#Get window screen
lRectangle = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).rectangle()
# Get Height/Weight
lSessionWeight = lRectangle.right - lRectangle.left
lSessionHeight = lRectangle.bottom - lRectangle.top
#Case fullscreen
if lSessionHeight == lHeight and lSessionWeight == lWeight:
lResult = True
return lResult

@ -0,0 +1,17 @@
from . import CMDStr # Create CMD Strings
from . import Connector # RDP API
def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath):
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
# Create CMD str to stop process
def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose)
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")

@ -3,6 +3,7 @@ from . import Connector
import os import os
import time # Time wait operations import time # Time wait operations
import pdb import pdb
import importlib # from dynamic import module
#Check for session is closed. Reopen if detected. Always keep session is active #Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout): def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True lFlagWhile = True
@ -55,12 +56,21 @@ def Monitor(inGlobalDict, inListUpdateTimeout):
########################################### ###########################################
# Check ActivityList from orchestrator # Check ActivityList from orchestrator
for lActivityItem in inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]: for lActivityItem in inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]:
# Check case CMDCommand #################
if lActivityItem["Type"] == "CMDCommand": #Call function from Activity structure
pass ################################################
# CMD command passed lSubmoduleFunctionName = lActivityItem["DefName"]
#Connector.SessionCMDRun(inSessionHex=lActivityItem["SessionHex"], inCMDCommandStr= lActivityItem["CMDValue"]) lFileFullPath = lActivityItem["ModulePath"] # "path\\to\\module.py"
# loop interval 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)
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"])
#################################################
inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = [] # Override the value
time.sleep(2) time.sleep(2)
return None return None
#TODO Def garbage window cleaner (if connection was lost) #TODO Def garbage window cleaner (if connection was lost)

@ -0,0 +1,106 @@
from . import Timer # Async thread
import threading # Create in another thread
import datetime # Datetime class
import copy # Copy struct functions
import time # time functions
import importlib # import lib functions
# Scheduler class - init and work by the configuration
# OOP
class Scheduler:
# Class properties
mSchedulerDict = None
#########################
# Init class
def __init__(self,inSchedulerDict):
self.Init(inSchedulerDict = inSchedulerDict)
# Init the class instance
def Init(self,inSchedulerDict):
self.mSchedulerDict = inSchedulerDict
# Init the threads
lTimerMainThread = threading.Thread(target = self.TimerMainThreadRun)
lTimerMainThread.start() # Start the Timer main thread
print (f"Class instance configuration: {self.mSchedulerDict}, Init has been completed")
########################
# Main timer thread - run when init class instance
def TimerMainThreadRun(self):
lDaemonStartDateTime=datetime.datetime.now()
lDaemonLoopSeconds=self.mSchedulerDict["ActivityTimeCheckLoopSeconds"]
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
#Вечный цикл
while True:
lCurrentDateTime = datetime.datetime.now()
#Циклический обход правил
lFlagSearchActivityType=True
for lIndex, lItem in enumerate(self.mSchedulerDict["ActivityTimeList"]):
#Проверка дней недели, в рамках которых можно запускать активность
lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6])
if lCurrentDateTime.weekday() in lItemWeekdayList:
if lFlagSearchActivityType:
#######################################################################
#Branch 1 - if has TimeHH:MM
#######################################################################
if "TimeHH:MM" in lItem:
#Вид активности - запуск процесса
#Сформировать временной штамп, относительно которого надо будет проверять время
#часовой пояс пока не учитываем
lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MM"],"%H:%M")
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}
#Запустить процесс - new code
#################
#Call function from Activity structure
################################################
lSubmoduleFunctionName = lItem["Activity"]["DefName"]
lFileFullPath = lItem["Activity"]["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)
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lItem["Activity"]["ArgList"],**lItem["Activity"]["ArgDict"])
#################################################
#######################################################################
#Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds
#######################################################################
if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem:
#Сформировать временной штамп, относительно которого надо будет проверять время
#часовой пояс пока не учитываем
lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStart"],"%H:%M")
lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStop"],"%H:%M")
lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day)
#Убедиться в том, что время наступило
if (
lCurrentDateTime<lActivityTimeEndDateTime and
lCurrentDateTime>=lActivityDateTime and
(lIndex,lActivityDateTime) not in lDaemonActivityLogDict):
#Запись в массив отработанных активностей
lDaemonActivityLogDict[(lIndex,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime}
#Call function from Activity structure
################################################
lSubmoduleFunctionName = lItem["Activity"]["DefName"]
lFileFullPath = lItem["Activity"]["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)
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lDef = getattr(lTechModuleFromSpec, lSubmoduleFunctionName) #(*lItem["Activity"]["ArgList"],**lItem["Activity"]["ArgDict"])
#################################################
#Запуск циклической процедуры
#Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"])
lTimer = Timer.RepeatedTimer(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lDef, *lItem["Activity"]["ArgList"], **lItem["Activity"]["ArgDict"]) # it auto-starts, no need of rt.start()
#Уснуть до следующего прогона
print (f"Loop has been completed")
time.sleep(lDaemonLoopSeconds)

@ -0,0 +1,31 @@
from threading import Timer
import datetime
class RepeatedTimer(object):
def __init__(self, interval, inDateTimeEnd, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.mDateTimeEnd = inDateTimeEnd # DateTime when stop
self.start()
def _run(self):
self.is_running = False
lResultGoLoop=True
lCurrentDateTime=datetime.datetime.now()
self.function(*self.args, **self.kwargs)
if lCurrentDateTime>=self.mDateTimeEnd:
lResultGoLoop=False
if lResultGoLoop is not None:
if lResultGoLoop:
self.start()
def start(self):
if not self.is_running:
self._timer = Timer(self.interval, self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False

@ -30,6 +30,7 @@ if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
######################################################### #########################################################
from pyOpenRPA.Tools.RobotRDPActive import Connector from pyOpenRPA.Tools.RobotRDPActive import Connector
from pyOpenRPA.Tools.RobotRDPActive import Monitor from pyOpenRPA.Tools.RobotRDPActive import Monitor
from pyOpenRPA.Tools.RobotRDPActive import Scheduler # Scheduler operations
#Disable certificate warning #Disable certificate warning
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f' lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f'
os.system(lCMDString) os.system(lCMDString)
@ -41,7 +42,8 @@ for lConfigurationItem in mGlobalDict["RDPList"]:
except Exception: except Exception:
pass pass
#Run monitor #Run monitor
print(mGlobalDict) #print(mGlobalDict)
Scheduler.Scheduler(mGlobalDict["Scheduler"]) # Init & Run Scheduler
Monitor.Monitor(mGlobalDict, 1) Monitor.Monitor(mGlobalDict, 1)
#Enable certificate warning #Enable certificate warning
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f' lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f'

@ -0,0 +1,39 @@
from pyOpenRPA.Tools.RobotRDPActive import Scheduler
inConfiguration={
"ActivityTimeCheckLoopSeconds":5, #Количество секунд, между циклами проверки действий
"ActivityTimeList": [
{
"TimeHH:MM": "22:23", #Time [HH:MM] to trigger activity
"WeekdayList": [1,2,3,4,5,6,7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
"Activity":{
"ModulePath": "Session\\SessionDefs.py", # "Session\\SessionDefs.py"
"DefName":"test", # Function name
"ArgList":[1,2,3], # Args list
"ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary
}
},
{
"TimeHH:MM": "14:17", #Time [HH:MM] to trigger activity
"WeekdayList": [1, 2, 3], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
"Activity":{
"ModulePath": "Session\\SessionDefs.py", # "Session\\SessionDefs.py"
"DefName":"test", # Function name
"ArgList":[1,2,3], # Args list
"ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary
}
},
{
"TimeHH:MMStart": "12:40", #Time [HH:MM] to trigger activity
"TimeHH:MMStop": "14:36",
"ActivityIntervalSeconds": 2,
"WeekdayList": [1, 2, 3, 4, 5, 6, 7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
"Activity":{
"ModulePath": "Session\\SessionDefs.py", # "Session\\SessionDefs.py"
"DefName":"test", # Function name
"ArgList":[1,2,3], # Args list
"ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary
}
}
]
}
lT = Scheduler.Scheduler(inConfiguration)

@ -1,5 +1,6 @@
#Robot RDPActive settings #Robot RDPActive settings
from pyOpenRPA.Robot import OrchestratorConnector from pyOpenRPA.Robot import OrchestratorConnector
from pyOpenRPA.Tools import RobotRDPActive # For RobotRDPActive folder purposes
import os import os
import logging import logging
import datetime import datetime
@ -8,6 +9,9 @@ lOrchestratorHost="localhost"
lOrchestratorPort=8081 lOrchestratorPort=8081
lOrchestratorProtocol="http" lOrchestratorProtocol="http"
lOrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz" lOrchestratorAuthToken="1992-04-03-0643-ru-b4ff-openrpa52zzz"
lRobotRDPActiveFolderPath = '\\'.join(RobotRDPActive.__file__.split('\\')[:-1])
print(f"{os.path.join(lRobotRDPActiveFolderPath,'SessionDefs.py')}")
def Settings(): def Settings():
mDict = { mDict = {
"RDPList": "RDPList":
@ -35,16 +39,51 @@ def Settings():
"IgnoreIndexList":[] "IgnoreIndexList":[]
}, },
"OrchestratorToRobotResetStorage": { "OrchestratorToRobotResetStorage": {
"SafeTurnOff":False #Control from orchestrator to safety turn off robot "SafeTurnOff":False ,#Control from orchestrator to safety turn off robot
"ActivityList":[ "ActivityList":[
{"Type":"CMDCommand", "CMDValue"}, #{
{"Type":"CreateFile","FileFullPath": "" ,"FileBytes": None} # "ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'SessionDefs.py')}", # "Session\\SessionDefs.py"
# "DefName":"test", # Function name
# "ArgList":[1,2,3], # Args list
# "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary
#}
] ]
}, },
"OrchestratorConnector": { "OrchestratorConnector": {
#Fill below #Fill below
}, },
"OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTerminateAll #Call this function when program must be shutted down (to kill threads from OrchestratorConnector) "OrchestratorConnectorTerminateAll":OrchestratorConnector.IntervalTerminateAll, #Call this function when program must be shutted down (to kill threads from OrchestratorConnector)
"Scheduler":None # !!! Will be filled below
}
###############
# Scheduler operations for RDP
###############
mDict["Scheduler"]={
"ActivityTimeCheckLoopSeconds":5, #Количество секунд, между циклами проверки действий
"ActivityTimeList": [
{
"TimeHH:MM": "22:23", #Time [HH:MM] to trigger activity
"WeekdayList": [1,2,3,4,5,6,7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
"Activity":{
"ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'GlobalDictSessionIndex_Defs.py')}", # "Session\\SessionDefs.py"
"DefName":"ProcessStop", # Function name
"ArgList":[], # Args list
"ArgDict":{"inGlobalDict": mDict, "inSessionIndex": 0, "inProcessName": "notepad.exe", "inFlagForceClose":True} # Args dictionary
}
},
{
"TimeHH:MMStart": "12:40", #Time [HH:MM] to trigger activity
"TimeHH:MMStop": "17:10",
"ActivityIntervalSeconds": 5,
"WeekdayList": [1, 2, 3, 4, 5, 6, 7], #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
"Activity":{
"ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'GlobalDictSessionIndex_Defs.py')}", # "RobotRDPActive\\SessionDefs.py"
"DefName":"ProcessStartIfNotRunning", # Function name
"ArgList":[], # Args list
"ArgDict":{"inGlobalDict": mDict, "inSessionIndex": 0, "inProcessName": "notepad.exe", "inFilePath": "notepad"} # Args dictionary
}
}
]
} }
###################### ######################
#OrchestratorConnector #OrchestratorConnector

Loading…
Cancel
Save