# Prefinal Orchestrator update (RobotRDPActive in Orchestrator)

dev-linux
Ivan Maslov 5 years ago
parent d809a9d5c7
commit b8e4cd82b5

@ -1,7 +1,7 @@
import psutil
import datetime
import logging
import sys # stdout fro logging
def RenderRobotR01(inGlobalConfiguration):
#Subheader Variants
lSubheaderRunTrueText="Состояние: <span style=\"color:green\">Работает</span>"
@ -74,12 +74,12 @@ def Settings():
mDict = {
"Server": {
"ListenPort_": "Порт, по которому можно подключиться к демону",
"ListenPort": 8081,
"ListenPort": 80,
"ListenURLList": [
{
"Description": "Local machine test",
"URL_": "Сетевое расположение сервера демона",
"URL": "http://127.0.0.1:8081"
"URL": ""
}
],
"AccessUsers": { #Default - all URL is blocked
@ -144,7 +144,32 @@ def Settings():
# "CheckTaskName": "notepad.exe", #Python function module name
# "Path": "notepad", #Python function name
# "ArgList": [] #Input python function args
#}
#},
# {
# "Type": "RDPSessionConnect", #Activity type - start/connect RDP Session
# "RDPSessionKeyStr": "notepad.exe", #Python function module name
# "RDPConfigurationDict": {}
# },
# {
# "Type": "RDPSessionLogoff", #Activity type - logoff RDP Session
# "RDPSessionKeyStr": "notepad.exe", #Python function module name
# },
# {
# "Type": "RDPSessionDisconnect", #Activity type - disconnect the RDP Session without logoff
# "RDPSessionKeyStr": "notepad.exe", #Python function module name
# },
# {
# "Type": "RDPSessionFileSend", #Activity type - send file to RDP session
# ...
# },
# {
# "Type": "RDPSessionFileRecieve", #Activity type - recieve file from rdp session
# ...
# },
# {
# "Type": "RDPSessionProcessStart", #Activity type -
# ...
# },
]
},
"Scheduler": {
@ -196,6 +221,57 @@ def Settings():
}
]
},
# # # # # # # # # # # # # #
"RobotRDPActive":{
"RDPList": {
"RDPSessionKey":{
"Host": "77.77.22.22", # Host address
"Port": "3389", # RDP Port
"Login": "test", # Login
"Password": "test", # Password
"Screen": {
"Width": 1680, # Width of the remote desktop in pixels
"Height": 1050, # Height of the remote desktop in pixels
# "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit": "32" # "32" or "24" or "16" or "15"
},
"SharedDriveList": ["c"], # List of the Root sesion hard drives
###### Will updated in program ############
"SessionHex": "", # Hex is created when robot runs
"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
"SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore
}
},
"ResponsibilityCheckIntervalSec": None,
# Seconds interval when Robot check the RDP responsibility. if None - dont check
"FullScreenRDPSessionKeyStr": None, # RDPSessionKeyStr of the current session which is full screened, None is no session in fullscreen
"ActivityList":[ # Technical Activity list for RobotRDPActive thread - equal to Main activity list, apply only RDP activity
# {
# "DefNameStr":"test", # Function name in RobotRDPActive.Processor
# "ArgList":[1,2,3], # Args list
# "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary
# },
#{
# "DefNameStr": "RDPSessionConnect", # Function name in RobotRDPActive.Processor
# "ArgList": [], # Args list
# "ArgDict": {"inRDPSessionKeyStr": "TestRDP", "inHostStr": "77.44.33.22", "inPortStr": "3389",
# "inLoginStr": "login", "inPasswordStr": "pass"} # Args dictionary
#},
# {
# "DefNameStr": "RDPSessionDisconnect", # Disconnect the RDP session without logoff. Function name in RobotRDPActive.Processor
# "ArgList": [], # Args list
# "ArgDict": {"inRDPSessionKeyStr": "TestRDP"}
# },
# {
# "DefNameStr": "RDPSessionReconnect", # Disconnect the RDP session without logoff. Function name in RobotRDPActive.Processor
# "ArgList": [], # Args list
# "ArgDict": {"inRDPSessionKeyStr": "TestRDP"}
# }
]
},
# # # # # # # # # # # # # #
"FileManager": {
"FileURLFilePathDict_help": "https://localhost:8081/filemanager/<file URL>. All FileURL s must be set in lowercase",
"FileURLFilePathDict": {
@ -224,6 +300,10 @@ def Settings():
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH)
####################Add console output
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(mRobotLoggerFormatter)
mRobotLogger.addHandler(handler)
############################################
###################################
#Init .py files from Settings folder

@ -15,9 +15,11 @@ 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
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
global gSettingsDict
#Call Settings function from argv[1] file
################################################
lSubmoduleFunctionName = "Settings"
@ -26,37 +28,41 @@ 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)
mGlobalDict = None
gSettingsDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
#mGlobalDict = Settings.Settings(sys.argv[1])
Processor.mGlobalDict = mGlobalDict
Timer.mGlobalDict = mGlobalDict
Timer.Processor.mGlobalDict = mGlobalDict
Server.mGlobalDict = mGlobalDict
Server.Processor.mGlobalDict = mGlobalDict
Processor.gSettingsDict = gSettingsDict
Timer.gSettingsDict = gSettingsDict
Timer.Processor.gSettingsDict = gSettingsDict
Server.gSettingsDict = gSettingsDict
Server.Processor.gSettingsDict = gSettingsDict
#Инициализация настроечных параметров
lDaemonLoopSeconds=mGlobalDict["Scheduler"]["ActivityTimeCheckLoopSeconds"]
lDaemonLoopSeconds=gSettingsDict["Scheduler"]["ActivityTimeCheckLoopSeconds"]
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
lDaemonStartDateTime=datetime.datetime.now()
#Инициализация сервера
lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict)
lThreadServer = Server.RobotDaemonServer("ServerThread", gSettingsDict)
lThreadServer.start()
# 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
mGlobalDict["Logger"].info("Scheduler loop init")
gSettingsDict["Logger"].info("Scheduler loop init")
# Выполнить активности при старте
for lActivityItem in mGlobalDict["OrchestratorStart"]["ActivityList"]:
for lActivityItem in gSettingsDict["OrchestratorStart"]["ActivityList"]:
Processor.ActivityListOrDict(lActivityItem)
#Вечный цикл
while True:
lCurrentDateTime = datetime.datetime.now()
#Циклический обход правил
lFlagSearchActivityType=True
for lIndex, lItem in enumerate(mGlobalDict["Scheduler"]["ActivityTimeList"]):
for lIndex, lItem in enumerate(gSettingsDict["Scheduler"]["ActivityTimeList"]):
#Проверка дней недели, в рамках которых можно запускать активность
lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6])
if lCurrentDateTime.weekday() in lItemWeekdayList:
@ -64,7 +70,7 @@ while True:
#Лог
lItemCopy = copy.deepcopy(lItem)
lItemCopy["DateTimeUTCStringStart"]=datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f")
mGlobalDict["Scheduler"]["LogList"].append(lItemCopy)
gSettingsDict["Scheduler"]["LogList"].append(lItemCopy)
#######################################################################
#Branch 1 - if has TimeHH:MM
#######################################################################

@ -29,6 +29,11 @@ import psutil
# "Value": <List, Dict, String, int>
# },
# {
# "Type": "GlobalDictKeyListValueAppend",
# "KeyList": ["key1","key2",...],
# "Value": <List, Dict, String, int>
# },
# {
# "Type": "GlobalDictKeyListValueGet",
# "KeyList": ["key1","key2",...]
# },
@ -72,9 +77,10 @@ import psutil
# "DateTimeUTCStringStart"
# "DateTimeUTCStringStop"
# "Result"
gSettingsDict = None
def Activity(inActivity):
#Глобальная переменная - глобальный словарь унаследованный от Settings.py
global mGlobalDict
global gSettingsDict
#Fill DateTimeUTCStringStart
inActivity["DateTimeUTCStringStart"] = datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f")
#Alias (compatibility)
@ -113,7 +119,7 @@ def Activity(inActivity):
#Обработка команды GlobalDictKeyListValueSet
###########################################################
if lItem["Type"]=="GlobalDictKeyListValueSet":
lDict = mGlobalDict
lDict = gSettingsDict
for lItem2 in lItem["KeyList"][:-1]:
#Check if key - value exists
if lItem2 in lDict:
@ -125,10 +131,25 @@ def Activity(inActivity):
lDict[lItem["KeyList"][-1]]=lItem["Value"]
lItem["Result"] = True
###########################################################
# Обработка команды GlobalDictKeyListValueAppend
###########################################################
if lItem["Type"] == "GlobalDictKeyListValueAppend":
lDict = gSettingsDict
for lItem2 in lItem["KeyList"][:-1]:
# Check if key - value exists
if lItem2 in lDict:
pass
else:
lDict[lItem2] = {}
lDict = lDict[lItem2]
# Set value
lDict[lItem["KeyList"][-1]].append(lItem["Value"])
lItem["Result"] = True
###########################################################
#Обработка команды GlobalDictKeyListValueGet
###########################################################
if lItem["Type"]=="GlobalDictKeyListValueGet":
lDict = mGlobalDict
lDict = gSettingsDict
for lItem2 in lItem["KeyList"][:-1]:
#Check if key - value exists
if lItem2 in lDict:
@ -147,7 +168,7 @@ def Activity(inActivity):
#Вид активности - запуск процесса
#Запись в массив отработанных активностей
#Лог
mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
#Запустить процесс
lItemArgs=[lItem["Path"]]
lItemArgs.extend(lItem["ArgList"])
@ -169,7 +190,7 @@ def Activity(inActivity):
#Вид активности - запуск процесса
#Запись в массив отработанных активностей
#Лог
mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)})
#Запустить процесс
lItemArgs=[lItem["Path"]]
lItemArgs.extend(lItem["ArgList"])
@ -189,7 +210,7 @@ def Activity(inActivity):
if lItem.get('User',"")!="":
lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"'
#Лог
mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Name"], "activityStartDateTime":str(lCurrentDateTime)})
gSettingsDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Name"], "activityStartDateTime":str(lCurrentDateTime)})
#Завершить процесс
os.system(lActivityCloseCommand)
#################################
@ -228,9 +249,9 @@ def Activity(inActivity):
#Trace activity
##################
#print(mGlobalDict)
if mGlobalDict["Processor"].get(f"LogType_{lItem['Type']}",True):
if gSettingsDict["Processor"].get(f"LogType_{lItem['Type']}", True):
#Add activity in TransactionList if it is applicable
mGlobalDict["Processor"]["LogList"].append(copy.deepcopy(lItem))
gSettingsDict["Processor"]["LogList"].append(copy.deepcopy(lItem))
#Вернуть результат
return lItem

@ -4,7 +4,6 @@ from . import ConnectorExceptions # Exceptions classes
import os #os for process run
import uuid #temp id for Template.rdp
import tempfile #Temporary location
import time
import subprocess
from . import Clipboard # Clipboard functions get/set
import keyboard # Keyboard functions
@ -140,31 +139,16 @@ def SessionRDPStart(inRDPFilePath):
raise ConnectorExceptions.SessionWindowNotExistError("Error when initialize the RDP session - No RDP windows has appreared!")
# Wait for init
time.sleep(3)
# set the fullscreen
SessionScreenFull(inSessionHex=lRDPFileName)
time.sleep(1)
# 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
SessionScreen100x550(lRDPFileName)
SessionScreenSize_X_Y_W_H(inSessionHex = lRDPFileName, inXInt = 10, inYInt = 10, inWInt = 550, inHInt = 350) #Prepare little window
return None
#Set fullscreen for app
def SessionScreenFull(inSessionHex):
#Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
except Exception as e:
return None
lRDPWindow.set_focus()
lRDPWindow.maximize()
#time.sleep(0.5)
@ -172,22 +156,34 @@ def SessionScreenFull(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
return None
#Set Little window of the session
def SessionScreen100x550(inSessionHex):
# Set the screen size
def SessionScreenSize_X_Y_W_H(inSessionHex, inXInt, inYInt, inWInt, inHInt):
#Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
except Exception as e:
return None
lRDPWindow.set_focus()
if SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
lRDPWindow.restore()
time.sleep(0.5)
lRDPWindow.move_window(10,10,550,100)
lRDPWindow.move_window(inXInt,inYInt,inWInt,inHInt)
return None
# Set Little window of the session
def SessionScreen100x550(inSessionHex):
SessionScreenSize_X_Y_W_H(inSessionHex = inSessionHex, inXInt = 10, inYInt = 10, inWInt = 550, inHInt = 100)
return None
# Session - close window
def SessionClose(inSessionHexStr):
#Close window
UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).close()
try:
UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).close()
except Exception as e:
pass
#Type command in CMD
# inSessionHex - SessionHex to catch window
# inModeStr "LISTEN", "CROSSCHECK", "RUN"
@ -208,7 +204,8 @@ def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK
# Run CMD operations
lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec)
# Exit fullscreen mode
SessionScreen100x550(inSessionHex)
SessionScreenSize_X_Y_W_H(inSessionHex=inSessionHex, inXInt=10, inYInt=10, inWInt=550,
inHInt=350) # Prepare little window
# Check if session is in Full screen mode
# Return True - is in fullscreen
# example print(Connector.SessionIsFullScreen(""))
@ -218,7 +215,10 @@ def SessionIsFullScreen(inSessionHexStr):
lWeight = GetSystemMetrics(0)
lHeight = GetSystemMetrics(1)
#Get window screen
lRectangle = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).rectangle()
try:
lRectangle = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHexStr}.*", "backend": "win32"}]).rectangle()
except Exception as e:
return lResult
# Get Height/Weight
lSessionWeight = lRectangle.right - lRectangle.left
lSessionHeight = lRectangle.bottom - lRectangle.top

@ -2,10 +2,10 @@ from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import time # Time wait operations
import pdb
import importlib # from dynamic import module
from . import ConnectorExceptions # Exceptions classes
import copy
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True

@ -0,0 +1,152 @@
# 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 . import CMDStr # Create CMD Strings
from . import Connector # RDP API
from . import ConnectorExceptions # Exceptions
import time # sleep function
# ATTENTION
gSettings = None # Gsettings will be initialized after the import module
# Create new RDPSession in RobotRDPActive
def RDPSessionConnect(inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr):
lRDPConfigurationItem = { # Init the configuration item
"Host": inHostStr, # Host address, example "77.77.22.22"
"Port": inPortStr, # RDP Port, example "3389"
"Login": inLoginStr, # Login, example "test"
"Password": inPasswordStr, # Password, example "test"
"Screen": {
"Width": 1680, # Width of the remote desktop in pixels, example 1680
"Height": 1050, # Height of the remote desktop in pixels, example 1050
# "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example
"FlagUseAllMonitors": False, # True or False, example False
"DepthBit": "32" # "32" or "24" or "16" or "15", example "32"
},
"SharedDriveList": ["c"], # List of the Root sesion hard drives, example ["c"]
###### Will updated in program ############
"SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example ""
"SessionIsWindowExistBool": False, # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False
"SessionIsWindowResponsibleBool": False, # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False
"SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False
}
# Add item in RDPList
gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem
# Create the RDP session
Connector.Session(lRDPConfigurationItem)
return True
# Disconnect the RDP session
def RDPSessionDisconnect(inRDPSessionKeyStr):
global gSettings
lSessionHex = gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
Connector.SessionClose(inSessionHexStr=lSessionHex)
return True
# RDP Session reconnect
def RDPSessionReconnect(inRDPSessionKeyStr):
global gSettings
lRDPConfigurationItem = gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]
RDPSessionDisconnect(inRDPSessionKeyStr=inRDPSessionKeyStr) # Disconnect the RDP
# Add item in RDPList
gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem
# Create the RDP session
Connector.Session(lRDPConfigurationItem)
return True
# Check RDP Session responsibility TODO NEED DEV + TEST
def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
global gSettings
inGlobalDict = gSettings
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
# set the fullscreen
Connector.SessionScreenFull(inSessionHex=lSessionHex)
time.sleep(1)
# Check RDP responsibility
lDoCheckResponsibilityBool = True
lDoCheckResponsibilityCountMax = 20
lDoCheckResponsibilityCountCurrent = 0
while lDoCheckResponsibilityBool:
# Check if counter is exceed - raise exception
if lDoCheckResponsibilityCountCurrent >= lDoCheckResponsibilityCountMax:
pass
#raise ConnectorExceptions.SessionWindowNotResponsibleError("Error when initialize the RDP session - RDP window is not responding!")
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
# increase the couter
lDoCheckResponsibilityCountCurrent+=1
return True
# Start process if it is not running
def RDPSessionProcessStartIfNotRunning(inRDPSessionKey, inProcessName, inFilePath, inFlagGetAbsPath=True):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Defs_SessionIndex.ProcessStartIfNotRunning: SessionIndex: {str(inRDPSessionKey)}, 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 RDPSessionProcessStop(inRDPSessionKey, inProcessName, inFlagForceClose):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# TODO Write in logger - warning
inGlobalDict["Logger"].warning(f"Defs_SessionIndex.ProcessStop: SessionIndex: {str(inRDPSessionKey)}, 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 RDPSessionFileStoredSend(inRDPSessionKey, inHostFilePath, inRDPFilePath):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePath, inRDPFilePath = inRDPFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Defs_SessionIndex.FileStoredSend: SessionIndex: {str(inRDPSessionKey)}, 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 RDPSessionFileStoredRecieve(inRDPSessionKey, inRDPFilePath, inHostFilePath):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePath, inHostFilePath = inHostFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Defs_SessionIndex.FileStoredRecieve: SessionIndex: {str(inRDPSessionKey)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult

@ -0,0 +1,142 @@
from pyOpenRPA.Robot import UIDesktop
import os
import time # Time wait operations
from . import ConnectorExceptions # Exceptions classes
from . import Connector
from . import Processor # Module for process some functions on thr RDP
# Main function
def RobotRDPActive(inGSettings):
# inGSettings = {
# ... "RobotRDPActive": {} ...
# }
#import pdb
#pdb.set_trace()
lLogger = inGSettings["Logger"] # Synonim
Processor.gSettings = inGSettings # Set gSettings in processor module
mGSettingsRDPActiveDict = inGSettings["RobotRDPActive"] # Get configuration from global dict settings
# Global error handler
try:
######## Init the RDP List
for lRDPSessionKeyStrItem in mGSettingsRDPActiveDict["RDPList"]:
lConfigurationItem = mGSettingsRDPActiveDict["RDPList"][lRDPSessionKeyStrItem]
lConfigurationItem["SessionIsWindowExistBool"] = False # Flag that session is not started
lConfigurationItem["SessionIsWindowResponsibleBool"] = False # Flag that session is not started
lConfigurationItem["SessionHex"] = " 77777sdfsdf77777dsfdfsf77777777" # Flag that session is not started
##########
# Run monitor - main loop
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
inGlobalDict = mGSettingsRDPActiveDict # Compatibility
inListUpdateTimeout = 1 # Compatibility
lFlagWhile = True
lResponsibilityCheckLastSec = time.time() # Get current time for check interval
while lFlagWhile:
try:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Check RDP window is OK - reconnect if connection was lost
lUIOSelectorList = []
lRDPConfigurationDictList = []
# Prepare selectors list for check
for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]:
lItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem]
lRDPConfigurationDictList.append(lItem) # Add RDP Configuration in list
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
# Run wait command
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
for lItem in lRDPDissappearList: # Reconnect if connection was lost
lRDPConfigurationDict = lRDPConfigurationDictList[lItem] # Get RDP Configuration list
lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
# Check if RDP window is not ignored
if not lRDPConfigurationDict["SessionIsIgnoredBool"]:
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!")
# 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!")
# general exceptions
except Exception as e:
# Write in logger - warning
lLogger.exception(f"!!! ATTENTION !!! Unrecognized error")
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Safe turn off the - no need because of Orchestrator control
#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
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Connector.SystemRDPWarningClickOk() # Click all warning messages
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Check if RDP session is full screen (if is not ignored)
if inGlobalDict["FullScreenRDPSessionKeyStr"] is not None:
lRDPSessionKeyStr = inGlobalDict["FullScreenRDPSessionKeyStr"] # Get the RDPSessionKeyStr
if lRDPSessionKeyStr in inGlobalDict["RDPList"]: # Session Key is in dict
lRDPConfigurationDict = inGlobalDict["RDPList"][lRDPSessionKeyStr]
#if not lRDPConfigurationDict["SessionIsIgnoredBool"]: # Session is not ignored
# Check if full screen
lIsFullScreenBool = Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDict["SessionHex"])
if not lIsFullScreenBool: # If not the full screen
# Check all RDP window and minimize it
for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]:
lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem]
if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]):
Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"], inXInt=10, inYInt=10,
inWInt=550,
inHInt=350) # Prepare little window
# Set full screen for new window
Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"])
else:
# Check all RDP window and minimize it
for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]:
lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem]
if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]):
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"]
inGlobalDict["ActivityList"] = []
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"])
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["ActivityList"] = lActivityListNew # Override the value
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
lLogger.warning(f"Host session has lost the GUI")
finally:
# Wait for the next iteration
time.sleep(0.7)
# Scheduler.Scheduler(mGSettingsRDPActiveDict["Scheduler"]) # Init & Run Scheduler TODO remake in processor list
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1)
except Exception as e:
# Write in logger - warning
lLogger.exception(f"!!! ATTENTION !!! Global error handler - look at code")

@ -1,7 +1,6 @@
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

@ -13,7 +13,7 @@ import importlib
lFolderPath = "/".join(__file__.split("/")[:-4])
sys.path.insert(0, lFolderPath)
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
global gSettingsDict
#Call Settings function from argv[1] file
################################################
lSubmoduleFunctionName = "Settings"
@ -22,10 +22,10 @@ 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)
mGlobalDict = None
gSettingsDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
#########################################################
from pyOpenRPA.Tools.RobotRDPActive import Connector
@ -35,17 +35,17 @@ from pyOpenRPA.Tools.RobotRDPActive import Scheduler # Scheduler operations
try:
#time.sleep()
######## Init the RDP List
for lConfigurationItem in mGlobalDict["RDPList"]:
for lConfigurationItem in gSettingsDict["RDPList"]:
lConfigurationItem["SessionIsWindowExistBool"]=False #Flag that session is not started
lConfigurationItem["SessionIsWindowResponsibleBool"]=False #Flag that session is not started
lConfigurationItem["SessionHex"]=" 77777sdfsdf77777dsfdfsf77777777" #Flag that session is not started
##########
#Run monitor
Scheduler.Scheduler(mGlobalDict["Scheduler"]) # Init & Run Scheduler
Monitor.Monitor(mGlobalDict, 1)
Scheduler.Scheduler(gSettingsDict["Scheduler"]) # Init & Run Scheduler
Monitor.Monitor(gSettingsDict, 1)
except Exception as e:
# Write in logger - warning
mGlobalDict["Logger"].exception(f"!!! ATTENTION !!! Global error handler - look at code")
gSettingsDict["Logger"].exception(f"!!! ATTENTION !!! Global error handler - look at code")
finally:
#Close all thread from OrchestratorConnection
mGlobalDict["OrchestratorConnectorTerminateAll"]()
gSettingsDict["OrchestratorConnectorTerminateAll"]()

@ -11,8 +11,9 @@ import uuid
import datetime
import os #for path operations
from http import cookies
global mGlobalDict
global gSettingsDict
from . import ServerSettings
import copy
#Authenticate function ()
# return dict
# {
@ -26,17 +27,21 @@ def AuthenticateVerify(inRequest):
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
inRequest.OpenRPA = {}
inRequest.OpenRPA["AuthToken"] = None
inRequest.OpenRPA["Domain"] = None
inRequest.OpenRPA["User"] = None
#pdb.set_trace()
if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value
if lCookieAuthToken:
#Find AuthToken in GlobalDict
if lCookieAuthToken in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}):
if lCookieAuthToken in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}):
#Auth Token Has Been Founded
lResult["Domain"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"]
lResult["User"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"]
lResult["Domain"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"]
lResult["User"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"]
#Set auth token
inRequest.OpenRPA["AuthToken"] = lCookieAuthToken
inRequest.OpenRPA["Domain"] = lResult["Domain"]
inRequest.OpenRPA["User"] = lResult["User"]
#Exit earlier
return lResult
######################################
@ -66,11 +71,11 @@ def AuthenticateVerify(inRequest):
lResult["User"] = lLogonResult["User"]
#Create token
lAuthToken=str(uuid.uuid1())
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie
inRequest.OpenRPA["AuthToken"] = lAuthToken
inRequest.OpenRPASetCookie = {}
@ -109,13 +114,13 @@ def UserAccessCheckBefore(inMethod, inRequest):
#go next if user is identified
lUserDict = None
if lAuthToken:
lUserDict = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]
lUserDict = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]
#pdb.set_trace()
########################################
########################################
#Check general before rule (without User domain)
#Check rules
for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []):
for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []):
#Go next execution if flag is false
if not lResult:
#Check if Method is identical
@ -125,21 +130,21 @@ def UserAccessCheckBefore(inMethod, inRequest):
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.startswith(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: Contains
elif lAccessRuleItem["MatchType"].upper() == "CONTAINS":
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.contains(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: Equal
elif lAccessRuleItem["MatchType"].upper() == "EQUAL":
if lAccessRuleItem["URL"].upper() == inRequest.path.upper():
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: EqualCase
elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE":
if lAccessRuleItem["URL"] == inRequest.path:
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
#########################################
#########################################
#Do check if lResult is false
@ -147,7 +152,7 @@ def UserAccessCheckBefore(inMethod, inRequest):
#Check access by User Domain
#Check rules to find first appicable
#Check rules
for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []):
for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []):
#Go next execution if flag is false
if not lResult:
#Check if Method is identical
@ -157,21 +162,21 @@ def UserAccessCheckBefore(inMethod, inRequest):
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.startswith(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
#check Match type variant: Contains
elif lAccessRuleItem["MatchType"].upper() == "CONTAINS":
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.contains(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: Equal
elif lAccessRuleItem["MatchType"].upper() == "EQUAL":
if lAccessRuleItem["URL"].upper() == inRequest.path.upper():
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: EqualCase
elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE":
if lAccessRuleItem["URL"] == inRequest.path:
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
#####################################
#####################################
#Return lResult
@ -221,24 +226,24 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lURLPath = self.path
lURLPath = lURLPath.upper()
if lURLPath.startswith(inURLItem["URL"].upper()):
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
# check Match type variant: Contains
elif inURLItem["MatchType"].upper() == "CONTAINS":
lURLPath = self.path
lURLPath = lURLPath.upper()
if lURLPath.contains(inURLItem["URL"].upper()):
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
# check Match type variant: Equal
elif inURLItem["MatchType"].upper() == "EQUAL":
if inURLItem["URL"].upper() == self.path.upper():
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
# check Match type variant: EqualCase
elif inURLItem["MatchType"].upper() == "EQUALCASE":
if inURLItem["URL"] == self.path:
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
return False
#ResponseContentTypeFile
@ -281,12 +286,12 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
# Logging
mGlobalDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}")
# gSettingsDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}")
if lFlagAccessUserBlock:
AuthenticateBlock(self)
#####################################
@ -295,7 +300,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
####################################
lFlagUserAccess = True
#If need user authentication
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lFlagUserAccess = UserAccessCheckBefore("GET", self)
######################################
if lFlagUserAccess:
@ -303,7 +308,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
############################
#New server engine (url from global dict (URLList))
############################
for lURLItem in mGlobalDict["Server"]["URLList"]:
for lURLItem in gSettingsDict["Server"]["URLList"]:
#Check if all condition are applied
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET")
@ -318,15 +323,15 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
self.send_header('Content-type','application/json')
self.end_headers()
# Send message back to client
message = json.dumps(mGlobalDict)
message = json.dumps(gSettingsDict)
# Write content as utf-8 data
self.wfile.write(bytes(message, "utf8"))
#Filemanager function
if self.path.lower().startswith('/filemanager/'):
lFileURL=self.path[13:]
# check if file in FileURL - File Path Mapping Dict
if lFileURL.lower() in mGlobalDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream',mGlobalDict["FileManager"]["FileURLFilePathDict"][lFileURL])
if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL])
else:
#Set access denied code
# Send response status code
@ -345,7 +350,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
@ -357,7 +362,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
####################################
lFlagUserAccess = True
#If need user authentication
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lFlagUserAccess = UserAccessCheckBefore("POST", self)
######################################
if lFlagUserAccess:
@ -365,7 +370,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
############################
#New server engine (url from global dict (URLList))
############################
for lURLItem in mGlobalDict["Server"]["URLList"]:
for lURLItem in gSettingsDict["Server"]["URLList"]:
#Check if all condition are applied
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST")
@ -416,16 +421,16 @@ class RobotDaemonServer(Thread):
Thread.__init__(self)
self.name = name
# Update the global dict
ServerSettings.SettingsUpdate(mGlobalDict)
ServerSettings.SettingsUpdate(inGlobalDict)
def run(self):
inServerAddress="";
inPort = mGlobalDict["Server"]["ListenPort"];
inPort = gSettingsDict["Server"]["ListenPort"];
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = (inServerAddress, inPort)
#httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
gSettingsDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
#httpd.serve_forever()
httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler)
#print('Starting server, use <Ctrl-C> to stop')

@ -3,6 +3,29 @@ import json
from desktopmagic.screengrab_win32 import (
getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage,
getRectAsImage, getDisplaysAsImages)
# /Orchestrator/RobotRDPActive/ControlPanelDictGet
def RobotRDPActive_ControlPanelDictGet(inRequest,inGlobalDict):
inResponseDict = inRequest.OpenRPAResponseDict
lResultDict = {
"DataList":[
# {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False}
]
}
# Iterate throught the RDP List
for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]:
lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][lRDPSessionKeyStrItem] # Get the configuration dict
lDataItemDict = {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} # Template
lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str
lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex
lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"]["FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window
lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored
lResultDict["DataList"].append(lDataItemDict)
# Send message back to client
message = json.dumps(lResultDict)
# Write content as utf-8 data
inResponseDict["Body"] = bytes(message, "utf8")
def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
inResponseDict = inRequest.OpenRPAResponseDict
# Create result JSON
@ -60,7 +83,8 @@ def SettingsUpdate(inGlobalConfiguration):
{"Method":"GET", "URL": "/favicon.ico", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\favicon.ico"), "ResponseContentType": "image/x-icon"},
{"Method":"GET", "URL": "/3rdParty/Handlebars/handlebars-v4.1.2.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js"), "ResponseContentType": "application/javascript"},
{"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": Monitor_ControlPanelDictGet, "ResponseContentType": "application/json"},
{"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": GetScreenshot, "ResponseContentType": "image/png"}
]
{"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": GetScreenshot, "ResponseContentType": "image/png"},
{"Method": "GET", "URL": "/Orchestrator/RobotRDPActive/ControlPanelDictGet", "MatchType": "Equal","ResponseDefRequestGlobal": RobotRDPActive_ControlPanelDictGet, "ResponseContentType": "application/json"}
]
inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList
return inGlobalConfiguration

@ -5,7 +5,7 @@ import importlib
import logging
from . import Processor
global mGlobalDict
global gSettingsDict
class RepeatedTimer(object):
def __init__(self, interval, function, *args, **kwargs):

@ -292,7 +292,49 @@
}
mGlobal.Monitor.fControlPanelRefresh()
mGlobal.Monitor.fControlPanelAutoUpdateRun(3);
////////////////////////////////
/////// /Orchestrator/RobotRDPActive/ControlPanelDictGet
///////////////////////////////
mGlobal.RobotRDPActive = {}
///Refresh control panel
mGlobal.RobotRDPActive.fControlPanelRefresh=function() {
///Загрузка данных
$.ajax({
type: "GET",
url: 'Orchestrator/RobotRDPActive/ControlPanelDictGet',
data: '',
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Сформировать HTML код новой таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON)
//Присвоить ответ в mGlobal.RobotRDPActive.mResponseList
mGlobal.RobotRDPActive.mResponseList = lResponseJSON
///Прогрузить новую таблицу
$(".openrpa-robotrdpactive-control-panel").html(lHTMLCode)
},
dataType: "text"
});
}
///
mGlobal.RobotRDPActive.mControlPanelAutoUpdateSeconds=3;
mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=3;
mGlobal.RobotRDPActive.fControlPanelAutoUpdateRun=function(inRefreshSeconds) {
mGlobal.RobotRDPActive.mControlPanelAutoUpdateSeconds=inRefreshSeconds;
//Функция обновления текста кнопки обновления
lControlPanelUpdate=function() {
mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent-1
if (mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent==-1) {
mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=mGlobal.RobotRDPActive.mControlPanelAutoUpdateSeconds;
mGlobal.RobotRDPActive.fControlPanelRefresh()
}
$(".openrpa-robotrdpactive-control-panel-general .openrpa-refresh-button").html("Refresh "+mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent);
}
mGlobal.RobotRDPActive.mControlPanelAutoUpdateTimerId=setInterval(lControlPanelUpdate,1000)
}
mGlobal.RobotRDPActive.fControlPanelRefresh()
mGlobal.RobotRDPActive.fControlPanelAutoUpdateRun(3);
mGlobal.Test=function() {
///Обнулить таблицу
lData = [
@ -339,9 +381,9 @@
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
lResponseJSON["actionListResult"][0]["result"].forEach(function(lItem){lItem["processPathName"]=("processPath" in lItem ? lItem["processPath"] : lItem["processName"])})
lResponseJSON[0]["Result"].forEach(function(lItem){lItem["processPathName"]=("processPath" in lItem ? lItem["processPath"] : lItem["processName"])})
///Отправить запрос на формирование таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-planloglist",lResponseJSON["actionListResult"][0]);
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-planloglist",lResponseJSON[0]);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
@ -349,12 +391,33 @@
dataType: "text"
});
}
///////////////////////////////
///Processor functions
///////////////////////////////
mGlobal.Processor = {}
mGlobal.Processor.ServerValueAppend = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueAppend",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [
{
@ -532,58 +595,17 @@
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
///Test
lTestDataTable = {
"Title":"Test",
"Columns":["Дата/Время","Статус","Клиент","Файл"],
"Rows":[
["2019.10.31 13:21","Успешно", "ООО БалтКам", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО Гренодер", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО БалтКам", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО Гренодер", "test.xml"],
["2019.10.31 13:21","Отказ", "ООО Сударь", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО БалтКам", "test.xml"],
["2019.10.31 13:21","Отказ", "ООО Гренодер", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО Гренодер", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО Сударь", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО БалтКам", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО Гренодер", "test.xml"],
["2019.10.31 13:21","Отказ", "ООО Сударь", "test.xml"],
["2019.10.31 13:21","Успешно", "ООО БалтКам", "test.xml"],
["f","s"]
]
}
//mGlobal.Modal.TableFilter.Show(lTestData)
///Test
lTestData = {
"Title":"Test",
"List":[
{"Header":"Head 09","Description":"Test 21.02.2019"},
{"Header":"Head 09","Description":"Test 21.02.2019"},
{"Header":"Head 09","Description":"Test 21.02.2019"},
{"Header":"Head 09","Description":"TestNew 21.02.2019"},
{"Header":"Head 09","Description":"Test 21.02.2019"},
{"Header":"Head 09","Description":"TestNew 21.02.2019"},
{"Header":"Head 09","Description":"Test 21.02.2019"},
{"Header":"Head 09","Description":"Test 21.02.2019"}
]
}
// mGlobal.Modal.ListFilter.Show(lTestData)
})
;
</script>
<style type="text/css">
body {
background-color: #FFFFFF;
}
.main.container {
margin-top: 2em;
}
.overlay {
float: left;
margin: 0em 3em 1em 0em;
@ -593,7 +615,6 @@
left: 0;
transition: left 0.5s ease;
}
.main.menu.fixed {
background-color: #FFFFFF;
border: 1px solid #DDD;
@ -602,14 +623,12 @@
.overlay.fixed .menu {
left: 800px;
}
.text.container .left.floated.image {
margin: 2em 2em 2em -4em;
}
.text.container .right.floated.image {
margin: 2em -4em 2em 2em;
}
.ui.footer.segment {
margin: 5em 0em 0em;
padding: 5em 0em;
@ -626,7 +645,7 @@
<h1 class="ui header inverted">Orchestrator Web GUI</h1>
</div>
<div class="two wide column">
<h5>by UnicodeLabs</h5>
<h5>by Ivan Maslov</h5>
</div>
</div>
@ -689,36 +708,65 @@
</div>
</div>
<div class="row black">
<div class="three wide column">
</div>
<div class="three wide column">
<h2 class="ui header inverted">Monitor</h2>
<div class="five wide column">
<h2 class="ui header inverted">Controls</h2>
</div>
<div class="two wide column">
<h2 class="ui header inverted">...</h2>
</div>
<div class="nine wide column">
<h2 class="ui header inverted">Robot RDP active list</h2>
</div>
</div>
<button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();">
<i class="desktop icon"></i>
Look machine screenshot
</button>
<button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();">
<i class="redo icon"></i>
Restart Orchestrator
</button>
<button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();">
<i class="info icon"></i>
Scheduler activity time list
<script class="openrpa-hidden-info-table-planloglist" style="display:none" type="text/x-handlebars-template">
<div class="row">
<div class="five wide column">
<button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();">
<i class="desktop icon"></i>
Look machine screenshot
</button>
<button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();">
<i class="redo icon"></i>
Restart Orchestrator
</button>
<button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();">
<i class="info icon"></i>
Scheduler activity time list
<script class="openrpa-hidden-info-table-planloglist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Time</th>
<th>Process path/Process name</th>
</tr>
</thead>
<tbody>
{{#Result}}
<tr>
<td>{{@index}}</td>
<td>{{TimeHH:MM}}{{TimeHH:MMStart}}</td>
<td>{{TimeHH:MMStop}}</td>
<td>{{Activity}}</td>
</tr>
{{/Result}}
</tbody>
</table>
</script>
</button>
<button class="ui labeled icon button" onclick="mGlobal.Processor.LogListShow();">
<i class="info icon"></i>
Processor logs
<script class="openrpa-hidden-info-table-activitylogschedulelist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Time</th>
<th>Process path/Process name</th>
<th>Process</th>
<th>Activity DateTime plan</th>
<th>Activity DateTime fact</th>
</tr>
</thead>
<tbody>
@ -726,117 +774,136 @@
<tr>
<td>{{@index}}</td>
<td>{{activityType}}</td>
<td>{{time}}</td>
<td>{{processPathName}}</td>
<td>{{processPath}}</td>
<td>{{activityDateTime}}</td>
<td class="negative
">{{activityStartDateTime}}</td>
</tr>
{{/result}}
</tbody>
</table>
</script>
</button>
<button class="ui labeled icon button" onclick="mGlobal.Processor.LogListShow();">
<i class="info icon"></i>
Processor logs
<script class="openrpa-hidden-info-table-activitylogschedulelist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Process</th>
<th>Activity DateTime plan</th>
<th>Activity DateTime fact</th>
</tr>
</thead>
<tbody>
{{#result}}
<tr>
<td>{{@index}}</td>
<td>{{activityType}}</td>
<td>{{processPath}}</td>
<td>{{activityDateTime}}</td>
<td class="negative
">{{activityStartDateTime}}</td>
</tr>
{{/result}}
</tbody>
</table>
</script>
</button>
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>Machine name</th>
<th>Machihe host</th>
<th>Status</th>
<th>Actions,length: {{childs.length}}</th>
</tr>
</thead>
<tbody>
{{#ListenURLList}}
<tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr>
{{/ListenURLList}}
</tbody>
</table>
</script>
<script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template">
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</button>
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>Machine name</th>
<th>Machihe host</th>
<th>Status</th>
<th>Actions,length: {{childs.length}}</th>
</tr>
</thead>
<tbody>
{{#ListenURLList}}
<tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr>
{{/ListenURLList}}
</tbody>
</table>
</script>
<script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template">
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</div>
{{/if}}
<table class="ui celled table selectable inverted">
<thead>
<tr>
{{#Columns}}
<th>{{{this}}}</th>
{{/Columns}}
</tr>
</thead>
<tbody>
{{#Rows}}
<tr>
{{#this}}
<td>
{{{this}}}
</td>
{{/this}}
</tr>
{{/Rows}}
</tbody>
</table>
</script>
<script class="openrpa-handlebar-template-list-filter" style="display:none" type="text/x-handlebars-template">
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</div>
{{/if}}
<div class="ui inverted segment">
<div class="ui inverted relaxed divided list">
{{#List}}
<div class="item">
<i class="map marker icon"></i>
<div class="content">
<a class="header">{{{Header}}}</a>
<div class="description">{{{Description}}}</div>
</div>
</div>
{{/List}}
</div>
</div>
</script>
</div>
{{/if}}
<table class="ui celled table selectable inverted">
<thead>
<tr>
{{#Columns}}
<th>{{{this}}}</th>
{{/Columns}}
</tr>
</thead>
<tbody>
{{#Rows}}
<tr>
{{#this}}
<td>
{{{this}}}
</td>
{{/this}}
</tr>
{{/Rows}}
</tbody>
</table>
</script>
<script class="openrpa-handlebar-template-list-filter" style="display:none" type="text/x-handlebars-template">
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
<div class="two wide column">
</div>
{{/if}}
<div class="ui inverted segment">
<div class="ui inverted relaxed divided list">
{{#List}}
<div class="item">
<i class="map marker icon"></i>
<div class="content">
<a class="header">{{{Header}}}</a>
<div class="description">{{{Description}}}</div>
<div class="nine wide column openrpa-robotrdpactive-control-panel-general">
<div class="ui info message">
<button class="ui icon button labeled " onclick="mGlobal.RobotRDPActive.fControlPanelRefresh();">
<i class="sync alternate icon"></i>
<div class="openrpa-refresh-button">Refresh</div>
</button>
</div>
<div class="openrpa-robotrdpactive-control-panel"></div>
<script class="openrpa-hidden-robotrdpactive-control-panel" style="display:none" type="text/x-handlebars-template">
<div class="ui inverted segment">
<div class="ui inverted relaxed divided list">
{{#DataList}}
<div class="item">
<div class="right floated content">
<div class="ui button" onclick="mGlobal.Processor.ServerValueAppend(['RobotRDPActive','ActivityList'],{'DefNameStr': 'RDPSessionReconnect', 'ArgList': [], 'ArgDict': {'inRDPSessionKeyStr': '{{{SessionKeyStr}}}'} })" >Reconnect</div>
</div>
<div class="right floated content">
{{#if IsIgnoredBool}}
<div class="ui button red" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','RDPList','{{{SessionKeyStr}}}','SessionIsIgnoredBool'],false);">Ignore</div>
{{else}}
<div class="ui button" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','RDPList','{{{SessionKeyStr}}}','SessionIsIgnoredBool'],true);">Ignore</div>
{{/if}}
</div>
<div class="right floated content">
{{#if IsFullScreenBool}}
<div class="ui button green" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','FullScreenRDPSessionKeyStr'],null);">Full screen</div>
{{else}}
<div class="ui button" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','FullScreenRDPSessionKeyStr'],'{{{SessionKeyStr}}}');">Full screen</div>
{{/if}}
</div>
<div class="content">
<div class="header">Session key: {{{SessionKeyStr}}}</div>
{{{SessionHexStr}}}
</div>
</div>
{{/DataList}}
</div>
</div>
{{/List}}
</div>
</script>
</div>
</script>
</div>
<div class="row openrpa-monitor">
</div>

@ -12,7 +12,7 @@ import datetime
import struct
import shutil
from pyOpenRPA.Robot import UIDesktop
global mGlobalDict
global gSettingsDict
####################################
#Info: Main module of the Robot app (OpenRPA - Robot)
####################################

@ -11,7 +11,7 @@ from . import RobotConnector
from . import JSONNormalize
import importlib
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
global gSettingsDict
#Call Settings function from argv[1] file
################################################
lSubmoduleFunctionName = "Settings"
@ -20,14 +20,14 @@ 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)
mGlobalDict = None
gSettingsDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
RobotConnector.mGlobalDict = mGlobalDict
RobotConnector.mGlobalDict = gSettingsDict
#Init the robot
RobotConnector.UIDesktop.Utils.ProcessBitness.SettingsInit(mGlobalDict["ProcessBitness"])
RobotConnector.UIDesktop.Utils.ProcessBitness.SettingsInit(gSettingsDict["ProcessBitness"])
# HTTP Studio web server class
class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
@ -144,13 +144,13 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
def run():
inServerAddress = "";
inPort = mGlobalDict["Server"]["ListenPort"];
inPort = gSettingsDict["Server"]["ListenPort"];
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
gSettingsDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
# Запуск адреса в браузере
os.system(f"explorer http://127.0.0.1:{str(inPort)}")
httpd.serve_forever()

@ -15,7 +15,7 @@ import importlib
from importlib import util
#Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict
global gSettingsDict
#Call Settings function from argv[1] file
################################################
lSubmoduleFunctionName = "Settings"
@ -24,18 +24,18 @@ 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)
mGlobalDict = None
gSettingsDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
#################################################
#mGlobalDict = Settings.Settings(sys.argv[1])
Server.mGlobalDict = mGlobalDict
Server.mGlobalDict = gSettingsDict
#Инициализация настроечных параметров
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
lDaemonStartDateTime=datetime.datetime.now()
#Инициализация сервера
lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict)
lThreadServer = Server.RobotDaemonServer("ServerThread", gSettingsDict)
lThreadServer.start()

@ -10,7 +10,7 @@ import uuid
import datetime
import os #for path operations
from http import cookies
global mGlobalDict
global gSettingsDict
from . import ServerSettings
#Authenticate function ()
# return dict
@ -30,10 +30,10 @@ def AuthenticateVerify(inRequest):
lCookieAuthToken = lCookies.get("AuthToken", "").value
if lCookieAuthToken:
#Find AuthToken in GlobalDict
if lCookieAuthToken in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}):
if lCookieAuthToken in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}):
#Auth Token Has Been Founded
lResult["Domain"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"]
lResult["User"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"]
lResult["Domain"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"]
lResult["User"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"]
#Set auth token
inRequest.OpenRPA["AuthToken"] = lCookieAuthToken
#Exit earlier
@ -65,11 +65,11 @@ def AuthenticateVerify(inRequest):
lResult["User"] = lLogonResult["User"]
#Create token
lAuthToken=str(uuid.uuid1())
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False
mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {}
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"]
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"]
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie
inRequest.OpenRPA["AuthToken"] = lAuthToken
inRequest.OpenRPASetCookie = {}
@ -108,13 +108,13 @@ def UserAccessCheckBefore(inMethod, inRequest):
#go next if user is identified
lUserDict = None
if lAuthToken:
lUserDict = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]
lUserDict = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]
#pdb.set_trace()
########################################
########################################
#Check general before rule (without User domain)
#Check rules
for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []):
for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []):
#Go next execution if flag is false
if not lResult:
#Check if Method is identical
@ -124,21 +124,21 @@ def UserAccessCheckBefore(inMethod, inRequest):
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.startswith(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: Contains
elif lAccessRuleItem["MatchType"].upper() == "CONTAINS":
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.contains(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: Equal
elif lAccessRuleItem["MatchType"].upper() == "EQUAL":
if lAccessRuleItem["URL"].upper() == inRequest.path.upper():
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: EqualCase
elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE":
if lAccessRuleItem["URL"] == inRequest.path:
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
#########################################
#########################################
#Do check if lResult is false
@ -146,7 +146,7 @@ def UserAccessCheckBefore(inMethod, inRequest):
#Check access by User Domain
#Check rules to find first appicable
#Check rules
for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []):
for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []):
#Go next execution if flag is false
if not lResult:
#Check if Method is identical
@ -156,21 +156,21 @@ def UserAccessCheckBefore(inMethod, inRequest):
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.startswith(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
#check Match type variant: Contains
elif lAccessRuleItem["MatchType"].upper() == "CONTAINS":
lURLPath = inRequest.path
lURLPath = lURLPath.upper()
if lURLPath.contains(lAccessRuleItem["URL"].upper()):
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: Equal
elif lAccessRuleItem["MatchType"].upper() == "EQUAL":
if lAccessRuleItem["URL"].upper() == inRequest.path.upper():
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
# check Match type variant: EqualCase
elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE":
if lAccessRuleItem["URL"] == inRequest.path:
lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict)
lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict)
#####################################
#####################################
#Return lResult
@ -220,24 +220,24 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lURLPath = self.path
lURLPath = lURLPath.upper()
if lURLPath.startswith(inURLItem["URL"].upper()):
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
# check Match type variant: Contains
elif inURLItem["MatchType"].upper() == "CONTAINS":
lURLPath = self.path
lURLPath = lURLPath.upper()
if lURLPath.contains(inURLItem["URL"].upper()):
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
# check Match type variant: Equal
elif inURLItem["MatchType"].upper() == "EQUAL":
if inURLItem["URL"].upper() == self.path.upper():
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
# check Match type variant: EqualCase
elif inURLItem["MatchType"].upper() == "EQUALCASE":
if inURLItem["URL"] == self.path:
URLItemDo(inURLItem, self, mGlobalDict)
URLItemDo(inURLItem, self, gSettingsDict)
return True
return False
#ResponseContentTypeFile
@ -280,12 +280,12 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
# Logging
mGlobalDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}")
gSettingsDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}")
if lFlagAccessUserBlock:
AuthenticateBlock(self)
#####################################
@ -294,7 +294,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
####################################
lFlagUserAccess = True
#If need user authentication
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lFlagUserAccess = UserAccessCheckBefore("GET", self)
######################################
if lFlagUserAccess:
@ -302,7 +302,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
############################
#New server engine (url from global dict (URLList))
############################
for lURLItem in mGlobalDict["Server"]["URLList"]:
for lURLItem in gSettingsDict["Server"]["URLList"]:
#Check if all condition are applied
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET")
@ -327,7 +327,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
@ -339,7 +339,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
####################################
lFlagUserAccess = True
#If need user authentication
if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lFlagUserAccess = UserAccessCheckBefore("POST", self)
######################################
if lFlagUserAccess:
@ -347,7 +347,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
############################
#New server engine (url from global dict (URLList))
############################
for lURLItem in mGlobalDict["Server"]["URLList"]:
for lURLItem in gSettingsDict["Server"]["URLList"]:
#Check if all condition are applied
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST")
@ -380,16 +380,16 @@ class RobotDaemonServer(Thread):
Thread.__init__(self)
self.name = name
# Update the global dict
ServerSettings.SettingsUpdate(mGlobalDict)
ServerSettings.SettingsUpdate(gSettingsDict)
def run(self):
inServerAddress="";
inPort = mGlobalDict["Server"]["ListenPort"];
inPort = gSettingsDict["Server"]["ListenPort"];
# Server settings
# Choose port 8080, for port 80, which is normally used for a http server, you need root access
server_address = (inServerAddress, inPort)
#httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
# Logging
mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
gSettingsDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}")
#httpd.serve_forever()
httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler)
#print('Starting server, use <Ctrl-C> to stop')

@ -1,76 +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
#ATTENTION
gSettings = None # Gsettings will be initialized after the import module
def ProcessStartIfNotRunning(inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True):
global gSettings
inGlobalDict = gSettings
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"Defs_SessionIndex.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(inSessionIndex, inProcessName, inFlagForceClose):
global gSettings
inGlobalDict = gSettings
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"Defs_SessionIndex.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(inSessionIndex, inHostFilePath, inRDPFilePath):
global gSettings
inGlobalDict = gSettings
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"Defs_SessionIndex.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(inSessionIndex, inRDPFilePath, inHostFilePath):
global gSettings
inGlobalDict = gSettings
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"Defs_SessionIndex.FileStoredRecieve: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
Loading…
Cancel
Save