# Fix in RobotRDPActive (for production run)

dev-linux
Ivan Maslov 4 years ago
parent bc56245394
commit dcbdb0e7da

@ -63,7 +63,7 @@ def RenderRobotRDPActive(inGlobalConfiguration):
################################ ################################
#Session state #Session state
lItemSessionState='<span style=\"color:red\">Disconnected</span>' lItemSessionState='<span style=\"color:red\">Disconnected</span>'
if lItem.get("FlagSessionIsActive",False): if lItem.get("SessionIsWindowExistBool",False):
lItemSessionState='<span style=\"color:green\">Connected</span>' lItemSessionState='<span style=\"color:green\">Connected</span>'
lResultDict["BodyKeyValueList"].append({"Key":f"[{str(lRDPListIndex)}]{lLabelSessionFullScreen}{lLabelIsIgnored}{lItem.get('Host','localhost')}:{lItem.get('Port','--')}","Value":f"{lItem.get('Login','--')}, {lItem.get('SessionHex','--')}, State {lItemSessionState}, {lSetFullScreenA}, {lIgnoreIndexListLink}"}) lResultDict["BodyKeyValueList"].append({"Key":f"[{str(lRDPListIndex)}]{lLabelSessionFullScreen}{lLabelIsIgnored}{lItem.get('Host','localhost')}:{lItem.get('Port','--')}","Value":f"{lItem.get('Login','--')}, {lItem.get('SessionHex','--')}, State {lItemSessionState}, {lSetFullScreenA}, {lIgnoreIndexListLink}"})
lRDPListIndex = lRDPListIndex + 1 lRDPListIndex = lRDPListIndex + 1

@ -11,4 +11,14 @@ def ProcessStop(inProcessName, inFlagForceClose):
lResult = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"' lResult = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose: if inFlagForceClose:
lResult+= " /F" lResult+= " /F"
return lResult return lResult
# Send file from Host to Session RDP using shared drive in RDP (force copy)
def FileStoredSend(inHostFilePath, inRDPFilePath):
lHostFileAbsPath = os.path.join("\\\\tsclient", os.path.abspath(inHostFilePath).replace(":","")) # \\tsclient\C\path\to\file
lHostRDPFileAbsPath = os.path.abspath(inRDPFilePath) # File location in RDP
lResult = f'copy /Y "{lHostFileAbsPath}" "{lHostRDPFileAbsPath}"'
# Send file from Session RDP to Host using shared drive in RDP (force copy)
def FileStoredRecieve(inRDPFilePath, inHostFilePath):
lHostFileAbsPath = os.path.join("\\\\tsclient", os.path.abspath(inHostFilePath).replace(":","")) # \\tsclient\C\path\to\file
lHostRDPFileAbsPath = os.path.abspath(inRDPFilePath) # File location in RDP
lResult = f'copy /Y "{lHostRDPFileAbsPath}" "{lHostFileAbsPath}"'

@ -2,15 +2,16 @@ import win32clipboard
import keyboard # keyboard functions import keyboard # keyboard functions
import time # Some operations need wait import time # Some operations need wait
import random # random number for test import random # random number for test
gWaitTextInClipboardSec = 1 # Second for wait text will be set in clipboard (for get operations)
# set clipboard data # set clipboard data
def TextSet(inTextStr): def TextSet(inTextStr):
win32clipboard.OpenClipboard() win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard() win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(inTextStr) win32clipboard.SetClipboardText(inTextStr)
win32clipboard.CloseClipboard() win32clipboard.CloseClipboard()
# get clipboard data # get clipboard data
def TextGet(): def TextGet(inWaitTextInClipboardSec = gWaitTextInClipboardSec):
time.sleep(inWaitTextInClipboardSec) # Wait for clipboard will save
win32clipboard.OpenClipboard() win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData() data = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard() win32clipboard.CloseClipboard()

@ -1,12 +1,13 @@
#Import parent folder to import current / other packages #Import parent folder to import current / other packages
from pyOpenRPA.Robot import UIDesktop #Lib to access RDP window from pyOpenRPA.Robot import UIDesktop #Lib to access RDP window
from . import ConnectorExceptions # Exceptions classes
import os #os for process run import os #os for process run
import uuid #temp id for Template.rdp import uuid #temp id for Template.rdp
import tempfile #Temporary location 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 keyboard # Keyboard functions
import time import time
import random # random integers import random # random integers
from win32api import GetSystemMetrics # Get Screen rect from win32api import GetSystemMetrics # Get Screen rect
@ -37,6 +38,7 @@ def Session(inRDPSessionConfiguration):
#Remove temp file #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 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 os.remove(lRDPFile) # delete the temp rdp
# Set the result
return inRDPSessionConfiguration return inRDPSessionConfiguration
#Add login/ password to the windows credentials to run RDP #Add login/ password to the windows credentials to run RDP
def SessionLoginPasswordSet(inHost, inLogin, inPassword): def SessionLoginPasswordSet(inHost, inLogin, inPassword):
@ -79,6 +81,9 @@ def SessionConfigurationCreate(inConfiguration):
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4]) return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart #RDPSessionStart
def SessionRDPStart(inRDPFilePath): def SessionRDPStart(inRDPFilePath):
#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)
#run rdp session #run rdp session
lItemArgs = [inRDPFilePath] lItemArgs = [inRDPFilePath]
subprocess.Popen(lItemArgs, shell=True) subprocess.Popen(lItemArgs, shell=True)
@ -92,10 +97,13 @@ def SessionRDPStart(inRDPFilePath):
{"title": "D&on't ask me again for connections to this computer", {"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}], "friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName}.*", [{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}] "class_name": "TscShellContainerClass", "backend": "win32"},{"depth_start":3, "depth_end": 3, "class_name":"UIMainClass"}]
], ],
30 30
) )
#Enable certificate warning
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f'
os.system(lCMDString)
#Click if 0 is appear (RUS) #Click if 0 is appear (RUS)
if 0 in lWaitResult: if 0 in lWaitResult:
#Check the box do not retry #Check the box do not retry
@ -129,7 +137,24 @@ def SessionRDPStart(inRDPFilePath):
) )
# Raise exception if RDP is not active # Raise exception if RDP is not active
if len(lWaitResult) == 0: if len(lWaitResult) == 0:
raise Exception("Error when initialize the RDP session!") raise ConnectorExceptions.SessionWindowNotExistError("Error when initialize the RDP session - No RDP windows has appreared!")
# Wait for init
time.sleep(3)
# Check RDP responsibility
lDoCheckResponsibilityBool = True
lDoCheckResponsibilityCountMax = 20
lDoCheckResponsibilityCountCurrent = 0
while lDoCheckResponsibilityBool:
# Check if counter is exceed - raise exception
if lDoCheckResponsibilityCountCurrent >= lDoCheckResponsibilityCountMax:
raise ConnectorExceptions.SessionWindowNotResponsibleError("Error when initialize the RDP session - RDP window is not responding!")
# Check responding
lDoCheckResponsibilityBool = not SystemRDPIsResponsible()
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
# increase the couter
lDoCheckResponsibilityCountCurrent+=1
#Prepare little window #Prepare little window
SessionScreen100x550(lRDPFileName) SessionScreen100x550(lRDPFileName)
return None return None
@ -139,6 +164,7 @@ def SessionScreenFull(inSessionHex):
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.set_focus() lRDPWindow.set_focus()
lRDPWindow.maximize() lRDPWindow.maximize()
#time.sleep(0.5)
if not SessionIsFullScreen(inSessionHex): if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}") lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5) time.sleep(0.5)
@ -155,29 +181,30 @@ def SessionScreen100x550(inSessionHex):
time.sleep(0.5) time.sleep(0.5)
lRDPWindow.move_window(10,10,550,100) lRDPWindow.move_window(10,10,550,100)
return None return None
# Session - close window
def SessionClose(inSessionHexStr):
#Close window
UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).close()
#Type command in CMD #Type command in CMD
# inFlagDoCrossCheck: True - Do check that CMD is executed (the text response will not be available) # inSessionHex - SessionHex to catch window
# inModeStr "LISTEN", "CROSSCHECK", "RUN" # inModeStr "LISTEN", "CROSSCHECK", "RUN"
# "LISTEN" - Get result of the cmd command in result TODO get home script # "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 # "CROSSCHECK" - Check if the command was successufully sent TODO get home script
# "RUN" - Run without crosscheck and get clipboard # "RUN" - Run without crosscheck and get clipboard
# return ... # return {
# "OutStr": <> # Result string
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN") # example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SessionCMDRun(inSessionHex,inCMDCommandStr, inModeStr="RUN"): def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK"):
lCMDPostFixStr = "" # Case default "RUN" # Init the result dict
if inModeStr == "CROSSCHECK": lResult = {"OutStr": None,"IsResponsibleBool":True}
lCMDPostFixStr = f"| echo {str(random.randrange(999,9999999))} | clip" # Enter full screen mode
elif inModeStr == "LISTEN":
lCMDPostFixStr = f"| clip"
SessionScreenFull(inSessionHex) SessionScreenFull(inSessionHex)
time.sleep(2) time.sleep(2)
UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) # Run CMD operations
keyboard.press_and_release('win+r') lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr)
time.sleep(1) # Exit fullscreen mode
keyboard.write(f"cmd /c {inCMDCommandStr} {lCMDPostFixStr}")
time.sleep(1)
# TODo cross check from clipboard
keyboard.press_and_release('enter')
SessionScreen100x550(inSessionHex) SessionScreen100x550(inSessionHex)
# Check if session is in Full screen mode # Check if session is in Full screen mode
# Return True - is in fullscreen # Return True - is in fullscreen
@ -196,3 +223,76 @@ def SessionIsFullScreen(inSessionHexStr):
if lSessionHeight == lHeight and lSessionWeight == lWeight: if lSessionHeight == lHeight and lSessionWeight == lWeight:
lResult = True lResult = True
return lResult 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
#Type command in CMD
# 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
# inClipboardTimeoutSec # Second for wait when clipboard will changed
# return {
# "OutStr": <> # Result string
# "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))
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
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
# Check if current RDP is responsible
def SystemRDPIsResponsible():
return SystemCMDRun(inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK")["IsResponsibleBool"]
# Click OK on error messages
def SystemRDPWarningClickOk():
# Try to click OK Error window in RUS version
while UIDesktop.UIOSelector_Exist_Bool([{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "ОК", "class_name": "Button"}]):
try:
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "ОК", "class_name": "Button"}]).click()
except Exception as e:
pass
# Try to click OK Error window in ENG version
while UIDesktop.UIOSelector_Exist_Bool([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "OK", "class_name": "Button"}]):
try:
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "OK", "class_name": "Button"}]).click()
except Exception as e:
pass

@ -0,0 +1,10 @@
#####################################
# RobotRDPActive Exceptions class
#####################################
class SessionWindowNotExistError(Exception): pass #Error when Window not exists
class SessionWindowNotResponsibleError(Exception): pass # Error when Window not responding
class HostNoGUIError(Exception): pass # Orchestrator session has no GUI
#try:
# raise SessionWindowNotResponsibleError("Test")
#except SessionWindowNotResponsibleError as e:
# print("Catched")

@ -1,18 +1,66 @@
# ATTENTION! HERE IS NO Relative import because it will be imported dynamically # 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 CMDStr # Create CMD Strings
from pyOpenRPA.Tools.RobotRDPActive import Connector # RDP API from pyOpenRPA.Tools.RobotRDPActive import Connector # RDP API
def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True): def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True):
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath) lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath)
# Calculate the session Hex # Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"] lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Run CMD # Check is Session is responsible
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN") 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 # Create CMD str to stop process
def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose): def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose):
lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"' lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose: if inFlagForceClose:
lCMDStr+= " /F" lCMDStr+= " /F"
# Calculate the session Hex # Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"] lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Run CMD # Check is Session is responsible
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN") 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

@ -4,73 +4,150 @@ import os
import time # Time wait operations import time # Time wait operations
import pdb import pdb
import importlib # from dynamic import module import importlib # from dynamic import module
from . import ConnectorExceptions # Exceptions classes
#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
lResponsibilityCheckLastSec = time.time() # Get current time for check interval
while lFlagWhile: while lFlagWhile:
# UIOSelector list init try:
lUIOSelectorList = [] # UIOSelector list init
#Prepare selectors list for check lUIOSelectorList = []
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]): #Prepare selectors list for check
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}]) for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
#Run wait command lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout) #Run wait command
########################################### #import pdb
#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["FlagSessionIsActive"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
###########################################
###########################################
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["FlagSessionIsActive"] = False # Set flag that session is disconnected
#pdb.set_trace() #pdb.set_trace()
#Session start if it is not in ignore list lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#add check for selector if it is not in ignoreIndexList #print(lRDPDissappearList)
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]: ###########################################
try: #Analyze if flag safeturn off is activated
Connector.Session(inGlobalDict["RDPList"][lItem]) if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
inGlobalDict["RDPList"][lItem]["FlagSessionIsActive"] = True # Flag that session is started lFlagWhile=False
except Exception: #Set status disconnected for all RDP List
pass for lItem in inGlobalDict["RDPList"]:
########################################### lItem["SessionIsWindowExistBool"]=False
#Check if from Orchestrator full screen session is set lItem["SessionIsWindowResponsibleBool"]=False
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] != inGlobalDict["FullScreenSessionIndex"]: #Kill all RDP sessions
#Do some switches os.system('taskkill /F /im mstsc.exe')
#If full screen mode we have now #Return from function
if inGlobalDict["FullScreenSessionIndex"] is not None: return
if inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["FlagSessionIsActive"]: ###########################################
Connector.SessionScreen100x550(inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionHex"]) ###########################################
#If new session is setted for lItem in lRDPDissappearList:
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] is not None: inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
if inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["FlagSessionIsActive"]: inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"]) #pdb.set_trace()
#Set one to other equal #Session start if it is not in ignore list
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] #add check for selector if it is not in ignoreIndexList
########################################### if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
# Check ActivityList from orchestrator try:
for lActivityItem in inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]: Connector.Session(inGlobalDict["RDPList"][lItem])
################# inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Flag that session is started
#Call function from Activity structure inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]= True
################################################ # Write in logger - info
lSubmoduleFunctionName = lActivityItem["DefName"] inGlobalDict["Logger"].info(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session has been initialized!")
lFileFullPath = lActivityItem["ModulePath"] # "path\\to\\module.py" # catch ConnectorExceptions.SessionWindowNotExistError
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3] except ConnectorExceptions.SessionWindowNotExistError as e:
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) # Write in logger - warning
if lSubmoduleFunctionName in dir(lTechModuleFromSpec): inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not exist!")
# Run SettingUpdate function in submodule # catch ConnectorExceptions.SessionWindowNotResponsibleError
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() except ConnectorExceptions.SessionWindowNotResponsibleError as e:
getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"]) inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Set flag that session is disconnected
################################################# inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = [] # Override the value # Write in logger - warning
time.sleep(2) 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 = []
for lActivityItem in inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]:
#################
#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)
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(2)
return None return None
#TODO Def garbage window cleaner (if connection was lost) #TODO Def garbage window cleaner (if connection was lost)

@ -19,7 +19,7 @@ class Scheduler:
# Init the threads # Init the threads
lTimerMainThread = threading.Thread(target = self.TimerMainThreadRun) lTimerMainThread = threading.Thread(target = self.TimerMainThreadRun)
lTimerMainThread.start() # Start the Timer main thread lTimerMainThread.start() # Start the Timer main thread
print (f"Class instance configuration: {self.mSchedulerDict}, Init has been completed") #print (f"Class instance configuration: {self.mSchedulerDict}, Init has been completed")
######################## ########################
# Main timer thread - run when init class instance # Main timer thread - run when init class instance
def TimerMainThreadRun(self): def TimerMainThreadRun(self):
@ -102,5 +102,5 @@ class Scheduler:
#Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"]) #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() 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") #print (f"Loop has been completed")
time.sleep(lDaemonLoopSeconds) time.sleep(lDaemonLoopSeconds)

@ -31,22 +31,21 @@ 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 from pyOpenRPA.Tools.RobotRDPActive import Scheduler # Scheduler operations
#Disable certificate warning #### Global error handler
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f' try:
os.system(lCMDString) #time.sleep()
#time.sleep() ######## Init the RDP List
for lConfigurationItem in mGlobalDict["RDPList"]: for lConfigurationItem in mGlobalDict["RDPList"]:
try: lConfigurationItem["SessionIsWindowExistBool"]=False #Flag that session is not started
Connector.Session(lConfigurationItem) lConfigurationItem["SessionIsWindowResponsibleBool"]=False #Flag that session is not started
lConfigurationItem["FlagSessionIsActive"]=True #Flag that session is started lConfigurationItem["SessionHex"]=" 77777sdfsdf77777dsfdfsf77777777" #Flag that session is not started
except Exception: ##########
pass #Run monitor
#Run monitor Scheduler.Scheduler(mGlobalDict["Scheduler"]) # Init & Run Scheduler
#print(mGlobalDict) Monitor.Monitor(mGlobalDict, 1)
Scheduler.Scheduler(mGlobalDict["Scheduler"]) # Init & Run Scheduler except Exception as e:
Monitor.Monitor(mGlobalDict, 1) # Write in logger - warning
#Enable certificate warning mGlobalDict["Logger"].exception(f"!!! ATTENTION !!! Global error handler - look at code")
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f' finally:
os.system(lCMDString) #Close all thread from OrchestratorConnection
#Close all thread from OrchestratorConnection mGlobalDict["OrchestratorConnectorTerminateAll"]()
mGlobalDict["OrchestratorConnectorTerminateAll"]()

@ -4,6 +4,7 @@ from pyOpenRPA.Tools import RobotRDPActive # For RobotRDPActive folder purposes
import os import os
import logging import logging
import datetime import datetime
import sys
#Definitions #Definitions
lOrchestratorHost="localhost" lOrchestratorHost="localhost"
lOrchestratorPort=8081 lOrchestratorPort=8081
@ -29,10 +30,13 @@ def Settings():
"DepthBit": "32" # "32" or "24" or "16" or "15" "DepthBit": "32" # "32" or "24" or "16" or "15"
}, },
"SharedDriveList":["c"], # List of the Root sesion hard drives "SharedDriveList":["c"], # List of the Root sesion hard drives
###### Will updated in program ############
"SessionHex":"", # Hex is created when robot runs "SessionHex":"", # Hex is created when robot runs
"FlagSessionIsActive": False "SessionIsWindowExistBool": False , # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds
"SessionIsWindowResponsibleBool": False # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too
} }
], ],
"ResponsibilityCheckIntervalSec": None, # Seconds interval when Robot check the RDP responsibility. if None - dont check
"FullScreenSessionIndex": None, #Index of the current session which is full screened, None is no session in fullscreen "FullScreenSessionIndex": None, #Index of the current session which is full screened, None is no session in fullscreen
"Logger": logging.getLogger("RobotRDPActive"), "Logger": logging.getLogger("RobotRDPActive"),
"OrchestratorToRobotStorage": { "OrchestratorToRobotStorage": {
@ -151,12 +155,17 @@ def Settings():
#Подготовка логгера Robot #Подготовка логгера Robot
######################### #########################
mRobotLogger=mDict["Logger"] mRobotLogger=mDict["Logger"]
mRobotLogger.setLevel(logging.INFO) mRobotLogger.setLevel(logging.INFO) #logging.DEBUG
# create the logging file handler # create the logging file handler
mRobotLoggerFH = logging.FileHandler("Reports\ReportRobotRDPActive_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log") mRobotLoggerFH = logging.FileHandler("Reports\ReportRobotRDPActive_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log")
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter) mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object # add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH) mRobotLogger.addHandler(mRobotLoggerFH)
####################Add console output
if mDict["Logs"]["FlagShowInConsole"]:
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(lRobotLoggerFormatter)
mRobotLogger.addHandler(handler)
############################################ ############################################
return mDict return mDict
Loading…
Cancel
Save