Что нового

Скрыть MsgBox и нажать на нем кнопку

Автор
T

The_Immortal

Новичок
Сообщения
84
Репутация
4
Alofa, попробовал ту строку заменить на
Код:
$aData = _WinAPI_EnumProcessWindows($iPid, False)
и на
Код:
$aData = _WinAPI_EnumDesktopWindows($hDesktop)
- всё равно та же ошибка... :scratch:

Ну насчет последнего понятно:
Код:
Local $hDesktop = _WinAPI_CreateDesktop
- Вы там выше объявляете hDesktop глобально, а потом внутри функции делаете данную переменную локальной. А вот _WinAPI_EnumProcessWindows() почему-то никак не хочет получать список окон по процессу. Может это как-то связано с тем, что он упрямо ищет окна на текущем рабочем столе? А EnumDesktopWindows() позволяет указать конкретный рабочий стол.

И ещё, Вы закрываете рабочий стол:
Код:
_WinAPI_CloseDesktop($hDesktop)
- вероятно это его не полное закрытие, т.к. попробуйте:
Код:
#include <WinAPISys.au3>

$hDesktop = _WinAPI_CreateDesktop('MyDesktop', $GENERIC_ALL)

_WinAPI_CloseDesktop($hDesktop) ; закрыли стол

If _WinAPI_OpenDesktop('MyDesktop', $GENERIC_ALL, 0, True) Then ; т.к. стол закрыт, _WinAPI_OpenDesktop не должна вернуть хэндл, а она его почему-то возвращает
	_WinAPI_SwitchDesktop($hDesktop)
	Sleep(5000)
	$hDefault = _WinAPI_OpenDesktop('Default', $GENERIC_ALL)
	_WinAPI_SwitchDesktop($hDefault)
EndIf


Т.е. получается что _WinAPI_OpenDesktop() заодно и создает указанный рабочий стол?
Или я что-то не так понял?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
The_Immortal, ваш код нормально отрабатывает, и _WinAPI_OpenDesktop() возвращает 0. Перегрузите компьютер и попробуйте еще раз.


Добавлено:
Сообщение автоматически объединено:

И да, старайтесь никогда не использовать GENERIC_ALL, лучше выставляйте только необходимые флаги.
 
Автор
T

The_Immortal

Новичок
Сообщения
84
Репутация
4
Б-р-р... Что-то пошло у меня не так. Перезагрузил машину. Пробую выполнить следующий код:

Код:
#include <WinAPIProc.au3>
#include <WinAPISys.au3>

Local $pText, $tProcess, $tStartup

Local $hDesktop = _WinAPI_CreateDesktop('MyDesktop', BitOR($DESKTOP_CREATEWINDOW, $DESKTOP_SWITCHDESKTOP))

If Not $hDesktop Then
	MsgBox(16, 'Ошибка!', 'Невозможно создать рабочий стол.')
	Exit
EndIf

Local $pText = _WinAPI_CreateString('MyDesktop')
Local $tProcess = DllStructCreate($tagPROCESS_INFORMATION)
Local $tStartup = DllStructCreate($tagSTARTUPINFO)
DllStructSetData($tStartup, 'Size', DllStructGetSize($tStartup))
DllStructSetData($tStartup, 'Desktop', $pText)
_WinAPI_CreateProcess("c:\Program Files (x86)\AutoIt3\Au3Info_x64.exe", '', 0, 0, 0, $CREATE_NEW_PROCESS_GROUP, 0, 0, $tStartup, $tProcess)

_WinAPI_CloseDesktop($hDesktop)


На что получаю:

12.11.2015-20.00.png


И дело не в кавычках: "c:\Program Files (x86)\AutoIt3\Au3Info_x64.exe"...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Посмотрите в менеджере событий более подробную информацию.
 
Автор
T

The_Immortal

Новичок
Сообщения
84
Репутация
4
Yashied, имеется в виду в системном журнале? Там ничего нет на эту тему.

Alofa, Вы не могли бы протестировать мой (а точнее Ваш) код (точь-в-точь) из 44-сообщения, предварительно перезагрузившись?
 
A

Alofa

Гость
Yashied сказал(а):
... Перегрузите компьютер и попробуйте еще раз.
Это-то и поставило все точки над "И".
Свой код признал неработоспособным:
Код:
_WinAPI_EnumProcessWindows ; Не ловит окна на другом рабочем столе


The_Immortal сказал(а):
... Вы не могли бы протестировать мой (а точнее Ваш) код (точь-в-точь) из 44-сообщения...
Да, такая же ошибка.
Мне кажется проблема в этом:
Код:
_WinAPI_CreateProcess("c:\Program Files (x86)\AutoIt3\Au3Info_x64.exe", '', 0, 0, 0, $CREATE_NEW_PROCESS_GROUP, 0, 0, $tStartup, $tProcess) ; Вы запускаете программу на другом рабочем столе...

_WinAPI_CloseDesktop($hDesktop) ; ...И тут же закрываете рабочий стол

Да и не мой это код - взят из справки.
 
Автор
T

The_Immortal

Новичок
Сообщения
84
Репутация
4
Alofa, Вы абсолютно правы. Проблема была как раз в последующем закрытии стола.
Код:
If ProcessClose ("Au3Info_x64.exe") Then
	_WinAPI_CloseDesktop($hDesktop) ; закрываем рабочий стол, убедившись, что процессов на нём нет.
EndIf
- таким образом ошибки не будет. Конечно, эта проверка затрагивает наличие только заведомо известного процесса, а так по-хорошему надо отлавливать все процессы/окна связанные с этим столом и прибивать их. Видимо, только после этого произойдет корректное закрытие рабочего стола, иначе будет возникать либо ошибка, либо он просто не закроется.
 
A

Alofa

Гость
The_Immortal
Ваш код оказался удачнее моего (+).
Спасибо за проявленное упорство и как следствие положительный результат.
Одновременно с вами и я начал потихоньку знакомится с "WinAPIEx.au3", а то когда бы еще руки (и голова) дошли...

Теперь о вашем коде:
The_Immortal сказал(а):
... Правда, я тут убрал разного рода проверки, завершение процесса, а также закрытие рабочего стола ...

- Надеюсь, вы предусмотрели выход из возможной "бесконечности" двух циклов
Код:
Func _GetWindow($ClassName)
    While 1
;		...
		While NOT _WinAPI_IsWindowVisible($hWnd)
;			...
		WEnd
	WEnd
EndFunc


- Из кода мне не совсем понятно:
Код:
; Как вы освобождаете память?
_WinAPI_FreeMemory() ; (https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_FreeMemory.htm)

;После использования
_WinAPI_CreateString() ; (https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_CreateString.htm)


- Не знаю как у вас, а когда я запускаю таким образом свою "program.exe", то к ней дочерним процессом подцепляется "ctfmon.exe". А после того как моя программа закрывается - дочерний процесс-то остается.
Прошу проверить у себя и учесть этот факт.
 

xXx

╚{■_■}╗
Меценат
Сообщения
248
Репутация
95
Вот еще пример.
Годы понадобились чтобы руки дошли до этого.
Скрипт открывает окно блокнота, пишет в него и сохраняет эту писанину в файл.
Код:
#include <WinAPISys.au3>
#include <WinAPIProc.au3>

Global $Prog = 'C:\Windows\notepad.exe' ; Программа для запуска
Global $sFile = @ScriptDir & '\TextFile.txt' ; Тестовый Файл

Global $ProgPid, $pText, $hWin, $hNewDesktop
Local $hPrev = _WinAPI_GetThreadDesktop(_WinAPI_GetCurrentThreadId())
$hNewDesktop = _WinAPI_CreateDesktop('MyDesktop', $DESKTOP_ALL_ACCESS) ; создаем скрытый рабочий стол
If Not $hNewDesktop Then Exit 1

; _WinAPI_SwitchDesktop($hNewDesktop)

$pText = _WinAPI_CreateString('MyDesktop')
$tProcess = DllStructCreate($tagPROCESS_INFORMATION)
$tStartup = DllStructCreate($tagSTARTUPINFO)
DllStructSetData($tStartup, 'Size', DllStructGetSize($tStartup))
DllStructSetData($tStartup, 'Desktop', $pText)

FileClose(FileOpen($sFile, 1)) ; Создаем файл

If _WinAPI_CreateProcess($Prog, $Prog & ' "' & $sFile & '"', 0, 0, 0, 0x00000200, 0, 0, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Then
    $ProgPid = DllStructGetData($tProcess, 'ProcessID') ; Узнаем PID процесса notepad.exe
EndIf

If $ProgPid Then $hWin = _WinGetHandle_ToDesktop($hNewDesktop, 'Notepad') ; получаем дескриптор окна блокнота

If $hWin Then ; Записываем текст, сохраняем и закрываем окно блокнота
    ControlSend($hWin, '', '[CLASS:Edit; INSTANCE:1]', 'Новая Запись ' & @YEAR & '-' & @MON & '-' & @MDAY & ' ' & @HOUR & ':' & @MIN & ':' & @SEC & @CRLF)
    WinClose($hWin)
    $hWin = _WinGetHandle_ToDesktop($hNewDesktop, '#32770') ; Ждем окно подтверждения сохранения
    If $hWin Then ControlClick($hWin, '', '[CLASS:Button; INSTANCE:1]') ; "Ok"
EndIf

; Sleep(3000)

_CloseDesktop($hNewDesktop) ; Закрываем 'MyDesktop'
_WinAPI_FreeMemory($pText) ; Освобождает память выделеную для $pText
; _WinAPI_SwitchDesktop($hPrev)


If MsgBox(262144 + 4, Default, 'Хотите открыть файл "' & $sFile & '" для проверки?') = 6 Then ShellExecute($sFile) ; Проверка

; =======================================================================================
Func _WinGetHandle_ToDesktop(ByRef $hDesktop, $ClassName)
    $iTimer = TimerInit() ; Включаем таймер - это необходимо для предотвращения возможного бесконечного цикла (перестраховка)
    While 1
        $aWindows = _WinAPI_EnumDesktopWindows($hDesktop) ; Перечисляет все окна верхнего уровня, связанные с указанным рабочим столом
        If IsArray($aWindows) Then ; Проверяет, является ли переменная массивом
            For $i = 1 To $aWindows[0][0]
                If $aWindows[$i][1] = $ClassName And WinGetProcess($aWindows[$i][0]) = $ProgPid Then
                    While Not _WinAPI_IsWindowVisible($aWindows[$i][0]) ; Получает видимость состояние указанного окна
                        If TimerDiff($iTimer) >= 10000 Then Return 0; Максимальное время работы данного цикла ~10 секунд
                        Sleep(150)
                    WEnd
                    Return $aWindows[$i][0]
                Else
                    ContinueLoop
                EndIf
            Next
        Else
            Sleep(150)
        EndIf

        If TimerDiff($iTimer) >= 10000 Then Return 0
    WEnd
EndFunc   ;==>_WinGetHandle_ToDesktop

Func _CloseDesktop($hDesktop)
    Local $aWindows = _WinAPI_EnumDesktopWindows($hDesktop)
    If IsArray($aWindows) Then
        For $i = 1 To $aWindows[0][0]
            WinClose($aWindows[$i][0])
        Next
    EndIf
    Return _WinAPI_CloseDesktop($hDesktop)
EndFunc   ;==>_CloseDesktop

Для того чтобы видеть, что происходит при этом, раскомментируйте некоторые стоки скрипта.
 
Последнее редактирование:
Верх