Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Получение лога из дочернего процесса  (Прочитано 35258 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 13-08-2010 07:01 » 

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

Основной процесс запускает дочерний процесс через WinAPI::CreateProcess. Дочерний процесс что-то делает и ведёт текстовый лог. Сейчас лог скидывается в текстовый файл, а вот как бы сделать так, чтобы через стандартный поток лог шёл сразу в основной процесс и там уже обрабатывался?
И будет ли это дело тормозить основной процесс?
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 13-08-2010 10:41 » 

Леш, смотри параметры CreateProcess - можно три потока для дочернего процесса задать (stdin, stdout, stderr). Конечно, трубы придется создать заранее.

http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx

LPSTARTUPINFO lpStartupInfo

http://msdn.microsoft.com/en-us/library/ms686331%28v=VS.85%29.aspx

HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 13-08-2010 13:10 » 

спасибо. Щас кое-что доделаю и стану ковыряться с этим )

вот тут ещё полезный примерчик нашёлся http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx
« Последнее редактирование: 15-08-2010 14:14 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 15-08-2010 17:32 » 

А для чего делается вот это
Код:
// Ensure the read handle to the pipe for STDOUT is not inherited.
   if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
      ErrorExit(TEXT("Stdout SetHandleInformation"));
...
...

// Ensure the write handle to the pipe for STDIN is not inherited.
   if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
      ErrorExit(TEXT("Stdin SetHandleInformation"));
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #4 : 15-08-2010 17:53 » 

Трубы как правило на одном конце затыкают. Тот ктго будет принимать, затыкает запись. И наоборот.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 15-08-2010 17:59 » 

Имя константы - HANDLE_FLAG_INHERIT - наводит на мысль, что в винде тоже можно управлять наследованием открытых файлов для дочернего процесса. Стоит обратиться в MSDN за деталями по SetHandleInformation().
В POSIX-системах по умолчанию все открытые файлы наследуются и можно пометить нужные через fcntl(), чтобы они не наследовались. Думаю тут аналогичный процесс показан.
« Последнее редактирование: 15-08-2010 18:01 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 15-08-2010 18:04 » 

Цитата
HANDLE_FLAG_INHERIT - If this flag is set, a child process created with the bInheritHandles parameter of CreateProcess set to TRUE will inherit the object handle.

а, ну, то есть, это "затыкание" выражается в том, что хендл не передаётся программистом дочернему процессу. А если случайно всё-таки он передал, то хендл будет там недействителен
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 15-08-2010 18:37 » 

Да, кстати, всё никак не могу победить такую штуку - когда запускаю дочерний процесс (у него своё окно есть, правда скрытое - задаю это ещё в структуре STARTUPINFO),  то фокус теряется с главного процесса.

Никакие SetFocus и обработка WM_KILLFOCUS для главного окна родительского процесса не спасают. Что тут сделать нужно, чтоб фокус оставался на окне главного процесса?
Записан

zubr
Гость
« Ответ #8 : 15-08-2010 20:16 » 

1. Дождаться окончания загрузки дочернего процесса.
2. Вызвать ShowWindow SW_SHOW, затем SetFocus для родительского процесса.
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 15-08-2010 20:34 » 

А если сделать также, как делает обычный пользователь? Установи фокус на другое окно и потом верни на свое.
Может есть более гуманные способы...
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 16-08-2010 03:38 » 

zubr, RXL, всё это пробовал раньше и попробовал на всякий случай сейчас ещё раз - не помогает.

Делал даже тупо Sleep(5000) (процесс запускается за это время уж точно на 100%) - потом фокус на рабочий стол, потом на главное окно. И нифига, всё равно фокус потерян
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #11 : 16-08-2010 08:52 » 

Ну а чего spy++ говорит? какие сообщения приходят окну (как родительскому, так и дочернему)? Речь конечно о сообщения, которые как-то влияют на отображение окон и потерю+захват фокуса.
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 16-08-2010 09:02 » 

lapulya, для главного окна происходит следующее (из состояния "в фокусе"+ "дочерний ещё не запущен"):



а для дочернего не могу посмотреть по техническим причинам Улыбаюсь

* activate.PNG (10.86 Кб - загружено 1695 раз.)
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 16-08-2010 09:02 » 

Делать ActivateWindow для главного окна я пробовал - нет реакции
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #14 : 16-08-2010 12:04 » 

В какой момент открыто окно дочернего процесса (это я про лог сообщений)?
А обойти эти технические причмны нельзя, чтобы посмотреть чтож там у дочки то?
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 16-08-2010 13:28 » 

lapulya, окно дочернего процесса вообще всегда невидимо, а лог записывался в текстовый файл на диске

А как обойти то ? Разве что записать все сообщения в оконной процедуре. Но это долго возиться

Да оно не так уж важно, так как у меня при запуске программы дочерние создаются, но всё равно неприятно )

Я , как руки дойдут, попробую тестовый проект сделать - может быть, у меня какая-то особенность вкралась
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 16-08-2010 18:22 » 

А нет апишки для побайтового сравнения двух файлов (на предмет одинаковые/разные)?
Не смог найти в MSDN

Или же придётся вручную делать маппинг обоих файлов, а потом memcmp()==0 ?

А зачем - так у меня дочерний процесс формируется копированием исходного экзешника, а потом переименовывается и запускается
Хочется избежать лишнего копирования
« Последнее редактирование: 16-08-2010 18:24 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 16-08-2010 19:47 » 

оть
Код:
//тест на необходимость копирования
//const char* pSrcModulePath
//const char* pDstModulePath
bool bNeedCopy=true;
{
HANDLE H1=0;
HANDLE H2=0;
HANDLE M1=0;
HANDLE M2=0;
void* pf1=0;
void* pf2=0;
for(;;)
{
H1=::CreateFile(pSrcModulePath,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
H2=::CreateFile(pDstModulePath,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
if(H1==INVALID_HANDLE_VALUE)break;
if(H2==INVALID_HANDLE_VALUE)break;

DWORD dwdSize=::GetFileSize(H1,0);
if(dwdSize!=::GetFileSize(H2,0))break;

M1=::CreateFileMapping(H1,0,PAGE_READONLY,0,dwdSize,0);
M2=::CreateFileMapping(H2,0,PAGE_READONLY,0,dwdSize,0);
if(M1==0)break;
if(M2==0)break;

pf1=::MapViewOfFile(M1,FILE_MAP_READ,0,0,dwdSize);
pf2=::MapViewOfFile(M2,FILE_MAP_READ,0,0,dwdSize);
if(pf1==0)break;
if(pf2==0)break;

if(0!=::memcmp(pf1,pf2,dwdSize))break;

bNeedCopy=false;
break;
}
if(pf1)::UnmapViewOfFile(pf1);pf1=0;
if(pf2)::UnmapViewOfFile(pf2);pf2=0;
if(M1)::CloseHandle(M1);M1=0;
if(M2)::CloseHandle(M2);M2=0;
if(H1)::CloseHandle(H1);H1=0;
if(H2)::CloseHandle(H2);H2=0;
}


//копируем
if(!bNeedCopy || ::CopyFile(pSrcModulePath, pDstModulePath,0))
{
    //запуск дочернего процесса
    ...
}
« Последнее редактирование: 16-08-2010 20:00 от Алексей1153++ » Записан

baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #18 : 17-08-2010 06:39 » 

А нет апишки для побайтового сравнения двух файлов (на предмет одинаковые/разные)?
Не смог найти в MSDN

Или же придётся вручную делать маппинг обоих файлов, а потом memcmp()==0 ?

А зачем - так у меня дочерний процесс формируется копированием исходного экзешника, а потом переименовывается и запускается
Хочется избежать лишнего копирования

Лёх, попробуй какую-нибудь функцию для взятия хэша, типа getmd5() или ече что-нибудь такое.. Сравнишь хэши. Не должно быть долго, зато самому писать не надо.
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 17-08-2010 08:31 » 

baldr, да уже написал вроде )) Но сильно сомневаюсь, что расчёт хеша будет быстрее, чем memcmp двух проекций. Файлы - по 5 метров, сравнивается мгновенно

Кстати, работают трубы, всё , победил )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 18-08-2010 06:49 » 

Жаль только, что отладку второй процесс уже не запустишь так, чтоб там были унаследованные хендлы (
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 19-08-2010 04:58 » 

А вот такой ещё вопрос. Что передать в качестве stdOUT хендла процессу, чтоб он выводил поток в окно отладки студии ? Такое возможно?
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 03-09-2010 07:11 » 

ещё вопрос:
как не заблокироваться при чтении из трубы я сделал через PeekNamedPipe , а воть как определить, что в трубу больше не надо записывать (что она полная), чтобы не заблокироваться ?
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 03-09-2010 08:35 » 

Леш, а что твой процесс будет делать, если труба полная? Тут либо писать (и блокироваться), либо увеличивать буфер, либо сбрасывать во временный файл, либо вообще отбрасывать.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #24 : 03-09-2010 10:09 » 

он просто перестанет записывать, пусть данные теряются. Главное, чтоб не застопорилось
Записан

resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 03-09-2010 23:04 » 

Чтоб не блокироваться на I/O операциях, весь мир издревле пользуется асинхронным I/O.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #26 : 04-09-2010 09:17 » 

resource, как его сделать асинхронным ?
Записан

Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 04-09-2010 11:38 » 

структуру  OVERLAPPED заполнить,  когда ReadFile/WriteFile вызываешь)
еще кажется при CreateFile  - флаг FILE_FLAG_OVERLAPPED поставить... в msdn надо глянуть)
либо сразу  ReadFileEx()использовать
« Последнее редактирование: 04-09-2010 11:43 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 04-09-2010 12:56 » 

В данном случае наверное не CreateFile, а CreateNamedPipe. dwOpenMode  должен включать FILE_FLAG_OVERLAPPED. Ну и дальше
Цитата: MSDN
The ReadFileEx and WriteFileEx functions can only be used with a pipe handle in overlapped mode. The ReadFile, WriteFile, ConnectNamedPipe, and TransactNamedPipe functions can execute either synchronously or as overlapped operations.
Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #29 : 04-09-2010 15:13 » 

соответственно)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines