Послать CTRL_C_EVENT консольному приложению

Тема в разделе "WASM.WIN32", создана пользователем Vladimir Bondarenko, 14 авг 2004.

  1. Vladimir Bondarenko

    Vladimir Bondarenko New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2004
    Сообщения:
    1
    Адрес:
    Ukraine
    Добрый день.



    Имеется консольное приложение, создаваемое через CreateProcess(CREATE_NEW_PROCESS_GROUP). Дескрипторы ввода-вывода переназначаются на анонимные пайпы.



    При некоторых условиях консольное приложение зацикливается и требуется послать ему Ctrl+C (оно умеет обрабатывать его).



    Попытка реализовать это через GenerateConsoleCtrlEvent(CTRL_C_EVENT,pInfo.dwProcessId) ни к чему не приводит: GetLastError возвращает 6 (неверный дескриптор).



    Как же всё-таки послать консольному приложению сигнал прерывания работы (Ctrl+C)?0
     
  2. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    На CTRL_BREAK_EVENT тоже не реагирует ?
     
  3. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
  4. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Vladimir Bondarenko

    А ведь действительно, так не выходит.



    Если, например, взять tutorial Iczelion'a ("пайпы") и добавить в него запись — не получается завершить консольное приложение таким способом.



    bogrus

    Да, и на это не реагирует. Но не само приложение (например, tracert) не реагирует на Ctrl+C/Ctrl+Break, а не реагирует на GenerateConsoleCtrlEvent.



    Но почему код ошибки 6? Ведь даже если в dwGroupProcessID указать 0 (отсылать всем процессам, разделяющим консоль с моим), то всё одно ошибка та же.



    Toxic

    Что-то я в том топике не нашёл решения проблемы. Может, поделишься?
     
  5. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    sensy

    Надо в GenerateConsoleCtrlEvent вместо pID слать ноль, а у себя поставить handler, который будет глушить стандартный обработчик Ctrl+С дла вызывающего процесса(т.е. твоего).





    Не надо ля-ля... Реагирует отлично.
     
  6. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Toxic
    Код (Text):
    1.  
    2. SetConsoleCtrlHandler(NULL,TRUE);
    3. .if !GenerateConsoleCtrlEvent(CTRL_C_EVENT,NULL){
    4.    DWORD r = GetLastError(); // результат 6
    5.    if!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,NULL){
    6.      r = GetLastError(); //результат 6
    7.      return NULL;
    8.      }
    9.    }
    10.  




    Или я неправильно ставлю обработчик?
     
  7. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    sensy

    Ох, а доки я за тебя читать буду?







    Т.е. ты просто глушишь Ctrl+C для себя и всех своих порождений.



    Надо дать в SetConsoleCtrlHandler указатель на свою процедуру обработчика, и там возвращать True по приходе Ctrl+C, тем самым блокируя передачу сигнала следующему обработчику в цепочке(который вызывает ExitProcess).
     
  8. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Toxic

    Хорошо, указал свой обработчик. Честно говоря, так сначала и собирался, но смутили слова
    , я подумал, что ignore Ctrl+C лучше.



    Но не в этом дело.


    Код (Text):
    1.  
    2. SetConsoleCtrlHandler(&Handler,TRUE);
    3. if !GenerateConsoleCtrlEvent(CTRL_C_EVENT,NULL){
    4.    DWORD r = GetLastError(); // результат 6
    5.    if!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,NULL){
    6.      r = GetLastError(); //результат 6
    7.      return r;
    8.      }
    9.    return r;
    10.    }
    11.  




    1) Функции по прежнему возвращают код ошибки 6;

    2) Управление в мой Handler так и не приходит.



    Можно пример кода рабочего? Или хотя бы объяснить, почему GetLastError = 6.
     
  9. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    sensy

    Дык непонятно, что ты запускаешь, как запускаешь и т.д.

    Я по вышеприведенной методике посылаю Ctrl+C на tracert - все сразу закрывается.

    Показывай свои СreateProcess и пайпы(если есть).



    [​IMG] _1113902227__tracert.jpg
     
  10. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Toxic

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


    Код (Text):
    1.  
    2. SetConsoleCtrlHandler(&Handler,TRUE);
    3. CreatePipe(&Pipes.hOutRead,&Pipes.hOutWrite,&SecAttrs,NULL);
    4. CreatePipe(&Pipes.hInRead,&Pipes.hInWrite,&SecAttrs,NULL);
    5. sInfo.dwFlags = STARTF_USESHOWWINDOW + STARTF_USESTDHANDLES;
    6. sInfo.wShowWindow = SW_HIDE;
    7. sInfo.hStdInput = Pipes.hInRead;
    8. sInfo.hStdOutput = Pipes.hOutWrite;
    9. sInfo.hStdError = Pipes.hOutWrite;
    10. CreateProcess(NULL,szCmdBuf,&SecAttrs,&SecAttrs,TRUE,NULL,NULL,NULL,&sInfo,&pInfo);
    11. CloseHandle(Pipes.hOutWrite);
    12. CloseHandle(Pipes.hInRead);
    13. // Break action
    14. if !GenerateConsoleCtrlEvent(CTRL_C_EVENT,NULL){
    15.    DWORD r = GetLastError(); // результат 6
    16.    if!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,NULL){
    17.      r = GetLastError(); //результат 6
    18.      return r;
    19.      }
    20.    return r;
    21.    }
    22.  
    И tracert всё равно продолжает работать…
     
  11. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    А саму консоль ты создал?
     
  12. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Toxic

    То есть? Работа с консолью - это дело подопытного приложения. Я же просто переназвачаю вход/выход его себе и всё. Или нет?



    Нужно и себе создавать консоль? Или как?
     
  13. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    AllocConsole

    CreatePipe

    SetStdHandle

    SetConsoleCtrlHandler

    CreateProcess

    GenerateConsoleCtrlEvent

    FreeConsole



    Читай MSDN:

     
  14. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    Я вот еще забавный случай вспомнил: дали мне оффлайновый форум какого-то дельфийского сайта. Там какой-то перец написал статью как с помощью пайпов и CreateProcess запустить консольное приложение и считать оттуда данные.

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

    И никто не обратил внимания, что в CreateProcess в hStdInput и hStdOutput переданы концы hRead и hWrite одного пайпа!
     
  15. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Toxic







    Даже если я — GUI-приложение?



    В MSDN есть пример с переназначением стандартных ввода-вывода, но там оба приложения консольные…
     
  16. Toxic

    Toxic New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2003
    Сообщения:
    19
    Адрес:
    Ukraine
    sensy





    А какая тебе разница? Разве в вышеприведенном скриншоте ты увидел консоль? Там как раз GUI, а консоль спрятана, чтобы глаза не мозолила.



    Ты уже давно мог бы все прочитать и поэкспериментировать - в MSDN по консолям достаточно инфы.
     
  17. sensy

    sensy New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2004
    Сообщения:
    29
    Интересно, что после AllocConsole открывается окно консоли и его никак не закрыть, вплоть до FreeConsole.



    Можно, конечно, через FindWindow найти его, но заголовок окна заранее не известен (зависит от имени файла).



    Кто-нибудь знает, как скрыть окно консоли?
     
  18. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Народ, объясните плз и мне тормозу - как через GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pr.dwProcessId) закрыть cmd.exe которое запустил так:
    CreateProcessA( PAnsiChar('C:\Windows\System32\cmd.exe'), PAnsiChar(''), nil, nil, True, CREATE_NEW_PROCESS_GROUP, nil, PAnsiChar('C:\Windows\System32'), st, pr )
    Пишет ошибку: Неверный дескриптор.