Запуск и управление другими приложениями
Меня тут попросили помочь немного, такая задача.
Дано: одна брокерская фирма, в которой брокер приходит утречком и включает комп,
1) запускает первую программу (работает с локальными базами данных), которая выдает модальное окно, не нажав в котором "Ок" дальше ничего не работает.
2) запускает вторую программу, которая связывается с сервером биржи и считывает котировки акций. В то время, как идет соединение, программа показывает песочные часы.
3) третья программа, которая занимается тем, что переводит данные второй программы в базу первой.
Задача: автоматизировать этот процесс, чтобы пользователь получил все три запущенные программы.
Проблемы:
1) Как запустить приложение отдельным процессом? Команда С++ system("application") останавливает выполнение базового приложения до завершение работы дочернего.
2) как нажать "Ок" в модальном окне.
3) как определить, занято ли еще приложение чтением данных (показывает ли песочные часы), или уже нет.
Какие идеи?
Запускается C:\prog.exe и устанавливется для него текущим каталог C:\
[COLOR=darkblue]
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
BOOL fCreated = CreateProcess(_T("C:\\prog.exe"),
NULL,NULL,NULL,FALSE, CREATE_NEW_CONSOLE, NULL, _T("C:\\"), &si, &pi);[/COLOR]
2) как нажать "Ок" в модальном окне.
Если внутри модального окна, то вызвать OnOK();
А если нужно закрыть со стороны, то если заголовок диалоговое окна напр. "Dialog1", тогда
[COLOR=darkblue]
CWnd *pWnd = FindWindow(NULL, "Dialog1");
if(pWnd!=NULL)pWnd->SendMessage(WM_COMMAND, IDOK, 0);
[/COLOR]
3) как определить, занято ли еще приложение чтением данных (показывает ли песочные часы), или уже нет.
Можно сделать это через события(Event), но для этого нужно изменить код второй программы, чтоб она сгенерировала событие.
Если вторая прога, после считывания сама завершает работу, то верхний код из 1) +сразу же
[COLOR=darkblue]
HANDLE hProcess = pi.hProcess;
WaitForSingleObject(hProcess, INFINITE);
[/COLOR]
и программа будет ждать до тех пор, пока prog.exe не завершит свою работу.
Перевел все это нашим программистам (на немецкий). У меня осталось еще 2 вопроса:
[COLOR=darkblue]
А как узнать имя окна?
Это понятно. Проблема в том, что модифицировать другую программу нельзя. И работу она не завершает, а продолжает дальше.
Другими словами: как определить, показывает ли курсор над ней еще песочные часы или нет?
Если так сделать нельзя, то как можно сделать, чтобы программа просто ждала 30-40 секунд?
Спасибо за ответы!!!
Заголовок окна. Это то что пишется в синей полосе в самом верху. Или на соответствующей кнопке на taskbar. Если это не диалоговое окно, тогда возможно для закрытия нужна будет команда
pWnd->SendMessage(WM_SYSCOMMAND, SC_CLOSE, 0);
//как можно сделать, чтобы программа просто ждала 30-40 секунд?
Sleep(30000);
Если вторая прога открывает файл, в которую записывает данные, с аттрибутом OF_SHARE_EXCLUSIVE или хотя бы OF_SHARE_DENY_WRITE, то можно попытаться в try/catch блоке открыть этот файл для записи через каждые 10 сек.
Вот ответ наших программистов:
>> CWnd *pWnd = FindWindow(NULL, "Dialog1");
>> if(pWnd!=NULL)pWnd->SendMessage(WM_COMMAND,IDOK, 0);
>ich habe es etwa in der Art programmiert, aber
> es gelingt mir nicht, ein
> ENTER oder IDOK o.д. zu senden. Das einzige,
> was immer klappt, ist, die
> Anwendung per WM_CLOSE zu schliessen.
> An dieser Stelle komme ich einfach nicht mehr weiter.
Перевод:
"Я попытался сделать что-то в этом роде, но мне не удалось послать сообщение ENTER или IDOK. Единственное, что работает, это закрытие окна при помощи команды WM_CLOSE.
С этой точки я не могу сдвинуться.
pWnd->SendMessage(WM_SYSCOMMAND, SC_CLOSE, 0);
Да, я и имел в виду заголовок, извините.
Я сам работаю не под С++, а в основном под Delphi (что касатеся Windows API, хотя вообще такого рода программированием редко занимаюсь) -- и я помню, что там можно было получать заголовок окна опрашивая массив открытых окон. Можно ли что-то такое сделать и в С++?
Это модальное окно, то есть содержание выбор "Ок" "Отмена". Как его закрыть с кодом завершение IDOK???
Обработку иссключений этот программист не знает и я думаю, это очень сложный путь. Проще действительно выждать сколько надо.
Спасибо за Вашу помощь, особенно вы выходной день!! Срок сдачи нашей программы -- понедельник, поэтому это так важно :)
>> CWnd *pWnd = FindWindow(NULL, "Dialog1");
>> if(pWnd!=NULL)pWnd->SendMessage(WM_COMMAND,IDOK, 0);
"Я попытался сделать что-то в этом роде, но мне не удалось послать сообщение ENTER или IDOK. Единственное, что работает, это закрытие окна при помощи команды WM_CLOSE.
Странно. Можно еще запустить Spy. Найти это окно и посмотреть чему равен Control ID кнопки Ok. Напр. если= 0x3E8, то теоретически[COLOR=darkblue]
CWnd *pWnd = FindWindow(NULL, "Dialog1");
if(pWnd!=NULL)pWnd->PostMessage(WM_COMMAND,0x3E8, 0);[/COLOR]
равнозначна нажатию на эту кнопку. В данном случае большой разницы нет, но наверно лучше использовать PostMessage. Это я ошибся.
EnumWindows перебирает все верхние окна активных приложений.EnumChildWindows находит дочерные окна для заданного окна.
Нужно нажать на ту кнопку. WM_CLOSE закрывает окно с кодом 2(IDCANCEL).
Незачто. Дело в том, что я тоже работаю, хочу иметь бОльшой выходной в конце/начала года. :)
SendMessage(DialogFensterHandle, WM_KEYDOWN, VK_RETURN, 0);
abzusenden und er sendet tatsachlich ein RETURN an die Schaltflache!
Das Problem ist nur, er macht es nur manchmal - das sind die schlimmsten
Fehler. Wenn ich zum Beispiel Windows herunterfahre, es wieder neustarte
und
dann das Programm neustarte - geht es immer. Aber danach geht es manchmal
und manchmal nicht. Ich wei? nicht woran das liegt.
Перевод:
Мне уже удалось послать комманду
SendMessage(DialogFensterHandle, WM_KEYDOWN, VK_RETURN, 0);
и она действительно посылает команду нажатия клавиши "Enter" на клавиатуре.
Проблема сейчас состоит в том, что это получается не всегда -- в этом самое ужасное. Например, когда я выхожу из Виндоуз и снова ее запускаю, затем запускаю мою программу -- это всегда получается. Однако потом иногда получается, а иногда нет. И я не знаю, от чего это зависит.
Можете помочь? Заранее спасибо...
(Если честно, эти немецкие программисты как дети прямо :) )
Однако потом иногда получается, а иногда нет. И я не знаю, от чего это зависит.
Если кнопка OK не имеет стандартный ID, то у меня как раз этот метод неработает. Окно закрывается, но код который привязан к кнопке не вызывается.
[COLOR=darkred]Им нужно бы запустить Spy и смотреть какие сообщения получает окно.[/COLOR] Тогда может смогут определить, почему иногда не закрывается.
Они узнавали через Spy ControlID Ok кнопки, и отправляли pWnd->PostMessage(WM_COMMAND, ControlID, 0); ???
Я думаю это лучший вариант закрытия диал.окна.
Описание Spy++ есть в MSDN.
Тем времене пришел еще один вопрос:
----
Meine Frage reduziert sich jetzt nur noch auf die Frage:
Wie finde ich heraus, was SendMessage zurückgegeben hat, ich möchte den Wert
abtesten.
Die restlichen Probleme habe ich alle gelöst.
----
Перевод:
Моя проблема теперь сводится только к одному вопросу:
Как я могу определить, что вернула функция SendMessage, я бы хотел протестировать это значение.
Все остальные проблемы уже решены.
Мне также прислали исходный код, но я думаю, он очень длинный, чтобы его публиковать здесь...
Как я могу определить, что вернула функция SendMessage, я бы хотел протестировать это значение.
char c[12];
itoa(lR, c, 10);
AfxMessageBox(c);
Теоретически LRESULT может быть равен 0(FALSE) или 1(TRUE) если команда была обработана