From 9a7fc13d9f0b925671447e090b9ea1dd8f9fbdef Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Fri, 2 Oct 2020 21:31:44 +0300 Subject: [PATCH] # in progress new orchestrator processor --- .../Settings/SettingsOrchestratorExample.py | 17 +- .../Orchestrator/BackwardCompatibility.py | 24 +- .../pyOpenRPA/Orchestrator/ControlPanel.py | 2 + Sources/pyOpenRPA/Orchestrator/Processor.py | 349 +++--------------- .../pyOpenRPA/Orchestrator/ProcessorOld.py | 301 +++++++++++++++ changelog.md | 7 + 6 files changed, 395 insertions(+), 305 deletions(-) create mode 100644 Sources/pyOpenRPA/Orchestrator/ControlPanel.py create mode 100644 Sources/pyOpenRPA/Orchestrator/ProcessorOld.py diff --git a/Orchestrator/Settings/SettingsOrchestratorExample.py b/Orchestrator/Settings/SettingsOrchestratorExample.py index 52030f51..e720dfff 100644 --- a/Orchestrator/Settings/SettingsOrchestratorExample.py +++ b/Orchestrator/Settings/SettingsOrchestratorExample.py @@ -256,12 +256,21 @@ def Settings(): } ] }, - "Processor": { - "LogType_CMDStart": True, #LogType_: if Trace for command is selected for False, the tracing will be off for such activity type. Default True - "LogList": [] #List of processor activity, which was executed. Fill list when orchestrator is running + "ProcessorDict": { # Has been changed. New general processor (one threaded) v.1.2.0 + "ActivityList": [ # List of the activities + # { + # "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + # "ArgGSettings": # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # }, + ], + "AliasDefDict": {}, # Storage for def with Str alias. To use it see pyOpenRPA.Orchestrator.ControlPanel + "CheckIntervalSecFloat": 1.0, # Interval for check gSettings in ProcessorDict > ActivityList + "ExecuteBool": True # Flag to execute thread processor }, "ControlPanelDict": { - "RefreshSeconds": 5, + "RefreshSeconds": 5, # deprecated parameter "RobotList": [ { "RenderFunction": RenderRobotR01, diff --git a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py index 763119c8..187feb5d 100644 --- a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py +++ b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py @@ -40,4 +40,26 @@ def Update(inGSettings): f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property") # Log about compatibility if "DefSettingsUpdatePathList" not in inGSettings["OrchestratorStart"]: # Add OrchestratorStart > "DefSettingsUpdatePathList" property inGSettings["OrchestratorStart"]["DefSettingsUpdatePathList"] = [] # List of the .py files which should be loaded before init the algorythms - if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list") # Log about compatibility \ No newline at end of file + if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list") # Log about compatibility + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # v1.1.20 to v1.2.0 + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Update Structure gSettings["Processor"] + if "Processor" in inGSettings: # Check if Processor exist + del inGSettings["Processor"] # Remove the key + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Remove old structure 'Processor'") # Log about compatibility + if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure + inGSettings["ProcessorDict"]={ + "ActivityList": [ # List of the activities + # { + # "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + # "ArgGSettings": # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # }, + ], + "AliasDefDict": {} , # Storage for def with Str alias. To use it see pyOpenRPA.Orchestrator.ControlPanel + "CheckIntervalSecFloat": 1.0, # Interval for check gSettings in ProcessorDict > ActivityList + "ExecuteBool": True # Flag to execute thread processor + } + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new structure 'ProcessorDict'") # Log about compatibility \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/ControlPanel.py b/Sources/pyOpenRPA/Orchestrator/ControlPanel.py new file mode 100644 index 00000000..283b94f5 --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/ControlPanel.py @@ -0,0 +1,2 @@ +# Defs to use in ControlPanel files to render panels (busines users + technical user manipulations) + diff --git a/Sources/pyOpenRPA/Orchestrator/Processor.py b/Sources/pyOpenRPA/Orchestrator/Processor.py index 2e64edb8..e14eec4d 100644 --- a/Sources/pyOpenRPA/Orchestrator/Processor.py +++ b/Sources/pyOpenRPA/Orchestrator/Processor.py @@ -1,301 +1,50 @@ -import datetime -import http.client -import json -import pdb -import os -import sys -import subprocess -import importlib -import psutil -#Input arg -# [ -# { -# "Type": , -# host: , -# port: , -# bodyObject: -# }, -# { -# "Type": "CMDStart", -# "Command": "" -# }, -# { -# "Type": "OrchestratorRestart" -# }, -# { -# "Type": "OrchestratorSessionSave" -# }, -# { -# "Type": "GlobalDictKeyListValueSet", -# "KeyList": ["key1","key2",...], -# "Value": -# }, -# { -# "Type": "GlobalDictKeyListValueAppend", -# "KeyList": ["key1","key2",...], -# "Value": -# }, -# { -# "Type": "GlobalDictKeyListValueOperator+", -# "KeyList": ["key1","key2",...], -# "Value": -# }, -# { -# "Type": "GlobalDictKeyListValueGet", -# "KeyList": ["key1","key2",...] -# }, -# { -# "Type":"ProcessStart", -# "Path":"", -# "ArgList":[] -# }, -# { -# "Type":"ProcessStartIfTurnedOff", -# "CheckTaskName":"", #Check if current task name is not active (then start process), -# "Path":"", -# "ArgList":[] -# }, -# { -# "Type":"ProcessStop", -# "Name":"", -# "FlagForce":True, -# "User":"" #Empty - all users, user or %username% -# }, -# { -# "Type":"PythonStart", -# "ModuleName":"", -# "FunctionName":"", -# "ArgList":[], -# "ArgDict":{} -# }, -# { -# "Type":"WindowsLogon", -# "Domain":"", -# "User":"", -# "Password":"" -# # Return "Result": True - user is logged on, False - user is not logged on -# } -# ] -################################## -#Output result -# with attributes: -# "DateTimeUTCStringStart" -# "DateTimeUTCStringStop" -# "Result" -gSettingsDict = None -def Activity(inActivity): - #Глобальная переменная - глобальный словарь унаследованный от Settings.py - global gSettingsDict - lL = gSettingsDict["Logger"] # Alias for logger - #Alias (compatibility) - lItem = inActivity - lCurrentDateTime = datetime.datetime.now() - ########################################################### - #Обработка запроса на отправку команды на удаленную машину - ########################################################### - if lItem["Type"]=="RemoteMachineProcessingRun": - lHTTPConnection = http.client.HTTPConnection(lItem["host"], lItem["port"], timeout=5) - try: - lHTTPConnection.request("POST","/ProcessingRun",json.dumps(lItem["bodyObject"])) - except Exception as e: - #Объединение словарей - lItem["Result"] = {"State":"disconnected","ExceptionString":str(e)} - else: - lHTTPResponse=lHTTPConnection.getresponse() - lHTTPResponseByteArray=lHTTPResponse.read() - lItem["Result"] = json.loads(lHTTPResponseByteArray.decode('utf8')) - ########################################################### - #Обработка команды CMDStart - ########################################################### - if lItem["Type"]=="CMDStart": - lCMDCode="cmd /c "+lItem["Command"] - subprocess.Popen(lCMDCode) - lResultCMDRun=1#os.system(lCMDCode) - lItem["Result"] = str(lResultCMDRun) - ########################################################### - #Обработка команды OrchestratorRestart - ########################################################### - if lItem["Type"]=="OrchestratorRestart": - # Dump RDP List in file json - lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") - lFile.write(json.dumps(gSettingsDict["RobotRDPActive"]["RDPList"])) # dump json to file - lFile.close() # Close the file - if lL: lL.info(f"Orchestrator has dump the RDP list before the restart. The RDP List is {gSettingsDict['RobotRDPActive']['RDPList']}. Do restart") - # Restart session - os.execl(sys.executable, os.path.abspath(__file__), *sys.argv) - lItem["Result"] = True - sys.exit(0) - ########################################################### - # Обработка команды OrchestratorSessionSave - ########################################################### - if lItem["Type"] == "OrchestratorSessionSave": - # Dump RDP List in file json - lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") - lFile.write(json.dumps(gSettingsDict["RobotRDPActive"]["RDPList"])) # dump json to file - lFile.close() # Close the file - if lL: lL.info( - f"Orchestrator has dump the RDP list before the restart. The RDP List is {gSettingsDict['RobotRDPActive']['RDPList']}") - lItem["Result"] = True - ########################################################### - #Обработка команды GlobalDictKeyListValueSet - ########################################################### - if lItem["Type"]=="GlobalDictKeyListValueSet": - 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]]=lItem["Value"] - lItem["Result"] = True - ########################################################### - # Обработка команды GlobalDictKeyListValueAppend - ########################################################### - if lItem["Type"] == "GlobalDictKeyListValueAppend": - lDict = gSettingsDict - for lItem2 in lItem["KeyList"][:-1]: - # Check if key - value exists - if lItem2 in lDict: - pass - else: - lDict[lItem2] = {} - lDict = lDict[lItem2] - # Set value - lDict[lItem["KeyList"][-1]].append(lItem["Value"]) - lItem["Result"] = True - ########################################################### - # Обработка команды GlobalDictKeyListValueOperator+ - ########################################################### - if lItem["Type"] == "GlobalDictKeyListValueOperator+": - 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]]+=lItem["Value"] - lItem["Result"] = True - ########################################################### - #Обработка команды GlobalDictKeyListValueGet - ########################################################### - if lItem["Type"]=="GlobalDictKeyListValueGet": - lDict = gSettingsDict - for lItem2 in lItem["KeyList"][:-1]: - #Check if key - value exists - if lItem2 in lDict: - pass - else: - lDict[lItem2]={} - lDict=lDict[lItem2] - #Return value - lItem["Result"]=lDict.get(lItem["KeyList"][-1],None) - ##################################### - #ProcessStart - ##################################### - if lItem["Type"]=="ProcessStart": - #Вид активности - запуск процесса - #Запись в массив отработанных активностей - #Запустить процесс - lItemArgs=[lItem["Path"]] - lItemArgs.extend(lItem["ArgList"]) - subprocess.Popen(lItemArgs,shell=True) - ##################################### - #ProcessStartIfTurnedOff - ##################################### - if lItem["Type"]=="ProcessStartIfTurnedOff": - #Check if process running - #remove .exe from Taskname if exists - lCheckTaskName = lItem["CheckTaskName"] - if len(lCheckTaskName)>4: - if lCheckTaskName[-4:].upper() != ".EXE": - lCheckTaskName = lCheckTaskName+".exe" - else: - lCheckTaskName = lCheckTaskName+".exe" - #Check if process exist - if not CheckIfProcessRunning(lCheckTaskName): - #Вид активности - запуск процесса - #Запись в массив отработанных активностей - #Запустить процесс - lItemArgs=[lItem["Path"]] - lItemArgs.extend(lItem["ArgList"]) - subprocess.Popen(lItemArgs,shell=True) - ################################# - #ProcessStop - ################################# - if lItem["Type"]=="ProcessStop": - #Вид активности - остановка процесса - #часовой пояс пока не учитываем - #Сформировать команду на завершение - lActivityCloseCommand='taskkill /im '+lItem["Name"] - #TODO Сделать безопасную обработку,если параметра нет в конфигурации - if lItem.get('FlagForce',False): - lActivityCloseCommand+=" /F" - #Завершить процессы только текущего пользоваиеля - if lItem.get('User',"")!="": - lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"' - #Завершить процесс - os.system(lActivityCloseCommand) - ################################# - #PythonStart - ################################# - if lItem["Type"]=="PythonStart": - try: - #Подключить модуль для вызова - lModule=importlib.import_module(lItem["ModuleName"]) - #Найти функцию - lFunction=getattr(lModule,lItem["FunctionName"]) - lItem["Result"]=lFunction(*lItem.get("ArgList",[]),**lItem.get("ArgDict",{})) - except Exception as e: - if lL: lL.exception("Loop activity error: module/function not founded") - ################################# - # Windows logon - ################################# - if lItem["Type"] == "WindowsLogon": - import win32security - try: - hUser = win32security.LogonUser( - lItem["User"], - lItem["Domain"], - lItem["Password"], - win32security.LOGON32_LOGON_NETWORK, - win32security.LOGON32_PROVIDER_DEFAULT - ) - except win32security.error: - lItem["Result"] = False - else: - lItem["Result"] = True - ################################### - #Вернуть результат - return lItem +# 1.2.0 - general processor - contains old orchestrator processor + RDPActive processor +import time, copy +# Run processor synchronious +def ProcessorRunSync(inGSettings): + """ + "ProcessorDict": { # Has been changed. New general processor (one threaded) v.1.2.0 + "ActivityList": [ # List of the activities + # { + # "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + # "ArgGSettings": # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # }, + ], + "AliasDefDict": {}, # Storage for def with Str alias. To use it see pyOpenRPA.Orchestrator.ControlPanel + "CheckIntervalSecFloat": 1.0 # Interval for check gSettings in ProcessorDict > ActivityList + "ExecuteBool": True # Flag to execute thread processor + """ + while inGSettings["ProcessorDict"]["ExecuteBool"]: + lActivityItem = inGSettings["ProcessorDict"]["ActivityList"].pop(0, None) # Extract the first item from processor queue + while lActivityItem is not None: + ActivityListExecute(inGSettings = inGSettings, inActivityList = [lActivityItem]) # execute the activity item + time.sleep(inGSettings["ProcessorDict"]["CheckIntervalSecFloat"]) # Sleep when list is empty -def ActivityListOrDict(inActivityListOrDict): - #Check arg type (list or dict) - if type(inActivityListOrDict)==list: - #List activity - lResult=[] - for lItem in inActivityListOrDict: - lResult.append(Activity(lItem)) - return lResult - if type(inActivityListOrDict)==dict: - #Dict activity - return Activity(inActivityListOrDict) - -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; \ No newline at end of file +# Execute ActivityItem list +# return the def result +def ActivityListExecute(inGSettings, inActivityList): + lL = inGSettings["Logger"] # Logger alias + lResultList = [] # init the result list + for lActivityItem in inActivityList: # Iterate throught the activity list + lDef = None # Def variable + if callable(lActivityItem["Def"]): # CHeck if def is callable + lDef = lActivityItem["Def"] # Get the def + else: # Is not callable - check alias + lDef = inGSettings["ProcessorDict"]["AliasDefDict"].pop(lActivityItem["Def"], None) # get def if def key in Alias def storage + # + lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None) + # # Prepare arg dict + if type(lGSettingsDictKey) is str: # check if gSetting key is in ArgDict + lActivityItem["ArgDict"]["lGSettingsDictKey"] = inGSettings # Set the gSettings in dict + # # Prepare arg list + elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict + lActivityItem["ArgList"].insert(lGSettingsDictKey,inGSettings)# Set the gSettings in list by the index + try: # try to run function from Processor.py + lActivityItemResult = lDef(*lActivityItem["ArgList"], **lActivityItem["ArgDict"]) + lResultList.append(lActivityItemResult) # return the result + except Exception as e: + if lL: lL.exception(f"Processor.ActivityListExecute: Exception in def execution - activity will be ignored. Activity item: {lActivityItem}") # Logging + lResultList.append(e) # return the generated exception + return lResultList # return the result list \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/ProcessorOld.py b/Sources/pyOpenRPA/Orchestrator/ProcessorOld.py new file mode 100644 index 00000000..2e64edb8 --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/ProcessorOld.py @@ -0,0 +1,301 @@ +import datetime +import http.client +import json +import pdb +import os +import sys +import subprocess +import importlib +import psutil +#Input arg +# [ +# { +# "Type": , +# host: , +# port: , +# bodyObject: +# }, +# { +# "Type": "CMDStart", +# "Command": "" +# }, +# { +# "Type": "OrchestratorRestart" +# }, +# { +# "Type": "OrchestratorSessionSave" +# }, +# { +# "Type": "GlobalDictKeyListValueSet", +# "KeyList": ["key1","key2",...], +# "Value": +# }, +# { +# "Type": "GlobalDictKeyListValueAppend", +# "KeyList": ["key1","key2",...], +# "Value": +# }, +# { +# "Type": "GlobalDictKeyListValueOperator+", +# "KeyList": ["key1","key2",...], +# "Value": +# }, +# { +# "Type": "GlobalDictKeyListValueGet", +# "KeyList": ["key1","key2",...] +# }, +# { +# "Type":"ProcessStart", +# "Path":"", +# "ArgList":[] +# }, +# { +# "Type":"ProcessStartIfTurnedOff", +# "CheckTaskName":"", #Check if current task name is not active (then start process), +# "Path":"", +# "ArgList":[] +# }, +# { +# "Type":"ProcessStop", +# "Name":"", +# "FlagForce":True, +# "User":"" #Empty - all users, user or %username% +# }, +# { +# "Type":"PythonStart", +# "ModuleName":"", +# "FunctionName":"", +# "ArgList":[], +# "ArgDict":{} +# }, +# { +# "Type":"WindowsLogon", +# "Domain":"", +# "User":"", +# "Password":"" +# # Return "Result": True - user is logged on, False - user is not logged on +# } +# ] +################################## +#Output result +# with attributes: +# "DateTimeUTCStringStart" +# "DateTimeUTCStringStop" +# "Result" +gSettingsDict = None +def Activity(inActivity): + #Глобальная переменная - глобальный словарь унаследованный от Settings.py + global gSettingsDict + lL = gSettingsDict["Logger"] # Alias for logger + #Alias (compatibility) + lItem = inActivity + lCurrentDateTime = datetime.datetime.now() + ########################################################### + #Обработка запроса на отправку команды на удаленную машину + ########################################################### + if lItem["Type"]=="RemoteMachineProcessingRun": + lHTTPConnection = http.client.HTTPConnection(lItem["host"], lItem["port"], timeout=5) + try: + lHTTPConnection.request("POST","/ProcessingRun",json.dumps(lItem["bodyObject"])) + except Exception as e: + #Объединение словарей + lItem["Result"] = {"State":"disconnected","ExceptionString":str(e)} + else: + lHTTPResponse=lHTTPConnection.getresponse() + lHTTPResponseByteArray=lHTTPResponse.read() + lItem["Result"] = json.loads(lHTTPResponseByteArray.decode('utf8')) + ########################################################### + #Обработка команды CMDStart + ########################################################### + if lItem["Type"]=="CMDStart": + lCMDCode="cmd /c "+lItem["Command"] + subprocess.Popen(lCMDCode) + lResultCMDRun=1#os.system(lCMDCode) + lItem["Result"] = str(lResultCMDRun) + ########################################################### + #Обработка команды OrchestratorRestart + ########################################################### + if lItem["Type"]=="OrchestratorRestart": + # Dump RDP List in file json + lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") + lFile.write(json.dumps(gSettingsDict["RobotRDPActive"]["RDPList"])) # dump json to file + lFile.close() # Close the file + if lL: lL.info(f"Orchestrator has dump the RDP list before the restart. The RDP List is {gSettingsDict['RobotRDPActive']['RDPList']}. Do restart") + # Restart session + os.execl(sys.executable, os.path.abspath(__file__), *sys.argv) + lItem["Result"] = True + sys.exit(0) + ########################################################### + # Обработка команды OrchestratorSessionSave + ########################################################### + if lItem["Type"] == "OrchestratorSessionSave": + # Dump RDP List in file json + lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") + lFile.write(json.dumps(gSettingsDict["RobotRDPActive"]["RDPList"])) # dump json to file + lFile.close() # Close the file + if lL: lL.info( + f"Orchestrator has dump the RDP list before the restart. The RDP List is {gSettingsDict['RobotRDPActive']['RDPList']}") + lItem["Result"] = True + ########################################################### + #Обработка команды GlobalDictKeyListValueSet + ########################################################### + if lItem["Type"]=="GlobalDictKeyListValueSet": + 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]]=lItem["Value"] + lItem["Result"] = True + ########################################################### + # Обработка команды GlobalDictKeyListValueAppend + ########################################################### + if lItem["Type"] == "GlobalDictKeyListValueAppend": + lDict = gSettingsDict + for lItem2 in lItem["KeyList"][:-1]: + # Check if key - value exists + if lItem2 in lDict: + pass + else: + lDict[lItem2] = {} + lDict = lDict[lItem2] + # Set value + lDict[lItem["KeyList"][-1]].append(lItem["Value"]) + lItem["Result"] = True + ########################################################### + # Обработка команды GlobalDictKeyListValueOperator+ + ########################################################### + if lItem["Type"] == "GlobalDictKeyListValueOperator+": + 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]]+=lItem["Value"] + lItem["Result"] = True + ########################################################### + #Обработка команды GlobalDictKeyListValueGet + ########################################################### + if lItem["Type"]=="GlobalDictKeyListValueGet": + lDict = gSettingsDict + for lItem2 in lItem["KeyList"][:-1]: + #Check if key - value exists + if lItem2 in lDict: + pass + else: + lDict[lItem2]={} + lDict=lDict[lItem2] + #Return value + lItem["Result"]=lDict.get(lItem["KeyList"][-1],None) + ##################################### + #ProcessStart + ##################################### + if lItem["Type"]=="ProcessStart": + #Вид активности - запуск процесса + #Запись в массив отработанных активностей + #Запустить процесс + lItemArgs=[lItem["Path"]] + lItemArgs.extend(lItem["ArgList"]) + subprocess.Popen(lItemArgs,shell=True) + ##################################### + #ProcessStartIfTurnedOff + ##################################### + if lItem["Type"]=="ProcessStartIfTurnedOff": + #Check if process running + #remove .exe from Taskname if exists + lCheckTaskName = lItem["CheckTaskName"] + if len(lCheckTaskName)>4: + if lCheckTaskName[-4:].upper() != ".EXE": + lCheckTaskName = lCheckTaskName+".exe" + else: + lCheckTaskName = lCheckTaskName+".exe" + #Check if process exist + if not CheckIfProcessRunning(lCheckTaskName): + #Вид активности - запуск процесса + #Запись в массив отработанных активностей + #Запустить процесс + lItemArgs=[lItem["Path"]] + lItemArgs.extend(lItem["ArgList"]) + subprocess.Popen(lItemArgs,shell=True) + ################################# + #ProcessStop + ################################# + if lItem["Type"]=="ProcessStop": + #Вид активности - остановка процесса + #часовой пояс пока не учитываем + #Сформировать команду на завершение + lActivityCloseCommand='taskkill /im '+lItem["Name"] + #TODO Сделать безопасную обработку,если параметра нет в конфигурации + if lItem.get('FlagForce',False): + lActivityCloseCommand+=" /F" + #Завершить процессы только текущего пользоваиеля + if lItem.get('User',"")!="": + lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"' + #Завершить процесс + os.system(lActivityCloseCommand) + ################################# + #PythonStart + ################################# + if lItem["Type"]=="PythonStart": + try: + #Подключить модуль для вызова + lModule=importlib.import_module(lItem["ModuleName"]) + #Найти функцию + lFunction=getattr(lModule,lItem["FunctionName"]) + lItem["Result"]=lFunction(*lItem.get("ArgList",[]),**lItem.get("ArgDict",{})) + except Exception as e: + if lL: lL.exception("Loop activity error: module/function not founded") + ################################# + # Windows logon + ################################# + if lItem["Type"] == "WindowsLogon": + import win32security + try: + hUser = win32security.LogonUser( + lItem["User"], + lItem["Domain"], + lItem["Password"], + win32security.LOGON32_LOGON_NETWORK, + win32security.LOGON32_PROVIDER_DEFAULT + ) + except win32security.error: + lItem["Result"] = False + else: + lItem["Result"] = True + ################################### + #Вернуть результат + return lItem + +def ActivityListOrDict(inActivityListOrDict): + #Check arg type (list or dict) + if type(inActivityListOrDict)==list: + #List activity + lResult=[] + for lItem in inActivityListOrDict: + lResult.append(Activity(lItem)) + return lResult + if type(inActivityListOrDict)==dict: + #Dict activity + return Activity(inActivityListOrDict) + +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; \ No newline at end of file diff --git a/changelog.md b/changelog.md index 4e9bfb1a..6adbdf74 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,10 @@ +[1.2.0] +- Consolidated processor from old orchestrator and from RDPActive processor (one threaded). Look in GSettings +- - Support old orchestrator structure Processor. +- - Support orchestrator start +- - Support scheduler +- - Support old items +- Backward compatibility from 1.1.13 [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