Форум программистов, компьютерный форум CyberForum.ru
CyberForum.ru - форум программистов и сисадминов > > >
Восстановить пароль Регистрация

Ответ Создать новую тему
 
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
03.12.2012, 15:06     Узнать о закрытии внешней программы
  #1
Я запускаю внешнюю программу при помощи ShellExecute. Как узнать, что внешняя программа закрывается? Можно ли вообще перехватывать любые события, происходящие в другой программе (если так же это моя программа)? Данными обмениваться необязательно. Очень нет времени изучать OLE или DDE. Нужно просто, чтобы первая программа узнала о завершении второй.
AdAgent
Объявления
03.12.2012, 15:06
mimicria
return (true);
1837 / 971 / 40
Регистрация: 19.04.2011
Сообщений: 2,033
03.12.2012, 15:38
  #2
Способов куча:
1. Искать окно FindWindow
2. Использовать WaitForSingleObject
3. Использовать GetProcessTimes (конкретно lpExitTime)
Я когда была необходимость запустить стороннюю программу и дождаться её завершения, не предпринимая никаких действий в процессе работы, использовал вместо ShellExecute() spawnlp() с параметром P_WAIT
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
04.12.2012, 14:09  [ТС]
  #3
Цитата Сообщение от mimicria Посмотреть сообщение
Я когда была необходимость запустить стороннюю программу и дождаться её завершения, не предпринимая никаких действий в процессе работы, использовал вместо ShellExecute() spawnlp() с параметром P_WAIT
А как не блокировать работу первой программы?
WaitForSingleObject - все равно блокирует насколько я понял. А FindWindow нужно вызывать самому (или опрашивать таймером, что не вариант).
BRcr
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
04.12.2012, 17:24
  #4
Укажи параметр P_NOWAIT вместо P_WAIT. Кто справку-то читать будет?
Ddv122
Почемучка)
1221 / 281 / 11
Регистрация: 23.12.2010
Сообщений: 1,900
Записей в блоге: 1
04.12.2012, 21:35
  #5
Извините, не сюда написал)
Но Спасибо за spawnlp()
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
07.12.2012, 14:00  [ТС]
  #6
Цитата Сообщение от BRcr Посмотреть сообщение
Укажи параметр P_NOWAIT вместо P_WAIT
А как узнать о завершении программы то?)
BRcr
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
07.12.2012, 14:49
  #7
Если подвешивать свою программу нельзя, тогда только опрашивать таймером или вынести ожидание в поток, других вариантов не ведаю.
При этом ты до сих пор не сообщил, почему это вдруг таймер не вариант...
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
07.12.2012, 16:08  [ТС]
  #8
Цитата Сообщение от BRcr Посмотреть сообщение
почему это вдруг таймер не вариант...
Включать таймер в программе А и проверять в нем FindWindow пробграммы B? Какой интервал задавать, чтобы не грузить систему? Не будет ли такого, что окна B уже не существует, но еще не выполнены операции деструктора B? Где гарантии, что пока программа B ищется на жестком диске и загружается в оперативную память сработает таймер в программе A? Все это наводит на мысли о ненадежности и нестабильности на разных компьютерах.
У Вас есть опыт, как это организовывается при помощи таймера, чтобы все было окей?

Добавлено через 1 минуту
О многопоточности думал. Но хотелось бы простой способ какой-нибудь.
BRcr
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
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 Кб, 13 просмотров)
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
14.12.2012, 21:25  [ТС]
  #10
Почему возникает предупреждение?
[BCC32 Warning] W8111 Accessing deprecated entity '_fastcall TThread::Resume()'
BRcr
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
14.12.2012, 22:02
  #11
Это значит, что эбаркадеровцы не гарантируют наличие данного метода в классе TThread в будущих версиях библиотеки VCL.
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
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
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
16.12.2012, 19:22
  #13
И что мешает поступить просто вот так?
Код C++
1
2
3
4
    void __fastcall action( ) {
        //Form1->lbl2->Caption = "процесс завершен";
        Form1->My_Method( );
    }
Добавлено через 1 минуту
Впрочем, если это не вариант, то покажу способ с шаблонами и указателями на методы класса...
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
16.12.2012, 20:08  [ТС]
  #14
Цитата Сообщение от BRcr Посмотреть сообщение
И что мешает поступить просто вот так?
Я бы хотел создать один раз класс process_await_thread, добавить его в свою библиотеку и использовать его в разных программах и проектах.
BRcr
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
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( );
    }
Синтаксис работы с указателями на функции-члены класса весьма кривой, но, увы, деваться от этого пока что некуда... разве что использовать какие-то простые вспомогательные функции в качестве интерфейса к методам класса, что тоже весьма коряво.
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
16.12.2012, 21:16  [ТС]
  #16
Спасибо большое, попробую.
Оффтопом:
Правильно ли я понимаю, что для работы
Код C++
1
2
 template <какой-то тип данных>
//здесь описание функции или класаа
нужно подключать не h-файл, а cpp-файл?
Я использую часто template, но подключать приходиться cpp-файлы, иначе жалуется линкер.

Например в h-файле UnitFunctions.h:
Код C++
1
2
template <class T>
void EnterRNumber(wchar_t &Key,T Obj); 
В cpp-файле UnitFunctions.cpp реализация:
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template <class T>
void EnterRNumber(char &Key,T Obj)
{
    if ((Key >= '0') && (Key <= '9')) {}  // цифры
    else if (Key == 8) {}  // <-
    else if ((Key == '.') || (Key == ',')) // запятая
    {
        if (Obj->Text.Pos(DecimalSeparator)!=0) // если запятая уже есть
                Key = 0;
        else // если ещё нет
                Key = DecimalSeparator;
    }
    else if (Key == '-') // минус
    {
        int l =  Obj->Text.Length();
        if ((Obj->Text.Pos('-')==1  || l>0 )) // минус уже есть и он на первом месте
                Key = 0;
        else // если ещё нет
                Key = '-';
    }
    else Key = 0; // не цифра
}
Где-то в другом файле MainForm.cpp:
Код C++
1
2
3
4
5
6
7
//#include "UnitFunctions.h"      // так не работает
#include "UnitFunctions.cpp"     // а так работает 
 
void __fastcall TFormMain::Edit1KeyPress(TObject *Sender, wchar_t &Key)
{
    EnterRNumber(Key, (TEdit*)Sender);
}
Я что-то делаю не так, или так и должно быть?
BRcr
Модератор
2911 / 1592 / 90
Регистрация: 03.02.2011
Сообщений: 3,878
Записей в блоге: 6
16.12.2012, 21:21
  #17
В данном случае содержимое файла UnitFunctions.h просто не принимает участия в твоем проекте.

Объявление и определение шаблонной функции или шаблонного метода должны быть в одном файле, такое вот ограничение. А уж .cpp это будет или .h - без разницы.
znseday
Форумчанин
14 / 14 / 1
Регистрация: 20.03.2012
Сообщений: 300
16.12.2012, 21:22  [ТС]     Узнать о закрытии внешней программы
  #18
Ну т.е. в cpp тоже
Код C++
1
void EnterRNumber(wchar_t &Key,T Obj)
(не то скопировал просто)
Yandex
Объявления
16.12.2012, 21:22
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать новую тему

Похожие темы
Тема Раздел Ответов Автор Дата
C++ Builder Сохранить значения переменных при закрытии программы
Нужно, чтобы при закрытии программы значения переменных (В процессе программы они часто менялись) записывались в файл, а после открытия этой же программы значения считывались с файла и присваивались...
C++ Builder 1 Andrey040601 30.08.2014 15:53
C++ Builder Доступ к компонентам внешней программы
Всем привет, мне надо обратиться к внешней программе(это я умею) и добраться в нем к компоненту Edit1, записать в него нужный текст заранее спасибо
C++ Builder 1 KARARIN 27.02.2013 23:58
C++ Builder Ошибка при закрытии программы в компиляторе, из-за TMediaPlayer
Программа сама по себе запускается и завершается без ошибок. Но стоит мне открыть аудио файл в TMediaPlayer и начать его проигрывать, то при попытке закрыть приложение выскакивает такая вот ошибка:...
C++ Builder 9 Deimon 27.11.2012 15:46
C++ Builder Как мне сделать так, чтобы данный текстовый файл был открыт один раз при запуске программы и закрыт при закрытии программы?
Привет! Возник следующий вопрос. Программа состоит из основного окна Form1 и нескольких Unit. По таймеру в Form1 запускается один из Unit'ов, в которых производятся некие вычисления и выводят данные...
C++ Builder 2 OmutMoren 13.09.2012 14:12
C++ Builder Сохранение в текстовом документе при закрытии программы
Начал пользоваться программкой C++Builder 6.В визуальном редакторе почти разобрался.А с кодами пока очень плохо понимаю куда и что вставлять.Хоть читал методичку.Вопросик как сделать чтоб при...
C++ Builder 31 iskatel73 04.06.2012 13:37
C++ Builder Перехватить событие из внешней программы
Подскажите где можно подробно почитать про события (по русски). Суть вопроса нужно перехватить событие (не знаю какое) чтобы подменить текст и вернуть во внешнюю программу, если это конечно...
C++ Builder 8 vladimir_sv 07.02.2012 17:45
C++ Builder сохранение данных об объектах при закрытии программы
Здравствуйте, уважаемые форумчане! У меня возникла следующая проблема: мне нужно при закрытии прораммы сохранить все данные об объектах, а точнее о массивах объектов,причем каждый из объектов...
C++ Builder 8 Iraida 26.09.2011 14:24
C++ Builder Выполнение кода при закрытии программы
Такой вопрос - как выполнить какие-то команды, когда пользователь закрывает программу, торкая кнопку "Закрыть" в шапке программы?
C++ Builder 11 Oskaria 13.03.2011 19:34
Опции темы

Текущее время: 19:50. Часовой пояс GMT +4.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.7 PL3
Copyright ©2000 - 2014, vBulletin Solutions, Inc.