Форум программистов, компьютерный форум CyberForum.ru

C++ Builder

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.94
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
#1

Узнать о закрытии внешней программы - C++ Builder

03.12.2012, 15:06. Просмотров 2170. Ответов 17
Метки нет (Все метки)

Я запускаю внешнюю программу при помощи ShellExecute. Как узнать, что внешняя программа закрывается? Можно ли вообще перехватывать любые события, происходящие в другой программе (если так же это моя программа)? Данными обмениваться необязательно. Очень нет времени изучать OLE или DDE. Нужно просто, чтобы первая программа узнала о завершении второй.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.12.2012, 15:06
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Узнать о закрытии внешней программы (C++ Builder):

Как мне сделать так, чтобы данный текстовый файл был открыт один раз при запуске программы и закрыт при закрытии программы? - C++ Builder
Привет! Возник следующий вопрос. Программа состоит из основного окна Form1 и нескольких Unit. По таймеру в Form1 запускается один из...

Доступ к компонентам внешней программы - C++ Builder
Всем привет, мне надо обратиться к внешней программе(это я умею) и добраться в нем к компоненту Edit1, записать в него нужный текст ...

Перехватить событие из внешней программы - C++ Builder
Подскажите где можно подробно почитать про события (по русски). Суть вопроса нужно перехватить событие (не знаю какое) чтобы подменить...

Выполнение кода при закрытии программы - C++ Builder
Такой вопрос - как выполнить какие-то команды, когда пользователь закрывает программу, торкая кнопку "Закрыть" в шапке программы?

сохранение данных об объектах при закрытии программы - C++ Builder
Здравствуйте, уважаемые форумчане! У меня возникла следующая проблема: мне нужно при закрытии прораммы сохранить все данные об объектах, а...

Сохранить значения переменных при закрытии программы - C++ Builder
Нужно, чтобы при закрытии программы значения переменных (В процессе программы они часто менялись) записывались в файл, а после открытия...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
mimicria
return (true);
1956 / 1093 / 91
Регистрация: 19.04.2011
Сообщений: 2,345
03.12.2012, 15:38 #2
Способов куча:
1. Искать окно FindWindow
2. Использовать WaitForSingleObject
3. Использовать GetProcessTimes (конкретно lpExitTime)
Я когда была необходимость запустить стороннюю программу и дождаться её завершения, не предпринимая никаких действий в процессе работы, использовал вместо ShellExecute() spawnlp() с параметром P_WAIT
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
04.12.2012, 14:09  [ТС] #3
Цитата Сообщение от mimicria Посмотреть сообщение
Я когда была необходимость запустить стороннюю программу и дождаться её завершения, не предпринимая никаких действий в процессе работы, использовал вместо ShellExecute() spawnlp() с параметром P_WAIT
А как не блокировать работу первой программы?
WaitForSingleObject - все равно блокирует насколько я понял. А FindWindow нужно вызывать самому (или опрашивать таймером, что не вариант).
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
04.12.2012, 17:24 #4
Укажи параметр P_NOWAIT вместо P_WAIT. Кто справку-то читать будет?
Ddv122
Почемучка)
1235 / 295 / 16
Регистрация: 23.12.2010
Сообщений: 1,998
Записей в блоге: 1
04.12.2012, 21:35 #5
Извините, не сюда написал)
Но Спасибо за spawnlp()
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
07.12.2012, 14:00  [ТС] #6
Цитата Сообщение от BRcr Посмотреть сообщение
Укажи параметр P_NOWAIT вместо P_WAIT
А как узнать о завершении программы то?)
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
07.12.2012, 14:49 #7
Если подвешивать свою программу нельзя, тогда только опрашивать таймером или вынести ожидание в поток, других вариантов не ведаю.
При этом ты до сих пор не сообщил, почему это вдруг таймер не вариант...
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
07.12.2012, 16:08  [ТС] #8
Цитата Сообщение от BRcr Посмотреть сообщение
почему это вдруг таймер не вариант...
Включать таймер в программе А и проверять в нем FindWindow пробграммы B? Какой интервал задавать, чтобы не грузить систему? Не будет ли такого, что окна B уже не существует, но еще не выполнены операции деструктора B? Где гарантии, что пока программа B ищется на жестком диске и загружается в оперативную память сработает таймер в программе A? Все это наводит на мысли о ненадежности и нестабильности на разных компьютерах.
У Вас есть опыт, как это организовывается при помощи таймера, чтобы все было окей?

Добавлено через 1 минуту
О многопоточности думал. Но хотелось бы простой способ какой-нибудь.
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
08.12.2012, 12:17 #9
Вообще-то с потоком оно и попроще будет, как на мой вкус...
Вот рабочий пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class TForm1
               : public TForm
{
__published: // IDE-managed Components
    TEdit *edit1;
    TButton *btn1;
    TLabel *lbl1;
    TLabel *lbl2;
    TButton *btn2;
    void __fastcall btn2Click( TObject *Sender );
private: // User declarations
public:  // User declarations
    __fastcall TForm1( TComponent *Owner );
};
// ---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
// ---------------------------------------------------------------------------
class process_await_thread
               : public TThread {
private:
 
protected:
 
public:
    HANDLE process;
    void __fastcall Execute( ) {
        WaitForSingleObject( process, INFINITE );
        Synchronize( &action );
    }
    void __fastcall action( ) {
        Form1->lbl2->Caption = "процесс завершен";
    }
    __fastcall process_await_thread( bool _suspended )
                   : TThread( _suspended ) {};
};
// ---------------------------------------------------------------------------
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void __fastcall TForm1::btn2Click( TObject *Sender ) { // запуск программы
    SHELLEXECUTEINFO ei;
    String filename = "notepad.exe";
 
    SecureZeroMemory( &ei, sizeof( SHELLEXECUTEINFO ) );
    ei.cbSize = sizeof( SHELLEXECUTEINFO );
    ei.fMask |= SEE_MASK_NOCLOSEPROCESS;
    ei.lpFile = ( LPCTSTR )filename.c_str( );
    ei.nShow |= SW_SHOWDEFAULT;
 
    if ( ShellExecuteEx( &ei ) ) {
        lbl2->Caption = "процесс запущен";
        process_await_thread *thr = new process_await_thread( true );
        thr->FreeOnTerminate = true;
        thr->process = ei.hProcess;
        thr->Resume( );
    }
}
Экзешник:
Вложения
Тип файла: rar Project1.rar (468.1 Кб, 25 просмотров)
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
14.12.2012, 21:25  [ТС] #10
Почему возникает предупреждение?
[BCC32 Warning] W8111 Accessing deprecated entity '_fastcall TThread::Resume()'
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
14.12.2012, 22:02 #11
Это значит, что эбаркадеровцы не гарантируют наличие данного метода в классе TThread в будущих версиях библиотеки VCL.
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
16.12.2012, 19:13  [ТС] #12
Как сделать, чтобы при закрытии процесса выполнялся метод другого объекта(класса)?
Я попробовал так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class process_await_thread
               : public TThread {
private:
 
protected:
 
public:
    HANDLE process;
 
    void (*func_action)(void);  // новое
 
    void __fastcall Execute( ) {
        WaitForSingleObject( process, INFINITE );
        Synchronize( &func_action );
    }
 
    __fastcall process_await_thread( bool _suspended )
                   : TThread( _suspended )
                        {func_action = NULL}; // новое
};
В другом классе:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void __fastcall TForm1::btn2Click( TObject *Sender ) { // запуск программы
    SHELLEXECUTEINFO ei;
    String filename = "notepad.exe";
 
    SecureZeroMemory( &ei, sizeof( SHELLEXECUTEINFO ) );
    ei.cbSize = sizeof( SHELLEXECUTEINFO );
    ei.fMask |= SEE_MASK_NOCLOSEPROCESS;
    ei.lpFile = ( LPCTSTR )filename.c_str( );
    ei.nShow |= SW_SHOWDEFAULT;
 
    if ( ShellExecuteEx( &ei ) ) {
        
        process_await_thread *thr = new process_await_thread( true );
 
        thr->func_action = &My_Method; // где My_Method пренадлежит TForm1
 
        thr->FreeOnTerminate = true;
        thr->process = ei.hProcess;
        thr->Resume( );
    }
}
Но компилятор выдает ошибку на приведение типов в методе Synchronize. Если посмотреть возможные параметры, то Synchronize вообще хочет принимать только указатели на методы класса TThread.

Как быть? Что то меня заклинило...
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
16.12.2012, 19:22 #13
И что мешает поступить просто вот так?
C++
1
2
3
4
    void __fastcall action( ) {
        //Form1->lbl2->Caption = "процесс завершен";
        Form1->My_Method( );
    }
Добавлено через 1 минуту
Впрочем, если это не вариант, то покажу способ с шаблонами и указателями на методы класса...
znseday
16 / 16 / 1
Регистрация: 20.03.2012
Сообщений: 452
16.12.2012, 20:08  [ТС] #14
Цитата Сообщение от BRcr Посмотреть сообщение
И что мешает поступить просто вот так?
Я бы хотел создать один раз класс process_await_thread, добавить его в свою библиотеку и использовать его в разных программах и проектах.
BRcr
4008 / 2297 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
16.12.2012, 20:50 #15
Тогда так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
template <class procs_provider>
class process_await_thread
               : public TThread {
private:
 
protected:
 
public:
    HANDLE process;
    procs_provider *a_class;
    void __fastcall( procs_provider::*action_proc )( );
 
    void __fastcall Execute( ) {
        WaitForSingleObject( process, INFINITE );
        Synchronize( &action );
    }
    void __fastcall action( ) {
        ( a_class->*action_proc )( );
    }
    __fastcall process_await_thread( bool _suspended )
                   : TThread( _suspended ) {};
};
// ---------------------------------------------------------------------------
class TForm1
               : public TForm
{
__published: // IDE-managed Components
    TMemo *memo1;
    TMemo *memo2;
    TButton *btn1;
    TComboBox *ComboBox1;
    TEdit *Edit1;
    TEdit *Edit2;
    void __fastcall btn1Click( TObject *Sender );
private: // User declarations
public:  // User declarations
    void __fastcall my_method( ) {
        ShowMessage( "in my_method" );
    }
    __fastcall TForm1( TComponent *Owner );
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    SHELLEXECUTEINFO ei;
    String filename = "notepad.exe";
 
    SecureZeroMemory( &ei, sizeof( SHELLEXECUTEINFO ) );
    ei.cbSize = sizeof( SHELLEXECUTEINFO );
    ei.fMask |= SEE_MASK_NOCLOSEPROCESS;
    ei.lpFile = ( LPCTSTR )filename.c_str( );
    ei.nShow |= SW_SHOWDEFAULT;
 
    typedef process_await_thread <TForm1> pat_for_form1;
    if ( ShellExecuteEx( &ei ) ) {
        pat_for_form1 *thr = new pat_for_form1( true );
        thr->FreeOnTerminate = true;
        thr->process = ei.hProcess;
        thr->a_class = this;
        thr->action_proc = &TForm1::my_method;
        thr->Resume( );
    }
Синтаксис работы с указателями на функции-члены класса весьма кривой, но, увы, деваться от этого пока что некуда... разве что использовать какие-то простые вспомогательные функции в качестве интерфейса к методам класса, что тоже весьма коряво.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.12.2012, 20:50
Привет! Вот еще темы с ответами:

Ошибка при закрытии программы в компиляторе, из-за TMediaPlayer - C++ Builder
Программа сама по себе запускается и завершается без ошибок. Но стоит мне открыть аудио файл в TMediaPlayer и начать его проигрывать, то...

Сохранение в текстовом документе при закрытии программы - C++ Builder
Начал пользоваться программкой C++Builder 6.В визуальном редакторе почти разобрался.А с кодами пока очень плохо понимаю куда и что...

Имитация нажатия кнопкой мыши в определенном окне внешней программы - C++ Builder
Нужна помощь вот в каков вопросе: как с имитировать нажатие мышкой в определенном окне(например в IE) Делал так: 1)Искал окно ...

Завершение программы при закрытии формы только по команде пользователя, а не по закрытию формы кодом - C++ Builder
В общем , когда программа открывается срабатывает событие OnShow() и открывается другая форма Form4-&gt;ShowModal(). В этой форме прогрессбар,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
16.12.2012, 20:50
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru