v1.1.0 After 2 month test prefinal with new improovements (+RobotRDPActive in Orchestrator + Easy ControlPanelTemplate)

dev-linux
Ivan Maslov 5 years ago
parent b8e4cd82b5
commit 18b98d89d3

@ -1,207 +0,0 @@
import psutil, datetime, logging, os, json
# # # # # # # ORCHESTRATOR CONTROL PANEL <Robot name> # # # # # # #
# Init parameters
gProcessNameWOEXE = "OpenRPA_RobotRDPActive_<RobotKeyName>"
gRDPOrchestratorStorageKey = "<RobotKeyName>"
gRDPStartFilePath = os.path.abspath(os.path.join(os.getcwd(), gRDPOrchestratorStorageKey+r"\pyOpenRPA.Tools.RobotRDPActive_x64.cmd")) # cwd is orchestrator working directory
gOrchestratorToRobotKeyList = ["Storage",gRDPOrchestratorStorageKey,"OrchestratorToRobotStorage"]
gOrchestratorToRobotResetKeyList = ["Storage",gRDPOrchestratorStorageKey,"OrchestratorToRobotResetStorage"]
gRobotToOrchestratorKeyList = ["Storage",gRDPOrchestratorStorageKey,"RobotToOrchestratorStorage"]
gRobotRDPActiveDefsFolderPath = ""
gRobotProcessNameWOEXE = "<RobotProcessName>"
gRobotProcessFilePath = r"path\to\start\link"
# Function, which is generate Dict for front-endswith
def ControlPanelRenderDict(inGSettings):
"""result={
"HeaderLeftText":"<Robot name>",
"HeaderRightText":"<header>",
"DataStorageKey":"Robot_Name", #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
"SubheaderText": "State: <span style=\"color:green\">Turned on</span>",
"BodyKeyValueList":[
{"Key":"Session list","Value":""},
{"Key":"Session list","Value":""}
],
"FooterText":"Last update: 9:38:00 09.10.2019",
"FooterButtonX2List":[
{"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lOnClickRunButton.replace("\\","\\\\")},
],
"FooterButtonX1List":[
{"Text":"Kill", "Color":"red", "Link":"", "OnClick": lOnClickForceCloseButton.replace("\\","\\\\")}
]
}"""
# START :: Create activities :: START #
## RDP Start
lActivityRDPStartEscaped = (f"mGlobal.Controller.CMDRunText('start cmd /K {gRDPStartFilePath}');").replace("\\","\\\\").replace("\"","\'") # Need escape because this is render on client side and after that it goes to server side :(
## RDP Safe turn off
lActivityRDPSafeOffEscaped = (f"mGlobal.Processor.ServerValueSet({json.dumps(gOrchestratorToRobotKeyList+['SafeTurnOff'])},true);").replace("\\","\\\\").replace("\"","\'")
## RDP Kill
lActivityRDPKillEscaped = (f"mGlobal.Controller.CMDRunText('taskkill /F /im {gProcessNameWOEXE}.exe');").replace("\\","\\\\").replace("\"","\'")
## Robot start
lActivityROBOTStartList = [
{
"ModulePath": f"{os.path.abspath(os.path.join(gRobotRDPActiveDefsFolderPath,'Defs_SessionIndex.py'))}", # "RobotRDPActive\\SessionDefs.py"
"DefName":"ProcessStartIfNotRunning", # Function name
"ArgList":[], # Args list
"ArgDict":{"inSessionIndex": 0, "inProcessName": f"{gRobotProcessNameWOEXE}.exe", "inFilePath": gRobotProcessFilePath} # Args dictionary
}
]
lActivityROBOTStartEscaped = f"mGlobal.Processor.ServerValueSet({json.dumps(gOrchestratorToRobotResetKeyList+['ActivityList'])},{json.dumps(lActivityROBOTStartList)});".replace("\"","\'")
## ROBOT r3 stop
lActivityROBOTStopList = [
{
"ModulePath": f"{os.path.abspath(os.path.join(gRobotRDPActiveDefsFolderPath,'Defs_SessionIndex.py'))}", # "Session\\SessionDefs.py"
"DefName":"ProcessStop", # Function name
"ArgList":[], # Args list
"ArgDict":{"inSessionIndex": 0, "inProcessName": f"{gRobotProcessNameWOEXE}.exe", "inFlagForceClose":True} # Args dictionary
}
]
lActivityROBOTStopEscaped = f"mGlobal.Processor.ServerValueSet({json.dumps(gOrchestratorToRobotResetKeyList+['ActivityList'])},{json.dumps(lActivityROBOTStopList)});".replace("\"","\'")
## ROBOT r3 restart
lActivityROBOTRestartList = lActivityROBOTStartList + lActivityROBOTStopList
lActivityROBOTRestartEscaped = f"mGlobal.Processor.ServerValueSet({json.dumps(gOrchestratorToRobotResetKeyList+['ActivityList'])},{json.dumps(lActivityROBOTRestartList)});".replace("\"","\'")
# END :: Create activities :: END #
# START :: Init result dict template :: START #
lBodyKeyValue_r3_start=f'<a onclick="{lActivityROBOTStartEscaped}" style=\"color:green\">Start</a>'
lBodyKeyValue_r3_stop=f'<a onclick="{lActivityROBOTStopEscaped}" style=\"color:red\">Stop</a>'
lBodyKeyValue_r3_restart=f'<a onclick="{lActivityROBOTRestartEscaped}" style=\"color:orange\">restart</a>'
lResultDict={
"HeaderLeftText":"ROBOT r4",
"HeaderRightText":"r4",
"DataStorageKey":gRDPOrchestratorStorageKey, #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
"SubheaderText":"<Subheader text>",
"BodyKeyValueList":[
{"Key":"ROBOT robots (r1-r5) list","Value":""},
{"Key":"r4","Value":f"{lBodyKeyValue_r3_start}, {lBodyKeyValue_r3_stop}, {lBodyKeyValue_r3_restart}"},
{"Key":"Session list","Value":""}
],
"FooterText":"Last update: 9:38:00 09.10.2019",
"FooterButtonX2List":[
{"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lActivityRDPStartEscaped},
{"Text":"Safe turn off", "Color":"orange", "Link":"", "OnClick": lActivityRDPSafeOffEscaped}
],
"FooterButtonX1List":[
{"Text":"Kill", "Color":"red", "Link":"", "OnClick": lActivityRDPKillEscaped}
],
"GlobalStorage": inGSettings.get("Storage",{}) # UNCOMMENT FOR DEBUG PURPOSE TO WATCH inGSettings on client side
}
# END :: Init result dict template :: END #
# START :: Fill BodyKeyValueList :: START #
## Read RDPList
lRDPList = TechDictKeyList_ItemGet(inDict=inGSettings, inKeyList=gRobotToOrchestratorKeyList+["RDPList"], inDefault=[])
lFullScreenSessionIndex = TechDictKeyList_ItemGet(inDict=inGSettings, inKeyList=gRobotToOrchestratorKeyList+["FullScreenSessionIndex"], inDefault=None)
lRDPListIndex = 0
for lItem in lRDPList:
### Lable that session has fullscreen
lLabelSessionFullScreen = ""
lLabelIsIgnored = ""
### Link set full screen
lOnClickSetFullScreen = f"mGlobal.Processor.ServerValueSet(['Storage','{gRDPOrchestratorStorageKey}','OrchestratorToRobotStorage','FullScreenSessionIndex'],{lRDPListIndex});"
lSetFullScreenA = f'<a onclick="{lOnClickSetFullScreen}" style=\"color:blue\">Set fullscreen</a>'
if lRDPListIndex == lFullScreenSessionIndex:
lLabelSessionFullScreen = '<span style=\"color:blue\">[Fullscreen]</span>'
lOnClickSetFullScreen = f"mGlobal.Processor.ServerValueSet(['Storage','{gRDPOrchestratorStorageKey}','OrchestratorToRobotStorage','FullScreenSessionIndex'],null);"
lSetFullScreenA = f'<a onclick="{lOnClickSetFullScreen}" style=\"color:blue\">Set minimized</a>'
lIgnoreIndexListOnClick = "$.ajax({type: 'POST', url: '{gRDPOrchestratorStorageKey}/IgnoreIndexListAppend', data: '"+str(lRDPListIndex)+"', success: function(lData,l2,l3){}, dataType: 'text'});"
lIgnoreIndexListLink = f'<a onclick="{lIgnoreIndexListOnClick}" style=\"color:red\">Ignore</a>'
### Check if in ignore
if lRDPListIndex in inGSettings.get("Storage",{}).get(gRDPOrchestratorStorageKey,{}).get("OrchestratorToRobotStorage",{}).get("IgnoreIndexList",[]):
lLabelIsIgnored = '<span style=\"color:red\">[Ignored]</span>'
lIgnoreIndexListOnClick = "$.ajax({type: 'POST', url: '"+gRDPOrchestratorStorageKey+"/IgnoreIndexListRemove', data: '"+str(lRDPListIndex)+"', success: function(lData,l2,l3){}, dataType: 'text'});"
lIgnoreIndexListLink = f'<a onclick="{lIgnoreIndexListOnClick}" style=\"color:red\">Unignore</a>'
### Session state
lItemSessionState='<span style=\"color:red\">Disconnected</span>'
if lItem.get("SessionIsWindowResponsibleBool",False):
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}"})
lRDPListIndex = lRDPListIndex + 1
# END :: Fill BodyKeyValueList :: END #
# START :: Fill SubheaderText :: START #
## Variants
lSubheaderRunTrueText="State: <span style=\"color:green\">Turned on</span>"
lSubheaderRunFalseText="State: <span style=\"color:red\">Turned off</span>"
if CheckIfProcessRunning(gProcessNameWOEXE):
lResultDict["SubheaderText"]=lSubheaderRunTrueText
else:
lResultDict["SubheaderText"]=lSubheaderRunFalseText
# END :: Fill SubheaderText :: END #
# Fill FooterText
lResultDict["FooterText"]=f'Last update: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}'
return lResultDict
# Check in control panel, that process is runnning
def CheckIfProcessRunning(processName):
'''Check if there is any running process that contains the given name processName.'''
#Iterate over the all the running process
for proc in psutil.process_iter():
try:
# Check if process name contains the given name string.
if processName.lower() in proc.name().lower():
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False
#Add to ignore list - AJAX request from client side
def IgnoreIndexListAppend(inRequest,inConfiguration):
lIgnoreList = TechDictKeyList_ItemGet(inDict=inConfiguration, inKeyList=gOrchestratorToRobotKeyList+["IgnoreIndexList"], inDefault=[])
lIgnoreIndex={}
if inRequest.headers.get('Content-Length') is not None:
lInputByteArrayLength = int(inRequest.headers.get('Content-Length'))
lInputByteArray=inRequest.rfile.read(lInputByteArrayLength)
#Превращение массива байт в объект
lIgnoreIndex=int(lInputByteArray.decode('utf8'))
#check if index not in list
if lIgnoreIndex not in lIgnoreList:
#append to list
lIgnoreList.append(lIgnoreIndex)
#remove from Ignore list - AJAX request from client side
def IgnoreIndexListRemove(inRequest,inConfiguration):
lIgnoreList = TechDictKeyList_ItemGet(inDict=inConfiguration, inKeyList=gOrchestratorToRobotKeyList+["IgnoreIndexList"], inDefault=[])
lIgnoreIndex={}
if inRequest.headers.get('Content-Length') is not None:
lInputByteArrayLength = int(inRequest.headers.get('Content-Length'))
lInputByteArray=inRequest.rfile.read(lInputByteArrayLength)
#Превращение массива байт в объект
lIgnoreIndex=int(lInputByteArray.decode('utf8'))
#check if index not in list
if lIgnoreIndex in lIgnoreList:
#append to list
lIgnoreList.remove(lIgnoreIndex) #Remove delete the element lIgnoreIndex
# Technical def - Get item by the list of keys
def TechDictKeyList_ItemGet(inDict, inKeyList, inDefault={}):
lResult=inDict
for lItem in inKeyList:
if lResult:
lResult = lResult.get(lItem,None)
if lResult is None:
lResult=inDefault
return lResult
# # # # # # # # # # # # # # # # # # # # # # # #
#Orchestrator settings
def SettingsUpdate(inGSettings):
#Add RobotRDPActive in control panel
inGSettings["ControlPanelDict"]["RobotList"].append({"RenderFunction": ControlPanelRenderDict})
#Default structure
inGSettings["Storage"][gRDPOrchestratorStorageKey]={
"OrchestratorToRobotResetStorage":{"SafeTurnOff":False, "ActivityList":[]},
"OrchestratorToRobotStorage":{
"FullScreenSessionIndex":None,
"IgnoreIndexList": []
}
}
#Add methods
inGSettings["Server"]["URLList"].append(
{
"Method":"POST",
"URL": f"/{gRDPOrchestratorStorageKey}/IgnoreIndexListAppend", #URL of the request
"MatchType": "Equal", #"BeginWith|Contains|Equal|EqualCase",
"ResponseDefRequestGlobal": IgnoreIndexListAppend #Function with str result
}
)
inGSettings["Server"]["URLList"].append(
{
"Method":"POST",
"URL": f"/{gRDPOrchestratorStorageKey}/IgnoreIndexListRemove", #URL of the request
"MatchType": "Equal", #"BeginWith|Contains|Equal|EqualCase",
"ResponseDefRequestGlobal": IgnoreIndexListRemove #Function with str result
}
)
return inGSettings

@ -0,0 +1,124 @@
import psutil, datetime, logging, os, json
# # # # # # # ORCHESTRATOR CONTROL PANEL <Robot name> # # # # # # #
# Init parameters
gRobotStartFilePathStr = r"path\to\start\file" # path\to\start\file
gRobotProcessNameWOEXEStr = "process name" # RobotProcessName
gRobotADLoginStr = "Login" # Login of the robot session
gRobotADPasswordStr = "Password" # Password for session
gRobotKeyStr = "Robot_Template"
gRDPSessionKeyStr = "RDP_Template"
gRDPSessionHostStr = "localhost" # Rdp session host
gRDPSessionPortStr = "3389" # Default 3389
gControlPanelKeyStr = "ControlPanel_Template"
gControlPanelCheckRobotProcessFromOrchestratorUserBool = True # Check process activity from orchestrator GUI session (with help of task manager, when users on the same machine)
# !! ATTENTION !! SCHEDULE TIME START STOP FILL BELOW IN ACTIVITY SECTION
gRobotToOrchestratorKeyList = ["Storage",gRobotKeyStr,"RobotToOrchestrator"]
gOrchestratorToRobotResetKeyList = ["Storage",gRobotKeyStr,"OrchestratorToRobotReset"]
gOrchestratorToRobotResetSafeStopKeyList = gOrchestratorToRobotResetKeyList+["SafeTurnOffBool"]
# Function, which is generate Dict for front-endswith
def ControlPanelRenderDict(inGSettings):
"""result={
"HeaderLeftText":"<Robot name>",
"HeaderRightText":"<header>",
"DataStorageKey":"Robot_Name", #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
"SubheaderText": "State: <span style=\"color:green\">Turned on</span>",
"BodyKeyValueList":[
{"Key":"Session list","Value":""},
{"Key":"Session list","Value":""}
],
"FooterText":"Last update: 9:38:00 09.10.2019",
"FooterButtonX2List":[
{"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lOnClickRunButton.replace("\\","\\\\")},
],
"FooterButtonX1List":[
{"Text":"Kill", "Color":"red", "Link":"", "OnClick": lOnClickForceCloseButton.replace("\\","\\\\")}
]
}"""
# START :: Create activities :: START #
## Robot START (create RDP session, send CMD to start process)
lActivityROBOTStartList = [
{ # Start RDP Session
"DefNameStr":"RDPSessionConnect", # Function name in RobotRDPActive.Processor
"ArgList":[], # Args list
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr, "inHostStr": gRDPSessionHostStr, "inPortStr": gRDPSessionPortStr, "inLoginStr": gRobotADLoginStr, "inPasswordStr": gRobotADPasswordStr} # Args dictionary
},
{ # Run robot file in RDP session
"DefNameStr":"RDPSessionProcessStartIfNotRunning", # Function name in RobotRDPActive.Processor
"ArgList":[], # Args list
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr, "inProcessNameWEXEStr": f"{gRobotProcessNameWOEXEStr}.exe", "inFilePathStr": gRobotStartFilePathStr, "inFlagGetAbsPathBool": False} # Args dictionary
}
]
lActivityROBOTStartEscaped = f"mGlobal.Processor.ServerValueSet({json.dumps(['RobotRDPActive','ActivityList'])},{json.dumps(lActivityROBOTStartList)});".replace("\"","\'")
## Robot SAFE STOP (SAFE STOP COMMAND (FROM ROBOT RULES), Logoff must do robot when safe turn off)
lActivityROBOTSafeStopEscaped = f"mGlobal.Processor.ServerValueSet({json.dumps(gOrchestratorToRobotResetSafeStopKeyList)},true);".replace("\"","\'")
## Robot FORCE STOP (create RDP session, send CMD to start process)
lActivityROBOTStopList = [
{ # Kill process
"DefNameStr":"RDPSessionProcessStop", # Function name in RobotRDPActive.Processor
"ArgList":[], # Args list
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr, "inProcessNameWEXEStr":f"{gRobotProcessNameWOEXEStr}.exe","inFlagForceCloseBool": True} # Args dictionary
},
{ # Logoff RDP Session
"DefNameStr":"RDPSessionLogoff", # Function name in RobotRDPActive.Processor
"ArgList":[], # Args list
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr} # Args dictionary
}
]
lActivityROBOTStopEscaped = f"mGlobal.Processor.ServerValueSet({json.dumps(['RobotRDPActive','ActivityList'])},{json.dumps(lActivityROBOTStopList)});".replace("\"","\'")
# END :: Create activities :: END #
# START :: Init result dict template :: START #
# lBodyKeyValue_r3_start=f'<a onclick="{lActivityROBOTStartEscaped}" style=\"color:green\">Start</a>'
lResultDict={
"HeaderLeftText":"ROBOT KEYWORD",
"HeaderRightText":"ROBOT NAME",
"DataStorageKey":gControlPanelKeyStr, # CLIENT SIDE:: Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
"SubheaderText":"<Subheader text, state filled below>",
"BodyKeyValueList":[
{"Key":"Info","Value":"1"},
{"Key":"Info","Value":"2"},
{"Key":"Info","Value":"3"},
{"Key":"Statistic","Value":""}
],
"FooterText":"Last update: 9:38:00 09.10.2019",
"FooterButtonX2List":[
{"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lActivityROBOTStartEscaped},
{"Text":"Safe turn off", "Color":"orange", "Link":"", "OnClick": lActivityROBOTSafeStopEscaped}
],
"FooterButtonX1List":[
{"Text":"Kill", "Color":"red", "Link":"", "OnClick": lActivityROBOTStopEscaped}
],
# "GlobalStorage": inGSettings.get("Storage",{}) # UNCOMMENT FOR DEBUG PURPOSE TO WATCH inGSettings on client side
}
# END :: Init result dict template :: END #
# START :: Fill BodyKeyValueList :: START #
# END :: Fill BodyKeyValueList :: END #
# START :: Fill SubheaderText :: START #
## FILL Robot state by the check the RDP session state
lSubheaderRunTrueText="State: <span style=\"color:green\">Turned on</span>"
lSubheaderRunFalseText="State: <span style=\"color:red\">Turned off</span>"
if gControlPanelCheckRobotProcessFromOrchestratorUserBool and gRDPSessionKeyStr in inGSettings["RobotRDPActive"]["RDPList"]:
lResultDict["SubheaderText"]=lSubheaderRunTrueText
else:
lResultDict["SubheaderText"]=lSubheaderRunFalseText
# END :: Fill SubheaderText :: END #
# Fill FooterText
lResultDict["FooterText"]=f'Last update: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}'
return lResultDict
# Technical def - Get item by the list of keys
def TechDictKeyList_ItemGet(inDict, inKeyList, inDefault={}):
lResult=inDict
for lItem in inKeyList:
if lResult:
lResult = lResult.get(lItem,None)
if lResult is None:
lResult=inDefault
return lResult
# # # # # # # # # # # # # # # # # # # # # # # #
#Orchestrator settings update
def SettingsUpdate(inGSettings):
#Add RobotRDPActive in control panel
inGSettings["ControlPanelDict"]["RobotList"].append({"RenderFunction": ControlPanelRenderDict, "KeyStr": gControlPanelKeyStr})
return inGSettings

@ -18,7 +18,8 @@ def SettingsUpdate(inDict):
#"FlagAccessDefRequestGlobalAuthenticate": TestDef #"FlagAccessDefRequestGlobalAuthenticate": TestDef
"FlagAccess": True "FlagAccess": True
} }
] ],
"ControlPanelKeyAllowedList": ["TestControlPanel", "RobotRDPActive","RobotScreenActive", "ControlPanel_Template"] # If empty - all is allowed
} }
} }
#Append to global list #Append to global list

@ -1,155 +0,0 @@
import psutil
import datetime
import logging
import os
import json
lProcessName = "OpenRPA_RobotRDPActive.exe"
lStartFilePath = os.path.join(os.getcwd(), "..\\Utils\\RobotRDPActive\\pyOpenRPA.Tools.RobotRDPActive_x64.cmd")
def RenderRobotRDPActive(inGlobalConfiguration):
#Subheader Variants
lSubheaderRunTrueText="State: <span style=\"color:green\">Turned on</span>"
lSubheaderRunFalseText="State: <span style=\"color:red\">Turned off</span>"
#Run button
#Такое большое количество слэшей связано с тем, что этот текст отправляется сначала в браузер, рендерится там, а потом отправляется на процессор оркестратора
lRobotRDPActivePath = f"start cmd /K {lStartFilePath}"
lOnClickRunButton=f"mGlobal.Controller.CMDRunText('{lRobotRDPActivePath}');"
#Safe turn off
lOnClickSafeTurnOff = "mGlobal.Processor.ServerValueSet(['Storage','RobotRDPActive','OrchestratorToRobotResetStorage','SafeTurnOff'],true);"
#Force close button
lOnClickForceCloseButton=f"mGlobal.Controller.CMDRunText('taskkill /F /im {lProcessName}');"
# # # # # Add recieve file activity
lTestRecieveActivityList = [
{
"ModulePath": f"{os.path.join(lRobotRDPActiveFolderPath,'Defs_SessionIndex.py')}", # "Session\\SessionDefs.py"
"DefName":"FileStoredRecieve", # Function name
"ArgList":[], # Args list
"ArgDict":{"inSessionIndex": 0, "inHostFilePath": "testRecieve.txt","inRDPFilePath": "C:\\Temp\\testRecieve.txt"} # Args dictionary
}
]
lOnClickTestSendBaumanStr = f"mGlobal.Processor.ServerValueSet(['Storage','RobotRDPActive','OrchestratorToRobotResetStorage','ActivityList'],{json.dumps(lTestRecieveActivityList)});"
#Result template
lResultDict={
"HeaderLeftText":"Keep active RDP sessions",
"HeaderRightText":"Tech",
"DataStorageKey":"RobotRDPActive", #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
"SubheaderText":lSubheaderRunFalseText,
"BodyKeyValueList":[
{"Key":"Session list","Value":""}
],
"FooterText":"Last update: 9:38:00 09.10.2019",
"FooterButtonX2List":[
{"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lOnClickRunButton.replace("\\","\\\\")},
{"Text":"Safe turn off", "Color":"orange", "Link":"", "OnClick": lOnClickSafeTurnOff.replace("\\","\\\\")}
],
"FooterButtonX1List":[
{"Text":"Kill", "Color":"red", "Link":"", "OnClick": lOnClickForceCloseButton.replace("\\","\\\\")}
]#,
#"GlobalStorage": inGlobalConfiguration.get("Storage",{})
}
#Read RDPList
lRDPList = inGlobalConfiguration.get("Storage",{}).get("RobotRDPActive",{}).get("RobotToOrchestratorStorage",{}).get("RDPList",[])
lFullScreenSessionIndex = inGlobalConfiguration.get("Storage",{}).get("RobotRDPActive",{}).get("RobotToOrchestratorStorage",{}).get("FullScreenSessionIndex",None)
lRDPListIndex = 0
for lItem in lRDPList:
#Lable that session has fullscreen
lLabelSessionFullScreen = ""
lLabelIsIgnored = ""
#Link set full screen
##############################
lOnClickSetFullScreen = f"mGlobal.Processor.ServerValueSet(['Storage','RobotRDPActive','OrchestratorToRobotStorage','FullScreenSessionIndex'],{lRDPListIndex});"
lSetFullScreenA = f'<a onclick="{lOnClickSetFullScreen}" style=\"color:blue\">Set fullscreen</a>'
if lRDPListIndex == lFullScreenSessionIndex:
lLabelSessionFullScreen = '<span style=\"color:blue\">[Fullscreen]</span>'
lOnClickSetFullScreen = f"mGlobal.Processor.ServerValueSet(['Storage','RobotRDPActive','OrchestratorToRobotStorage','FullScreenSessionIndex'],null);"
lSetFullScreenA = f'<a onclick="{lOnClickSetFullScreen}" style=\"color:blue\">Set minimized</a>'
#################################
lIgnoreIndexListOnClick = "$.ajax({type: 'POST', url: 'RobotRDPActive/IgnoreIndexListAppend', data: '"+str(lRDPListIndex)+"', success: function(lData,l2,l3){}, dataType: 'text'});"
lIgnoreIndexListLink = f'<a onclick="{lIgnoreIndexListOnClick}" style=\"color:red\">Ignore</a>'
#Check if in ignore
if lRDPListIndex in inGlobalConfiguration.get("Storage",{}).get("RobotRDPActive",{}).get("OrchestratorToRobotStorage",{}).get("IgnoreIndexList",[]):
lLabelIsIgnored = '<span style=\"color:red\">[Ignored]</span>'
lIgnoreIndexListOnClick = "$.ajax({type: 'POST', url: 'RobotRDPActive/IgnoreIndexListRemove', data: '"+str(lRDPListIndex)+"', success: function(lData,l2,l3){}, dataType: 'text'});"
lIgnoreIndexListLink = f'<a onclick="{lIgnoreIndexListOnClick}" style=\"color:red\">Unignore</a>'
################################
#Session state
lItemSessionState='<span style=\"color:red\">Disconnected</span>'
if lItem.get("SessionIsWindowResponsibleBool",False):
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}"})
lRDPListIndex = lRDPListIndex + 1
#Check if process running
if CheckIfProcessRunning("OpenRPA_RobotRDPActive"):
lResultDict["SubheaderText"]=lSubheaderRunTrueText
#Process not running
lResultDict["FooterText"]=f'Last update: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}'
return lResultDict
#Add to ignore list
def IgnoreIndexListAppend(inRequest,inConfiguration):
lIgnoreList = inConfiguration["Storage"]["RobotRDPActive"]["OrchestratorToRobotStorage"]["IgnoreIndexList"]
lIgnoreIndex={}
if inRequest.headers.get('Content-Length') is not None:
lInputByteArrayLength = int(inRequest.headers.get('Content-Length'))
lInputByteArray=inRequest.rfile.read(lInputByteArrayLength)
#Превращение массива байт в объект
lIgnoreIndex=int(lInputByteArray.decode('utf8'))
#check if index not in list
if lIgnoreIndex not in lIgnoreList:
#append to list
lIgnoreList.append(lIgnoreIndex)
#remove from Ignore list
def IgnoreIndexListRemove(inRequest,inConfiguration):
lIgnoreList = inConfiguration["Storage"]["RobotRDPActive"]["OrchestratorToRobotStorage"]["IgnoreIndexList"]
lIgnoreIndex={}
if inRequest.headers.get('Content-Length') is not None:
lInputByteArrayLength = int(inRequest.headers.get('Content-Length'))
lInputByteArray=inRequest.rfile.read(lInputByteArrayLength)
#Превращение массива байт в объект
lIgnoreIndex=int(lInputByteArray.decode('utf8'))
#check if index not in list
if lIgnoreIndex in lIgnoreList:
#append to list
lIgnoreList.remove(lIgnoreIndex) #Remove delete the element lIgnoreIndex
def CheckIfProcessRunning(processName):
'''
Check if there is any running process that contains the given name processName.
'''
#Iterate over the all the running process
for proc in psutil.process_iter():
try:
# Check if process name contains the given name string.
if processName.lower() in proc.name().lower():
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False;
#Orchestrator settings
def SettingsUpdate(inDict):
#Add RobotRDPActive in control panel
inDict["ControlPanelDict"]["RobotList"].append({"RenderFunction": RenderRobotRDPActive})
#Default structure
inDict["Storage"]["RobotRDPActive"]={
"OrchestratorToRobotResetStorage":{"SafeTurnOff":False},
"OrchestratorToRobotStorage":{
"FullScreenSessionIndex":None,
"IgnoreIndexList": []
}
}
#Add methods
inDict["Server"]["URLList"].append(
{
"Method":"POST",
"URL": "/RobotRDPActive/IgnoreIndexListAppend", #URL of the request
"MatchType": "Equal", #"BeginWith|Contains|Equal|EqualCase",
"ResponseDefRequestGlobal": IgnoreIndexListAppend #Function with str result
}
)
inDict["Server"]["URLList"].append(
{
"Method":"POST",
"URL": "/RobotRDPActive/IgnoreIndexListRemove", #URL of the request
"MatchType": "Equal", #"BeginWith|Contains|Equal|EqualCase",
"ResponseDefRequestGlobal": IgnoreIndexListRemove #Function with str result
}
)
return inDict

@ -56,5 +56,5 @@ def CheckIfProcessRunning(processName):
#Orchestrator settings #Orchestrator settings
def SettingsUpdate(inDict): def SettingsUpdate(inDict):
#Add RobotRDPActive in control panel #Add RobotRDPActive in control panel
inDict["ControlPanelDict"]["RobotList"].append({"RenderFunction": RenderRobotScreenActive}) inDict["ControlPanelDict"]["RobotList"].append({"RenderFunction": RenderRobotScreenActive , "KeyStr": "RobotScreenActive"})
return inDict return inDict

@ -85,7 +85,7 @@ def Settings():
"AccessUsers": { #Default - all URL is blocked "AccessUsers": { #Default - all URL is blocked
"FlagCredentialsAsk": True, #Turn on Authentication "FlagCredentialsAsk": True, #Turn on Authentication
"RuleDomainUserDict": { "RuleDomainUserDict": {
#("DOMAIN", "USER"): { !!!!!only in upper case!!!! #("DOMAIN", "USER"): { !!!!! only in upper case !!!!
# "MethodMatchURLBeforeList": [ # "MethodMatchURLBeforeList": [
# { # {
# "Method":"GET|POST", # "Method":"GET|POST",
@ -94,7 +94,8 @@ def Settings():
# "FlagAccessDefRequestGlobalAuthenticate": None, #Return bool # "FlagAccessDefRequestGlobalAuthenticate": None, #Return bool
# "FlagAccess": True # "FlagAccess": True
# } # }
# ] # ],
# "ControlPanelKeyAllowedList":[] # If empty - all is allowed
#} #}
}, },
"RuleMethodMatchURLBeforeList": [ #General MethodMatchURL list (no domain/user) "RuleMethodMatchURLBeforeList": [ #General MethodMatchURL list (no domain/user)
@ -217,7 +218,8 @@ def Settings():
"RefreshSeconds": 5, "RefreshSeconds": 5,
"RobotList": [ "RobotList": [
{ {
"RenderFunction": RenderRobotR01 "RenderFunction": RenderRobotR01,
"KeyStr":"TestControlPanelKey"
} }
] ]
}, },

@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.0.42 Version: 1.1.0
Summary: First open source RPA platform for business Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov Author: Ivan Maslov

@ -1,14 +1,38 @@
pyOpenRPA-1.0.42.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.42.dist-info/METADATA,sha256=Spesv5ub8aq5ymKhq_1kDDFQ2lrCrTwXfF8PakH7OO8,3542 pyOpenRPA-1.1.0.dist-info/METADATA,sha256=yrWtVmt4O4pYWpBBOCBXDwfe6CVB7Qpkfkb1TnBiBEs,3541
pyOpenRPA-1.0.42.dist-info/RECORD,, pyOpenRPA-1.1.0.dist-info/RECORD,,
pyOpenRPA-1.0.42.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.1.0.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.42.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.1.0.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436 pyOpenRPA/Orchestrator/Orchestrator.py,sha256=0Q4VYZPdXV2qmLuowMWD_vERj1GQurQx_VFwfsxuucQ,7076
pyOpenRPA/Orchestrator/Processor.py,sha256=kmGNIqe6AZMSrzCt1QlonEy58ecFeLunjo8AeRMsufU,11091 pyOpenRPA/Orchestrator/Processor.py,sha256=wqhbAcR9-7OszRHSX2u7BSONPNIMkEbDexvW47h0xdM,11954
pyOpenRPA/Orchestrator/Server.py,sha256=s1ujCuRX6YxRllqPn541Df4pJP7kOexiS3RIuoT4nyE,22053 pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=jOXJTLwg8cJx6D-rN8J4dn5RCb2nepAhCH4F9hYVUdM,4912 pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=YB5HJL-Qf4IlVrFHyRv_ZMJ0Vo4vjyYqWKjvrTnf1k4,1564
pyOpenRPA/Orchestrator/Timer.py,sha256=FQZ3y6G9d47Ybx7RewzePKQV77H4gCkx5SaeFVlsuhc,2095 pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=2nm5S_FOfnLkDVdlm2MVag9vL3DlyJ98LnwYNMzFNho,15914
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=su4tsDD_ZMbQz6Tbmqj55SM0ZZxuQw9tfPcytaB8wzs,32953 pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=WgGqWoPAnMeXpI_w3iuFX0KUBssvlSk9MuPBuIsNOuY,491
pyOpenRPA/Orchestrator/RobotRDPActive/GlobalDictSessionIndex_Defs.py,sha256=4BbAozLyOlXJxNw0NAlHt38-AyV-B6-Nl1M1AY8CTtk,4212
pyOpenRPA/Orchestrator/RobotRDPActive/Monitor.py,sha256=Y4mhNslK0EBS1LIDfK67j3lkjTZSU5xq-HUl9XNKW-U,10609
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=DrvRm6ZLgrGNcD8EjyKbZ4HZPfiGjQftuWDfqLeM6hw,7627
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=vsISwvRTMbbEtL_u9PU-rP6W71VUhAUBLMblOSGp2BE,9893
pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144
pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077
pyOpenRPA/Orchestrator/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Orchestrator/RobotRDPActive/__main__.py,sha256=z9PaUK4_nBiGd0YJdYVHV_rFx6VjZaxrrmKxSyoTFwY,2508
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/CMDStr.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Clipboard.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/ConnectorExceptions.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/GlobalDictSessionIndex_Defs.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Processor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/RobotRDPActive.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=gqJO6FRDKTBZytJVdJgPF1PvOf05qYUyKDBJJkEpLzk,22755
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=mpPAxAe6PvmKaZlreaoQAy_5wV80edz_0qc-iFrEmBQ,7123
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=t-s45l9APe-wUWazdFVRP2aIsKpsNtlwU_xuSuP2d0Q,36537
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430 pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144 pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -192,7 +216,7 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli
pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123 pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123
pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713 pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722 pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722
pyOpenRPA/Robot/OrchestratorConnector.py,sha256=Fihxz-jH9M4VakXEE0SZ0Vo9tLEQk8Tcg_C4HoH45gI,20037 pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx_v3MfBoKzoQ,20445
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476 pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476
@ -221,8 +245,8 @@ pyOpenRPA/Robot/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347 pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912 pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
pyOpenRPA/Studio/RobotConnector.py,sha256=tQVC8X0k1HMHAAwAtkhtmeNA0cLMY3wuO-RCbgshdMk,5036 pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038
pyOpenRPA/Studio/Studio.py,sha256=zpIGLMM2FBsUt2pC3x3BBm2zZ0n42MPfG7zgqtKxF6o,8338 pyOpenRPA/Studio/Studio.py,sha256=UoMDqnZm-MCiZHR8ToLTHHPN0Yx0Oa6-VOTJdUtoMKE,8352
pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777 pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Studio/Web/Index.xhtml,sha256=RqFW3qC1pFRr-qWEEDlCEhL9l3PwANyRbll3KZJnLvo,47927 pyOpenRPA/Studio/Web/Index.xhtml,sha256=RqFW3qC1pFRr-qWEEDlCEhL9l3PwANyRbll3KZJnLvo,47927
pyOpenRPA/Studio/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430 pyOpenRPA/Studio/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
@ -236,8 +260,8 @@ pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343
pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=DZSb17fiCAYLdNVTLFJ7nTbQhk29PjzxE9OL6ydCDcI,1645 pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655
pyOpenRPA/Tools/RobotDB/Server.py,sha256=MYIbO5vGH1FKgJVu3dQnscKRgN8or0FV8ZxAQbdC2Rc,19865 pyOpenRPA/Tools/RobotDB/Server.py,sha256=rjW9Sg-j9P8pFQD66Uih-rke6-f6sCulinwi4_W-3mc,19933
pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406
pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140
@ -247,15 +271,6 @@ pyOpenRPA/Tools/RobotDB/__pycache__/Server.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,, pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=qU5SXwHgQU177MjqEHyOwJDLAcSVnIkKKw76iD09J1w,7275
pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=H7ciateTh-hml8z69EYZjYgqdTZGkDRtnFwuYnytrCw,3278
pyOpenRPA/Tools/RobotRDPActive/Template.rdp,sha256=qPCLkjzTdYKURK7nRApkPUjRuS4K20vDPj9DIUNSSkE,2392
pyOpenRPA/Tools/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/RobotRDPActive/__main__.py,sha256=mVk8zVqcBrzAwwn7tbZPXFWTQbWUkgU6w89nbY6GN-8,2340
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114 pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114
pyOpenRPA/Tools/RobotScreenActive/Monitor.py,sha256=TV-YisVqa_uGiyJLG9oK4u-5aDjGiFYZFh1dPjOgYc8,492 pyOpenRPA/Tools/RobotScreenActive/Monitor.py,sha256=TV-YisVqa_uGiyJLG9oK4u-5aDjGiFYZFh1dPjOgYc8,492
pyOpenRPA/Tools/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606 pyOpenRPA/Tools/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606
@ -267,15 +282,14 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/Crypter.py,sha256=VRrE5-oQxQtvMEPHM1lMXp2CKnceNBmIWJnsJoJkaVE,3616 pyOpenRPA/Tools/SafeSource/Crypter.py,sha256=VRrE5-oQxQtvMEPHM1lMXp2CKnceNBmIWJnsJoJkaVE,3616
pyOpenRPA/Tools/SafeSource/DistrCreate.py,sha256=-_8BTle57LBKVknnB_3af-LghxrRmRGfRNu08CLNIvY,3232 pyOpenRPA/Tools/SafeSource/DistrCreate.py,sha256=-_8BTle57LBKVknnB_3af-LghxrRmRGfRNu08CLNIvY,3232
pyOpenRPA/Tools/SafeSource/DistrRun.py,sha256=TH4uExbufnOubBrTiO8Ccw00E5K6zaJ59-vApSxQ0iY,6661 pyOpenRPA/Tools/SafeSource/DistrRun.py,sha256=zwUh6Jy-rDAZHV6fcTUMupkukojntFMroHJHMsNQgrE,9637
pyOpenRPA/Tools/SafeSource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/SafeSource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/SafeSource/__main__.py,sha256=g5aYWnuUZoM2jDX2mSIl9tRAJg05tu5VxD2rGJWcACg,649 pyOpenRPA/Tools/SafeSource/__main__.py,sha256=g5aYWnuUZoM2jDX2mSIl9tRAJg05tu5VxD2rGJWcACg,649
pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrRun.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=9w2hSRgGrWKyQb3T_j71u7VoYGZsrTZz189nKtqEmOQ,175 pyOpenRPA/__init__.py,sha256=77eUDvkFqIZMsTqBvMu8L_kbwNSHWSXsJmPZaAgGrVQ,174
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,

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

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

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

@ -0,0 +1,40 @@
import win32clipboard
import keyboard # keyboard functions
import time # Some operations need wait
import random # random number for test
gWaitTextInClipboardSec = 1 # Second for wait text will be set in clipboard (for get operations)
# set clipboard data
def TextSet(inTextStr):
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(inTextStr)
win32clipboard.CloseClipboard()
# get clipboard data
def TextGet(inWaitTextInClipboardSec = gWaitTextInClipboardSec):
time.sleep(inWaitTextInClipboardSec) # Wait for clipboard will save
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
return data
# Test in has text cursor and ready to apply
def InputIsFocused():
keyboard.press_and_release("ctrl+a")
keyboard.press_and_release("backspace") # remove old text
lTextForTest = str(random.randrange(100,99999))
keyboard.write(lTextForTest)
keyboard.press_and_release("ctrl+a")
keyboard.press_and_release("ctrl+c")
time.sleep(2)
keyboard.press_and_release("backspace") # remove old text
lClipboardText = TextGet()
lResult = lClipboardText == lTextForTest
return lResult
# Check if cmd is opened
def CMDIsOpen():
lTextForTest = str(random.randrange(100,99999))
keyboard.write(lTextForTest+" |clip")
keyboard.press_and_release("enter")
time.sleep(2)
lClipboardText = TextGet()
lResult = lClipboardText == lTextForTest
return lResult

@ -0,0 +1,308 @@
#Import parent folder to import current / other packages
from pyOpenRPA.Robot import UIDesktop #Lib to access RDP window
from . import ConnectorExceptions # Exceptions classes
import os #os for process run
import uuid #temp id for Template.rdp
import tempfile #Temporary location
import subprocess
from . import Clipboard # Clipboard functions get/set
import keyboard # Keyboard functions
import time
import random # random integers
from win32api import GetSystemMetrics # Get Screen rect
#Connect to RDP session
"""
{
"Host": "", #Host address
"Port": "", #RDP Port
"Login": "", # Login
"Password": "", #Password
"Screen": {
"Resolution":"FullScreen", #"640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit":"" #"32" or "24" or "16" or "15"
}
}
"""
def Session(inRDPSessionConfiguration):
#RDPConnector.SessionConnect(mConfiguration)
#RDPConnector.LoginPassSet("111.222.222.111","ww","dd")
(lRDPFile, lSessionHex) = SessionConfigurationCreate(inRDPSessionConfiguration)
#Set session hex in globalDict
inRDPSessionConfiguration["SessionHex"] = lSessionHex
#Set login/password
SessionLoginPasswordSet(inRDPSessionConfiguration["Host"],inRDPSessionConfiguration["Login"],inRDPSessionConfiguration["Password"])
#Start session
SessionRDPStart(lRDPFile)
#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
os.remove(lRDPFile) # delete the temp rdp
# Set the result
return inRDPSessionConfiguration
#Add login/ password to the windows credentials to run RDP
def SessionLoginPasswordSet(inHost, inLogin, inPassword):
#Clear old login/password if it exists
#os.system(f"cmdkey /delete:TERMSRV/{inHost}") #Dont need to delete because new user password will clear the previous creds
#Set login password for host
os.system(f'cmdkey /generic:TERMSRV/{inHost} /user:{inLogin} /pass:"{inPassword}"')
return None
#Create current .rdp file with settings
#Return (full path to file, session hex)
def SessionConfigurationCreate(inConfiguration):
#RobotRDPActive folder path
lFileFullPath=__file__
lFileFullPath = lFileFullPath.replace("/","\\")
lRobotRDPActiveFolderPath = "\\".join(lFileFullPath.split("\\")[:-1])
#Full path to Template.rdp file
lRDPTemplateFileFullPath = os.path.join(lRobotRDPActiveFolderPath, "Template.rdp")
#Open template file (.rdp encoding is USC-2 LE BOM = UTF-16 LE) http://qaru.site/questions/7156020/python-writing-a-ucs-2-little-endian-utf-16-le-file-with-bom
lRDPTemplateFileContent = open(lRDPTemplateFileFullPath, "r", encoding="utf-16-le").read()
#Prepare host:port
lHostPort=inConfiguration['Host']
if 'Port' in inConfiguration:
if inConfiguration['Port']:
lHostPort=f"{lHostPort}:{inConfiguration['Port']}"
# Generate parameter for .rdp "drivestoredirect:s:C:\;"
lDriveStoreDirectStr = ""
for lItem in inConfiguration['SharedDriveList']:
lDriveStoreDirectStr+=f"{lItem.upper()}:\\;" # Attention - all drives must be only in upper case!!!
#Replace {Width}, {Height}, {BitDepth}, {HostPort}, {Login}
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Width}", str(inConfiguration.get('Screen',{}).get("Width",1680)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Height}", str(inConfiguration.get('Screen',{}).get("Height",1050)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{BitDepth}", inConfiguration.get('Screen',{}).get("DepthBit","32"))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{HostPort}", lHostPort)
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Login}", inConfiguration['Login'])
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{SharedDriveList}", lDriveStoreDirectStr)
#Save template to temp file
lRDPCurrentFileFullPath = os.path.join(tempfile.gettempdir(), f"{uuid.uuid4().hex}.rdp")
open(lRDPCurrentFileFullPath, "w", encoding="utf-16-le").write(lRDPTemplateFileContent)
#Return .rdp full path
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart
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
lItemArgs = [inRDPFilePath]
subprocess.Popen(lItemArgs, shell=True)
#Wait for UAC unknown publisher exists
lRDPFileName = (inRDPFilePath.split("\\")[-1])[0:-4]
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}],
[{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"},{"depth_start":3, "depth_end": 3, "class_name":"UIMainClass"}]
],
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)
if 0 in lWaitResult:
#Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}]).check()
#Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title":"Подкл&ючить", "class_name":"Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
# Click if 1 is appear (ENG)
if 1 in lWaitResult:
# Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}]).check()
# Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "Co&nnect", "class_name": "Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
# Raise exception if RDP is not active
if len(lWaitResult) == 0:
raise ConnectorExceptions.SessionWindowNotExistError("Error when initialize the RDP session - No RDP windows has appreared!")
# Wait for init
time.sleep(3)
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
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)
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
return None
# Set the screen size
def SessionScreenSize_X_Y_W_H(inSessionHex, inXInt, inYInt, inWInt, inHInt):
lDoBool = True
while lDoBool:
#Prepare little window
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
except Exception as e:
return None
try:
lRDPWindow.set_focus()
if SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
lRDPWindow.restore()
time.sleep(0.5)
lRDPWindow.move_window(inXInt,inYInt,inWInt,inHInt)
except Exception as e:
time.sleep(1)
else:
lDoBool = False
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
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"
# "LISTEN" - Get result of the cmd command in result TODO get home script
# "CROSSCHECK" - Check if the command was successufully sent TODO get home script
# "RUN" - Run without crosscheck and get clipboard
# return {
# "OutStr": <> # Result string
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5):
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
# Enter full screen mode
SessionScreenFull(inSessionHex)
time.sleep(2)
# Run CMD operations
lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec)
# Exit fullscreen mode
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(""))
def SessionIsFullScreen(inSessionHexStr):
#Default resul
lResult = False
lWeight = GetSystemMetrics(0)
lHeight = GetSystemMetrics(1)
#Get window screen
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
#Case fullscreen
if lSessionHeight == lHeight and lSessionWeight == lWeight:
lResult = True
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")

@ -0,0 +1,66 @@
# ATTENTION! HERE IS NO Relative import because it will be imported dynamically
# All function check the flag SessionIsWindowResponsibleBool == True else no cammand is processed
# All functions can return None, Bool or Dict { "IsSuccessful": True }
from pyOpenRPA.Tools.RobotRDPActive import CMDStr # Create CMD Strings
from pyOpenRPA.Tools.RobotRDPActive import Connector # RDP API
def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True):
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStartIfNotRunning: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Create CMD str to stop process
def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose):
lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# TODO Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStop: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def FileStoredSend(inGlobalDict, inSessionIndex, inHostFilePath, inRDPFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePath, inRDPFilePath = inRDPFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredSend: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def FileStoredRecieve(inGlobalDict, inSessionIndex, inRDPFilePath, inHostFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePath, inHostFilePath = inHostFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredRecieve: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult

@ -0,0 +1,158 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import time # Time wait operations
import importlib # from dynamic import module
from . import ConnectorExceptions # Exceptions classes
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True
lResponsibilityCheckLastSec = time.time() # Get current time for check interval
while lFlagWhile:
try:
# UIOSelector list init
lUIOSelectorList = []
#Prepare selectors list for check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
#Run wait command
#import pdb
#pdb.set_trace()
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#print(lRDPDissappearList)
###########################################
#Analyze if flag safeturn off is activated
if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
lFlagWhile=False
#Set status disconnected for all RDP List
for lItem in inGlobalDict["RDPList"]:
lItem["SessionIsWindowExistBool"]=False
lItem["SessionIsWindowResponsibleBool"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
###########################################
###########################################
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
#pdb.set_trace()
#Session start if it is not in ignore list
#add check for selector if it is not in ignoreIndexList
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Flag that session is started
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]= True
# Write in logger - info
inGlobalDict["Logger"].info(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session has been initialized!")
# catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not exist!")
# catch ConnectorExceptions.SessionWindowNotResponsibleError
except ConnectorExceptions.SessionWindowNotResponsibleError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not responsible!")
# general exceptions
except Exception as e:
# Write in logger - warning
inGlobalDict["Logger"].exception(f"!!! ATTENTION !!! Unrecognized error")
#######################
# Click all warning messages
Connector.SystemRDPWarningClickOk()
#######################
###########################################
#Check if from Orchestrator full screen session is set
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] != inGlobalDict["FullScreenSessionIndex"]:
#Do some switches
#If full screen mode we have now
if inGlobalDict["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreen100x550(inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionHex"])
#If new session is setted
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"])
#Set one to other equal
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]
###########################################
####################################
##### Block check responsibility interval [ResponsibilityCheckIntervalSec]
if inGlobalDict['ResponsibilityCheckIntervalSec']: # Do check if ResponsibilityCheckIntervalSec is not None
if (time.time - lResponsibilityCheckLastSec()) > inGlobalDict['ResponsibilityCheckIntervalSec']:
# Set new time
lResponsibilityCheckLastSec = time.time()
# Do responsibility check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
# Check RDP responsibility
lDoCheckResponsibilityBool = True
lDoCheckResponsibilityCountMax = 20
lDoCheckResponsibilityCountCurrent = 0
while lDoCheckResponsibilityBool:
# Enter full screen mode
Connector.SessionScreenFull(lItem['SessionHex'])
time.sleep(2)
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
# Check if counter is exceed - raise exception
if lDoCheckResponsibilityCountCurrent >= lDoCheckResponsibilityCountMax:
lItem["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
lItem["SessionIsWindowResponsibleBool"]=False
# Session window is not responsible - restart RDP (close window here - next loop will reconnect)
Connector.SessionClose(lItem['SessionHex'])
# Turn off the loop
lDoCheckResponsibilityBool = False
else:
# Exit fullscreen mode
Connector.SessionScreen100x550(lItem['SessionHex'])
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
# increase the couter
lDoCheckResponsibilityCountCurrent+=1
####################################
# Check ActivityList from orchestrator
lActivityListNew = []
lActivityListOld = inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]+inGlobalDict["ActivityListStart"]
inGlobalDict["ActivityListStart"] = []
for lActivityItem in lActivityListOld:
#################
#Call function from Activity structure
################################################
lSubmoduleFunctionName = lActivityItem["DefName"]
lFileFullPath = lActivityItem["ModulePath"] # "path\\to\\module.py"
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
# Set gSettings in module
lTechModuleFromSpec.gSettings = inGlobalDict
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lActivityItemResult=getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"])
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
if lActivityItemResultType is bool:
if not lActivityItemResult:
# Activity is not done - add to list (retry in future)
lActivityListNew.append(lActivityItem)
#################################################
inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = lActivityListNew # Override the value
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Host session has lost the GUI")
finally:
# Wait for the next iteration
time.sleep(0.7)
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -0,0 +1,147 @@
# 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"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
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
# Logoff the RDP session
def RDPSessionLogoff(inRDPSessionKeyStr):
global gSettings
lResult = True
lCMDStr = "shutdown -L" # CMD logoff command
# Calculate the session Hex
lSessionHex = gSettings["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# 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(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPath= inFlagGetAbsPathBool)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# Create CMD str to stop process
def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = f'taskkill /im "{inProcessNameWEXEStr}" /fi "username eq %USERNAME%"'
if inFlagForceCloseBool:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePathStr, inRDPFilePath = inRDPFilePathStr)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr, {}).get("SessionHex", None)
#lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePathStr, inHostFilePath = inHostFilePathStr)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
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")

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

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

@ -13,7 +13,7 @@ import importlib
lFolderPath = "/".join(__file__.split("/")[:-4]) lFolderPath = "/".join(__file__.split("/")[:-4])
sys.path.insert(0, lFolderPath) sys.path.insert(0, lFolderPath)
#Единый глобальный словарь (За основу взять из Settings.py) #Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict global gSettingsDict
#Call Settings function from argv[1] file #Call Settings function from argv[1] file
################################################ ################################################
lSubmoduleFunctionName = "Settings" lSubmoduleFunctionName = "Settings"
@ -22,28 +22,30 @@ lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
mGlobalDict = None gSettingsDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec): if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule # Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
################################################# #################################################
######################################################### #########################################################
from pyOpenRPA.Tools.RobotRDPActive import Connector from pyOpenRPA.Tools.RobotRDPActive import Connector
from pyOpenRPA.Tools.RobotRDPActive import Monitor from pyOpenRPA.Tools.RobotRDPActive import Monitor
#Disable certificate warning from pyOpenRPA.Tools.RobotRDPActive import Scheduler # Scheduler operations
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f' #### Global error handler
os.system(lCMDString) try:
#time.sleep() #time.sleep()
for lConfigurationItem in mGlobalDict["RDPList"]: ######## Init the RDP List
try: for lConfigurationItem in gSettingsDict["RDPList"]:
Connector.Session(lConfigurationItem) lConfigurationItem["SessionIsWindowExistBool"]=False #Flag that session is not started
lConfigurationItem["FlagSessionIsActive"]=True #Flag that session is started lConfigurationItem["SessionIsWindowResponsibleBool"]=False #Flag that session is not started
except Exception: lConfigurationItem["SessionHex"]=" 77777sdfsdf77777dsfdfsf77777777" #Flag that session is not started
pass ##########
#Run monitor #Run monitor
Monitor.Monitor(mGlobalDict, 1) Scheduler.Scheduler(gSettingsDict["Scheduler"]) # Init & Run Scheduler
#Enable certificate warning Monitor.Monitor(gSettingsDict, 1)
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f' except Exception as e:
os.system(lCMDString) # Write in logger - warning
#Close all thread from OrchestratorConnection gSettingsDict["Logger"].exception(f"!!! ATTENTION !!! Global error handler - look at code")
mGlobalDict["OrchestratorConnectorTerminateAll"]() finally:
#Close all thread from OrchestratorConnection
gSettingsDict["OrchestratorConnectorTerminateAll"]()

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

@ -3,16 +3,45 @@ import json
from desktopmagic.screengrab_win32 import ( from desktopmagic.screengrab_win32 import (
getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage, getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage,
getRectAsImage, getDisplaysAsImages) 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): def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
inResponseDict = inRequest.OpenRPAResponseDict inResponseDict = inRequest.OpenRPAResponseDict
# Create result JSON # Create result JSON
lResultJSON = {"RenderRobotList": []} lResultJSON = {"RenderRobotList": []}
lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"]
for lItem in lRenderFunctionsRobotList: for lItem in lRenderFunctionsRobotList:
# Выполнить вызов и записать результат lUACBool = True # Check if render function is applicable User Access Rights (UAC)
lItemResultDict = lItem["RenderFunction"](inGlobalDict) if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# RunFunction lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())]
lResultJSON["RenderRobotList"].append(lItemResultDict) if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]:
lUACBool = False # UAC Check is not passed - False for user
if lUACBool: # Run function if UAC is TRUE
# Выполнить вызов и записать результат
lItemResultDict = lItem["RenderFunction"](inGlobalDict)
# RunFunction
lResultJSON["RenderRobotList"].append(lItemResultDict)
# Send message back to client # Send message back to client
message = json.dumps(lResultJSON) message = json.dumps(lResultJSON)
# Write content as utf-8 data # Write content as utf-8 data
@ -60,7 +89,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": "/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": "/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": "/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 inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList
return inGlobalConfiguration return inGlobalConfiguration

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

@ -292,7 +292,49 @@
} }
mGlobal.Monitor.fControlPanelRefresh() mGlobal.Monitor.fControlPanelRefresh()
mGlobal.Monitor.fControlPanelAutoUpdateRun(3); 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() { mGlobal.Test=function() {
///Обнулить таблицу ///Обнулить таблицу
lData = [ lData = [
@ -339,9 +381,9 @@
function(lData,l2,l3) function(lData,l2,l3)
{ {
var lResponseJSON=JSON.parse(lData) 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 код ///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode); $('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show'); $('.ui.modal.basic').modal('show');
@ -349,12 +391,33 @@
dataType: "text" dataType: "text"
}); });
} }
/////////////////////////////// ///////////////////////////////
///Processor functions ///Processor functions
/////////////////////////////// ///////////////////////////////
mGlobal.Processor = {} 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) { mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [ lData = [
{ {
@ -532,58 +595,17 @@
///Установить HTML код ///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode); 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> </script>
<style type="text/css"> <style type="text/css">
body { body {
background-color: #FFFFFF; background-color: #FFFFFF;
} }
.main.container { .main.container {
margin-top: 2em; margin-top: 2em;
} }
.overlay { .overlay {
float: left; float: left;
margin: 0em 3em 1em 0em; margin: 0em 3em 1em 0em;
@ -593,7 +615,6 @@
left: 0; left: 0;
transition: left 0.5s ease; transition: left 0.5s ease;
} }
.main.menu.fixed { .main.menu.fixed {
background-color: #FFFFFF; background-color: #FFFFFF;
border: 1px solid #DDD; border: 1px solid #DDD;
@ -602,14 +623,12 @@
.overlay.fixed .menu { .overlay.fixed .menu {
left: 800px; left: 800px;
} }
.text.container .left.floated.image { .text.container .left.floated.image {
margin: 2em 2em 2em -4em; margin: 2em 2em 2em -4em;
} }
.text.container .right.floated.image { .text.container .right.floated.image {
margin: 2em -4em 2em 2em; margin: 2em -4em 2em 2em;
} }
.ui.footer.segment { .ui.footer.segment {
margin: 5em 0em 0em; margin: 5em 0em 0em;
padding: 5em 0em; padding: 5em 0em;
@ -626,7 +645,7 @@
<h1 class="ui header inverted">Orchestrator Web GUI</h1> <h1 class="ui header inverted">Orchestrator Web GUI</h1>
</div> </div>
<div class="two wide column"> <div class="two wide column">
<h5>by UnicodeLabs</h5> <h5>by Ivan Maslov</h5>
</div> </div>
</div> </div>
@ -689,36 +708,65 @@
</div> </div>
</div> </div>
<div class="row black"> <div class="row black">
<div class="three wide column"> <div class="five wide column">
<h2 class="ui header inverted">Controls</h2>
</div>
<div class="three wide column">
<h2 class="ui header inverted">Monitor</h2>
</div> </div>
<div class="two wide column"> <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>
</div> </div>
<button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();"> <div class="row">
<i class="desktop icon"></i> <div class="five wide column">
Look machine screenshot <button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();">
</button> <i class="desktop icon"></i>
<button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();"> Look machine screenshot
<i class="redo icon"></i> </button>
Restart Orchestrator <button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();">
</button> <i class="redo icon"></i>
<button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();"> Restart Orchestrator
<i class="info icon"></i> </button>
Scheduler activity time list <button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();">
<script class="openrpa-hidden-info-table-planloglist" style="display:none" type="text/x-handlebars-template"> <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"> <table class="ui celled table">
<thead> <thead>
<tr> <tr>
<th>#</th> <th>#</th>
<th>Activity type</th> <th>Activity type</th>
<th>Time</th> <th>Process</th>
<th>Process path/Process name</th> <th>Activity DateTime plan</th>
<th>Activity DateTime fact</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -726,117 +774,136 @@
<tr> <tr>
<td>{{@index}}</td> <td>{{@index}}</td>
<td>{{activityType}}</td> <td>{{activityType}}</td>
<td>{{time}}</td> <td>{{processPath}}</td>
<td>{{processPathName}}</td> <td>{{activityDateTime}}</td>
<td class="negative
">{{activityStartDateTime}}</td>
</tr> </tr>
{{/result}} {{/result}}
</tbody> </tbody>
</table> </table>
</script> </script>
</button> </button>
<button class="ui labeled icon button" onclick="mGlobal.Processor.LogListShow();">
<i class="info icon"></i> <script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
Processor logs <table class="ui celled table">
<script class="openrpa-hidden-info-table-activitylogschedulelist" style="display:none" type="text/x-handlebars-template"> <thead>
<table class="ui celled table"> <tr>
<thead> <th>Machine name</th>
<tr> <th>Machihe host</th>
<th>#</th> <th>Status</th>
<th>Activity type</th> <th>Actions,length: {{childs.length}}</th>
<th>Process</th> </tr>
<th>Activity DateTime plan</th> </thead>
<th>Activity DateTime fact</th> <tbody>
</tr> {{#ListenURLList}}
</thead> <tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr>
<tbody> {{/ListenURLList}}
{{#result}} </tbody>
<tr> </table>
<td>{{@index}}</td> </script>
<td>{{activityType}}</td>
<td>{{processPath}}</td> <script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template">
<td>{{activityDateTime}}</td> {{#if Title}}
<td class="negative <h1>{{{Title}}}</h1>
">{{activityStartDateTime}}</td> {{/if}}
</tr> {{#if FilterOnKeyUp}}
{{/result}} <div class="ui icon input search" style="width:500px;">
</tbody> <input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
</table> <i class="inverted circular search link icon"></i>
</script> </div>
</button> {{/if}}
<table class="ui celled table selectable inverted">
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template"> <thead>
<table class="ui celled table"> <tr>
<thead> {{#Columns}}
<tr> <th>{{{this}}}</th>
<th>Machine name</th> {{/Columns}}
<th>Machihe host</th> </tr>
<th>Status</th> </thead>
<th>Actions,length: {{childs.length}}</th> <tbody>
</tr> {{#Rows}}
</thead> <tr>
<tbody> {{#this}}
{{#ListenURLList}} <td>
<tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr> {{{this}}}
{{/ListenURLList}} </td>
</tbody> {{/this}}
</table> </tr>
</script> {{/Rows}}
</tbody>
<script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template"> </table>
{{#if Title}} </script>
<h1>{{{Title}}}</h1> <script class="openrpa-handlebar-template-list-filter" style="display:none" type="text/x-handlebars-template">
{{/if}} {{#if Title}}
{{#if FilterOnKeyUp}} <h1>{{{Title}}}</h1>
<div class="ui icon input search" style="width:500px;"> {{/if}}
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search..."> {{#if FilterOnKeyUp}}
<i class="inverted circular search link icon"></i> <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> </div>
{{/if}} <div class="two wide column">
<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> </div>
{{/if}} <div class="nine wide column openrpa-robotrdpactive-control-panel-general">
<div class="ui inverted segment"> <div class="ui info message">
<div class="ui inverted relaxed divided list"> <button class="ui icon button labeled " onclick="mGlobal.RobotRDPActive.fControlPanelRefresh();">
{{#List}} <i class="sync alternate icon"></i>
<div class="item"> <div class="openrpa-refresh-button">Refresh</div>
<i class="map marker icon"></i> </button>
<div class="content"> </div>
<a class="header">{{{Header}}}</a> <div class="openrpa-robotrdpactive-control-panel"></div>
<div class="description">{{{Description}}}</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>
</div> </div>
{{/List}} </script>
</div>
</div> </div>
</script> </div>
<div class="row openrpa-monitor"> <div class="row openrpa-monitor">
</div> </div>

@ -383,6 +383,13 @@ def IntervalDataReceiveResetAsync(*args,**kwargs):
if "Interval" in lKwargs: if "Interval" in lKwargs:
lInterval = lKwargs["Interval"] lInterval = lKwargs["Interval"]
del lKwargs["Interval"] del lKwargs["Interval"]
# Reset the storage before start
DataSendSync(
RobotValue=lKwargs["RobotResetValue"],
OrchestratorKeyList=lKwargs["OrchestratorKeyList"], OrchestratorProtocol=lKwargs["OrchestratorProtocol"],
OrchestratorHost=lKwargs["OrchestratorHost"], OrchestratorPort=lKwargs["OrchestratorPort"],
OrchestratorAuthToken=lKwargs["OrchestratorAuthToken"]
)
lTimer = TimerRepeat.TimerRepeat(lInterval, DataReceiveResetAsync, lArgs, lKwargs) lTimer = TimerRepeat.TimerRepeat(lInterval, DataReceiveResetAsync, lArgs, lKwargs)
lTimer.start() lTimer.start()
#Add timer to general list to stop this when needed #Add timer to general list to stop this when needed

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

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

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

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

@ -1,136 +0,0 @@
#Import parent folder to import current / other packages
from pyOpenRPA.Robot import UIDesktop #Lib to access RDP window
import os #os for process run
import uuid #temp id for Template.rdp
import tempfile #Temporary location
import time
import subprocess
#Connect to RDP session
"""
{
"Host": "", #Host address
"Port": "", #RDP Port
"Login": "", # Login
"Password": "", #Password
"Screen": {
"Resolution":"FullScreen", #"640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit":"" #"32" or "24" or "16" or "15"
}
}
"""
def Session(inRDPSessionConfiguration):
#RDPConnector.SessionConnect(mConfiguration)
#RDPConnector.LoginPassSet("111.222.222.111","ww","dd")
(lRDPFile, lSessionHex) = SessionConfigurationCreate(inRDPSessionConfiguration)
#Set session hex in globalDict
inRDPSessionConfiguration["SessionHex"] = lSessionHex
#Set login/password
SessionLoginPasswordSet(inRDPSessionConfiguration["Host"],inRDPSessionConfiguration["Login"],inRDPSessionConfiguration["Password"])
#Start session
SessionRDPStart(lRDPFile)
#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
os.remove(lRDPFile) # delete the temp rdp
return inRDPSessionConfiguration
#Add login/ password to the windows credentials to run RDP
def SessionLoginPasswordSet(inHost, inLogin, inPassword):
#Clear old login/password if it exists
#os.system(f"cmdkey /delete:TERMSRV/{inHost}") #Dont need to delete because new user password will clear the previous creds
#Set login password for host
os.system(f"cmdkey /generic:TERMSRV/{inHost} /user:{inLogin} /pass:{inPassword}")
return None
#Create current .rdp file with settings
#Return (full path to file, session hex)
def SessionConfigurationCreate(inConfiguration):
#RobotRDPActive folder path
lFileFullPath=__file__
lFileFullPath = lFileFullPath.replace("/","\\")
lRobotRDPActiveFolderPath = "\\".join(lFileFullPath.split("\\")[:-1])
#Full path to Template.rdp file
lRDPTemplateFileFullPath = os.path.join(lRobotRDPActiveFolderPath, "Template.rdp")
#Open template file (.rdp encoding is USC-2 LE BOM = UTF-16 LE) http://qaru.site/questions/7156020/python-writing-a-ucs-2-little-endian-utf-16-le-file-with-bom
lRDPTemplateFileContent = open(lRDPTemplateFileFullPath, "r", encoding="utf-16-le").read()
#Prepare host:port
lHostPort=inConfiguration['Host']
if 'Port' in inConfiguration:
if inConfiguration['Port']:
lHostPort=f"{lHostPort}:{inConfiguration['Port']}"
#Replace {Width}, {Height}, {BitDepth}, {HostPort}, {Login}
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Width}", str(inConfiguration.get('Screen',{}).get("Width",1680)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Height}", str(inConfiguration.get('Screen',{}).get("Height",1050)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{BitDepth}", inConfiguration.get('Screen',{}).get("DepthBit","32"))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{HostPort}", lHostPort)
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Login}", inConfiguration['Login'])
#Save template to temp file
lRDPCurrentFileFullPath = os.path.join(tempfile.gettempdir(), f"{uuid.uuid4().hex}.rdp")
open(lRDPCurrentFileFullPath, "w", encoding="utf-16-le").write(lRDPTemplateFileContent)
#Return .rdp full path
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart
def SessionRDPStart(inRDPFilePath):
#run rdp session
lItemArgs = [inRDPFilePath]
subprocess.Popen(lItemArgs, shell=True)
#Wait for UAC unknown publisher exists
lRDPFileName = (inRDPFilePath.split("\\")[-1])[0:-4]
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}],
[{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
#Click if 0 is appear (RUS)
if 0 in lWaitResult:
#Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}]).check()
#Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title":"Подкл&ючить", "class_name":"Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
# Click if 1 is appear (ENG)
if 1 in lWaitResult:
# Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}]).check()
# Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "Co&nnect", "class_name": "Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
#Prepare little window
SessionScreen100x550(lRDPFileName)
return None
#Set fullscreen for app
def SessionScreenFull(inSessionHex):
#Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.maximize()
lRDPWindow.set_focus()
return None
#Set Little window of the session
def SessionScreen100x550(inSessionHex):
#Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.restore()
lRDPWindow.move_window(10,10,550,100)
return None

@ -1,55 +0,0 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import pdb
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True
while lFlagWhile:
# UIOSelector list init
lUIOSelectorList = []
#Prepare selectors list for check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
#Run wait command
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
###########################################
#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()
#Session start if it is not in ignore list
#add check for selector if it is not in ignoreIndexList
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
inGlobalDict["RDPList"][lItem]["FlagSessionIsActive"] = True # Flag that session is started
except Exception:
pass
###########################################
#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"]]["FlagSessionIsActive"]:
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"]]["FlagSessionIsActive"]:
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"])
#Set one to other equal
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -8,18 +8,35 @@ from . import Crypter # Crypto functions
import datetime #Datetime import datetime #Datetime
import hashlib #Get hash of the word import hashlib #Get hash of the word
import pyautogui import pyautogui
import os
import glob # list files
EXT = '.cry' EXT = '.cry'
gExtensionName = "cry"
# How to run # How to run
# sys.meta_path.append(Base64Importer(root_pkg_path)) # sys.meta_path.append(Base64Importer(root_pkg_path))
# Init cryptographer # Init cryptographer
def CryptographerInit(inFolderPath): def CryptographerInit(inFolderPathList, inKey):
sys.meta_path.append(Base64Importer(inFolderPath)) #sys.meta_path.append(Base64Importer(inFolderPath))
# Flag add subfolder, which contains extension files
#path = 'c:\\projects\\hc2\\'
#folders = []
# Recursive walk throught the tree
# r=root, d=directories, f = files
#import pdb
#pdb.set_trace()
for lItem in inFolderPathList:
sys.meta_path.append(Base64Importer(os.path.abspath(lItem), inKey=inKey))
#for r, d, f in os.walk(lItem):
# for folder in d:
#folders.append(os.path.join(r, folder))
#sys.meta_path.append(Base64Importer(os.path.join(r, folder), inKey=inKey))
# pass
#for f in folders:
# print(f)
#=============================================================================== #===============================================================================
class Base64Importer(object): class Base64Importer(object):
"""Служит для поиска и импорта python-модулей, кодированных в base64 """Служит для поиска и импорта python-модулей, кодированных в base64
Класс реализует Import Protocol (PEP 302) для возможности импортирования Класс реализует Import Protocol (PEP 302) для возможности импортирования
модулей, зашифрованных в base64 из указанного пакета. модулей, зашифрованных в base64 из указанного пакета.
""" """
@ -27,25 +44,28 @@ class Base64Importer(object):
def __init__(self, root_package_path, inKey): def __init__(self, root_package_path, inKey):
self.mKeyStr = inKey self.mKeyStr = inKey
self.__modules_info = self.__collect_modules_info(root_package_path) self.__modules_info = self.__collect_modules_info(root_package_path)
# Create list of cry files when run
#for lItem in root_package_path_list:
# lCryptedFileList = [f for f in glob.glob(os.path.join(lItem,f"**/*.{EXT}"), recursive=True)]
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
def find_module(self, fullname, path=None): def find_module(self, fullname, path=None):
"""Метод будет вызван при импорте модулей """Метод будет вызван при импорте модулей
Если модуль с именем fullname является base64 и находится в заданной Если модуль с именем fullname является base64 и находится в заданной
папке, данный метод вернёт экземпляр импортёра (finder), либо None, если папке, данный метод вернёт экземпляр импортёра (finder), либо None, если
модуль не является base64. модуль не является base64.
""" """
#print(f"find_module:: Fullname: {fullname}, path: {path}")
#print(f"modules info: {self.__modules_info}")
if fullname in self.__modules_info: if fullname in self.__modules_info:
return self return self
return None return None
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
def load_module(self, fullname): def load_module(self, fullname):
"""Метод загружает base64 модуль """Метод загружает base64 модуль
Если модуль с именем fullname является base64, то метод попытается его Если модуль с именем fullname является base64, то метод попытается его
загрузить. Возбуждает исключение ImportError в случае любой ошибки. загрузить. Возбуждает исключение ImportError в случае любой ошибки.
""" """
#print(f"load_module:: Fullname: {fullname}")
if not fullname in self.__modules_info: if not fullname in self.__modules_info:
raise ImportError(fullname) raise ImportError(fullname)
# Для потокобезопасности # Для потокобезопасности
@ -53,6 +73,8 @@ class Base64Importer(object):
try: try:
mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
mod.__file__ = "<{}>".format(self.__class__.__name__) mod.__file__ = "<{}>".format(self.__class__.__name__)
mod.__file__ = self.__modules_info[fullname]['filename'] #Hotfix
#print(f"MODFILE::{mod.__file__}")
mod.__loader__ = self mod.__loader__ = self
if self.is_package(fullname): if self.is_package(fullname):
mod.__path__ = [] mod.__path__ = []
@ -61,7 +83,10 @@ class Base64Importer(object):
mod.__package__ = fullname.rpartition('.')[0] mod.__package__ = fullname.rpartition('.')[0]
src = self.get_source(fullname) src = self.get_source(fullname)
try: try:
exec(src) in mod.__dict__ #__name__ = "pyPackage"
#print(f"MODNAME:: {mod.__name__}")
#exec(src) in mod.__dict__
exec(src,mod.__dict__)
except: except:
del sys.modules[fullname] del sys.modules[fullname]
raise ImportError(fullname) raise ImportError(fullname)
@ -98,33 +123,55 @@ class Base64Importer(object):
"""Собирает информацию о модулях из указанного пакета """Собирает информацию о модулях из указанного пакета
""" """
modules = {} modules = {}
"""
p = os.path.abspath(root_package_path) p = os.path.abspath(root_package_path)
dir_name = os.path.dirname(p) + os.sep dir_name = os.path.dirname(p) + os.sep
#dir_name = "" # Hotfix 2020 03 19
#print(f"__collect_modules_info:: root_package_path: {root_package_path}")
for root, _, files in os.walk(p): for root, _, files in os.walk(p):
# Информация о текущем пакете # Информация о текущем пакете
filename = os.path.join(root, '__init__' + EXT) filename = os.path.join(root, '__init__' + EXT)
p_fullname = root.rpartition(dir_name)[2].replace(os.sep, '.') p_fullname = root.rpartition(dir_name)[2].replace(os.sep, '.')
modules[p_fullname] = { modules[p_fullname] = {
'filename': filename, 'filename': filename,
'ispackage': True 'ispackage': True
} }
# Информация о модулях в текущем пакете # Информация о модулях в текущем пакете
for f in files: for f in files:
if not f.endswith(EXT): if not f.endswith(EXT):
continue continue
filename = os.path.join(root, f) filename = os.path.join(root, f)
fullname = '.'.join([p_fullname, os.path.splitext(f)[0]]) fullname = '.'.join([p_fullname, os.path.splitext(f)[0]])
fullname = os.path.splitext(f)[0]
modules[fullname] = { modules[fullname] = {
'filename': filename, 'filename': filename,
'ispackage': False 'ispackage': False
} }
"""
# # # # # # # # # # #
# New way of collection
lRootAbsPath = os.path.abspath(root_package_path)
#print(lRootAbsPath)
lNewPathIndex = len(lRootAbsPath)+len(os.sep) # Len of the root path + len sep
lCryptedFileList = [f for f in glob.glob(os.path.join(lRootAbsPath,f"**/*.{gExtensionName}"), recursive=True)]
#print(lCryptedFileList)
for lCryptedItemFullPath in lCryptedFileList:
# Get Module name
lModuleName = lCryptedItemFullPath[lNewPathIndex:-(1+len(gExtensionName))].replace(os.sep, '.')
# Check if file is not __init__.{EXT} - This is package
if f"__init__.{EXT}" in lCryptedItemFullPath:
# Add package
lModuleName = lModuleName.replace(f"{os.sep}__init__.{gExtensionName}","")
modules[lModuleName] = {
'filename': lCryptedItemFullPath,
'ispackage': True
}
else:
# Add item
modules[lModuleName] = {
'filename': lCryptedItemFullPath,
'ispackage': False
}
return modules return modules
# Settings # Settings
gInUncryptedExtension = "py" # cry for filename.cry gInUncryptedExtension = "py" # cry for filename.cry
@ -142,20 +189,25 @@ gSettings = {
} }
} }
# Create process run # Settings
def Run(): gInUncryptedExtension = "py" # cry for filename.cry
global gSettings gOutCryptedExtension = "cry" # cry for filename.cry
print(f"{str(datetime.datetime.now())}: Run decryptography") gFileMaskToDelete = "pyc" #Remove all .pyc files
############# Step 5 - Ask and confirm the secret word print(f"{str(datetime.datetime.now())}: Run decryptography")
lKeyHashStr_1 = hashlib.sha256(pyautogui.password('Please enter the key to protect source code').encode("utf-8")).digest() ############# Step 5 - Ask and confirm the secret word
lKeyHashStr_2 = hashlib.sha256(pyautogui.password('Please repeat the key to protect source code').encode("utf-8")).digest() lKeyHashStr_1 = hashlib.sha256(pyautogui.password('Please enter the key to protect source code').encode("utf-8")).digest()
if lKeyHashStr_1 == lKeyHashStr_2: lKeyHashStr_2 = hashlib.sha256(pyautogui.password('Please repeat the key to protect source code').encode("utf-8")).digest()
sys.meta_path.append(Base64Importer("TestPackage",inKey = lKeyHashStr_1)) if lKeyHashStr_1 == lKeyHashStr_2:
#CryptographerInit("", inKey = lKeyHashStr_1) #sys.meta_path.append(Base64Importer("TestPackage",inKey = lKeyHashStr_1))
#Init the functions CryptographerInit(sys.argv[1:], inKey = lKeyHashStr_1)
import runpy print(f"{str(datetime.datetime.now())}: Cryprography module has been successfully initialized")
runpy.run_module(**gSettings["run_module"]) if __name__ == "__main__":
else: #import runpy
raise Exception("User set different secret key 1 and key 2") #runpy.run_module(**gSettings["run_module"])
############ Step 6 - Final stage #runpy.run_path("pyPackage_Settings", init_globals=None, run_name=None)
print(f"{str(datetime.datetime.now())}: Cryprography module has been successfully initialized") # Here is the execution code...
#############
###########
#######
else:
raise Exception("User set different secret key 1 and key 2")

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs) The OpenRPA package (from UnicodeLabs)
""" """
__version__ = 'v1.0.42' __version__ = 'v1.1.0'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>' __author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot #from .Core import Robot

@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.0.42 Version: 1.1.0
Summary: First open source RPA platform for business Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov Author: Ivan Maslov

@ -1,14 +1,38 @@
pyOpenRPA-1.0.42.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.0.42.dist-info/METADATA,sha256=Spesv5ub8aq5ymKhq_1kDDFQ2lrCrTwXfF8PakH7OO8,3542 pyOpenRPA-1.1.0.dist-info/METADATA,sha256=yrWtVmt4O4pYWpBBOCBXDwfe6CVB7Qpkfkb1TnBiBEs,3541
pyOpenRPA-1.0.42.dist-info/RECORD,, pyOpenRPA-1.1.0.dist-info/RECORD,,
pyOpenRPA-1.0.42.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.1.0.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.0.42.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.1.0.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436 pyOpenRPA/Orchestrator/Orchestrator.py,sha256=0Q4VYZPdXV2qmLuowMWD_vERj1GQurQx_VFwfsxuucQ,7076
pyOpenRPA/Orchestrator/Processor.py,sha256=kmGNIqe6AZMSrzCt1QlonEy58ecFeLunjo8AeRMsufU,11091 pyOpenRPA/Orchestrator/Processor.py,sha256=wqhbAcR9-7OszRHSX2u7BSONPNIMkEbDexvW47h0xdM,11954
pyOpenRPA/Orchestrator/Server.py,sha256=s1ujCuRX6YxRllqPn541Df4pJP7kOexiS3RIuoT4nyE,22053 pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=jOXJTLwg8cJx6D-rN8J4dn5RCb2nepAhCH4F9hYVUdM,4912 pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=YB5HJL-Qf4IlVrFHyRv_ZMJ0Vo4vjyYqWKjvrTnf1k4,1564
pyOpenRPA/Orchestrator/Timer.py,sha256=FQZ3y6G9d47Ybx7RewzePKQV77H4gCkx5SaeFVlsuhc,2095 pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=2nm5S_FOfnLkDVdlm2MVag9vL3DlyJ98LnwYNMzFNho,15914
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=su4tsDD_ZMbQz6Tbmqj55SM0ZZxuQw9tfPcytaB8wzs,32953 pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=WgGqWoPAnMeXpI_w3iuFX0KUBssvlSk9MuPBuIsNOuY,491
pyOpenRPA/Orchestrator/RobotRDPActive/GlobalDictSessionIndex_Defs.py,sha256=4BbAozLyOlXJxNw0NAlHt38-AyV-B6-Nl1M1AY8CTtk,4212
pyOpenRPA/Orchestrator/RobotRDPActive/Monitor.py,sha256=Y4mhNslK0EBS1LIDfK67j3lkjTZSU5xq-HUl9XNKW-U,10609
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=DrvRm6ZLgrGNcD8EjyKbZ4HZPfiGjQftuWDfqLeM6hw,7627
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=vsISwvRTMbbEtL_u9PU-rP6W71VUhAUBLMblOSGp2BE,9893
pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144
pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077
pyOpenRPA/Orchestrator/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Orchestrator/RobotRDPActive/__main__.py,sha256=z9PaUK4_nBiGd0YJdYVHV_rFx6VjZaxrrmKxSyoTFwY,2508
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/CMDStr.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Clipboard.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/ConnectorExceptions.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/GlobalDictSessionIndex_Defs.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Processor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/RobotRDPActive.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=gqJO6FRDKTBZytJVdJgPF1PvOf05qYUyKDBJJkEpLzk,22755
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=mpPAxAe6PvmKaZlreaoQAy_5wV80edz_0qc-iFrEmBQ,7123
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=t-s45l9APe-wUWazdFVRP2aIsKpsNtlwU_xuSuP2d0Q,36537
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430 pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144 pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -192,7 +216,7 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli
pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123 pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123
pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713 pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722 pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722
pyOpenRPA/Robot/OrchestratorConnector.py,sha256=Fihxz-jH9M4VakXEE0SZ0Vo9tLEQk8Tcg_C4HoH45gI,20037 pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx_v3MfBoKzoQ,20445
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476 pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476
@ -221,8 +245,8 @@ pyOpenRPA/Robot/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347 pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912 pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
pyOpenRPA/Studio/RobotConnector.py,sha256=tQVC8X0k1HMHAAwAtkhtmeNA0cLMY3wuO-RCbgshdMk,5036 pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038
pyOpenRPA/Studio/Studio.py,sha256=zpIGLMM2FBsUt2pC3x3BBm2zZ0n42MPfG7zgqtKxF6o,8338 pyOpenRPA/Studio/Studio.py,sha256=UoMDqnZm-MCiZHR8ToLTHHPN0Yx0Oa6-VOTJdUtoMKE,8352
pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777 pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Studio/Web/Index.xhtml,sha256=RqFW3qC1pFRr-qWEEDlCEhL9l3PwANyRbll3KZJnLvo,47927 pyOpenRPA/Studio/Web/Index.xhtml,sha256=RqFW3qC1pFRr-qWEEDlCEhL9l3PwANyRbll3KZJnLvo,47927
pyOpenRPA/Studio/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430 pyOpenRPA/Studio/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
@ -236,8 +260,8 @@ pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343
pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=DZSb17fiCAYLdNVTLFJ7nTbQhk29PjzxE9OL6ydCDcI,1645 pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655
pyOpenRPA/Tools/RobotDB/Server.py,sha256=MYIbO5vGH1FKgJVu3dQnscKRgN8or0FV8ZxAQbdC2Rc,19865 pyOpenRPA/Tools/RobotDB/Server.py,sha256=rjW9Sg-j9P8pFQD66Uih-rke6-f6sCulinwi4_W-3mc,19933
pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406
pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140
@ -247,15 +271,6 @@ pyOpenRPA/Tools/RobotDB/__pycache__/Server.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,, pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=qU5SXwHgQU177MjqEHyOwJDLAcSVnIkKKw76iD09J1w,7275
pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=H7ciateTh-hml8z69EYZjYgqdTZGkDRtnFwuYnytrCw,3278
pyOpenRPA/Tools/RobotRDPActive/Template.rdp,sha256=qPCLkjzTdYKURK7nRApkPUjRuS4K20vDPj9DIUNSSkE,2392
pyOpenRPA/Tools/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/RobotRDPActive/__main__.py,sha256=mVk8zVqcBrzAwwn7tbZPXFWTQbWUkgU6w89nbY6GN-8,2340
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114 pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114
pyOpenRPA/Tools/RobotScreenActive/Monitor.py,sha256=TV-YisVqa_uGiyJLG9oK4u-5aDjGiFYZFh1dPjOgYc8,492 pyOpenRPA/Tools/RobotScreenActive/Monitor.py,sha256=TV-YisVqa_uGiyJLG9oK4u-5aDjGiFYZFh1dPjOgYc8,492
pyOpenRPA/Tools/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606 pyOpenRPA/Tools/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606
@ -267,15 +282,14 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/Crypter.py,sha256=VRrE5-oQxQtvMEPHM1lMXp2CKnceNBmIWJnsJoJkaVE,3616 pyOpenRPA/Tools/SafeSource/Crypter.py,sha256=VRrE5-oQxQtvMEPHM1lMXp2CKnceNBmIWJnsJoJkaVE,3616
pyOpenRPA/Tools/SafeSource/DistrCreate.py,sha256=-_8BTle57LBKVknnB_3af-LghxrRmRGfRNu08CLNIvY,3232 pyOpenRPA/Tools/SafeSource/DistrCreate.py,sha256=-_8BTle57LBKVknnB_3af-LghxrRmRGfRNu08CLNIvY,3232
pyOpenRPA/Tools/SafeSource/DistrRun.py,sha256=TH4uExbufnOubBrTiO8Ccw00E5K6zaJ59-vApSxQ0iY,6661 pyOpenRPA/Tools/SafeSource/DistrRun.py,sha256=zwUh6Jy-rDAZHV6fcTUMupkukojntFMroHJHMsNQgrE,9637
pyOpenRPA/Tools/SafeSource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/SafeSource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/SafeSource/__main__.py,sha256=g5aYWnuUZoM2jDX2mSIl9tRAJg05tu5VxD2rGJWcACg,649 pyOpenRPA/Tools/SafeSource/__main__.py,sha256=g5aYWnuUZoM2jDX2mSIl9tRAJg05tu5VxD2rGJWcACg,649
pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrRun.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=9w2hSRgGrWKyQb3T_j71u7VoYGZsrTZz189nKtqEmOQ,175 pyOpenRPA/__init__.py,sha256=77eUDvkFqIZMsTqBvMu8L_kbwNSHWSXsJmPZaAgGrVQ,174
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,

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

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

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

@ -0,0 +1,40 @@
import win32clipboard
import keyboard # keyboard functions
import time # Some operations need wait
import random # random number for test
gWaitTextInClipboardSec = 1 # Second for wait text will be set in clipboard (for get operations)
# set clipboard data
def TextSet(inTextStr):
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(inTextStr)
win32clipboard.CloseClipboard()
# get clipboard data
def TextGet(inWaitTextInClipboardSec = gWaitTextInClipboardSec):
time.sleep(inWaitTextInClipboardSec) # Wait for clipboard will save
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
return data
# Test in has text cursor and ready to apply
def InputIsFocused():
keyboard.press_and_release("ctrl+a")
keyboard.press_and_release("backspace") # remove old text
lTextForTest = str(random.randrange(100,99999))
keyboard.write(lTextForTest)
keyboard.press_and_release("ctrl+a")
keyboard.press_and_release("ctrl+c")
time.sleep(2)
keyboard.press_and_release("backspace") # remove old text
lClipboardText = TextGet()
lResult = lClipboardText == lTextForTest
return lResult
# Check if cmd is opened
def CMDIsOpen():
lTextForTest = str(random.randrange(100,99999))
keyboard.write(lTextForTest+" |clip")
keyboard.press_and_release("enter")
time.sleep(2)
lClipboardText = TextGet()
lResult = lClipboardText == lTextForTest
return lResult

@ -0,0 +1,308 @@
#Import parent folder to import current / other packages
from pyOpenRPA.Robot import UIDesktop #Lib to access RDP window
from . import ConnectorExceptions # Exceptions classes
import os #os for process run
import uuid #temp id for Template.rdp
import tempfile #Temporary location
import subprocess
from . import Clipboard # Clipboard functions get/set
import keyboard # Keyboard functions
import time
import random # random integers
from win32api import GetSystemMetrics # Get Screen rect
#Connect to RDP session
"""
{
"Host": "", #Host address
"Port": "", #RDP Port
"Login": "", # Login
"Password": "", #Password
"Screen": {
"Resolution":"FullScreen", #"640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit":"" #"32" or "24" or "16" or "15"
}
}
"""
def Session(inRDPSessionConfiguration):
#RDPConnector.SessionConnect(mConfiguration)
#RDPConnector.LoginPassSet("111.222.222.111","ww","dd")
(lRDPFile, lSessionHex) = SessionConfigurationCreate(inRDPSessionConfiguration)
#Set session hex in globalDict
inRDPSessionConfiguration["SessionHex"] = lSessionHex
#Set login/password
SessionLoginPasswordSet(inRDPSessionConfiguration["Host"],inRDPSessionConfiguration["Login"],inRDPSessionConfiguration["Password"])
#Start session
SessionRDPStart(lRDPFile)
#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
os.remove(lRDPFile) # delete the temp rdp
# Set the result
return inRDPSessionConfiguration
#Add login/ password to the windows credentials to run RDP
def SessionLoginPasswordSet(inHost, inLogin, inPassword):
#Clear old login/password if it exists
#os.system(f"cmdkey /delete:TERMSRV/{inHost}") #Dont need to delete because new user password will clear the previous creds
#Set login password for host
os.system(f'cmdkey /generic:TERMSRV/{inHost} /user:{inLogin} /pass:"{inPassword}"')
return None
#Create current .rdp file with settings
#Return (full path to file, session hex)
def SessionConfigurationCreate(inConfiguration):
#RobotRDPActive folder path
lFileFullPath=__file__
lFileFullPath = lFileFullPath.replace("/","\\")
lRobotRDPActiveFolderPath = "\\".join(lFileFullPath.split("\\")[:-1])
#Full path to Template.rdp file
lRDPTemplateFileFullPath = os.path.join(lRobotRDPActiveFolderPath, "Template.rdp")
#Open template file (.rdp encoding is USC-2 LE BOM = UTF-16 LE) http://qaru.site/questions/7156020/python-writing-a-ucs-2-little-endian-utf-16-le-file-with-bom
lRDPTemplateFileContent = open(lRDPTemplateFileFullPath, "r", encoding="utf-16-le").read()
#Prepare host:port
lHostPort=inConfiguration['Host']
if 'Port' in inConfiguration:
if inConfiguration['Port']:
lHostPort=f"{lHostPort}:{inConfiguration['Port']}"
# Generate parameter for .rdp "drivestoredirect:s:C:\;"
lDriveStoreDirectStr = ""
for lItem in inConfiguration['SharedDriveList']:
lDriveStoreDirectStr+=f"{lItem.upper()}:\\;" # Attention - all drives must be only in upper case!!!
#Replace {Width}, {Height}, {BitDepth}, {HostPort}, {Login}
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Width}", str(inConfiguration.get('Screen',{}).get("Width",1680)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Height}", str(inConfiguration.get('Screen',{}).get("Height",1050)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{BitDepth}", inConfiguration.get('Screen',{}).get("DepthBit","32"))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{HostPort}", lHostPort)
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Login}", inConfiguration['Login'])
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{SharedDriveList}", lDriveStoreDirectStr)
#Save template to temp file
lRDPCurrentFileFullPath = os.path.join(tempfile.gettempdir(), f"{uuid.uuid4().hex}.rdp")
open(lRDPCurrentFileFullPath, "w", encoding="utf-16-le").write(lRDPTemplateFileContent)
#Return .rdp full path
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart
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
lItemArgs = [inRDPFilePath]
subprocess.Popen(lItemArgs, shell=True)
#Wait for UAC unknown publisher exists
lRDPFileName = (inRDPFilePath.split("\\")[-1])[0:-4]
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}],
[{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"},{"depth_start":3, "depth_end": 3, "class_name":"UIMainClass"}]
],
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)
if 0 in lWaitResult:
#Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}]).check()
#Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title":"Подкл&ючить", "class_name":"Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
# Click if 1 is appear (ENG)
if 1 in lWaitResult:
# Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}]).check()
# Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "Co&nnect", "class_name": "Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
# Raise exception if RDP is not active
if len(lWaitResult) == 0:
raise ConnectorExceptions.SessionWindowNotExistError("Error when initialize the RDP session - No RDP windows has appreared!")
# Wait for init
time.sleep(3)
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
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)
if not SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
return None
# Set the screen size
def SessionScreenSize_X_Y_W_H(inSessionHex, inXInt, inYInt, inWInt, inHInt):
lDoBool = True
while lDoBool:
#Prepare little window
try:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
except Exception as e:
return None
try:
lRDPWindow.set_focus()
if SessionIsFullScreen(inSessionHex):
lRDPWindow.type_keys("^%{BREAK}")
time.sleep(0.5)
lRDPWindow.restore()
time.sleep(0.5)
lRDPWindow.move_window(inXInt,inYInt,inWInt,inHInt)
except Exception as e:
time.sleep(1)
else:
lDoBool = False
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
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"
# "LISTEN" - Get result of the cmd command in result TODO get home script
# "CROSSCHECK" - Check if the command was successufully sent TODO get home script
# "RUN" - Run without crosscheck and get clipboard
# return {
# "OutStr": <> # Result string
# "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK
# }
# example Connector.SessionCMDRun("4d1e48f3ff6c45cc810ea25d8adbeb50","start notepad", "RUN")
def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK", inClipboardTimeoutSec = 5):
# Init the result dict
lResult = {"OutStr": None,"IsResponsibleBool":True}
# Enter full screen mode
SessionScreenFull(inSessionHex)
time.sleep(2)
# Run CMD operations
lResult = SystemCMDRun(inCMDCommandStr = inCMDCommandStr, inModeStr = inModeStr, inClipboardTimeoutSec = inClipboardTimeoutSec)
# Exit fullscreen mode
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(""))
def SessionIsFullScreen(inSessionHexStr):
#Default resul
lResult = False
lWeight = GetSystemMetrics(0)
lHeight = GetSystemMetrics(1)
#Get window screen
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
#Case fullscreen
if lSessionHeight == lHeight and lSessionWeight == lWeight:
lResult = True
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")

@ -0,0 +1,66 @@
# ATTENTION! HERE IS NO Relative import because it will be imported dynamically
# All function check the flag SessionIsWindowResponsibleBool == True else no cammand is processed
# All functions can return None, Bool or Dict { "IsSuccessful": True }
from pyOpenRPA.Tools.RobotRDPActive import CMDStr # Create CMD Strings
from pyOpenRPA.Tools.RobotRDPActive import Connector # RDP API
def ProcessStartIfNotRunning(inGlobalDict, inSessionIndex, inProcessName, inFilePath, inFlagGetAbsPath=True):
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStartIfNotRunning: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Create CMD str to stop process
def ProcessStop(inGlobalDict, inSessionIndex, inProcessName, inFlagForceClose):
lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"'
if inFlagForceClose:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
else:
# TODO Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.ProcessStop: SessionIndex: {str(inSessionIndex)}, ProcessName: {inProcessName}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def FileStoredSend(inGlobalDict, inSessionIndex, inHostFilePath, inRDPFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePath, inRDPFilePath = inRDPFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredSend: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def FileStoredRecieve(inGlobalDict, inSessionIndex, inRDPFilePath, inHostFilePath):
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePath, inHostFilePath = inHostFilePath)
# Calculate the session Hex
lSessionHex = inGlobalDict["RDPList"][inSessionIndex]["SessionHex"]
# Check is Session is responsible
if inGlobalDict["RDPList"][inSessionIndex]["SessionIsWindowResponsibleBool"]:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
else:
# Write in logger - warning
inGlobalDict["Logger"].warning(f"GlobalDictSessionIndex_Defs.FileStoredRecieve: SessionIndex: {str(inSessionIndex)}, HostFilePath: {inHostFilePath}:: Session is not responsible!")
lResult = False # Set false result - function has not been done
return lResult

@ -0,0 +1,158 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import time # Time wait operations
import importlib # from dynamic import module
from . import ConnectorExceptions # Exceptions classes
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True
lResponsibilityCheckLastSec = time.time() # Get current time for check interval
while lFlagWhile:
try:
# UIOSelector list init
lUIOSelectorList = []
#Prepare selectors list for check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
#Run wait command
#import pdb
#pdb.set_trace()
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
#print(lRDPDissappearList)
###########################################
#Analyze if flag safeturn off is activated
if inGlobalDict.get("OrchestratorToRobotResetStorage",{}).get("SafeTurnOff",False):
lFlagWhile=False
#Set status disconnected for all RDP List
for lItem in inGlobalDict["RDPList"]:
lItem["SessionIsWindowExistBool"]=False
lItem["SessionIsWindowResponsibleBool"]=False
#Kill all RDP sessions
os.system('taskkill /F /im mstsc.exe')
#Return from function
return
###########################################
###########################################
for lItem in lRDPDissappearList:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
#pdb.set_trace()
#Session start if it is not in ignore list
#add check for selector if it is not in ignoreIndexList
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Flag that session is started
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]= True
# Write in logger - info
inGlobalDict["Logger"].info(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session has been initialized!")
# catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not exist!")
# catch ConnectorExceptions.SessionWindowNotResponsibleError
except ConnectorExceptions.SessionWindowNotResponsibleError as e:
inGlobalDict["RDPList"][lItem]["SessionIsWindowExistBool"] = True # Set flag that session is disconnected
inGlobalDict["RDPList"][lItem]["SessionIsWindowResponsibleBool"]=False
# Write in logger - warning
inGlobalDict["Logger"].warning(f"SessionHex: {str(inGlobalDict['RDPList'][lItem]['SessionHex'])}:: Session is not responsible!")
# general exceptions
except Exception as e:
# Write in logger - warning
inGlobalDict["Logger"].exception(f"!!! ATTENTION !!! Unrecognized error")
#######################
# Click all warning messages
Connector.SystemRDPWarningClickOk()
#######################
###########################################
#Check if from Orchestrator full screen session is set
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] != inGlobalDict["FullScreenSessionIndex"]:
#Do some switches
#If full screen mode we have now
if inGlobalDict["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreen100x550(inGlobalDict["RDPList"][inGlobalDict["FullScreenSessionIndex"]]["SessionHex"])
#If new session is setted
if inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"] is not None:
if inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionIsWindowExistBool"]:
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"])
#Set one to other equal
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]
###########################################
####################################
##### Block check responsibility interval [ResponsibilityCheckIntervalSec]
if inGlobalDict['ResponsibilityCheckIntervalSec']: # Do check if ResponsibilityCheckIntervalSec is not None
if (time.time - lResponsibilityCheckLastSec()) > inGlobalDict['ResponsibilityCheckIntervalSec']:
# Set new time
lResponsibilityCheckLastSec = time.time()
# Do responsibility check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
# Check RDP responsibility
lDoCheckResponsibilityBool = True
lDoCheckResponsibilityCountMax = 20
lDoCheckResponsibilityCountCurrent = 0
while lDoCheckResponsibilityBool:
# Enter full screen mode
Connector.SessionScreenFull(lItem['SessionHex'])
time.sleep(2)
# Check responding
lDoCheckResponsibilityBool = not Connector.SystemRDPIsResponsible()
# Check if counter is exceed - raise exception
if lDoCheckResponsibilityCountCurrent >= lDoCheckResponsibilityCountMax:
lItem["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
lItem["SessionIsWindowResponsibleBool"]=False
# Session window is not responsible - restart RDP (close window here - next loop will reconnect)
Connector.SessionClose(lItem['SessionHex'])
# Turn off the loop
lDoCheckResponsibilityBool = False
else:
# Exit fullscreen mode
Connector.SessionScreen100x550(lItem['SessionHex'])
# Wait if is not responding
if lDoCheckResponsibilityBool:
time.sleep(3)
# increase the couter
lDoCheckResponsibilityCountCurrent+=1
####################################
# Check ActivityList from orchestrator
lActivityListNew = []
lActivityListOld = inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"]+inGlobalDict["ActivityListStart"]
inGlobalDict["ActivityListStart"] = []
for lActivityItem in lActivityListOld:
#################
#Call function from Activity structure
################################################
lSubmoduleFunctionName = lActivityItem["DefName"]
lFileFullPath = lActivityItem["ModulePath"] # "path\\to\\module.py"
lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
# Set gSettings in module
lTechModuleFromSpec.gSettings = inGlobalDict
if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule
#mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
lActivityItemResult=getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(*lActivityItem["ArgList"],**lActivityItem["ArgDict"])
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
if lActivityItemResultType is bool:
if not lActivityItemResult:
# Activity is not done - add to list (retry in future)
lActivityListNew.append(lActivityItem)
#################################################
inGlobalDict["OrchestratorToRobotResetStorage"]["ActivityList"] = lActivityListNew # Override the value
except RuntimeError as e:
# case noGUI error passed - do nothing
# Write in logger - warning
inGlobalDict["Logger"].warning(f"Host session has lost the GUI")
finally:
# Wait for the next iteration
time.sleep(0.7)
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -0,0 +1,147 @@
# 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"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
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
# Logoff the RDP session
def RDPSessionLogoff(inRDPSessionKeyStr):
global gSettings
lResult = True
lCMDStr = "shutdown -L" # CMD logoff command
# Calculate the session Hex
lSessionHex = gSettings["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# 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(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPath= inFlagGetAbsPathBool)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# Create CMD str to stop process
def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = f'taskkill /im "{inProcessNameWEXEStr}" /fi "username eq %USERNAME%"'
if inFlagForceCloseBool:
lCMDStr+= " /F"
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# Send file from Host to Session RDP using shared drive in RDP
def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePathStr, inRDPFilePath = inRDPFilePathStr)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr, {}).get("SessionHex", None)
#lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
return lResult
# Recieve file from Session RDP to Host using shared drive in RDP
def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr):
global gSettings
inGlobalDict = gSettings
lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePathStr, inHostFilePath = inHostFilePathStr)
# Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Run CMD
if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120)
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")

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

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

@ -13,7 +13,7 @@ import importlib
lFolderPath = "/".join(__file__.split("/")[:-4]) lFolderPath = "/".join(__file__.split("/")[:-4])
sys.path.insert(0, lFolderPath) sys.path.insert(0, lFolderPath)
#Единый глобальный словарь (За основу взять из Settings.py) #Единый глобальный словарь (За основу взять из Settings.py)
global mGlobalDict global gSettingsDict
#Call Settings function from argv[1] file #Call Settings function from argv[1] file
################################################ ################################################
lSubmoduleFunctionName = "Settings" lSubmoduleFunctionName = "Settings"
@ -22,28 +22,30 @@ lModuleName = (lFileFullPath.split("\\")[-1])[0:-3]
lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath)
lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification)
lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec)
mGlobalDict = None gSettingsDict = None
if lSubmoduleFunctionName in dir(lTechModuleFromSpec): if lSubmoduleFunctionName in dir(lTechModuleFromSpec):
# Run SettingUpdate function in submodule # Run SettingUpdate function in submodule
mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)()
################################################# #################################################
######################################################### #########################################################
from pyOpenRPA.Tools.RobotRDPActive import Connector from pyOpenRPA.Tools.RobotRDPActive import Connector
from pyOpenRPA.Tools.RobotRDPActive import Monitor from pyOpenRPA.Tools.RobotRDPActive import Monitor
#Disable certificate warning from pyOpenRPA.Tools.RobotRDPActive import Scheduler # Scheduler operations
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 0 /f' #### Global error handler
os.system(lCMDString) try:
#time.sleep() #time.sleep()
for lConfigurationItem in mGlobalDict["RDPList"]: ######## Init the RDP List
try: for lConfigurationItem in gSettingsDict["RDPList"]:
Connector.Session(lConfigurationItem) lConfigurationItem["SessionIsWindowExistBool"]=False #Flag that session is not started
lConfigurationItem["FlagSessionIsActive"]=True #Flag that session is started lConfigurationItem["SessionIsWindowResponsibleBool"]=False #Flag that session is not started
except Exception: lConfigurationItem["SessionHex"]=" 77777sdfsdf77777dsfdfsf77777777" #Flag that session is not started
pass ##########
#Run monitor #Run monitor
Monitor.Monitor(mGlobalDict, 1) Scheduler.Scheduler(gSettingsDict["Scheduler"]) # Init & Run Scheduler
#Enable certificate warning Monitor.Monitor(gSettingsDict, 1)
lCMDString = 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Terminal Server Client" /v "AuthenticationLevelOverride" /t "REG_DWORD" /d 2 /f' except Exception as e:
os.system(lCMDString) # Write in logger - warning
#Close all thread from OrchestratorConnection gSettingsDict["Logger"].exception(f"!!! ATTENTION !!! Global error handler - look at code")
mGlobalDict["OrchestratorConnectorTerminateAll"]() finally:
#Close all thread from OrchestratorConnection
gSettingsDict["OrchestratorConnectorTerminateAll"]()

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

@ -3,16 +3,45 @@ import json
from desktopmagic.screengrab_win32 import ( from desktopmagic.screengrab_win32 import (
getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage, getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage,
getRectAsImage, getDisplaysAsImages) 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): def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
inResponseDict = inRequest.OpenRPAResponseDict inResponseDict = inRequest.OpenRPAResponseDict
# Create result JSON # Create result JSON
lResultJSON = {"RenderRobotList": []} lResultJSON = {"RenderRobotList": []}
lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"]
for lItem in lRenderFunctionsRobotList: for lItem in lRenderFunctionsRobotList:
# Выполнить вызов и записать результат lUACBool = True # Check if render function is applicable User Access Rights (UAC)
lItemResultDict = lItem["RenderFunction"](inGlobalDict) if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# RunFunction lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())]
lResultJSON["RenderRobotList"].append(lItemResultDict) if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]:
lUACBool = False # UAC Check is not passed - False for user
if lUACBool: # Run function if UAC is TRUE
# Выполнить вызов и записать результат
lItemResultDict = lItem["RenderFunction"](inGlobalDict)
# RunFunction
lResultJSON["RenderRobotList"].append(lItemResultDict)
# Send message back to client # Send message back to client
message = json.dumps(lResultJSON) message = json.dumps(lResultJSON)
# Write content as utf-8 data # Write content as utf-8 data
@ -60,7 +89,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": "/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": "/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": "/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 inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList
return inGlobalConfiguration return inGlobalConfiguration

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

@ -292,7 +292,49 @@
} }
mGlobal.Monitor.fControlPanelRefresh() mGlobal.Monitor.fControlPanelRefresh()
mGlobal.Monitor.fControlPanelAutoUpdateRun(3); 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() { mGlobal.Test=function() {
///Обнулить таблицу ///Обнулить таблицу
lData = [ lData = [
@ -339,9 +381,9 @@
function(lData,l2,l3) function(lData,l2,l3)
{ {
var lResponseJSON=JSON.parse(lData) 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 код ///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode); $('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show'); $('.ui.modal.basic').modal('show');
@ -349,12 +391,33 @@
dataType: "text" dataType: "text"
}); });
} }
/////////////////////////////// ///////////////////////////////
///Processor functions ///Processor functions
/////////////////////////////// ///////////////////////////////
mGlobal.Processor = {} 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) { mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [ lData = [
{ {
@ -532,58 +595,17 @@
///Установить HTML код ///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode); 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> </script>
<style type="text/css"> <style type="text/css">
body { body {
background-color: #FFFFFF; background-color: #FFFFFF;
} }
.main.container { .main.container {
margin-top: 2em; margin-top: 2em;
} }
.overlay { .overlay {
float: left; float: left;
margin: 0em 3em 1em 0em; margin: 0em 3em 1em 0em;
@ -593,7 +615,6 @@
left: 0; left: 0;
transition: left 0.5s ease; transition: left 0.5s ease;
} }
.main.menu.fixed { .main.menu.fixed {
background-color: #FFFFFF; background-color: #FFFFFF;
border: 1px solid #DDD; border: 1px solid #DDD;
@ -602,14 +623,12 @@
.overlay.fixed .menu { .overlay.fixed .menu {
left: 800px; left: 800px;
} }
.text.container .left.floated.image { .text.container .left.floated.image {
margin: 2em 2em 2em -4em; margin: 2em 2em 2em -4em;
} }
.text.container .right.floated.image { .text.container .right.floated.image {
margin: 2em -4em 2em 2em; margin: 2em -4em 2em 2em;
} }
.ui.footer.segment { .ui.footer.segment {
margin: 5em 0em 0em; margin: 5em 0em 0em;
padding: 5em 0em; padding: 5em 0em;
@ -626,7 +645,7 @@
<h1 class="ui header inverted">Orchestrator Web GUI</h1> <h1 class="ui header inverted">Orchestrator Web GUI</h1>
</div> </div>
<div class="two wide column"> <div class="two wide column">
<h5>by UnicodeLabs</h5> <h5>by Ivan Maslov</h5>
</div> </div>
</div> </div>
@ -689,36 +708,65 @@
</div> </div>
</div> </div>
<div class="row black"> <div class="row black">
<div class="three wide column"> <div class="five wide column">
<h2 class="ui header inverted">Controls</h2>
</div>
<div class="three wide column">
<h2 class="ui header inverted">Monitor</h2>
</div> </div>
<div class="two wide column"> <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>
</div> </div>
<button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();"> <div class="row">
<i class="desktop icon"></i> <div class="five wide column">
Look machine screenshot <button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();">
</button> <i class="desktop icon"></i>
<button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();"> Look machine screenshot
<i class="redo icon"></i> </button>
Restart Orchestrator <button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();">
</button> <i class="redo icon"></i>
<button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();"> Restart Orchestrator
<i class="info icon"></i> </button>
Scheduler activity time list <button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();">
<script class="openrpa-hidden-info-table-planloglist" style="display:none" type="text/x-handlebars-template"> <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"> <table class="ui celled table">
<thead> <thead>
<tr> <tr>
<th>#</th> <th>#</th>
<th>Activity type</th> <th>Activity type</th>
<th>Time</th> <th>Process</th>
<th>Process path/Process name</th> <th>Activity DateTime plan</th>
<th>Activity DateTime fact</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -726,117 +774,136 @@
<tr> <tr>
<td>{{@index}}</td> <td>{{@index}}</td>
<td>{{activityType}}</td> <td>{{activityType}}</td>
<td>{{time}}</td> <td>{{processPath}}</td>
<td>{{processPathName}}</td> <td>{{activityDateTime}}</td>
<td class="negative
">{{activityStartDateTime}}</td>
</tr> </tr>
{{/result}} {{/result}}
</tbody> </tbody>
</table> </table>
</script> </script>
</button> </button>
<button class="ui labeled icon button" onclick="mGlobal.Processor.LogListShow();">
<i class="info icon"></i> <script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
Processor logs <table class="ui celled table">
<script class="openrpa-hidden-info-table-activitylogschedulelist" style="display:none" type="text/x-handlebars-template"> <thead>
<table class="ui celled table"> <tr>
<thead> <th>Machine name</th>
<tr> <th>Machihe host</th>
<th>#</th> <th>Status</th>
<th>Activity type</th> <th>Actions,length: {{childs.length}}</th>
<th>Process</th> </tr>
<th>Activity DateTime plan</th> </thead>
<th>Activity DateTime fact</th> <tbody>
</tr> {{#ListenURLList}}
</thead> <tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr>
<tbody> {{/ListenURLList}}
{{#result}} </tbody>
<tr> </table>
<td>{{@index}}</td> </script>
<td>{{activityType}}</td>
<td>{{processPath}}</td> <script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template">
<td>{{activityDateTime}}</td> {{#if Title}}
<td class="negative <h1>{{{Title}}}</h1>
">{{activityStartDateTime}}</td> {{/if}}
</tr> {{#if FilterOnKeyUp}}
{{/result}} <div class="ui icon input search" style="width:500px;">
</tbody> <input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
</table> <i class="inverted circular search link icon"></i>
</script> </div>
</button> {{/if}}
<table class="ui celled table selectable inverted">
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template"> <thead>
<table class="ui celled table"> <tr>
<thead> {{#Columns}}
<tr> <th>{{{this}}}</th>
<th>Machine name</th> {{/Columns}}
<th>Machihe host</th> </tr>
<th>Status</th> </thead>
<th>Actions,length: {{childs.length}}</th> <tbody>
</tr> {{#Rows}}
</thead> <tr>
<tbody> {{#this}}
{{#ListenURLList}} <td>
<tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr> {{{this}}}
{{/ListenURLList}} </td>
</tbody> {{/this}}
</table> </tr>
</script> {{/Rows}}
</tbody>
<script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template"> </table>
{{#if Title}} </script>
<h1>{{{Title}}}</h1> <script class="openrpa-handlebar-template-list-filter" style="display:none" type="text/x-handlebars-template">
{{/if}} {{#if Title}}
{{#if FilterOnKeyUp}} <h1>{{{Title}}}</h1>
<div class="ui icon input search" style="width:500px;"> {{/if}}
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search..."> {{#if FilterOnKeyUp}}
<i class="inverted circular search link icon"></i> <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> </div>
{{/if}} <div class="two wide column">
<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> </div>
{{/if}} <div class="nine wide column openrpa-robotrdpactive-control-panel-general">
<div class="ui inverted segment"> <div class="ui info message">
<div class="ui inverted relaxed divided list"> <button class="ui icon button labeled " onclick="mGlobal.RobotRDPActive.fControlPanelRefresh();">
{{#List}} <i class="sync alternate icon"></i>
<div class="item"> <div class="openrpa-refresh-button">Refresh</div>
<i class="map marker icon"></i> </button>
<div class="content"> </div>
<a class="header">{{{Header}}}</a> <div class="openrpa-robotrdpactive-control-panel"></div>
<div class="description">{{{Description}}}</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>
</div> </div>
{{/List}} </script>
</div>
</div> </div>
</script> </div>
<div class="row openrpa-monitor"> <div class="row openrpa-monitor">
</div> </div>

@ -383,6 +383,13 @@ def IntervalDataReceiveResetAsync(*args,**kwargs):
if "Interval" in lKwargs: if "Interval" in lKwargs:
lInterval = lKwargs["Interval"] lInterval = lKwargs["Interval"]
del lKwargs["Interval"] del lKwargs["Interval"]
# Reset the storage before start
DataSendSync(
RobotValue=lKwargs["RobotResetValue"],
OrchestratorKeyList=lKwargs["OrchestratorKeyList"], OrchestratorProtocol=lKwargs["OrchestratorProtocol"],
OrchestratorHost=lKwargs["OrchestratorHost"], OrchestratorPort=lKwargs["OrchestratorPort"],
OrchestratorAuthToken=lKwargs["OrchestratorAuthToken"]
)
lTimer = TimerRepeat.TimerRepeat(lInterval, DataReceiveResetAsync, lArgs, lKwargs) lTimer = TimerRepeat.TimerRepeat(lInterval, DataReceiveResetAsync, lArgs, lKwargs)
lTimer.start() lTimer.start()
#Add timer to general list to stop this when needed #Add timer to general list to stop this when needed

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

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

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

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

@ -1,136 +0,0 @@
#Import parent folder to import current / other packages
from pyOpenRPA.Robot import UIDesktop #Lib to access RDP window
import os #os for process run
import uuid #temp id for Template.rdp
import tempfile #Temporary location
import time
import subprocess
#Connect to RDP session
"""
{
"Host": "", #Host address
"Port": "", #RDP Port
"Login": "", # Login
"Password": "", #Password
"Screen": {
"Resolution":"FullScreen", #"640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen
"FlagUseAllMonitors": False, # True or False
"DepthBit":"" #"32" or "24" or "16" or "15"
}
}
"""
def Session(inRDPSessionConfiguration):
#RDPConnector.SessionConnect(mConfiguration)
#RDPConnector.LoginPassSet("111.222.222.111","ww","dd")
(lRDPFile, lSessionHex) = SessionConfigurationCreate(inRDPSessionConfiguration)
#Set session hex in globalDict
inRDPSessionConfiguration["SessionHex"] = lSessionHex
#Set login/password
SessionLoginPasswordSet(inRDPSessionConfiguration["Host"],inRDPSessionConfiguration["Login"],inRDPSessionConfiguration["Password"])
#Start session
SessionRDPStart(lRDPFile)
#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
os.remove(lRDPFile) # delete the temp rdp
return inRDPSessionConfiguration
#Add login/ password to the windows credentials to run RDP
def SessionLoginPasswordSet(inHost, inLogin, inPassword):
#Clear old login/password if it exists
#os.system(f"cmdkey /delete:TERMSRV/{inHost}") #Dont need to delete because new user password will clear the previous creds
#Set login password for host
os.system(f"cmdkey /generic:TERMSRV/{inHost} /user:{inLogin} /pass:{inPassword}")
return None
#Create current .rdp file with settings
#Return (full path to file, session hex)
def SessionConfigurationCreate(inConfiguration):
#RobotRDPActive folder path
lFileFullPath=__file__
lFileFullPath = lFileFullPath.replace("/","\\")
lRobotRDPActiveFolderPath = "\\".join(lFileFullPath.split("\\")[:-1])
#Full path to Template.rdp file
lRDPTemplateFileFullPath = os.path.join(lRobotRDPActiveFolderPath, "Template.rdp")
#Open template file (.rdp encoding is USC-2 LE BOM = UTF-16 LE) http://qaru.site/questions/7156020/python-writing-a-ucs-2-little-endian-utf-16-le-file-with-bom
lRDPTemplateFileContent = open(lRDPTemplateFileFullPath, "r", encoding="utf-16-le").read()
#Prepare host:port
lHostPort=inConfiguration['Host']
if 'Port' in inConfiguration:
if inConfiguration['Port']:
lHostPort=f"{lHostPort}:{inConfiguration['Port']}"
#Replace {Width}, {Height}, {BitDepth}, {HostPort}, {Login}
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Width}", str(inConfiguration.get('Screen',{}).get("Width",1680)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Height}", str(inConfiguration.get('Screen',{}).get("Height",1050)))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{BitDepth}", inConfiguration.get('Screen',{}).get("DepthBit","32"))
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{HostPort}", lHostPort)
lRDPTemplateFileContent = lRDPTemplateFileContent.replace("{Login}", inConfiguration['Login'])
#Save template to temp file
lRDPCurrentFileFullPath = os.path.join(tempfile.gettempdir(), f"{uuid.uuid4().hex}.rdp")
open(lRDPCurrentFileFullPath, "w", encoding="utf-16-le").write(lRDPTemplateFileContent)
#Return .rdp full path
return (lRDPCurrentFileFullPath, (lRDPCurrentFileFullPath.split("\\")[-1])[0:-4])
#RDPSessionStart
def SessionRDPStart(inRDPFilePath):
#run rdp session
lItemArgs = [inRDPFilePath]
subprocess.Popen(lItemArgs, shell=True)
#Wait for UAC unknown publisher exists
lRDPFileName = (inRDPFilePath.split("\\")[-1])[0:-4]
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title": "Подключение к удаленному рабочему столу", "class_name": "#32770", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}],
[{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}],
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
#Click if 0 is appear (RUS)
if 0 in lWaitResult:
#Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title": "Боль&ше не выводить запрос о подключениях к этому компьютеру", "friendly_class_name": "CheckBox"}]).check()
#Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Подключение к удаленному рабочему столу", "backend": "win32"},
{"title":"Подкл&ючить", "class_name":"Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
# Click if 1 is appear (ENG)
if 1 in lWaitResult:
# Check the box do not retry
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "D&on't ask me again for connections to this computer",
"friendly_class_name": "CheckBox"}]).check()
# Go to connection
UIDesktop.UIOSelector_Get_UIO([{"title": "Remote Desktop Connection", "class_name": "#32770", "backend": "win32"},
{"title": "Co&nnect", "class_name": "Button"}]).click()
lWaitResult = UIDesktop.UIOSelectorsSecs_WaitAppear_List(
[
[{"title_re": f"{lRDPFileName}.*",
"class_name": "TscShellContainerClass", "backend": "win32"}]
],
30
)
#Prepare little window
SessionScreen100x550(lRDPFileName)
return None
#Set fullscreen for app
def SessionScreenFull(inSessionHex):
#Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.maximize()
lRDPWindow.set_focus()
return None
#Set Little window of the session
def SessionScreen100x550(inSessionHex):
#Prepare little window
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.restore()
lRDPWindow.move_window(10,10,550,100)
return None

@ -1,55 +0,0 @@
from pyOpenRPA.Robot import UIDesktop
from . import Connector
import os
import pdb
#Check for session is closed. Reopen if detected. Always keep session is active
def Monitor(inGlobalDict, inListUpdateTimeout):
lFlagWhile = True
while lFlagWhile:
# UIOSelector list init
lUIOSelectorList = []
#Prepare selectors list for check
for lIndex, lItem in enumerate(inGlobalDict["RDPList"]):
lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}])
#Run wait command
lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout)
###########################################
#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()
#Session start if it is not in ignore list
#add check for selector if it is not in ignoreIndexList
if lItem not in inGlobalDict["OrchestratorToRobotStorage"]["IgnoreIndexList"]:
try:
Connector.Session(inGlobalDict["RDPList"][lItem])
inGlobalDict["RDPList"][lItem]["FlagSessionIsActive"] = True # Flag that session is started
except Exception:
pass
###########################################
#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"]]["FlagSessionIsActive"]:
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"]]["FlagSessionIsActive"]:
Connector.SessionScreenFull(inGlobalDict["RDPList"][inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]]["SessionHex"])
#Set one to other equal
inGlobalDict["FullScreenSessionIndex"] = inGlobalDict["OrchestratorToRobotStorage"]["FullScreenSessionIndex"]
return None
#TODO Def garbage window cleaner (if connection was lost)

@ -8,18 +8,35 @@ from . import Crypter # Crypto functions
import datetime #Datetime import datetime #Datetime
import hashlib #Get hash of the word import hashlib #Get hash of the word
import pyautogui import pyautogui
import os
import glob # list files
EXT = '.cry' EXT = '.cry'
gExtensionName = "cry"
# How to run # How to run
# sys.meta_path.append(Base64Importer(root_pkg_path)) # sys.meta_path.append(Base64Importer(root_pkg_path))
# Init cryptographer # Init cryptographer
def CryptographerInit(inFolderPath): def CryptographerInit(inFolderPathList, inKey):
sys.meta_path.append(Base64Importer(inFolderPath)) #sys.meta_path.append(Base64Importer(inFolderPath))
# Flag add subfolder, which contains extension files
#path = 'c:\\projects\\hc2\\'
#folders = []
# Recursive walk throught the tree
# r=root, d=directories, f = files
#import pdb
#pdb.set_trace()
for lItem in inFolderPathList:
sys.meta_path.append(Base64Importer(os.path.abspath(lItem), inKey=inKey))
#for r, d, f in os.walk(lItem):
# for folder in d:
#folders.append(os.path.join(r, folder))
#sys.meta_path.append(Base64Importer(os.path.join(r, folder), inKey=inKey))
# pass
#for f in folders:
# print(f)
#=============================================================================== #===============================================================================
class Base64Importer(object): class Base64Importer(object):
"""Служит для поиска и импорта python-модулей, кодированных в base64 """Служит для поиска и импорта python-модулей, кодированных в base64
Класс реализует Import Protocol (PEP 302) для возможности импортирования Класс реализует Import Protocol (PEP 302) для возможности импортирования
модулей, зашифрованных в base64 из указанного пакета. модулей, зашифрованных в base64 из указанного пакета.
""" """
@ -27,25 +44,28 @@ class Base64Importer(object):
def __init__(self, root_package_path, inKey): def __init__(self, root_package_path, inKey):
self.mKeyStr = inKey self.mKeyStr = inKey
self.__modules_info = self.__collect_modules_info(root_package_path) self.__modules_info = self.__collect_modules_info(root_package_path)
# Create list of cry files when run
#for lItem in root_package_path_list:
# lCryptedFileList = [f for f in glob.glob(os.path.join(lItem,f"**/*.{EXT}"), recursive=True)]
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
def find_module(self, fullname, path=None): def find_module(self, fullname, path=None):
"""Метод будет вызван при импорте модулей """Метод будет вызван при импорте модулей
Если модуль с именем fullname является base64 и находится в заданной Если модуль с именем fullname является base64 и находится в заданной
папке, данный метод вернёт экземпляр импортёра (finder), либо None, если папке, данный метод вернёт экземпляр импортёра (finder), либо None, если
модуль не является base64. модуль не является base64.
""" """
#print(f"find_module:: Fullname: {fullname}, path: {path}")
#print(f"modules info: {self.__modules_info}")
if fullname in self.__modules_info: if fullname in self.__modules_info:
return self return self
return None return None
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
def load_module(self, fullname): def load_module(self, fullname):
"""Метод загружает base64 модуль """Метод загружает base64 модуль
Если модуль с именем fullname является base64, то метод попытается его Если модуль с именем fullname является base64, то метод попытается его
загрузить. Возбуждает исключение ImportError в случае любой ошибки. загрузить. Возбуждает исключение ImportError в случае любой ошибки.
""" """
#print(f"load_module:: Fullname: {fullname}")
if not fullname in self.__modules_info: if not fullname in self.__modules_info:
raise ImportError(fullname) raise ImportError(fullname)
# Для потокобезопасности # Для потокобезопасности
@ -53,6 +73,8 @@ class Base64Importer(object):
try: try:
mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
mod.__file__ = "<{}>".format(self.__class__.__name__) mod.__file__ = "<{}>".format(self.__class__.__name__)
mod.__file__ = self.__modules_info[fullname]['filename'] #Hotfix
#print(f"MODFILE::{mod.__file__}")
mod.__loader__ = self mod.__loader__ = self
if self.is_package(fullname): if self.is_package(fullname):
mod.__path__ = [] mod.__path__ = []
@ -61,7 +83,10 @@ class Base64Importer(object):
mod.__package__ = fullname.rpartition('.')[0] mod.__package__ = fullname.rpartition('.')[0]
src = self.get_source(fullname) src = self.get_source(fullname)
try: try:
exec(src) in mod.__dict__ #__name__ = "pyPackage"
#print(f"MODNAME:: {mod.__name__}")
#exec(src) in mod.__dict__
exec(src,mod.__dict__)
except: except:
del sys.modules[fullname] del sys.modules[fullname]
raise ImportError(fullname) raise ImportError(fullname)
@ -98,33 +123,55 @@ class Base64Importer(object):
"""Собирает информацию о модулях из указанного пакета """Собирает информацию о модулях из указанного пакета
""" """
modules = {} modules = {}
"""
p = os.path.abspath(root_package_path) p = os.path.abspath(root_package_path)
dir_name = os.path.dirname(p) + os.sep dir_name = os.path.dirname(p) + os.sep
#dir_name = "" # Hotfix 2020 03 19
#print(f"__collect_modules_info:: root_package_path: {root_package_path}")
for root, _, files in os.walk(p): for root, _, files in os.walk(p):
# Информация о текущем пакете # Информация о текущем пакете
filename = os.path.join(root, '__init__' + EXT) filename = os.path.join(root, '__init__' + EXT)
p_fullname = root.rpartition(dir_name)[2].replace(os.sep, '.') p_fullname = root.rpartition(dir_name)[2].replace(os.sep, '.')
modules[p_fullname] = { modules[p_fullname] = {
'filename': filename, 'filename': filename,
'ispackage': True 'ispackage': True
} }
# Информация о модулях в текущем пакете # Информация о модулях в текущем пакете
for f in files: for f in files:
if not f.endswith(EXT): if not f.endswith(EXT):
continue continue
filename = os.path.join(root, f) filename = os.path.join(root, f)
fullname = '.'.join([p_fullname, os.path.splitext(f)[0]]) fullname = '.'.join([p_fullname, os.path.splitext(f)[0]])
fullname = os.path.splitext(f)[0]
modules[fullname] = { modules[fullname] = {
'filename': filename, 'filename': filename,
'ispackage': False 'ispackage': False
} }
"""
# # # # # # # # # # #
# New way of collection
lRootAbsPath = os.path.abspath(root_package_path)
#print(lRootAbsPath)
lNewPathIndex = len(lRootAbsPath)+len(os.sep) # Len of the root path + len sep
lCryptedFileList = [f for f in glob.glob(os.path.join(lRootAbsPath,f"**/*.{gExtensionName}"), recursive=True)]
#print(lCryptedFileList)
for lCryptedItemFullPath in lCryptedFileList:
# Get Module name
lModuleName = lCryptedItemFullPath[lNewPathIndex:-(1+len(gExtensionName))].replace(os.sep, '.')
# Check if file is not __init__.{EXT} - This is package
if f"__init__.{EXT}" in lCryptedItemFullPath:
# Add package
lModuleName = lModuleName.replace(f"{os.sep}__init__.{gExtensionName}","")
modules[lModuleName] = {
'filename': lCryptedItemFullPath,
'ispackage': True
}
else:
# Add item
modules[lModuleName] = {
'filename': lCryptedItemFullPath,
'ispackage': False
}
return modules return modules
# Settings # Settings
gInUncryptedExtension = "py" # cry for filename.cry gInUncryptedExtension = "py" # cry for filename.cry
@ -142,20 +189,25 @@ gSettings = {
} }
} }
# Create process run # Settings
def Run(): gInUncryptedExtension = "py" # cry for filename.cry
global gSettings gOutCryptedExtension = "cry" # cry for filename.cry
print(f"{str(datetime.datetime.now())}: Run decryptography") gFileMaskToDelete = "pyc" #Remove all .pyc files
############# Step 5 - Ask and confirm the secret word print(f"{str(datetime.datetime.now())}: Run decryptography")
lKeyHashStr_1 = hashlib.sha256(pyautogui.password('Please enter the key to protect source code').encode("utf-8")).digest() ############# Step 5 - Ask and confirm the secret word
lKeyHashStr_2 = hashlib.sha256(pyautogui.password('Please repeat the key to protect source code').encode("utf-8")).digest() lKeyHashStr_1 = hashlib.sha256(pyautogui.password('Please enter the key to protect source code').encode("utf-8")).digest()
if lKeyHashStr_1 == lKeyHashStr_2: lKeyHashStr_2 = hashlib.sha256(pyautogui.password('Please repeat the key to protect source code').encode("utf-8")).digest()
sys.meta_path.append(Base64Importer("TestPackage",inKey = lKeyHashStr_1)) if lKeyHashStr_1 == lKeyHashStr_2:
#CryptographerInit("", inKey = lKeyHashStr_1) #sys.meta_path.append(Base64Importer("TestPackage",inKey = lKeyHashStr_1))
#Init the functions CryptographerInit(sys.argv[1:], inKey = lKeyHashStr_1)
import runpy print(f"{str(datetime.datetime.now())}: Cryprography module has been successfully initialized")
runpy.run_module(**gSettings["run_module"]) if __name__ == "__main__":
else: #import runpy
raise Exception("User set different secret key 1 and key 2") #runpy.run_module(**gSettings["run_module"])
############ Step 6 - Final stage #runpy.run_path("pyPackage_Settings", init_globals=None, run_name=None)
print(f"{str(datetime.datetime.now())}: Cryprography module has been successfully initialized") # Here is the execution code...
#############
###########
#######
else:
raise Exception("User set different secret key 1 and key 2")

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs) The OpenRPA package (from UnicodeLabs)
""" """
__version__ = 'v1.0.42' __version__ = 'v1.1.0'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>' __author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot #from .Core import Robot

@ -159,18 +159,25 @@ def SessionScreenFull(inSessionHex):
# Set the screen size # Set the screen size
def SessionScreenSize_X_Y_W_H(inSessionHex, inXInt, inYInt, inWInt, inHInt): def SessionScreenSize_X_Y_W_H(inSessionHex, inXInt, inYInt, inWInt, inHInt):
#Prepare little window lDoBool = True
try: while lDoBool:
lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}]) #Prepare little window
except Exception as e: try:
return None lRDPWindow = UIDesktop.UIOSelector_Get_UIO([{"title_re": f"{inSessionHex}.*", "backend": "win32"}])
lRDPWindow.set_focus() except Exception as e:
if SessionIsFullScreen(inSessionHex): return None
lRDPWindow.type_keys("^%{BREAK}") try:
time.sleep(0.5) lRDPWindow.set_focus()
lRDPWindow.restore() if SessionIsFullScreen(inSessionHex):
time.sleep(0.5) lRDPWindow.type_keys("^%{BREAK}")
lRDPWindow.move_window(inXInt,inYInt,inWInt,inHInt) time.sleep(0.5)
lRDPWindow.restore()
time.sleep(0.5)
lRDPWindow.move_window(inXInt,inYInt,inWInt,inHInt)
except Exception as e:
time.sleep(1)
else:
lDoBool = False
return None return None
# Set Little window of the session # Set Little window of the session

@ -38,9 +38,10 @@ def RDPSessionConnect(inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPa
# Disconnect the RDP session # Disconnect the RDP session
def RDPSessionDisconnect(inRDPSessionKeyStr): def RDPSessionDisconnect(inRDPSessionKeyStr):
global gSettings global gSettings
lSessionHex = gSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"] lSessionHex = gSettings["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None) if lSessionHex:
Connector.SessionClose(inSessionHexStr=lSessionHex) gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
Connector.SessionClose(inSessionHexStr=lSessionHex)
return True return True
# RDP Session reconnect # RDP Session reconnect
@ -54,6 +55,19 @@ def RDPSessionReconnect(inRDPSessionKeyStr):
Connector.Session(lRDPConfigurationItem) Connector.Session(lRDPConfigurationItem)
return True return True
# Logoff the RDP session
def RDPSessionLogoff(inRDPSessionKeyStr):
global gSettings
lResult = True
lCMDStr = "shutdown -L" # CMD logoff command
# Calculate the session Hex
lSessionHex = gSettings["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
if lSessionHex:
gSettings["RobotRDPActive"]["RDPList"].pop(inRDPSessionKeyStr,None)
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN")
return lResult
# Check RDP Session responsibility TODO NEED DEV + TEST # Check RDP Session responsibility TODO NEED DEV + TEST
def RDPSessionResponsibilityCheck(inRDPSessionKeyStr): def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
global gSettings global gSettings
@ -81,72 +95,53 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr):
return True return True
# Start process if it is not running # Start process if it is not running
def RDPSessionProcessStartIfNotRunning(inRDPSessionKey, inProcessName, inFilePath, inFlagGetAbsPath=True): def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True):
global gSettings global gSettings
inGlobalDict = gSettings inGlobalDict = gSettings
lResult = True lResult = True
lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessName,inFilePath, inFlagGetAbsPath= inFlagGetAbsPath) lCMDStr = CMDStr.ProcessStartIfNotRunning(inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPath= inFlagGetAbsPathBool)
# Calculate the session Hex # Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"] lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Check is Session is responsible # Run CMD
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]: if lSessionHex:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN") 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 return lResult
# Create CMD str to stop process # Create CMD str to stop process
def RDPSessionProcessStop(inRDPSessionKey, inProcessName, inFlagForceClose): def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool):
global gSettings global gSettings
inGlobalDict = gSettings inGlobalDict = gSettings
lResult = True lResult = True
lCMDStr = f'taskkill /im "{inProcessName}" /fi "username eq %USERNAME%"' lCMDStr = f'taskkill /im "{inProcessNameWEXEStr}" /fi "username eq %USERNAME%"'
if inFlagForceClose: if inFlagForceCloseBool:
lCMDStr+= " /F" lCMDStr+= " /F"
# Calculate the session Hex # Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"] lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Check is Session is responsible # Run CMD
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]: if lSessionHex:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="RUN") 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 return lResult
# Send file from Host to Session RDP using shared drive in RDP # Send file from Host to Session RDP using shared drive in RDP
def RDPSessionFileStoredSend(inRDPSessionKey, inHostFilePath, inRDPFilePath): def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr):
global gSettings global gSettings
inGlobalDict = gSettings inGlobalDict = gSettings
lResult = True lResult = True
lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePath, inRDPFilePath = inRDPFilePath) lCMDStr = CMDStr.FileStoredSend(inHostFilePath = inHostFilePathStr, inRDPFilePath = inRDPFilePathStr)
# Calculate the session Hex # Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"] lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr, {}).get("SessionHex", None)
# Check is Session is responsible #lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr]["SessionHex"]
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]: # Run CMD
# Run CMD if lSessionHex:
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120) 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 return lResult
# Recieve file from Session RDP to Host using shared drive in RDP # Recieve file from Session RDP to Host using shared drive in RDP
def RDPSessionFileStoredRecieve(inRDPSessionKey, inRDPFilePath, inHostFilePath): def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr):
global gSettings global gSettings
inGlobalDict = gSettings inGlobalDict = gSettings
lResult = True lResult = True
lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePath, inHostFilePath = inHostFilePath) lCMDStr = CMDStr.FileStoredRecieve(inRDPFilePath = inRDPFilePathStr, inHostFilePath = inHostFilePathStr)
# Calculate the session Hex # Calculate the session Hex
lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionHex"] lSessionHex = inGlobalDict["RobotRDPActive"]["RDPList"].get(inRDPSessionKeyStr,{}).get("SessionHex", None)
# Check is Session is responsible # Run CMD
if inGlobalDict["RobotRDPActive"]["RDPList"][inRDPSessionKey]["SessionIsWindowResponsibleBool"]: if lSessionHex:
# Run CMD
Connector.SessionCMDRun(inSessionHex=lSessionHex, inCMDCommandStr=lCMDStr, inModeStr="LISTEN", inClipboardTimeoutSec = 120) 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 return lResult

@ -1,3 +1,11 @@
# inRequest.OpenRPA = {}
# inRequest.OpenRPA["AuthToken"] = None
# inRequest.OpenRPA["Domain"] = None
# inRequest.OpenRPA["User"] = None
# lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None}
# self.OpenRPAResponseDict = lResponseDict
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn from socketserver import ThreadingMixIn
import threading import threading
@ -78,6 +86,8 @@ def AuthenticateVerify(inRequest):
gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie #Set-cookie
inRequest.OpenRPA["AuthToken"] = lAuthToken inRequest.OpenRPA["AuthToken"] = lAuthToken
inRequest.OpenRPA["Domain"] = lResult["Domain"]
inRequest.OpenRPA["User"] = lResult["User"]
inRequest.OpenRPASetCookie = {} inRequest.OpenRPASetCookie = {}
#New engine of server #New engine of server
inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken

@ -32,10 +32,16 @@ def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
lResultJSON = {"RenderRobotList": []} lResultJSON = {"RenderRobotList": []}
lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"]
for lItem in lRenderFunctionsRobotList: for lItem in lRenderFunctionsRobotList:
# Выполнить вызов и записать результат lUACBool = True # Check if render function is applicable User Access Rights (UAC)
lItemResultDict = lItem["RenderFunction"](inGlobalDict) if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# RunFunction lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())]
lResultJSON["RenderRobotList"].append(lItemResultDict) if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]:
lUACBool = False # UAC Check is not passed - False for user
if lUACBool: # Run function if UAC is TRUE
# Выполнить вызов и записать результат
lItemResultDict = lItem["RenderFunction"](inGlobalDict)
# RunFunction
lResultJSON["RenderRobotList"].append(lItemResultDict)
# Send message back to client # Send message back to client
message = json.dumps(lResultJSON) message = json.dumps(lResultJSON)
# Write content as utf-8 data # Write content as utf-8 data

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs) The OpenRPA package (from UnicodeLabs)
""" """
__version__ = 'v1.0.42' __version__ = 'v1.1.0'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>' __author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot #from .Core import Robot

@ -1,3 +1,5 @@
[1.1.0]
After 2 month test prefinal with new improovements (+RobotRDPActive in Orchestrator + Easy ControlPanelTemplate)
Beta before 1.1.0 (new way of OpenRPA with improovments. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1 Beta before 1.1.0 (new way of OpenRPA with improovments. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1
[1.0.37] [1.0.37]
Minor fix in RobotRDPActive Minor fix in RobotRDPActive

Loading…
Cancel
Save