#1.0.25 #Safe call #UIDesktop (no Robot.py is needed) #Need test

dev-linux
Ivan Maslov 5 years ago
parent 3abf2b1761
commit e00eb589ac

8
.gitignore vendored

@ -3,11 +3,11 @@
#Игнорируем папки распакованного блокнота #Игнорируем папки распакованного блокнота
/**/Resources/Editor/Notepad++_7_7_x64/* /**/Resources/Editor/Notepad++_7_7_x64/*
/**/Resources/Editor/Notepad++_7_7_x32/* /**/Resources/Editor/Notepad++_7_7_x32/*
/**/Orchestrator/Reports /**/Orchestrator/**/Reports
/**/Sources/Reports /**/Robot/**/Reports
/**/Sources/build /**/Sources/build
/**/Sources/dist /**/Sources/dist
/**/Studio/Reports /**/Studio/**/Reports
/**/OpenRPA_Orchestrator.exe /**/OpenRPA_Orchestrator.exe
/**/OpenRPAOrchestrator.exe /**/OpenRPAOrchestrator.exe
/**/OpenRPARobotGUIx32.exe /**/OpenRPARobotGUIx32.exe
@ -16,5 +16,5 @@
/**/OpenRPARobot.exe /**/OpenRPARobot.exe
/**/breakpoints.lst /**/breakpoints.lst
/**/Orchestrator/screenshot.png /**/Orchestrator/screenshot.png
.idea/** **/.idea/**
/**/screenshot.png /**/screenshot.png

@ -0,0 +1,16 @@
import keyboard
import subprocess
import time
import Settings
import sys
sys.path.insert(0,"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Sources")
from pyOpenRPA.Robot import UIDesktop #OpenRPA UIDesktop
global mSettingsDict
mSettingsDict = Settings.Settings()
#UIDesktop initialization
UIDesktop.Utils.ProcessBitness.SettingsInit(mSettingsDict.get("pyOpenRPA",{}).get("Robot",{}).get("UIDesktop",{}).get("Utils",{}).get("ProcessBitness",None))
#Robot script
#UIDesktop.UIOSelector_Get_UIO([{"title_re":".*Configu.*", "backend":"uia"}]).draw_outline()
UIDesktop.UIOSelectorUIOActivity_Run_Dict([{"title_re":".*Configu.*", "backend":"uia"}],"draw_outline")

@ -0,0 +1,3 @@
cd %~dp0
..\..\..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe "Script.py"
pause >nul

@ -0,0 +1,18 @@
def Settings():
lResult={
"pyOpenRPA":{
"Robot":{
"UIDesktop":{
"Utils":{
"ProcessBitness":{
"Python32FullPath": "..\\..\\..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
"Python64FullPath": None, #Set from user
"Python32ProcessName": "OpenRPA_UIDesktopX32.exe", #Config set once
"Python64ProcessName": "OpenRPA_UIDesktopX64.exe" #Config set once
}
}
}
}
}
}
return lResult

@ -1,81 +0,0 @@
import pywinauto #Is needed to detect OS bitness
import struct # Need to detect Current process bitness
import subprocess #Need to create subprocess
import os # Is needed to check file/folder path
############################################
####Module, which control the Bitness between 32 and 64 python (needed for pywinauto framework to work correctly)
############################################
global mSettingsDict
mSettingsDict = {
"BitnessProcessCurrent": "64", # "64" or "32"
"BitnessOS": "64", # "64" or "32"
"Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
"Python64FullPath": None, #Set from user
"Python32ProcessName": "OpenRPAUIDesktopX32.exe", #Config set once
"Python64ProcessName": "OpenRPAUIDesktopX64.exe", #Config set once
"Python32Process":None,
"Python64Process":None,
"PythonArgs":["-m","pyOpenRPA"] #Start other bitness openRPA process with PIPE channel
}
#Init the global configuration
def SettingsInit(inSettingsDict):
global mSettingsDict
#Update values in settings from input
mSettingsDict.update(inSettingsDict)
#mSettingsDict = inSettingsDict
####################
#Detect OS bitness
####BitnessOS#######
lBitnessOS="32";
if pywinauto.sysinfo.is_x64_OS():
lBitnessOS="64";
inSettingsDict["BitnessOS"]=lBitnessOS
####################
#Detect current process bitness
####BitnessProcessCurrent#######
lBitnessProcessCurrent = str(struct.calcsize("P") * 8)
inSettingsDict["BitnessProcessCurrent"]=lBitnessProcessCurrent
#####################################
#Create the other bitness process if OS is 64 and we have another Python path
##########################################################################
#Check if OS is x64, else no 64 is applicable
if mSettingsDict["BitnessOS"]=="64":
#Check if current bitness is 64
if mSettingsDict["BitnessProcessCurrent"]=="64":
#create x32 if Python 32 path is exists
if mSettingsDict["Python32FullPath"] and mSettingsDict["Python32ProcessName"]:
#Calculate python.exe folder path
lPython32FolderPath= "\\".join(mSettingsDict["Python32FullPath"].split("\\")[:-1])
lPython32NewNamePath = f"{lPython32FolderPath}\\{mSettingsDict["Python32ProcessName"]}"
if not os.path.isfile(lPython32NewNamePath):
shutil.copyfile(mSettingsDict["Python32FullPath"],lPython32NewNamePath)
mSettingsDict["Python32Process"] = subprocess.Popen([lPython32NewNamePath] + mSettingsDict["Python32FullPath"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
else:
#bitness current process is 32
#return x64 if it is exists
if mSettingsDict["Python64Process"]:
#Calculate python.exe folder path
lPython64FolderPath= "\\".join(mSettingsDict["Python64FullPath"].split("\\")[:-1])
lPython64NewNamePath = f"{lPython64FolderPath}\\{mSettingsDict["Python64ProcessName"]}"
if not os.path.isfile(lPython64NewNamePath):
shutil.copyfile(mSettingsDict["Python32FullPath"],lPython64NewNamePath)
mSettingsDict["Python64Process"] = subprocess.Popen([lPython64NewNamePath] + mSettingsDict["Python64FullPath"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
#Return the other module bitnes
def OtherBitnessGet():
#Result template
lResult = None
global mSettingsDict
#Check if OS is x64, else no 64 is applicable
if mSettingsDict["BitnessOS"]=="64":
#Check if current bitness is 64
if mSettingsDict["BitnessProcessCurrent"]=="64":
#return x32 if it is exists
if mSettingsDict["Python32Process"]:
lResult = mSettingsDict["Python32Process"]
else:
#bitness current process is 32
#return x64 if it is exists
if mSettingsDict["Python64Process"]:
lResult = mSettingsDict["Python64Process"]
#Exit
return lResult

@ -14,6 +14,7 @@ import time
import traceback import traceback
from . import ProcessCommunicator from . import ProcessCommunicator
from . import JSONNormalize from . import JSONNormalize
from . import Utils #For ProcessBitness
from threading import Timer from threading import Timer
import datetime import datetime
import logging import logging
@ -34,7 +35,16 @@ mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter) mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object # add handler to logger object
mRobotLogger.addHandler(mRobotLoggerFH) mRobotLogger.addHandler(mRobotLoggerFH)
############################################
#When import UIDesktop init the other bitness python
#For this type UIDesktop.Utils.ProcessBitness.SettingsInit(inSettingsDict)
#inSettingsDict = {
# "Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
# "Python64FullPath": None, #Set from user
# "Python32ProcessName": "OpenRPAUIDesktopX32.exe", #Config set once
# "Python64ProcessName": "OpenRPAUIDesktopX64.exe" #Config set once
#}
############################################
#logging.basicConfig(filename="Reports\ReportRobotGUIRun_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") #logging.basicConfig(filename="Reports\ReportRobotGUIRun_"+datetime.datetime.now().strftime("%Y_%m_%d")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
@ -258,14 +268,32 @@ def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException
return lResult return lResult
################################################################################################# #################################################################################################
#Check if UIO exist (Identified by the UIOSelector) #Check if UIO exist (Identified by the UIOSelector)
#inSpecificationList - UIOSelector #!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#UIOSelector
#old name - - #old name - -
def UIOSelector_Exist_Bool (inSpecificationList): def UIOSelector_Exist_Bool (inUIOSelector):
lResult=False lResult=False
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Получить родительский объект если на вход ничего не поступило #Получить родительский объект если на вход ничего не поступило
lResultList=UIOSelector_Get_UIOList(inSpecificationList,None,False) lResultList=UIOSelector_Get_UIOList(inUIOSelector, None, False)
if len(lResultList)>0: if len(lResultList)>0:
lResult=True lResult=True
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool",
"ArgumentList": [inUIOSelector],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lResult = lPIPEResponseDict["Result"]
return lResult return lResult
################################################################################################# #################################################################################################
#Wait for UIO is appear (at least one of them or all at the same time) #Wait for UIO is appear (at least one of them or all at the same time)
@ -385,6 +413,21 @@ def UIOSelector_Get_BitnessInt (inSpecificationList):
lResult=32 lResult=32
return lResult return lResult
################################################################################################# #################################################################################################
#Get process bitness ("32" or "64")
#inSpecificationList - UIOSelector
#old name - None
#return None (if Process not found), int 32, or int 64
def UIOSelector_Get_BitnessStr (inSpecificationList):
lResult=None
#Получить объект Application (Для проверки разрядности)
lRootElement=PWASpecification_Get_PWAApplication(inSpecificationList)
if lRootElement is not None:
if lRootElement.is64bit():
lResult="64"
else:
lResult="32"
return lResult
#################################################################################################
#Get OS bitness (32 or 64) #Get OS bitness (32 or 64)
#old name - None #old name - None
#return int 32, or int 64 #return int 32, or int 64
@ -393,6 +436,18 @@ def Get_OSBitnessInt ():
if pywinauto.sysinfo.is_x64_OS(): if pywinauto.sysinfo.is_x64_OS():
lResult=64; lResult=64;
return lResult; return lResult;
#################################################################################################
#Safe get other process or None if destination app is the other/same bitness
#inUIOSelector - selector of the destination
#return None or process (of the other bitness)
def UIOSelector_SafeOtherGet_Process(inUIOSelector):
#Default value
lResult = None
#Get selector bitness
lUIOSelectorAppBitness = UIOSelector_Get_BitnessStr(inUIOSelector)
if lUIOSelectorAppBitness and Utils.ProcessBitness.mSettingsDict["BitnessProcessCurrent"] != lUIOSelectorAppBitness:
lResult = Utils.ProcessBitness.OtherProcessGet()
return lResult
################################################################################################## ##################################################################################################
#inControlSpecificationArray - List of dict, dict in pywinauto.find_windows notation #inControlSpecificationArray - List of dict, dict in pywinauto.find_windows notation
#Backend selection - attribute "backend" ("win32" || "uia") in 1-st list element #Backend selection - attribute "backend" ("win32" || "uia") in 1-st list element
@ -523,11 +578,15 @@ def UIOSelector_SearchChildByMouse_UIO(inElementSpecification):
#################################################################################################### ####################################################################################################
#inElementSpecification - UIOSelector #inElementSpecification - UIOSelector
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#old name - AutomationSearchMouseElementHierarchy #old name - AutomationSearchMouseElementHierarchy
def UIOSelector_SearchChildByMouse_UIOTree(inElementSpecification): def UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector):
lItemInfo = [] lItemInfo = []
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Запустить функцию поиска элемента по мыши #Запустить функцию поиска элемента по мыши
lElementList = UIOSelector_SearchChildByMouse_UIO(inElementSpecification) lElementList = UIOSelector_SearchChildByMouse_UIO(inUIOSelector)
lElement = lElementList[-1]['element'] lElement = lElementList[-1]['element']
#Detect backend of the elements #Detect backend of the elements
lFlagIsBackendWin32 = True lFlagIsBackendWin32 = True
@ -565,6 +624,20 @@ def UIOSelector_SearchChildByMouse_UIOTree(inElementSpecification):
lListIterator=lListIterator+1 lListIterator=lListIterator+1
#Добавить информацию о Backend в первый объект #Добавить информацию о Backend в первый объект
lItemInfo[0]["backend"]=lElement.backend.name lItemInfo[0]["backend"]=lElement.backend.name
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_SearchChildByMouse_UIOTree",
"ArgumentList": [inUIOSelector],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lItemInfo = lPIPEResponseDict["Result"]
#Вернуть результат #Вернуть результат
return lItemInfo return lItemInfo
#################################################################################################### ####################################################################################################
@ -600,41 +673,36 @@ def UIO_GetCtrlIndex_Int(inElement):
return lResult return lResult
#################################################################################################### ####################################################################################################
#Получить список информационных объектов, который удовлетворяет условиям # Get the UIO Info list for the selected criteria
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#inSpecificationList - UIOSelector #inSpecificationList - UIOSelector
#old name - PywinautoExtElementsGetInfo #old name - PywinautoExtElementsGetInfo
def UIOSelector_Get_UIOInfoList (inSpecificationList,inElement=None): def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None):
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Получить родительский объект если на вход ничего не поступило #Получить родительский объект если на вход ничего не поступило
lResultList=UIOSelector_Get_UIOList(inSpecificationList,inElement) lResultList=UIOSelector_Get_UIOList(inUIOSelector, inElement)
lIterator = 0 lIterator = 0
for lItem in lResultList: for lItem in lResultList:
lResultList[lIterator]=UIOEI_Convert_UIOInfo(lResultList[lIterator].element_info) lResultList[lIterator]=UIOEI_Convert_UIOInfo(lResultList[lIterator].element_info)
lIterator = lIterator + 1 lIterator = lIterator + 1
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Get_UIOInfoList",
"ArgumentList": [inUIOSelector, inElement],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lResultList = lPIPEResponseDict["Result"]
return lResultList return lResultList
####################################################################################################
#Check is the UIO/UIO's by the UIOSelector exist
#inSpecificationList - UIOSelector
#old name - PywinautoExtElementExist
def UIOSelector_IsExist_Bool (inSpecificationList):
return len(UIOSelector_Get_UIOList(inSpecificationList))>0
####################################################################################################
#Wait for the UIO by the UIOSelector appear
#inSpecificationList - UIOSelector
#result - { }
#old name - PywinautoExtElementWaitAppear
#############
#Внимание! Старая функция (на замену ей пришла UIOSelectorSecs_WaitAppear_Bool)
#############
def UIOSelector_WaitAppear_Dict(inSpecificationList,inTimeout=60):
lTimeoutSeconds = 0
while (not UIOSelector_IsExist_Bool(inSpecificationList) and inTimeout>lTimeoutSeconds):
lTimeoutSeconds = lTimeoutSeconds + 0.5
#Заснуть на полсекунды
time.sleep(0.5)
return UIOSelector_IsExist_Bool(inSpecificationList)
#################################################################################################### ####################################################################################################
#Try to restore (maximize) window, if it's was minimized #Try to restore (maximize) window, if it's was minimized
#(особенность uia backend - он не может прицепиться к окну, если оно свернуто) #(особенность uia backend - он не может прицепиться к окну, если оно свернуто)
@ -655,11 +723,15 @@ def UIOSelector_TryRestore_Dict(inSpecificationList):
return lResult return lResult
#################################################################################################### ####################################################################################################
#Get the list of the UI object activities #Get the list of the UI object activities
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#inControlSpecificationArray - UIOSelector #inControlSpecificationArray - UIOSelector
#old name - ElementActionGetList #old name - ElementActionGetList
def UIOSelector_Get_UIOActivityList (inControlSpecificationArray): def UIOSelector_Get_UIOActivityList (inUIOSelector):
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Получить объект #Получить объект
lObject=UIOSelector_Get_UIO(inControlSpecificationArray) lObject=UIOSelector_Get_UIO(inUIOSelector)
lActionList=dir(lObject) lActionList=dir(lObject)
lResult=dir(lObject) lResult=dir(lObject)
#Выполнить чистку списка от неактуальных методов #Выполнить чистку списка от неактуальных методов
@ -670,17 +742,36 @@ def UIOSelector_Get_UIOActivityList (inControlSpecificationArray):
#Удалить те, которые начинаются с символа верхнего регистра #Удалить те, которые начинаются с символа верхнего регистра
if lActionItem[0].isupper(): if lActionItem[0].isupper():
lResult.remove(lActionItem) lResult.remove(lActionItem)
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Get_UIOActivityList",
"ArgumentList": [inUIOSelector],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lResult = lPIPEResponseDict["Result"]
return lResult return lResult
#################################################################################################### ####################################################################################################
#Run the activity in UIO (UI Object) #Run the activity in UIO (UI Object)
#inControlSpecificationArray - UIOSelector #!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#inUIOSelector
#inActionName - UIOActivity (name) from Pywinauto #inActionName - UIOActivity (name) from Pywinauto
#old name - ElementRunAction #old name - ElementRunAction
def UIOSelectorUIOActivity_Run_Dict(inControlSpecificationArray,inActionName,inArgumentList=[],inkwArgumentObject={}): def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=[], inkwArgumentObject={}):
lResult={} lResult={}
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
#Run activity if SafeOtherProcess is None
if lSafeOtherProcess is None:
#Определить объект #Определить объект
lObject=UIOSelector_Get_UIO(inControlSpecificationArray) lObject=UIOSelector_Get_UIO(inUIOSelector)
#Получить метод для вызова #Получить метод для вызова
lFunction = getattr(lObject, inActionName) lFunction = getattr(lObject, inActionName)
#Выполнить действие #Выполнить действие
@ -701,26 +792,55 @@ def UIOSelectorUIOActivity_Run_Dict(inControlSpecificationArray,inActionName,inA
return lResult return lResult
else: else:
raise e raise e
else:
#Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelectorUIOActivity_Run_Dict",
"ArgumentList": [inUIOSelector, inActionName, inArgumentList, inkwArgumentObject],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lResult = lPIPEResponseDict["Result"]
return lResult return lResult
#################################################################################################### ####################################################################################################
#Get the UIO dict of the attributes #Get the UIO dict of the attributes
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#old name - ElementGetInfo #old name - ElementGetInfo
def UIOSelector_Get_UIOInfo(inControlSpecificationArray): def UIOSelector_Get_UIOInfo(inUIOSelector):
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Подготовка входного массива #Подготовка входного массива
inControlSpecificationArray=UIOSelector_SearchUIONormalize_UIOSelector(inControlSpecificationArray) inUIOSelector=UIOSelector_SearchUIONormalize_UIOSelector(inUIOSelector)
#Выполнить идентификацию объектов, если передан массив #Выполнить идентификацию объектов, если передан массив
lResultList=[]; lResultList=[];
if len(inControlSpecificationArray) > 0: if len(inUIOSelector) > 0:
#Получить объект #Получить объект
lTempObject=UIOSelector_Get_UIO(inControlSpecificationArray) lTempObject=UIOSelector_Get_UIO(inUIOSelector)
#Получить инфо объект #Получить инфо объект
lTempObjectInfo = lTempObject.element_info lTempObjectInfo = lTempObject.element_info
#Добавить информацию об обнаруженом объекте #Добавить информацию об обнаруженом объекте
lResultList.append(UIOEI_Convert_UIOInfo(lTempObjectInfo)); lResultList.append(UIOEI_Convert_UIOInfo(lTempObjectInfo))
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Get_UIOInfo",
"ArgumentList": [inUIOSelector],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lResultList = lPIPEResponseDict["Result"]
return lResultList return lResultList
#################################################################################################### ####################################################################################################
#Search child UIO by the: Parent UIO, X, Y #Search child UIO by the: Parent UIO, X, Y
#inHierarchyList: [{"index":<>,"element":<>}] - technical argument for internal purpose #inHierarchyList: [{"index":<>,"element":<>}] - technical argument for internal purpose
@ -812,17 +932,21 @@ def UIOXY_SearchChild_ListDict(inRootElement,inX,inY,inHierarchyList=[]):
################################################################################################### ###################################################################################################
#Get list of child UIO's by Parent UIOSelector #Get list of child UIO's by Parent UIOSelector
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#inControlSpecificationArray- UIOSelector #inControlSpecificationArray- UIOSelector
#old name - ElementGetChildElementList #old name - ElementGetChildElementList
def UIOSelector_GetChildList_UIOList(inControlSpecificationArray=[],inBackend=mDefaultPywinautoBackend): def UIOSelector_GetChildList_UIOList(inUIOSelector=[], inBackend=mDefaultPywinautoBackend):
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Подготовка входного массива #Подготовка входного массива
inControlSpecificationArray=UIOSelector_SearchUIONormalize_UIOSelector(inControlSpecificationArray) inUIOSelector=UIOSelector_SearchUIONormalize_UIOSelector(inUIOSelector)
#Выполнить идентификацию объектов, если передан массив #Выполнить идентификацию объектов, если передан массив
lResultList=[]; lResultList=[];
#ctypes.windll.user32.MessageBoxW(0, str(inControlSpecificationArray), "Your title", 1) #ctypes.windll.user32.MessageBoxW(0, str(inControlSpecificationArray), "Your title", 1)
if len(inControlSpecificationArray) > 0: if len(inUIOSelector) > 0:
#Получить объект #Получить объект
lTempObject = UIOSelector_Get_UIO(inControlSpecificationArray) lTempObject = UIOSelector_Get_UIO(inUIOSelector)
#Получить список дочерних объектов #Получить список дочерних объектов
lTempChildList = lTempObject.children() lTempChildList = lTempObject.children()
lIterator=0 lIterator=0
@ -841,6 +965,20 @@ def UIOSelector_GetChildList_UIOList(inControlSpecificationArray=[],inBackend=mD
#Установка бэк-енда на первый элемент #Установка бэк-енда на первый элемент
for lItem in lResultList: for lItem in lResultList:
lItem["backend"]=inBackend lItem["backend"]=inBackend
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_GetChildList_UIOList",
"ArgumentList": [inUIOSelector, inBackend],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
lResultList = lPIPEResponseDict["Result"]
return lResultList return lResultList
#################################################################################################### ####################################################################################################
@ -1080,17 +1218,53 @@ def BackendStr_GetTopLevelList_UIOInfo(inBackend=mDefaultPywinautoBackend):
################################################################################################### ###################################################################################################
#Highlight the UI object #Highlight the UI object
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#old name - ElementDrawOutlineNew #old name - ElementDrawOutlineNew
def UIOSelector_Highlight(inSpecificationArray): def UIOSelector_Highlight(inUIOSelector):
UIO_Highlight(UIOSelector_Get_UIO(inSpecificationArray)) #Check the bitness
return lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
UIO_Highlight(UIOSelector_Get_UIO(inUIOSelector))
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool",
"ArgumentList": [inUIOSelector],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
return lPIPEResponseDict["Result"]
return True
################################################################################################### ###################################################################################################
#inSpecificationArray - UIOSelector #inSpecificationArray - UIOSelector
#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!
#old name - ElementDrawOutlineNewFocus #old name - ElementDrawOutlineNewFocus
def UIOSelector_FocusHighlight(inSpecificationArray): def UIOSelector_FocusHighlight(inUIOSelector):
UIO_FocusHighlight(UIOSelector_Get_UIO(inSpecificationArray)) #Check the bitness
return lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
UIO_FocusHighlight(UIOSelector_Get_UIO(inUIOSelector))
else:
# Run function from other process with help of PIPE
lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool",
"ArgumentList": [inUIOSelector],
"ArgumentDict": {}}
# Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами
ProcessCommunicator.ProcessChildSendObject(lSafeOtherProcess, lPIPEResuestDict)
# Get answer from child process
lPIPEResponseDict = ProcessCommunicator.ProcessChildReadWaitObject(lSafeOtherProcess)
if lPIPEResponseDict["ErrorFlag"]:
raise Exception(
f"Exception was occured in child process (message): {lPIPEResponseDict['ErrorMessage']}, (traceback): {lPIPEResponseDict['ErrorTraceback']}")
else:
return lPIPEResponseDict["Result"]
return True
################################################################################################### ###################################################################################################
#old name - draw_outline_new #old name - draw_outline_new

@ -0,0 +1,85 @@
import pywinauto #Is needed to detect OS bitness
import struct # Need to detect Current process bitness
import subprocess #Need to create subprocess
import os # Is needed to check file/folder path
import shutil #os operations
import pdb
############################################
####Module, which control the Bitness between 32 and 64 python (needed for pywinauto framework to work correctly)
############################################
global mSettingsDict
mSettingsDict = {
"BitnessProcessCurrent": "64", # "64" or "32"
"BitnessOS": "64", # "64" or "32"
"Python32FullPath": None, #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
"Python64FullPath": None, #Set from user
"Python32ProcessName": "OpenRPAUIDesktopX32.exe", #Config set once
"Python64ProcessName": "OpenRPAUIDesktopX64.exe", #Config set once
"Python32Process":None,
"Python64Process":None,
"PythonArgs":["-m","pyOpenRPA.Robot"] #Start other bitness openRPA process with PIPE channel
}
#Init the global configuration
def SettingsInit(inSettingsDict):
if inSettingsDict:
global mSettingsDict
#Update values in settings from input
mSettingsDict.update(inSettingsDict)
#mSettingsDict = inSettingsDict
####################
#Detect OS bitness
####BitnessOS#######
lBitnessOS="32";
if pywinauto.sysinfo.is_x64_OS():
lBitnessOS="64";
inSettingsDict["BitnessOS"]=lBitnessOS
####################
#Detect current process bitness
####BitnessProcessCurrent#######
lBitnessProcessCurrent = str(struct.calcsize("P") * 8)
inSettingsDict["BitnessProcessCurrent"]=lBitnessProcessCurrent
#####################################
#Create the other bitness process if OS is 64 and we have another Python path
##########################################################################
#Check if OS is x64, else no 64 is applicable
if mSettingsDict["BitnessOS"]=="64":
#Check if current bitness is 64
if mSettingsDict["BitnessProcessCurrent"]=="64":
#create x32 if Python 32 path is exists
if mSettingsDict["Python32FullPath"] and mSettingsDict["Python32ProcessName"]:
#Calculate python.exe folder path
lPython32FolderPath= "\\".join(mSettingsDict["Python32FullPath"].split("\\")[:-1])
lPython32NewNamePath = f"{lPython32FolderPath}\\{mSettingsDict['Python32ProcessName']}"
if not os.path.isfile(lPython32NewNamePath):
shutil.copyfile(mSettingsDict["Python32FullPath"],lPython32NewNamePath)
#pdb.set_trace()
mSettingsDict["Python32Process"] = subprocess.Popen([lPython32NewNamePath] + mSettingsDict["PythonArgs"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
else:
#bitness current process is 32
#return x64 if it is exists
if mSettingsDict["Python64Process"]:
#Calculate python.exe folder path
lPython64FolderPath= "\\".join(mSettingsDict["Python64FullPath"].split("\\")[:-1])
lPython64NewNamePath = f"{lPython64FolderPath}\\{mSettingsDict['Python64ProcessName']}"
if not os.path.isfile(lPython64NewNamePath):
shutil.copyfile(mSettingsDict["Python64FullPath"],lPython64NewNamePath)
mSettingsDict["Python64Process"] = subprocess.Popen([lPython64NewNamePath] + mSettingsDict["PythonArgs"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
#Return the other module bitnes
def OtherProcessGet():
#Result template
lResult = None
global mSettingsDict
#Check if OS is x64, else no 64 is applicable
if mSettingsDict["BitnessOS"]=="64":
#Check if current bitness is 64
if mSettingsDict["BitnessProcessCurrent"]=="64":
#return x32 if it is exists
if mSettingsDict["Python32Process"]:
lResult = mSettingsDict["Python32Process"]
else:
#bitness current process is 32
#return x64 if it is exists
if mSettingsDict["Python64Process"]:
lResult = mSettingsDict["Python64Process"]
#Exit
return lResult

@ -0,0 +1 @@
from . import ProcessBitness

@ -28,6 +28,7 @@ while True:
lFunction = getattr(UIDesktop,lJSONInput['ActivityName']) lFunction = getattr(UIDesktop,lJSONInput['ActivityName'])
lProcessResponse["Result"]=JSONNormalize.JSONNormalizeDictListStrIntBool(lFunction(*lJSONInput['ArgumentList'],**lJSONInput['ArgumentDict'])) lProcessResponse["Result"]=JSONNormalize.JSONNormalizeDictListStrIntBool(lFunction(*lJSONInput['ArgumentList'],**lJSONInput['ArgumentDict']))
except Exception as e: except Exception as e:
lProcessResponse["Result"] = None
#Установить флаг ошибки #Установить флаг ошибки
lProcessResponse["ErrorFlag"]=True lProcessResponse["ErrorFlag"]=True
#Зафиксировать traceback #Зафиксировать traceback

@ -1,4 +1,24 @@
Beta before 1.0.1 (new way of OpenRPA with improovments. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1 Beta before 1.0.1 (new way of OpenRPA with improovments. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1
[1.0.25]
*Dont upload to PyPi* - Not tested
Created safe call function in UIDesktop
UIOSelector_SafeOtherGet_Process
Safe call in UIDesktop for:
- UIOSelectorUIOActivity_Run_Dict
- UIOSelector_Exist_Bool
- UIOSelector_Highlight
- UIOSelector_FocusHighlight
- UIOSelector_SearchChildByMouse_UIOTree
- UIOSelector_GetChildList_UIOList
- UIOSelector_Get_UIOInfoList
- UIOSelector_Get_UIOInfo
- UIOSelector_Get_UIOActivityList
UIOSelectorSecs_WaitAppear_Bool
UIOSelectorSecs_WaitDisappear_Bool
UIOSelectorsSecs_WaitAppear_List
UIOSelectorsSecs_WaitDisappear_List
[1.0.24] [1.0.24]
1.0.1 Beta 1.0.1 Beta
Refactoring (Studio Orchestrator in pyOpenRPA package) Refactoring (Studio Orchestrator in pyOpenRPA package)

Loading…
Cancel
Save