:: Visual Foxpro, Foxpro for DOS
Re: Как перехватить stdout/stderr при вызове внешней программы?
medstrах

Сообщений: 1810
Дата регистрации: 10.06.2019
of63
Ястно, кода нет, очередной пишущий в стол...
Ты не обратил внимание на фразу "мне нужен"
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
_vit

Сообщений: 5176
Дата регистрации: 29.07.2002
kvichans
of63
А вот так?
o=CreateObject("Wscript.Shell")
x=o.Exec("cmd /c dir")
x.Terminate()
? x.StdOut.ReadAll
(c Piva)
Ух ты! Выглядит здорово. Буду это осваивать

В этом коде две алгоритмические ошибки.

1. сначала запускается процесс (команда dir в данном случае)
x=o.Exec("cmd /c dir")
и тут же посылается команда закрыть его.
x.Terminate()
Terminate() - посылает оконное сообщение WM_CLOSE главному окну процесса.
В результате ваш внешний процесс который вы запустили может не успеть выполнить свою работу
И здесь
x.StdOut.ReadAll
вы можете не получить ничего или только часть данных.

2. Terminate() не закрываеет процесс мгновенно получив сообщение WM_CLOSE приложение может
производить еще какие то действия и выводить данные.
А x.StdOut.ReadAll уже считывает данные хотя вывод может еще быть не законченным.

Прежде чем читать надо убедиться что приложение (процесс) завершен
т.е. ждать пока
x.Status = 1

В случае когда запускаемое внешнее приложение само завершается выполнив свою функцию как команда dir например
правильно будет так:

o=Createobject("Wscript.Shell")
x=o.Exec("cmd /c dir c:")
Do While x.Status = 0
DoEvents
Enddo
? x.StdOut.ReadAll

x.Terminate() следует использовать с осторожностью если внешнее приложение само не завершается как например - notepad.

o=Createobject("Wscript.Shell")
x=o.Exec("notepad.exe")
WAIT WINDOW TIMEOUT 5
x.terminate()
Do While x.Status = 0
DoEvents
Enddo
? x.StdOut.ReadAll
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
_vit

Сообщений: 5176
Дата регистрации: 29.07.2002
И еще вариант.

LOCAL loWSS
loWSS = CreateObject("WScript.Shell")
loWSS.Run("cmd /c dir > d:/out.txt 2>&1", 0, .t.)

Здесь можете ознакомиться в чем разница между вариантами.
www.script-coding.com
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
() Надеюсь ТС решит проблу, и расскажет её нам, коллективу )
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
kvichans
Автор

Сообщений: 307
Откуда: Москва
Дата регистрации: 19.01.2006
of63
() Надеюсь ТС решит проблу, и расскажет её нам, коллективу )
Работаю над этим

------------------
Андрей, FoxPro с 2003 года
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
kvichans
Автор

Сообщений: 307
Откуда: Москва
Дата регистрации: 19.01.2006
Идея оказалась хорошая.
Вот так работает
function call_py(sPyBody, sPyFile, sPyCmd, tWait)
* sPyBody - py-code to execute
* sPyFile - temporary file to save py-code
* sPyCmd - Python exe-file (likes c:\Programs\Anaconda3\python.exe)
* tWait - Max time to do (secs)
* Save py-body to file
* sPyBody = STRCONV(sPyBody, 9) && Convert to UTF-8 (if need)
STRTOFILE(sPyBody, sPyFile)
* Execute
LOCAL sExec, oWSh, tStart, oProc
sExec = sPyCmd + [ "] + sPyFile + ["]
oWSh = CreateObject("Wscript.Shell")
oProc = oWSh.Exec(sExec) && Start...
tStart = SECONDS()
DO WHILE oProc.Status = 0
DOEVENTS
INKEY(0.1) && =Sleep
IF tStart+tWait < SECONDS() && ...secs! Try to kill process
oProc.terminate()
ENDIF
IF tStart+tWait+1 < SECONDS() && ...secs! Panic: process is not finished
EXIT
ENDIF
ENDDO
IF oProc.Status = 0 && Panic: process is not finished
trace("SKIP! Process not finished: "+sExec)
RETURN
ENDIF
* Show results
LOCAL sOut, sErr
sOut = oProc.StdOut.ReadAll()
sErr = oProc.StdErr.ReadAll()
trace(sOut)
IF !EMPTY(sErr)
trace(sErr)
ENDIF
endfunc

Засыпание на 0.1 сек добавлено для разгрузки процессора.
Без него тоже работает, но успевает (на крохотном пи-коде) прокрутить десятки тысяч циклов.

Из недостатков пока вижу только один. При каждом выполнении Питона выскакивает окно терминала.


------------------
Андрей, FoxPro с 2003 года




Исправлено 2 раз(а). Последнее : kvichans, 08.07.19 17:22
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
medstrах

Сообщений: 1810
Дата регистрации: 10.06.2019
kvichans
Из недостатков пока вижу только один. При каждом выполнении Питона выскакивает окно терминала.
А нельзя как-то стартовать питон на другом десктопе, чтобы избежать подобного эффекта? Помнится, Рома демонстрировал запуск приложения на других десктопах.
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
В интернетах пишут, что у шелла есть .Run, 3й параметр -
Параметр может принимать целые значения от 0 до 10. Согласно документации, в языке vbscript можно использовать именованные константы, но, они не всегда дают ожидаемый результат, и так как эти значения между собой повторяются, я упомянул лишь три:
•0 – скрывает окно, будет виден только процесс в диспетчере задач.
•1 – нормальный режим
•2 – свернутый вид
•3 – развернутый вид


scriptcoding.ru
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
kvichans
Автор

Сообщений: 307
Откуда: Москва
Дата регистрации: 19.01.2006
of63
.Run, 3й параметр - может принимать целые значения от 0 до 10.
Да. Этим я уже давно пользуюсь. Ставлю 7 и окно появляется только в TaskBar-е.
Но при таком запуске нет перехвата потоков


------------------
Андрей, FoxPro с 2003 года
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
_vit

Сообщений: 5176
Дата регистрации: 29.07.2002
of63
В интернетах пишут, что у шелла есть .Run, 3й параметр -
Параметр может принимать целые значения от 0 до 10. Согласно документации, в языке vbscript можно использовать именованные константы, но, они не всегда дают ожидаемый результат, и так как эти значения между собой повторяются, я упомянул лишь три:
•0 – скрывает окно, будет виден только процесс в диспетчере задач.
•1 – нормальный режим
•2 – свернутый вид
•3 – развернутый вид


scriptcoding.ru

Это так. Только второй параметр ;)

третий определяет будет ли ожидаться завершение процесса.

_vit
И еще вариант.
LOCAL loWSS
loWSS = CreateObject("WScript.Shell")
loWSS.Run("cmd /c dir > d:/out.txt 2>&1", 0, .t.)

но тогда придется повозится что-бы закрыть питоновскую программу по таймауту.



Исправлено 1 раз(а). Последнее : _vit, 08.07.19 18:05
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
_vit

Сообщений: 5176
Дата регистрации: 29.07.2002
kvichans
of63
.Run, 3й параметр - может принимать целые значения от 0 до 10.
Да. Этим я уже давно пользуюсь. Ставлю 7 и окно появляется только в TaskBar-е.
Но при таком запуске нет перехвата потоков

Выводить в файл.

Или возьми себя в руки и реализуй задачу с использованием CreateProcess WinAPI.
Тогда сможешь вертеть как хочешь.;)
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
BOOL CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);

Проще сочинить вспомогательную фоксовую прогу, и запустить её, в фоне, или как, мтк. Чем не параллельный процесс. Многопроцессорность )))
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
kvichans
Автор

Сообщений: 307
Откуда: Москва
Дата регистрации: 19.01.2006
_vit
... с использованием CreateProcess WinAPI. Тогда сможешь вертеть как хочешь.;)
Меня и найденный способ вполне устроил.
Всем спасибо.


------------------
Андрей, FoxPro с 2003 года
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
medstrах

Сообщений: 1810
Дата регистрации: 10.06.2019
kvichans
Всем спасибо.
Спасибо мало, мог бы и закинуть десяток баксов в виде благодарности
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Обойдемся. ТС, не прими за чистую монету )
Ratings: 0 negative/0 positive
Re: Как перехватить stdout/stderr при вызове внешней программы?
medstrах

Сообщений: 1810
Дата регистрации: 10.06.2019
of63
Обойдемся. ТС, не прими за чистую монету )
Почему ты так не ценишь себя?
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 18 (Гостей: 18)

© 2000-2024 Fox Club 
Яндекс.Метрика