Опять посылка CTRL+C в консоль!!!!!
От: Аноним  
Дата: 05.05.05 14:42
Оценка:
Слущайте народ кто может всетаки разобрался что делать если надо послать в консоль CTRL+C (тобишь сигнал SIGINT)...
Поясняю есть GUI процес который порождает потоки: в для перехвата ввода/вывода и строит консольный процесс... в определенный момент надо в дочернюю консоль послать CTRL+C или SIGINT (тока так)...те фактически с эмитировать нажатие пользователем сочетание(CTRL+C), но так как консольный процесс дочерний то соотв окна не видно и делать надо программно...

Функция GenerateConsoleCtrlEvent(CTRL_C_EVENT,dwChildConsolePID) — не работает возвращает код ошибки = 6 (неправильный хендл) — и консоль сигнала не получает... с какими тока флагами я не пытался строить процесс...

Может есть альтернатива? например как в Unix kill(pid,signal)...

ПЛИЗ помогите! Неужели в Windows не как из GUI приложения не послать сигнал CTRL+C(SIGINT) в косоль?

07.05.05 02:27: Перенесено из 'C/C++'
Re: Опять посылка CTRL+C в консоль!!!!!
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.05.05 15:11
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Функция GenerateConsoleCtrlEvent(CTRL_C_EVENT,dwChildConsolePID) — не работает возвращает код ошибки = 6 (неправильный хендл) — и консоль сигнала не получает... с какими тока флагами я не пытался строить процесс...


Ты бы хоть показал, как получаешь dwChildConsolePID, который передаешь в GenerateConsoleCtrlEvent. Например, ты вот это описание читал:

dwProcessGroupId
Identifier of the process group to receive the signal. A process group is created when the CREATE_NEW_PROCESS_GROUP flag is specified in a call to the CreateProcess function. The process identifier of the new process is also the process group identifier of a new process group. The process group includes all processes that are descendants of the root process. Only those processes in the group that share the same console as the calling process receive the signal. In other words, if a process in the group creates a new console, that process does not receive the signal, nor do its descendants.
If this parameter is zero, the signal is generated in all processes that share the console of the calling process.

... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Опять посылка CTRL+C в консоль!!!!!
От: Аноним  
Дата: 06.05.05 08:42
Оценка:
E>Ты бы хоть показал, как получаешь dwChildConsolePID, который передаешь в GenerateConsoleCtrlEvent. Например, ты вот это описание читал:
E>

E>dwProcessGroupId
E>Identifier of the process group to receive the signal. A process group is created when the CREATE_NEW_PROCESS_GROUP flag is specified in a call to the CreateProcess function. The process identifier of the new process is also the process group identifier of a new process group. The process group includes all processes that are descendants of the root process. Only those processes in the group that share the same console as the calling process receive the signal. In other words, if a process in the group creates a new console, that process does not receive the signal, nor do its descendants.
E>If this parameter is zero, the signal is generated in all processes that share the console of the calling process.


dwChildConsolePID я получаю при создании консоли как процесса (CreateProcess) — но мне не важно каким образом и с какими флагами создавать — меня тока интересует как мне созданной консоле с известным PID послать сигнал какой нибуть хоть, в данном случае сигнал SIGINT...
Фактически проимитировать нажатие пользователем CTRL+C — но т.к. окна как такового не существует и потоки ввода/вывода я перехватываю (попытки заслать "^C" тоже бесполезны), то ничего не остается как послать сигнал SIGINT — вот я и ищу алтернативу Unix функции kill(pid, signal)

Не ужели нет нормальной альтернативы в Windows
Re[3]: Опять посылка CTRL+C в консоль!!!!!
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.05.05 09:03
Оценка:
Здравствуйте, <Аноним>, Вы писали:


E>>Ты бы хоть показал, как получаешь dwChildConsolePID, который передаешь в GenerateConsoleCtrlEvent. Например, ты вот это описание читал:

E>>

E>>dwProcessGroupId
E>>Identifier of the process group to receive the signal. A process group is created when the CREATE_NEW_PROCESS_GROUP flag is specified in a call to the CreateProcess function. The process identifier of the new process is also the process group identifier of a new process group. The process group includes all processes that are descendants of the root process. Only those processes in the group that share the same console as the calling process receive the signal. In other words, if a process in the group creates a new console, that process does not receive the signal, nor do its descendants.
E>>If this parameter is zero, the signal is generated in all processes that share the console of the calling process.


А>dwChildConsolePID я получаю при создании консоли как процесса (CreateProcess) — но мне не важно каким образом и с какими флагами создавать — меня тока интересует как мне созданной консоле с известным PID послать сигнал какой нибуть хоть, в данном случае сигнал SIGINT...

А>Фактически проимитировать нажатие пользователем CTRL+C — но т.к. окна как такового не существует и потоки ввода/вывода я перехватываю (попытки заслать "^C" тоже бесполезны), то ничего не остается как послать сигнал SIGINT — вот я и ищу алтернативу Unix функции kill(pid, signal)

Но как я понял выделенный текст в документации, dwChildConsolePID должен быть именно идентификатором группы процессов, который равен идентификатору нового процесса, если в CreateProcess был передан флаг CREATE_NEW_PROCESS_GROUP. Может быть попробовать создать дочерний процесс именно с этим флагом и затем воспользоваться GenerateConsoleCtrlEvent?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Опять посылка CTRL+C в консоль!!!!!
От: Аноним  
Дата: 06.05.05 09:47
Оценка:
To eao197

Т.е. если я правильно понял мне нужно создать процесс с флагом CREATE_NEW_PROCESS_GROUP затем в нем создать дочерний (т.е. мне необходимый) и тока тогда GenerateConsoleCtrlEvent будет работать?

А так чтоб просто есть GUI приложение я в нем создаю нить в ней создаю консольный процесс (с флагами если надо) например "cmd.exe"
— естественно что я знаю о нем тока потоки ввода/вывода и PID, а когда мне надо чтоб мог послать ему SIGINT (типа GenerateConsoleCtrlEvent(CTRL_C_EVENT,PID))..

или в windows так нельзя?
Re[5]: Опять посылка CTRL+C в консоль!!!!!
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.05.05 09:52
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>To eao197


А>Т.е. если я правильно понял мне нужно создать процесс с флагом CREATE_NEW_PROCESS_GROUP затем в нем создать дочерний (т.е. мне необходимый) и тока тогда GenerateConsoleCtrlEvent будет работать?


А>А так чтоб просто есть GUI приложение я в нем создаю нить в ней создаю консольный процесс (с флагами если надо) например "cmd.exe"

А> — естественно что я знаю о нем тока потоки ввода/вывода и PID, а когда мне надо чтоб мог послать ему SIGINT (типа GenerateConsoleCtrlEvent(CTRL_C_EVENT,PID))..

Лично я никогда GenerateConsoleCtrlEvent не пользовался, но как я понял ее описание, то из GUI нужно создать консольный процесс с флагом CREATE_NEW_PROCESS_GROUP. И именно по его PID-у можно будет посылать CTRL_C_EVENT.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Опять посылка CTRL+C в консоль!!!!!
От: Аноним  
Дата: 06.05.05 12:20
Оценка:
E>Лично я никогда GenerateConsoleCtrlEvent не пользовался, но как я понял ее описание, то из GUI нужно создать консольный процесс с флагом CREATE_NEW_PROCESS_GROUP. И именно по его PID-у можно будет посылать CTRL_C_EVENT.

Я так тоже понял, пробовал и не работает это — функция GenerateConsoleCtrlEvent возвращает 0 — а GetLastError() возвращает 6 т.е. мол хендл плохой....
Re[7]: Опять посылка CTRL+C в консоль!!!!!
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.05.05 13:26
Оценка:
E>>Лично я никогда GenerateConsoleCtrlEvent не пользовался, но как я понял ее описание, то из GUI нужно создать консольный процесс с флагом CREATE_NEW_PROCESS_GROUP. И именно по его PID-у можно будет посылать CTRL_C_EVENT.

А>Я так тоже понял, пробовал и не работает это — функция GenerateConsoleCtrlEvent возвращает 0 — а GetLastError() возвращает 6 т.е. мол хендл плохой....


Приведите кусок кода. Сдается мне, что вместо идентификатора процесса вы подсовываете его хендл.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[7]: Опять посылка CTRL+C в консоль!!!!!
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.05.05 13:29
Оценка: 1 (1)
Здравствуйте, <Аноним>, Вы писали:


E>>Лично я никогда GenerateConsoleCtrlEvent не пользовался, но как я понял ее описание, то из GUI нужно создать консольный процесс с флагом CREATE_NEW_PROCESS_GROUP. И именно по его PID-у можно будет посылать CTRL_C_EVENT.


А>Я так тоже понял, пробовал и не работает это — функция GenerateConsoleCtrlEvent возвращает 0 — а GetLastError() возвращает 6 т.е. мол хендл плохой....

А>

Да уж, RTFM в действии

Вот что сказано в MSDN про значение CTRL_C_EVENT:

Generates a CTRL+C signal. This signal cannot be generated for process groups. If dwProcessGroupId is nonzero, this function will succeed, but the CTRL+C signal will not be received by processes within the specified process group.


Т.е. процесс не сможет сгенерировать CTRL+C для другого процесса. Только CTRL_BREAK_EVENT, что, в принципе, одно и то же.

Далее, про аргумент dwProcessGroupId:

Identifier of the process group to receive the signal. A process group is created when the CREATE_NEW_PROCESS_GROUP flag is specified in a call to the CreateProcess function. The process identifier of the new process is also the process group identifier of a new process group. The process group includes all processes that are descendants of the root process. Only those processes in the group that share the same console as the calling process receive the signal. In other words, if a process in the group creates a new console, that process does not receive the signal, nor do its descendants.

If this parameter is zero, the signal is generated in all processes that share the console of the calling process.


Т.е., в твоем случае действительно придется создавать некий управляющий консольный процесс, который в своей консоли запускает уже те процессы, которые нужно. Но они будут дочерними не для GUI-приложения, а для управляющего процесса. Далее, каждый дочерний процесс должен создаваться с флагом CREATE_NEW_PROCESS_GROUP. И тогда он сможет получать CTRL_BREAK_EVENT от управляющего процесса.

Я проверял это вот на таких программках (консольных правда, но все подтверждается):
// child_2.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <iostream>
#include <fstream>

static const char * log_file_name;
static HANDLE shutdown_event;

static BOOL
handle_event( const char * log_event_name )
    {
        std::ofstream f( log_file_name, std::ios::out | std::ios::app );

        f << log_event_name << std::endl;

        SetEvent( shutdown_event );

        return TRUE;
    }

static BOOL CALLBACK
HandlerRoutine( DWORD dwCtrlType )
{
    switch( dwCtrlType ) {
        case CTRL_C_EVENT :
            return handle_event( "CTRL_C_EVENT" );

        case CTRL_BREAK_EVENT :
            return handle_event( "CTRL_BREAK_EVENT" );

        case CTRL_CLOSE_EVENT :
            return handle_event( "CTRL_CLOSE_EVENT" );

        case CTRL_LOGOFF_EVENT :
            return handle_event( "CTRL_LOGOFF_EVENT" );

        case CTRL_SHUTDOWN_EVENT :
            return handle_event( "CTRL_SHUTDOWN_EVENT" );

    }

    return FALSE;
}

int
main( int argc, char ** argv )
    {
        if( 2 == argc )
            {
                log_file_name = argv[ 1 ];

                shutdown_event = CreateEvent( 0, TRUE, FALSE, 0 );

                if( !SetConsoleCtrlHandler( HandlerRoutine, TRUE ) )
                    handle_event( "SetConsoleCtrlHandler failed!" );

                WaitForSingleObject( shutdown_event, INFINITE );
            }

        return 0;
    }

// parent_3.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <iostream>

int
main( int, char ** )
    {
        PROCESS_INFORMATION pi;
        STARTUPINFO si = { sizeof( STARTUPINFO ) };

        if( CreateProcess( 0, "child_2 child_2.log",
                0, // lpProcessAttributes,
                0, // lpThreadAttributes,
                FALSE, // bInheritHandles,
                CREATE_NEW_PROCESS_GROUP, // dwCreationFlag,
                0, // lpEnvironment,
                0, // lpCurrentDirectory,
                &si, // lpStatupInfo,
                &pi ) )
            {
                CloseHandle( pi.hProcess );
                CloseHandle( pi.hThread );

                Sleep( 1000 );

                if( !GenerateConsoleCtrlEvent( CTRL_BREAK_EVENT, pi.dwProcessId ) )
                    std::cout << "GenerateConsoleCtrlEvent failed: "
                            << GetLastError() << std::endl; 
            }
        else
            std::cout << "CreateProcess failed: " << GetLastError() << std::endl;

        return 0;
    }


Когда все запускается в таком виде, в child_2.log оказывается запись CTRL_BREAK_EVENT.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: Опять посылка CTRL+C в консоль!!!!!
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.05.05 14:23
Оценка: 9 (2) +1
E>Т.е., в твоем случае действительно придется создавать некий управляющий консольный процесс, который в своей консоли запускает уже те процессы, которые нужно. Но они будут дочерними не для GUI-приложения, а для управляющего процесса. Далее, каждый дочерний процесс должен создаваться с флагом CREATE_NEW_PROCESS_GROUP. И тогда он сможет получать CTRL_BREAK_EVENT от управляющего процесса.

Угу, именно так и советуют в гугле. Причем там такая схема — делать некий промежуточный консольный экзешник, который запускать из гуя, а уже он дергает другой экзешник в своей консоли... А я вот тут подумал — а почему бы просто не сделать сначала AllocConsole в гуи приложении, затем в этой консоли запустить нужный процесс, по завершении которого эту консоль собственно убить? Все проще чем с раздельными процессами. Попробовал — очевидно, все как и дОлжно — работает:

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    AllocConsole();
    if (CreateProcess("tst.exe", NULL, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi))
    {
        Sleep(2000); // пусть немного поживет....
        GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pi.dwProcessId);
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        FreeConsole();
    }
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: Опять посылка CTRL+C в консоль!!!!!
От: Аноним  
Дата: 06.05.05 14:39
Оценка:
Спасибо вот теперь все становиться на свое место — тока вот CTRL+BREAK(CTRL_BREAK_EVENT) и CTRL+С(CTRL_С_EVENT) отличаються — в первом это убить приложение, во втором преостановить — мне в принципе нужен случай 2 CTRL+C но на крайняк можно и второй...
Спасибо далее сам поплыву.... ну а если найдет кто альтернативу более простую то приму к сведению и заранее спасибо!!!
Re[9]: Опять посылка CTRL+C в консоль!!!!!
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.05.05 15:11
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Спасибо вот теперь все становиться на свое место — тока вот CTRL+BREAK(CTRL_BREAK_EVENT) и CTRL+С(CTRL_С_EVENT) отличаються — в первом это убить приложение, во втором преостановить — мне в принципе нужен случай 2 CTRL+C но на крайняк можно и второй...

А>Спасибо далее сам поплыву.... ну а если найдет кто альтернативу более простую то приму к сведению и заранее спасибо!!!

Ну, навскидку, такой способ (за работоспособность не ручаюсь): CreateProcess в PROCESS_INFORMATION возвращает dwThreadId -- идентификатор главной нити запущенного процесса. Можно попробовать получить из него HANDLE и передать в SuspendThread. Если порожденный процесс однопоточный, то он дожен приостановиться
... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.