Что нового

Непредсказуемое поведение RunWait

tech-gs

Знающий
Сообщения
54
Репутация
5
Проблема в следующем.
Выполнение функции RunWait досрочно прерывается с кодом возврата -1, если запущена и завершена еще одна RunWait.
Может где-то ошибка в программе, но подозреваю что это глюк AutoIt. Надеюсь гуру форума помогут разобраться с проблемой.

Код:
#Include-Once
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#Include <Timers.au3>
AutoItSetOption('MustDeclareVars', 1)

Global $hGUI = GUICreate('Testing CMD', 300, 100, Default, Default)
Global $btn1 = GUICtrlCreateButton('Run Cmd1', 40, 40, 90, 24)
Global $btn2 = GUICtrlCreateButton('Run Cmd2', 170, 40, 90, 24)

Global $Cmd1 = '"' & @COMSPEC & '" /v:on /c "@echo off & title Testing CMD1 & echo. & echo Testing CMD1 & echo ======================= & echo. & echo Normal return code - 35 & echo Autoexit from 30 sec... & echo. & set RET=35 & ping -n 30 localhost > nul & exit /b !RET!"'
Global $Cmd2 = '"' & @COMSPEC & '" /v:on /c "@echo off & title Testing CMD2 & echo. & echo Testing CMD2 & echo ======================= & echo. & echo Normal return code - 20 & echo Autoexit from 5 sec...  & echo. & set RET=20 & ping -n  5 localhost > nul & exit /b !RET!"'
;	MsgBox(64, 'Command info', 'Command cmd1:' & @LF & $Cmd1 & @LF & @LF & 'Command cmd2:' & @LF & $Cmd2)
Global $ret = 0, $msg = 0

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")
GUIRegisterMsg($WM_TIMER, '_WM_TIMER')
Global $iTimer1 = _Timer_SetTimer($hGUI, 500)


	While 1
		$msg = GUIGetMsg()

		Switch $msg
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch

	WEnd

	GUIDelete()
	Exit


Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
#forceref $hWnd, $Msg
Local $nNotifyCode = BitShift($wParam, 16) ; Hi Word
Local $nID = BitAND($wParam, 0x0000FFFF) ; Low Word - PID
Local $hCtrl = $lParam

	Switch $nID
		Case 0
		Case $btn1
			$ret = RunWait($Cmd1, '', @SW_SHOW)
			MsgBox(64, 'Info Button1 (ID=' & $nID & ')', 'Command Cmd1 completed' & @LF & @LF & 'Exit code ' & $ret, 0)
		Case $btn2
			$ret = RunWait($Cmd2, '', @SW_SHOW)
			MsgBox(64, 'Info Button2 (ID=' & $nID & ')', 'Command Cmd2 completed' & @LF & @LF & 'Exit code ' & $ret, 3)
	EndSwitch

	Return $GUI_RUNDEFMSG
EndFunc

Func _WM_TIMER($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $ilParam

	Switch _Timer_GetTimerID($iwParam)
		Case $iTimer1
;			...
	EndSwitch

	Return $GUI_RUNDEFMSG
EndFunc


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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Кто же из обработчиков WM-сообщений вызывает RunWait()...

[quote author=AutoIt Help]
Warning: blocking of running user functions which executes window messages with commands such as "Msgbox()" can lead to unexpected behavior, the return to the system should be as fast as possible !!!
[/quote]
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Понятно что так не правильно, но проблема все же существует.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
tech-gs сказал(а):
Понятно что так не правильно, но проблема все же существует.

В чем проблема? Зачем здесь вообще нужна WM_COMMAND?
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Хотелось бы чтобы первая RunWait отработала до конца.
Возможно ли реализовать по другому запуск двух процессов с ожиданием отработки каждого?


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

Yashied сказал(а):
Зачем здесь вообще нужна WM_COMMAND

Это всего лишь кусок программы. В ней события реализованы через WM_COMMAND.


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

Yashied сказал(а):

Хотелось бы не только дождаться отработки обоих процессов, но и вернуть код возврата из CMD.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
...
$Pid1 = Run('prog1.exe')
$Pid2 = Run('prog2.exe')
...
While 1
	Sleep(100)
	...
	If ProcessExists($Pid1) Then
		...
	EndIf
	...
	If ProcessExists($Pid1) Then
		...
	EndIf
	...
WEnd
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Yashied сказал(а):
$Pid1 = RunWait('prog1.exe')
$Pid2 = RunWait('prog2.exe')

$Pid2 = RunWait('prog2.exe') ведь срабатывает только после отработки $Pid1 = RunWait('prog1.exe'), а если использовать Run(...), то не вернуть код возврата CMD.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Это я перепутал. Конечно же не RunWait(), а просто Run(). А дальше проверяешь в цикле существование процессов по их PID'ам. Но EXITCODE таким образом ты не получишь... Есть другие способы, но нужно знать точно, что ты хочешь сделать, и что за программы в RunWait(). AutoIt'овские?
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Yashied сказал(а):
что ты хочешь сделать и что за программы в RunWait()

Через RunWait запускается две копии командной строки, как и в приведенном примере. Наверное нет смысла приводить, что именно делается в CMD. Если вкратце - в каждом сеансе запускается та или иная консольная утилита, устанавливающая %ERRORLEVEL%. Код возврата оба сеанса реализуют через set RET=!ERRORLEVEL! & ... & exit /b !RET!
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Тогда самый оптимальный вариант, это создание еще одного небольшого AutoIt скрипта, который будет реализовывать RunWait() и отправлять результат в основной скрипт с помощью WM_COPYDATA. Тебе остается только ловить эти сообщения. Сможешь?

P.S

Можно даже реализовать все в одном скрипте.
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
С WM_COPYDATA пока не работал, попробую разобраться. Только вот не хотелось бы делить программу на несколько экзешников.


Yashied сказал(а):
Кто же из обработчиков WM-сообщений вызывает RunWait()
А если RunWait будут вызываться, например, из таймеров или т.п. - так будет корректно, но первый RunWait все равно не отработает правильно. Значит это глюк функции? :-\
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
RunWait() останавливает выполнение программы на неопределенное время. Поэтому, не из "таймеров", не из WM ее вызывать нельзя. Если бы твоя программа была написана, например, на C#, то после первого же вызова RunWait() из WM она бы наглухо повисла. AutoIt не предусматривает более одного запуска RunWait() одновременно, т.к. не поддерживает потоки. Следовательно, в этом нет никакого смысла.
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Yashied
Информации по WM_COPYDATA ни в справке, ни по форуму не нашел. Подкинь, плиз, хотя бы костяк реализации передачи данных между программами или внутри одного скрипта.
 

Yashied

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

:smile:

20-30 мин...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
; http://autoit-script.ru/index.php?topic=3768.0

#NoTrayIcon

#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>

Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)

Global Const $RECEIVER_NAME = 'MzXq@Cmd#10'
Global Const $tagRUNWAIT = 'int ExitCode;dword ID'

If ($CmdLine[0] = 2) And (StringInStr($CmdLine[1], '/runwait:') = 1) And (StringInStr($CmdLine[2], '/id:') = 1) Then
	$ExitCode = RunWait(StringTrimLeft($CmdLine[1], 9))
	If @error Then
		$ExitCode = -1
	EndIf
	_SendMsg(WinGetHandle($RECEIVER_NAME), $ExitCode, Number(StringTrimLeft($CmdLine[2], 4)))
	Exit
EndIf

; Окно для приема сообщений WM_COPYDATA (можно и в основное окно, но заголовок должен быть уникальным)
$hReceiver = GUICreate($RECEIVER_NAME)

; GUI
$hForm = GUICreate('MyGUI', 573, 252)

; Бонус :-)
InetGet('http://yashied.narod2.ru/ProjectFiles/Miscellaneous/Dark_Archon_Black.gif', @TempDir & '\Dark_Archon_Black.gif')
GUICtrlCreatePic(@TempDir & '\Dark_Archon_Black.gif', 222, 100, 128, 128)
GUICtrlSetState(-1, $GUI_DISABLE)

; Run 1
GUICtrlCreateLabel('RunWait(', 20, 20, 48, 14)
$Input1 = GUICtrlCreateInput('cmd.exe', 69, 17, 320, 19)
GUICtrlCreateLabel(')=', 393, 20, 11, 14)
$Input2 = GUICtrlCreateInput('', 406, 17, 77, 19)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button1 = GUICtrlCreateButton('Run', 494, 14, 60, 25)
$Dummy1 = GUICtrlCreateDummy()

; Run 2
GUICtrlCreateLabel('RunWait(', 20, 20+40, 48, 14)
$Input3 = GUICtrlCreateInput('cmd.exe', 69, 17+40, 320, 19)
GUICtrlCreateLabel(')=', 393, 20+40, 11, 14)
$Input4 = GUICtrlCreateInput('', 406, 17+40, 77, 19)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button2 = GUICtrlCreateButton('Run', 494, 14+40, 60, 25)
$Dummy2 = GUICtrlCreateDummy()

GUIRegisterMsg($WM_COPYDATA, 'WM_COPYDATA')
GUISetState()

While 1
	Switch GUIGetMsg()
		Case 0
			ContinueLoop
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Button1
			If @compiled Then
				Run(@ScriptFullPath & '" /runwait:' & GUICtrlRead($Input1) & '" ' & '/id:1')
			Else
				Run(@AutoItExe & ' "' & @ScriptFullPath & '" ' & '"/runwait:' & GUICtrlRead($Input1) & '" ' & '/id:1')
			EndIf
			GUICtrlSetState($Button1, $GUI_DISABLE)
			GUICtrlSetState($Input1, $GUI_DISABLE)
			GUICtrlSetData($Input2, 'WAIT...')
		Case $Button2
			If @compiled Then
				Run(@ScriptFullPath & '" /runwait:' & GUICtrlRead($Input3) & '" ' & '/id:2')
			Else
				Run(@AutoItExe & ' "' & @ScriptFullPath & '" ' & '"/runwait:' & GUICtrlRead($Input3) & '" ' & '/id:2')
			EndIf
			GUICtrlSetState($Button2, $GUI_DISABLE)
			GUICtrlSetState($Input3, $GUI_DISABLE)
			GUICtrlSetData($Input4, 'WAIT...')
		Case $Dummy1 ; Приходит от WM_COPYDATA при завершении программы с ID = 1 ("/id:1")
			$ExitCode = GUICtrlRead($Dummy1)
			If $ExitCode = -1 Then
				$ExitCode = 'ERROR'
			EndIf
			GUICtrlSetData($Input2, $ExitCode)
			GUICtrlSetState($Button1, $GUI_ENABLE)
			GUICtrlSetState($Input1, $GUI_ENABLE)
		Case $Dummy2 ; Приходит от WM_COPYDATA при завершении программы с ID = 2 ("/id:2")
			$ExitCode = GUICtrlRead($Dummy2)
			If $ExitCode = -1 Then
				$ExitCode = 'ERROR'
			EndIf
			GUICtrlSetData($Input4, $ExitCode)
			GUICtrlSetState($Button2, $GUI_ENABLE)
			GUICtrlSetState($Input3, $GUI_ENABLE)
	EndSwitch
WEnd

FileDelete(@TempDir & '\Dark_Archon_Black.gif')

Func _SendMsg($hWnd, $iExitCode, $iID)

	Local $tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr')
	Local $tRW = DllStructCreate($tagRUNWAIT)
	Local $Ret

	DllStructSetData($tRW, 'ExitCode', $iExitCode)
	DllStructSetData($tRW, 'ID', $iID)
	DllStructSetData($tCOPYDATA, 1, 0)
	DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tRW))
	DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tRW))
	$Ret = DllCall('user32.dll', 'lresult', 'SendMessage', 'hwnd', $hWnd, 'uint', $WM_COPYDATA, 'ptr', 0, 'ptr', DllStructGetPtr($tCOPYDATA))
	If (@error) Or (Not $Ret[0]) Then
		Return 0
	EndIf
	Return 1
EndFunc   ;==>_SendMsg

Func WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $hReceiver

			Local $tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr', $lParam)
			Local $tRW = DllStructCreate($tagRUNWAIT, DllStructGetData($tCOPYDATA, 3))
			Local $ExitCode = DllStructGetData($tRW, 'ExitCode')
			Local $ID = DllStructGetData($tRW, 'ID')

			Switch $ID
				Case 1 ; "/id:1"
					GUICtrlSendToDummy($Dummy1, $ExitCode)
				Case 2 ; "/id:2"
					GUICtrlSendToDummy($Dummy2, $ExitCode)
				Case Else

			EndSwitch
			Return 1
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COPYDATA
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Все работает. Великолепное решение!
Правда, не совсем понял технологию передачи кода возврата в соответствующий Dummy.

И еще требуется одно уточнение. Здесь скрипт дважды не запускается, а создается лишь две формы (одна из которых скрыта), между которыми и происходит передача данных?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Нет. При нажатии кнопки "Run", скрипт запускает сам себя еще раз с параметрами

"/runwait:... /id:..."

В первом параметре передается непосредственно строка для RunWait(), во втором - уникальный номер (ID), в данном случае 1 или 2, который, вместе с кодом возврата $ExitCode, отсылается обратно в основную программу с помощью WM_COPYDATA. Именно по этому ID, основная программа и определяет, от какого именно процесса пришло сообщение, и, следовательно, какому Dummy нужно передать значение $ExitCode. Так понятно?

P.S

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вот тот же пример, но без второго (скрытого) окна. Здесь хендл окна основной программы, т.е. того, в которое необходимо послать сообщение WM_COPYDATA, передается в третьем параметре (в отличии от заголовков, хендлы уникальны в пределах всей системы):

"/runwait:... /id:... /handle:..."

Код:
; http://autoit-script.ru/index.php?topic=3768.0

#NoTrayIcon

#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>

Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)

Global Const $tagRUNWAIT = 'int ExitCode;dword ID'

If ($CmdLine[0] = 3) And (StringInStr($CmdLine[1], '/runwait:') = 1) And (StringInStr($CmdLine[2], '/id:') = 1) And (StringInStr($CmdLine[3], '/handle:') = 1) Then
	$ExitCode = RunWait(StringTrimLeft($CmdLine[1], 9))
	If @error Then
		$ExitCode = -1
	EndIf
	_SendMsg(Number(StringTrimLeft($CmdLine[3], 8)), $ExitCode, Number(StringTrimLeft($CmdLine[2], 4)))
	Exit
EndIf

; GUI
$hForm = GUICreate('MyGUI', 573, 252)

; Бонус :-)
InetGet('http://yashied.narod2.ru/ProjectFiles/Miscellaneous/Dark_Archon_Black.gif', @TempDir & '\Dark_Archon_Black.gif')
GUICtrlCreatePic(@TempDir & '\Dark_Archon_Black.gif', 222, 100, 128, 128)
GUICtrlSetState(-1, $GUI_DISABLE)

; Run 1
GUICtrlCreateLabel('RunWait(', 20, 20, 48, 14)
$Input1 = GUICtrlCreateInput('cmd.exe', 69, 17, 320, 19)
GUICtrlCreateLabel(')=', 393, 20, 11, 14)
$Input2 = GUICtrlCreateInput('', 406, 17, 77, 19)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button1 = GUICtrlCreateButton('Run', 494, 14, 60, 25)
$Dummy1 = GUICtrlCreateDummy()

; Run 2
GUICtrlCreateLabel('RunWait(', 20, 20+40, 48, 14)
$Input3 = GUICtrlCreateInput('cmd.exe', 69, 17+40, 320, 19)
GUICtrlCreateLabel(')=', 393, 20+40, 11, 14)
$Input4 = GUICtrlCreateInput('', 406, 17+40, 77, 19)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button2 = GUICtrlCreateButton('Run', 494, 14+40, 60, 25)
$Dummy2 = GUICtrlCreateDummy()

GUIRegisterMsg($WM_COPYDATA, 'WM_COPYDATA')
GUISetState()

While 1
	Switch GUIGetMsg()
		Case 0
			ContinueLoop
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Button1
			If @compiled Then
				Run(@ScriptFullPath & '" /runwait:' & GUICtrlRead($Input1) & '" ' & '/id:1')
			Else
				Run(@AutoItExe & ' "' & @ScriptFullPath & '" ' & '"/runwait:' & GUICtrlRead($Input1) & '" ' & '/id:1 /handle:' & Number($hForm))
			EndIf
			GUICtrlSetState($Button1, $GUI_DISABLE)
			GUICtrlSetState($Input1, $GUI_DISABLE)
			GUICtrlSetData($Input2, 'WAIT...')
		Case $Button2
			If @compiled Then
				Run(@ScriptFullPath & '" /runwait:' & GUICtrlRead($Input3) & '" ' & '/id:2')
			Else
				Run(@AutoItExe & ' "' & @ScriptFullPath & '" ' & '"/runwait:' & GUICtrlRead($Input3) & '" ' & '/id:2 /handle:' & Number($hForm))
			EndIf
			GUICtrlSetState($Button2, $GUI_DISABLE)
			GUICtrlSetState($Input3, $GUI_DISABLE)
			GUICtrlSetData($Input4, 'WAIT...')
		Case $Dummy1 ; Приходит от WM_COPYDATA при завершении программы с ID = 1 ("/id:1")
			$ExitCode = GUICtrlRead($Dummy1)
			If $ExitCode = -1 Then
				$ExitCode = 'ERROR'
			EndIf
			GUICtrlSetData($Input2, $ExitCode)
			GUICtrlSetState($Button1, $GUI_ENABLE)
			GUICtrlSetState($Input1, $GUI_ENABLE)
		Case $Dummy2 ; Приходит от WM_COPYDATA при завершении программы с ID = 2 ("/id:2")
			$ExitCode = GUICtrlRead($Dummy2)
			If $ExitCode = -1 Then
				$ExitCode = 'ERROR'
			EndIf
			GUICtrlSetData($Input4, $ExitCode)
			GUICtrlSetState($Button2, $GUI_ENABLE)
			GUICtrlSetState($Input3, $GUI_ENABLE)
	EndSwitch
WEnd

FileDelete(@TempDir & '\Dark_Archon_Black.gif')

Func _SendMsg($hWnd, $iExitCode, $iID)

	Local $tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr')
	Local $tRW = DllStructCreate($tagRUNWAIT)
	Local $Ret

	DllStructSetData($tRW, 'ExitCode', $iExitCode)
	DllStructSetData($tRW, 'ID', $iID)
	DllStructSetData($tCOPYDATA, 1, 0)
	DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tRW))
	DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tRW))
	$Ret = DllCall('user32.dll', 'lresult', 'SendMessage', 'hwnd', $hWnd, 'uint', $WM_COPYDATA, 'ptr', 0, 'ptr', DllStructGetPtr($tCOPYDATA))
	If (@error) Or (Not $Ret[0]) Then
		Return 0
	EndIf
	Return 1
EndFunc   ;==>_SendMsg

Func WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm

			Local $tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr', $lParam)
			Local $tRW = DllStructCreate($tagRUNWAIT, DllStructGetData($tCOPYDATA, 3))
			Local $ExitCode = DllStructGetData($tRW, 'ExitCode')
			Local $ID = DllStructGetData($tRW, 'ID')

			Switch $ID
				Case 1 ; "/id:1"
					GUICtrlSendToDummy($Dummy1, $ExitCode)
				Case 2 ; "/id:2"
					GUICtrlSendToDummy($Dummy2, $ExitCode)
				Case Else

			EndSwitch
			Return 1
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COPYDATA
 
Автор
T

tech-gs

Знающий
Сообщения
54
Репутация
5
Спасибо, примерно понятно.
Но здесь может быть один недостаток. Если программа сама по себе массивная и запускается долго, то будет большая пауза перед выполнением второй команды, связанная с запуском второй копии программы. Это можно попробовать решить, например, заранее скомпилировав маленький exe-шник (строки 1 - 21), отвечающий за выполнение следующей RunWait, устанавливать его через FileInstall(...) куда-нибудь в TEMP, а по окончании его работы убивать.

И еще один вопрос. В таком виде можно ли через WM_COPYDATA реализовать перенаправление вывода из cmd-окна в основную форму, чтобы визуально избавиться от cmd-окон, но видеть результаты их работы?
Пробовал это сделать через
Код:
$iOutTo = GUICtrlCreateEdit('', 10, 28, $FW-22, $FH-116, $ES_MULTILINE+$WS_VSCROLL+$ES_AUTOVSCROLL+$ES_READONLY)
	...
	$Pid = Run($sCmd, '', @SW_HIDE, $STDIN_CHILD+$STDERR_CHILD + $STDOUT_CHILD+$STDERR_MERGED)
	If $Pid Then
		While 1
			$Line = StdoutRead($Pid)
			If @error Then ExitLoop
			If @extended <> 0 Then
				$Line = _StringOEM2ANSI($Line)
				$Data &= $Line
				If $Data <> '' Then
					GUICtrlSetData($iOutTo, $Line, 1)
				EndIf
			EndIf
			Sleep(10)
		WEnd
	EndIf

но в таком виде информация в $iOutTo почему-то вставляется совсем не построчно, а большими блоками, причем последние данные вообще теряются.
 
Верх