Что нового

Некорректно работает 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 238
Репутация
1 123
По сути 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 238
Репутация
1 123
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 238
Репутация
1 123
Начну с блокнота. Вы используете 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], "текст") ; установка текста в третий элемент
 
Верх