Что нового

Некорректно работает ControlSetText или ControlSend в поле CLASS:TextArea при неактивном окне

soundiks

Новичок
Сообщения
3
Репутация
0
Доброго времени суток.

Помогите пожалуйста. До этого времени я всегда находил ответы на все вопросы связанные с autoit, но ту какая-то мистика. Проблема связана скорее с программой, которую я пытаюсь автоматизировать, а не с AutoIt, но надеюсь дело во мне.

Программа: PTC Creo (CAD программа, если кому-то интересно)

Суть: Первая версия моей программы исполняла то что нужно, но не в фоновом режиме, т.е. нельзя трогать мышь и клавиатуру. К сожалению я только недавно узнал, что ControlSend и подобное работает фоново не требуя активности окна, соотвественно понял, что могу довольно легко переписать все для работы в фоне, но возникли трудности.

Нужно в определенном окне данной программы в поле вставить текст (в данном случае не важно какой), а скорее важно сделать это так, чтобы работало 100%. а не через раз.

Изначально все работало вот так (то есть работа осуществлялась не в фоне, но работало стабильно, основное что нужно, это в [CLASS:TextArea; INSTANCE:5] подставить другое значение):
Код:
WinActivate("Search Tool")
WinWaitActive("Search Tool", "", 10)

ControlClick ("Search Tool:1", "", "[CLASS:TextArea; INSTANCE:5]", "main", 1)   ;SAME EVERYTIME
   sleep(250)
ControlSend("Search Tool:1", '', "[CLASS:TextArea; INSTANCE:5]", '^v')    ;SAME EVERYTIME
   sleep(250)
send('{BACKSPACE}')
   sleep(250)
ControlClick ("Search Tool:1", "", "[CLASS:Layout; INSTANCE:16]", "main", 1, 5, 5)    ;NO BUILD QUERY
   sleep(250)

ControlClick ("Search Tool:1", "", "[CLASS:List; INSTANCE:12]", "main", 1, 7, 7)      ;SAME EVERYTIME
   sleep(250)

ControlClick ("Search Tool:1", "", "[CLASS:Layout; INSTANCE:17]", "main", 1)     ;NO BUILD QUERY
   sleep(250)
ControlClick ("Search Tool:1", "", "[CLASS:Layout; INSTANCE:20]", "main", 1, 406, 5)     ;NO BUILD QUERY
   sleep(250)


Теперь же переписал вот таким образом:
Код:
WinWait("Search Tool:1")
$search_creo_wnd = WinGetTitle("Search Tool:1")
   sleep(250)
ControlClick ($search_creo_wnd, "", "[CLASS:TextArea; INSTANCE:5]", "main", 1)   ;SAME EVERYTIME
   sleep(250)
ControlSend($search_creo_wnd, '', "[CLASS:TextArea; INSTANCE:5]", '^a')
   sleep(500)
ControlSend($search_creo_wnd, '', "[CLASS:TextArea; INSTANCE:5]", '^v')    ;SAME EVERYTIME
   sleep(250)
ControlSend($search_creo_wnd, '', "[CLASS:TextArea; INSTANCE:5]", '{BACKSPACE}')
   sleep(250)
ControlClick ($search_creo_wnd, "", "[CLASS:Layout; INSTANCE:16]", "main", 1, 5, 5)    ;NO BUILD QUERY
   sleep(250)
ControlClick ($search_creo_wnd, "", "[CLASS:List; INSTANCE:12]", "main", 1, 7, 7)      ;SAME EVERYTIME
   sleep(250)
ControlClick ($search_creo_wnd, "", "[CLASS:Layout; INSTANCE:17]", "main", 1)     ;NO BUILD QUERY
   sleep(250)
ControlClick ($search_creo_wnd, "", "[CLASS:Layout; INSTANCE:20]", "main", 1, 406, 5)     ;NO BUILD QUERY
   sleep(250)


Все бы хорошо, но теперь это корректно работает всего 1 раз из десяти (имеется ввиду выполнение каждого действия в этом окне, часть стали пропускаться и т.д.). БОльшие паузы тоже не дают результата, как ни странно.

По сути 1ое от второго несильно отличается, но в активном окне это срабатывает четко, а в неактивном нет, дело тут думаю в том, что класс поля не Edit как в блокноте, а TextArea.:scratch:Я так думаю, потому что функция ControlSetText не срабатывает никак (точнее в AutoItWindowsInfo видно, что текст вставился, но при этом в самом окне ничего не изменяется, т.е. элемент содержит теперь текст и свое значение, не изменившееся).

Ниже на скриншоте видно что я имею ввиду, скрин уже после запуска скрипта, значение "123" стоит как вкопанное.
Annotation 2019-09-23 124637.png

Еще подозреваю, что в неактивном окне плохо работают такие вещи как Ctrl+C/Ctrl+V/Ctrl+A. Но опять же ControlSetText не срабатывает впринципе.

Вопросов несколько:
1. Можно ли заставить работать ControlSetText в таком случае?
2. Как заставить второй вариант, работающий с неактивным окном, работать корректно и 10 из 10?

P.S. ControlFocus не помогает, да и окно активным от него становится.
P.S.2. К сожалению написание всей этой автоматизации уже является костылем для крео, и костыль с этим окошком и нажиманием в нем кнопулек и редактированием этого поля обойти не представляется возможным.
P.S.3. Могу подробнее описать суть всей программы, если кому-то потребуется, но думаю в данном контексте это не поможет.
P.S.4. Простите за мой код, скорее всего для многих он выглядит весьма плохо, но пишу как умею.
 

InnI

AutoIT Гуру
Сообщения
4,635
Репутация
1,311
По сути 1ое от второго несильно отличается
Отличается. И сильно. В первом случае ожидание активного окна. Окно станет активно только когда появятся и смогут работать все контролы. Во втором случае ожидание создания окна. При этом контролов ещё может не быть, а вы уже пытаетесь с ними работать. Для начала попробуйте во втором случае добавить задержку в несколько секунд после ожидания окна. Если получится, то можно будет заменить её на ожидание конкретного контрола.

Ещё непонятен этот момент
Код:
$search_creo_wnd = WinGetTitle("Search Tool:1")
Если "Search Tool:1" - это полный заголовок окна, то вы его и получите. Т.е. никакого смысла в этой строке не будет. Если же "Search Tool:1" - это начало заголовка, то убедитесь, что вы находите нужное окно. Или вы хотели использовать WinGetHandle()?
 
Автор
S

soundiks

Новичок
Сообщения
3
Репутация
0
Отличается. И сильно. В первом случае ожидание активного окна. Окно станет активно только когда появятся и смогут работать все контролы. Во втором случае ожидание создания окна. При этом контролов ещё может не быть, а вы уже пытаетесь с ними работать. Для начала попробуйте во втором случае добавить задержку в несколько секунд после ожидания окна. Если получится, то можно будет заменить её на ожидание конкретного контрола.

Ещё непонятен этот момент
Код:
$search_creo_wnd = WinGetTitle("Search Tool:1")
Если "Search Tool:1" - это полный заголовок окна, то вы его и получите. Т.е. никакого смысла в этой строке не будет. Если же "Search Tool:1" - это начало заголовка, то убедитесь, что вы находите нужное окно. Или вы хотели использовать WinGetHandle()?

С заголовком окна понял, изначально хотел сделать WinGetHandle, написал другое, но по сути получилось что не имеет смысла (заголовок всегда одинаковый и это он полный), спасибо.

Пауза не решает проблему, сколько не жди в это поле значение вводится через раз, причем видно, что оно иногда выделяется, иногда срабаывает Backspace.. в общем по-разному каждый раз, даже если делать между всеми операциями паузы в 1.5 сек, то это не влияет положительно. Если речь идет об ожидании выполнения контрола, то он сам по себе сколько не жди срабатывает далеко не всегда. Если может каким-то образом заставить ждать именно успешного выполнения контрола - то тоже не факт что поможет, потому что ControlGetText возвращает всегда "0".
 

InnI

AutoIT Гуру
Сообщения
4,635
Репутация
1,311
ControlGetText возвращает всегда "0"
Т.к. Au3Info определяет текст, значит не всегда "0". Или не для всех контролов.
На скрине элементы похожи на combobox'ы. Испытайте на них ControlCommand() с параметром "GetCurrentSelection".
Если совсем ничего не поможет - пробуйте UIAutomate
 
Автор
S

soundiks

Новичок
Сообщения
3
Репутация
0
Т.к. Au3Info определяет текст, значит не всегда "0". Или не для всех контролов.
На скрине элементы похожи на combobox'ы. Испытайте на них ControlCommand() с параметром "GetCurrentSelection".
Если совсем ничего не поможет - пробуйте UIAutomate

Целый день я бьюсь с этой кнопкой. ControlCommand ничего не выдает. Эти элементы AutoIt не видит как ComboBox. Если раскрыть список, то видит его как List, но ничего оттуда не видит, ибо не ComboBox, как я понимаю.

Попробовал UIAutomate -но тоже не срабатывает. Возможно я неправильно все записываю, судя по тому что у меня не получается даже ввести какой-либо текст в блокнот. Ниже примеры того, что я делаю с блокнотом и со своим многострадальным полем:

Код:
#include "UIAutomate.au3"
AutoItSetOption('WinTitleMatchMode',2)

$hWnd = WinGetHandle('Notepad')

$oParent_1 = _UIA_GetElementFromHandle($hWnd)

$oElement = _UIA_GetControlTypeElement($oParent_1, 0xC36E, "123") ;UIA_EditControlTypeId
_UIA_ElementTextSetValue($oElement, "Скрипт сработал")


Хотя нажать на кнопку "File" в блокноте я смог с первого раза с помощью UIAutomate, вот выдержка из Inspect по окну блокнота:
How found: Mouse move (631,392)
hwnd=0x00080A26 32bit class="Edit" style=0x50200104 ex=0x0
Name: "Text Editor"
ControlType: UIA_DocumentControlTypeId (0xC36E)
LocalizedControlType: "document"
BoundingRectangle: {l:515 t:349 r:962 b:559}
IsEnabled: true
IsOffscreen: false
IsKeyboardFocusable: true
HasKeyboardFocus: true
AccessKey: ""
ProcessId: 7056
RuntimeId: [2A.80A26]
AutomationId: "15"
FrameworkId: "Win32"
ClassName: "Edit"
NativeWindowHandle: 0x80A26
IsContentElement: true
ProviderDescription: "[pid:9128,providerId:0x80A26 Main:Nested [pid:7056,providerId:0x80A26 Annotation(parent link):Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main:Microsoft: EDIT Proxy (unmanaged:uiautomationcore.dll)]; Nonclient:Microsoft: Non-Client Proxy (unmanaged:uiautomationcore.dll); Hwnd(parent link):Microsoft: HWND Proxy (unmanaged:uiautomationcore.dll)]"
IsPassword: false
HelpText: ""
LegacyIAccessible.ChildId: 0
LegacyIAccessible.DefaultAction: ""
LegacyIAccessible.Description: ""
LegacyIAccessible.Help: ""
LegacyIAccessible.KeyboardShortcut: ""
LegacyIAccessible.Name: "Text Editor"
LegacyIAccessible.Role: editable text (0x2A)
LegacyIAccessible.State: focused,focusable (0x100004)
LegacyIAccessible.Value: "123"
Scroll.HorizontallyScrollable: false
Scroll.HorizontalScrollPercent: 0.000000
Scroll.HorizontalViewSize: 100.000000
Scroll.VerticallyScrollable: false
Scroll.VerticalScrollPercent: 0.000000
Scroll.VerticalViewSize: 100.000000
Value.IsReadOnly: false
Value.Value: "123"
IsAnnotationPatternAvailable: false
IsDragPatternAvailable: false
IsDockPatternAvailable: false
IsDropTargetPatternAvailable: false
IsExpandCollapsePatternAvailable: false
IsGridItemPatternAvailable: false
IsGridPatternAvailable: false
IsInvokePatternAvailable: false
IsItemContainerPatternAvailable: false
IsLegacyIAccessiblePatternAvailable: true
IsMultipleViewPatternAvailable: false
IsObjectModelPatternAvailable: false
IsRangeValuePatternAvailable: false
IsScrollItemPatternAvailable: false
IsScrollPatternAvailable: true
IsSelectionItemPatternAvailable: false
IsSelectionPatternAvailable: false
IsSpreadsheetItemPatternAvailable: false
IsSpreadsheetPatternAvailable: false
IsStylesPatternAvailable: false
IsSynchronizedInputPatternAvailable: false
IsTableItemPatternAvailable: false
IsTablePatternAvailable: false
IsTextChildPatternAvailable: false
IsTextEditPatternAvailable: false
IsTextPatternAvailable: true
IsTextPattern2Available: true
IsTogglePatternAvailable: false
IsTransformPatternAvailable: false
IsTransform2PatternAvailable: false
IsValuePatternAvailable: true
IsVirtualizedItemPatternAvailable: false
IsWindowPatternAvailable: false
IsCustomNavigationPatternAvailable: false
FirstChild: "Vertical" scroll bar
LastChild: "Vertical" scroll bar
Next: (null) title bar
Previous: [null]
Other Props: Object has no additional properties
Children: "Vertical" scroll bar
Ancestors: "*Untitled - Notepad" window
"Desktop 1" pane
[ No Parent ]

Что-то делаю неправильно. А также я хочу заметить, что inspect видит, что в поле введено "123"!

Не смотря на неудачу, я все равно написал это дело для своей задачи, но тоже не сработало, вот код:
Код:
#include "UIAutomate.au3"
AutoItSetOption('WinTitleMatchMode',2)

$hSearch = WinGetHandle('Search')

$oParent = _UIA_GetElementFromHandle($hSearch)

$oElement = _UIA_GetControlTypeElement($oParent, 0xC371, "123") ;UIA_EditControlTypeId
_UIA_ElementTextSetValue($oElement, "То что я хочу вставить")


А вот то, что выдает inspect по моему полю:
How found: Mouse move (368,240)
hwnd=0x00030AC8 64bit class="TextArea" style=0x56000000 ex=0x0
Name: ""
ControlType: UIA_PaneControlTypeId (0xC371)
LocalizedControlType: "pane"
BoundingRectangle: {l:332 t:233 r:467 b:251}
IsEnabled: true
IsOffscreen: false
IsKeyboardFocusable: true
HasKeyboardFocus: false
AccessKey: ""
ProcessId: 11508
RuntimeId: [2A.30AC8]
FrameworkId: "Win32"
ClassName: "TextArea"
NativeWindowHandle: 0x30AC8
ProviderDescription: "[pid:9128,providerId:0x30AC8 Main:Nested [pid:11508,providerId:0x30AC8 Annotation(parent link):Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main:Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]; Hwnd(parent link):Microsoft: HWND Proxy (unmanaged:uiautomationcore.dll)]"
IsPassword: false
HelpText: ""
LegacyIAccessible.ChildId: 0
LegacyIAccessible.DefaultAction: ""
LegacyIAccessible.Description: ""
LegacyIAccessible.Help: ""
LegacyIAccessible.KeyboardShortcut: ""
LegacyIAccessible.Name: ""
LegacyIAccessible.Role: client (0xA)
LegacyIAccessible.State: focusable (0x100000)
LegacyIAccessible.Value: ""
IsAnnotationPatternAvailable: false
IsDragPatternAvailable: false
IsDockPatternAvailable: false
IsDropTargetPatternAvailable: false
IsExpandCollapsePatternAvailable: false
IsGridItemPatternAvailable: false
IsGridPatternAvailable: false
IsInvokePatternAvailable: false
IsItemContainerPatternAvailable: false
IsLegacyIAccessiblePatternAvailable: true
IsMultipleViewPatternAvailable: false
IsObjectModelPatternAvailable: false
IsRangeValuePatternAvailable: false
IsScrollItemPatternAvailable: false
IsScrollPatternAvailable: false
IsSelectionItemPatternAvailable: false
IsSelectionPatternAvailable: false
IsSpreadsheetItemPatternAvailable: false
IsSpreadsheetPatternAvailable: false
IsStylesPatternAvailable: false
IsSynchronizedInputPatternAvailable: false
IsTableItemPatternAvailable: false
IsTablePatternAvailable: false
IsTextChildPatternAvailable: false
IsTextEditPatternAvailable: false
IsTextPatternAvailable: false
IsTextPattern2Available: false
IsTogglePatternAvailable: false
IsTransformPatternAvailable: false
IsTransform2PatternAvailable: false
IsValuePatternAvailable: false
IsVirtualizedItemPatternAvailable: false
IsWindowPatternAvailable: false
IsCustomNavigationPatternAvailable: false
FirstChild: [null]
LastChild: [null]
Next: [null]
Previous: [null]
Other Props: Object has no additional properties
Children: Container has no children
Ancestors: "" pane
"" pane
"" pane
"" pane
"" pane
"" pane
"" pane
"" pane
"" pane
"" pane
"" pane
"Search Tool:1" window
"Desktop 1" pane
[ No Parent ]

И хочу обратить внимание, что для примера в момент Inspect в моем поле тоже введено "123", но этой информации опять же нигде нет.

Ошибки по блокноту:
!> _UIA_GetControlTypeElement : элементы указанного типа не найдены ------- Здесь я понимаю, что явно не по правильному элементу осуществляю поиск, соответственно, раз я ничего не нашел отсюда вторая ошибка ниже.
!> _UIA_ElementTextSetValue : первый параметр не является объектом

Ошибки по моему окошку:
!> _UIA_GetControlTypeElement : значение указанного свойства найденных элементов не соответствует заданному ------- Тут же он находит подобные элементы в данном окошке, но значение, по которому я предлагаю искать (а именно "123" для примера), отсутствует в свойствах этих элементов.
!> _UIA_ElementTextSetValue : первый параметр не является объектом

Вроде все подробно описал, вопрос собственно где я облажался?
 

InnI

AutoIT Гуру
Сообщения
4,635
Репутация
1,311
Начну с блокнота. Вы используете Inspect_W10 на Windows выше 7. В этом случае поле редактирования определяется как "UIA_DocumentControlTypeId" и нужно указать версию элемента выше 1 (или 0 для автоопределения). Если вы будете использовать Inspect_W7, то данный элемент определится как "UIA_EditControlTypeId" и можно версию элемента не указывать (по умолчанию версия 1). Я специально приложил две утилиты Inspect для возможности сравнения свойств на разных Windows. Например, для Win8+
Код:
#include "UIAutomate.au3"
$UIA_ElementVersion = 2 ; см. раздел #ГЛОБАЛЬНЫЕ_ПЕРЕМЕННЫЕ# в файле UIAutomate.au3

Далее. В функции _UIA_GetControlTypeElement четвёртый параметр по умолчанию "Name". Если у вас в поле редактирования указано "123", то это значение Inspect определит, как "Value.Value". Вот это свойство и нужно указать четвёртым параметром
Код:
$oElement = _UIA_GetControlTypeElement($oParent_1, "UIA_EditControlTypeId", "123", "Value.Value") ; для элемента версии 1


Теперь по окну "Search Tool:1". Если Inspect "не видит" введённого значения "123", значит элемент это значение не возвращает. С этим ничего не сделать - так элемент создали разработчики.
Работать с одинаковыми элементами можно по индексу в массиве _UIA_FindAllElements(). Индекс будет играть роль instance
Код:
$aAll = _UIA_FindAllElements($oParent, "ClassName", "TextArea")
_UIA_ElementTextSetValue($aAll[3], "текст") ; установка текста в третий элемент
 
Верх