Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.07.18;
Скачать: [xml.tar.bz2];

Вниз

Трудная задача   Найти похожие ветки 

 
DeepProg   (2002-06-22 16:09) [0]

Здравствуйте, товарищи!
Задача: приложение1 должно запустить другое приложение2 (вызов произвожу в FormCreate), а затем послать последнему пару обращений (ЗАМЕЧАНИЕ: эти обращения производятся к уже полностью запущенному приложению2 ).
Проблема: как сделать так, чтобы после выполнения ShellExecute (запускаю приложение2 ) приложение1 не посылало обращение до тех пор пока полностью ни активизируется приложение2, иначе возникает ошибка EOleSysError ‘Операция недоступна’. До настоящего времени я пользовался таймерами, но эта идея мне разонравилась, так, как впоследствии все выглядит слишком громоздко и не дает никакой гарантии, что пользователь не задержится где-нибудь на пару секунд и не выбьет таким образом стройную систему таймеров. Может можно как-то проверять готовность приложения2?


 
Юрий Зотов   (2002-06-22 16:33) [1]

Используйте связку CreateProcess + WaitForInputIdle.

CreateProcess дает хэндл запущенного процесса, который надо передать в WaitForInputIdle. А сама WaitForInputIdle (со вторым параметром INFINITE) задерживает выполнение Вашей программы до тех пор, пока запущенная программа полностью не активизируется и не перейдет к ожиданию действий юзера.


 
DeepProg   (2002-06-23 15:03) [2]


> Юрий Зотов © (22.06.02 16:33)
> Используйте связку CreateProcess + WaitForInputIdle.
>
> CreateProcess дает хэндл запущенного процесса, который надо
> передать в WaitForInputIdle. А сама WaitForInputIdle (со
> вторым параметром INFINITE) задерживает выполнение Вашей
> программы до тех пор, пока запущенная программа полностью
> не активизируется и не перейдет к ожиданию действий юзера.
>


Эту связку надо применить в Batch file для проекта или где? Расскажите, пожалуйста, поподробнее - это для меня сейчас темный лес.


 
Юрий Зотов   (2002-06-23 16:04) [3]

Вместо ShellExecute используйте CreateProcess (примеров полно хоть на этом же сайте, сделайте поиск). А потом сразу вызывайте WaitForInputIdle.

if CreateProcess(..., ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
CloseHandle(ProcessInfo.hProcess);
... // В этой точке запущенное приложение уже готово к работе
end;


 
VID   (2002-06-23 17:17) [4]

to Юрий Зотов: нефигово!


 
DeepProg   (2002-06-23 17:58) [5]


> VID © (23.06.02 17:17)
> to Юрий Зотов: нефигово!

ПОлностью согласен. Thanx!


 
DeepProg   (2002-06-24 19:08) [6]


> Юрий Зотов © (23.06.02 16:04)
> Вместо ShellExecute используйте CreateProcess (примеров
> полно хоть на этом же сайте, сделайте поиск). А потом сразу
> вызывайте WaitForInputIdle

Я не нашел никакого толквого описания этой функции. Сориентируйте меня, пожалуйста, или подскажите, где можно достать исчерпывающую информацию о CreateProcess, особенно это касается вариантов значений ее свойств.


 
Юрий Зотов   (2002-06-25 00:23) [7]

Исчерпывающую - в SDK и MSDN, естественно. И, пожалуй, в 3-м издании книги Джеффри Рихтера "Windows для профессионалов".

А если неисчерпывающую, то вот простейший, но вполне корректный, вполне рабочий и один из наиболее распространенных вызовов:

var
StartInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
...
ZeroMemory(@StartInfo, SizeOf(StartInfo));
StartInfo.cb := SizeOf(StartInfo);
if CreateProcess(nil, PChar(командная_строка), nil, nil, False, 0, nil, nil, StartInfo, ProcessInfo) then ...



 
DeepProg   (2002-06-25 17:23) [8]

Оказывается, в моем случае, внешнее приложение считается полностью активизированным, когда предлагает пользователю диалог с настройками, а те обращения, о которых я говорил в описании задачи, должны быть посланы уже после закрытия этого диалога. Можно ли программно (то есть из моего приложения) активизировать в этом диалоге клавишу OK или просто закрыть его?


 
Malder   (2002-06-25 18:36) [9]

DeepProg, используй DDE и не мучайся...


 
petr_v_a   (2002-06-25 19:07) [10]

Можно, обычным образом.
Ищем окно диалога (FindWindow) и посылаем ему WM_SYSCOMMAND с SC_CLOSE. Или ищем окно кнопки ОК (FindWindowEx) и посылаем ему WM_LBUTTONDOWN, затем WM_LBUTTONUP.


 
DeepProg   (2002-06-26 18:19) [11]

I beg your pardon, but теперь мне нужна информация о функции
«FindWindowEx(Parent:HWND, Child:HWND, ClassName:Pchar, WiindowName:Pchar);»,
по каждому из парамтров, кроме WindowName.
(Наверное ее можно достать из Help"a полоной версии Delphi, т.к. у себя я этого не нашел.)

Или скажите, хотя бы как определить lpClassName окна для функции FindWindow, если внешнее приложение, которое показывает вышеупомянутый диалог - AutoCAD.

Да и насчет DDE - по-моему здесь это пока не к месту.


 
Cobalt   (2002-06-26 21:04) [12]

>теперь мне нужна информация о функции ХХХХ
Вместе с (ИМХО) любой версией Дельфей поставляется MS SDK Help Files (раздел Shared Files при установке), вот там и ищите.
Эти файлы можно найти в меню "DelphiX\Help\MS SDK Help Files"


 
Malder   (2002-06-26 21:26) [13]

Ну если у тебя такая обрезанная Дельфя, то лови:

The FindWindowEx function retrieves the handle to a window whose class name and window name match the specified strings. The function searches child windows, beginning with the one following the given child window.

HWND FindWindowEx(

HWND hwndParent, // handle to parent window
HWND hwndChildAfter, // handle to a child window
LPCTSTR lpszClass, // pointer to class name
LPCTSTR lpszWindow // pointer to window name
);


Parameters

hwndParent

Identifies the parent window whose child windows are to be searched.
If hwndParent is NULL, the function uses the desktop window as the parent window. The function searches among windows that are child windows of the desktop.

hwndChildAfter

Identifies a child window. The search begins with the next child window in the Z order. hwndChildAfter must be a direct child window of hwndParent, not just a descendant window.
If hwndChildAfter is NULL, the search begins with the first child window of hwndParent.
Note that if both hwndParent and hwndChildAfter are NULL, the function searches all top-level windows.

lpszClass

Points to a null-terminated string that specifies the class name or is an atom that identifies the class-name string. If this parameter is an atom, it must be a global atom created by a previous call to the GlobalAddAtom function. The atom, a 16-bit value, must be placed in the low-order word of lpszClass; the high-order word must be zero.

lpszWindow

Points to a null-terminated string that specifies the window name (the window"s title). If this parameter is NULL, all window names match.



Return Values

If the function succeeds, the return value is the handle to the window that has the specified class and window names.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.


 
DeepProg   (2002-06-27 16:31) [14]

Нет, я решительно не понимаю в чем теперь проблема!!

Вот отрывок кода «Трудной задачи». Конечной целью этого отрывка является закрытие вышеупомянутого диалога настроек. Код с комментариями, пожалуйста, помогите разобраться, где ошибка.

procedure TForm1.FormCreate(Sender: TObject);
var
SI: TStartupInfo;
PI: TProcessInformation;
begin
ZeroMemory(@SI,SizeOf(SI));
SI.cb:=SizeOf(SI);
if CreateProcess(...,SI,PI) then
begin
CloseHandle(PI.hThread);
WaitForInputIdle(PI.hProcess,INFINITE);
CloseHandle(PI.hProcess);
end;
a:=GetClassName(handle,"ClassName",32);// определяю класс окна AutoCAD
// до сих пор все работает
SendMessage( // хочу закрыть вылезший диалог
FindWindowEx( //ищу его окно

{в данном случае,
понятие "окно кнопи ОК" не подходит, т.к. в диалоге
она не выделена - активна RadioGroup, предлагающие
настройки}

FindWindow(PChar(a),nil), // hwndParent сам AutoCAD
Parent.Handle,
// если не ошибся здесь то это стало быть - диалог

nil, // как достать его lpszClass не уразумел
"Загрузка"),
// имя окна диалога. В будующем его ждет занчение nil

WM_CLOSE,0,0); // посылаю диалогу сообщение
// здесь вылезает ошибка EAccessViolation
end;

Может окно диалога не понимает WM_CLOSE?

И еще кое-что – после диалога AutoCAD дальше грузится, можно ли будет вызвать WaitForInutIdle вне CreateProcess, т. к. во время этой догрузки обращения, посылаемые AutoCAD"у (те самые, из-за которых весь сыр-бор) еще не могкт быть приняты и опять сгенерируется исключение EoleSysError “Операция недоступна”.

P.S. Огромное спасибо за то, что все еще интересуетесь этой проблемой!!!


 
DeepProg   (2002-06-27 16:33) [15]

Вот отрывок кода «Трудной задачи». Конечной целью этого отрывка является закрытие вышеупомянутого диалога настроек. Код с комментариями, пожалуйста, помогите разобраться, где ошибка.
procedure TForm1.FormCreate(Sender: TObject);
var
SI: TStartupInfo;
PI: TProcessInformation;
begin
ZeroMemory(@SI,SizeOf(SI));
SI.cb:=SizeOf(SI);
if CreateProcess(...,SI,PI) then
begin
CloseHandle(PI.hThread);
WaitForInputIdle(PI.hProcess,INFINITE);
CloseHandle(PI.hProcess);
end;
a:=GetClassName(handle,"ClassName",32);// определяю класс окна AutoCAD
// до сих пор все работает
SendMessage( // хочу закрыть вылезший диалог
FindWindowEx( //ищу его окно

{в данном случае,
понятие "окно кнопи ОК" не подходит, т.к. в диалоге
она не выделена - активна RadioGroup, предлагающие
настройки}

FindWindow(PChar(a),nil), // hwndParent сам AutoCAD
Parent.Handle,
// если не ошибся здесь то это стало быть - диалог

nil, // как достать его lpszClass не уразумел
"Загрузка"),
// имя окна диалога. В будующем его ждет занчение nil

WM_CLOSE,0,0); // посылаю диалогу сообщение
// здесь вылезает ошибка EAccessViolation
end;


Может окно диалога не понимает WM_CLOSE?

Огромное спасибо за то, что все еще интересуетесь этой проблемой!!!


 
Юрий Зотов   (2002-06-29 19:04) [16]

Увы, дела весьма печальные. Вот только явные ошибки (а есть еще и другие).

1. a:=GetClassName(handle,"ClassName",32);
И хэндл не тот, и буфер не тот.

2. PChar(a)
Количество символов выдается за адрес тела строки. Отсюда, скорее всего, и Access Violation.

3. Parent.Handle
И Parent не тот, и хэндл снова не тот. Если Parent=nil (что, скорее всего, так и есть), то тоже даст Access Violation.

4. Не надо мудрить, попробуйте проще:
SendMessage(FindWindow(nil, "Загрузка"), WM_CLOSE, 0, 0)


 
DeepProg   (2002-07-02 11:03) [17]

C этим все в порядке. Я уже давно разобрался.
Посмотрите пожалуйста ветку "WaitForInputIdle use again"!!!!!


 
DeepProg   (2002-07-04 19:56) [18]

Ну раз не хотите смотреть вышеназванную ветку, то даю новую ориентировку:
форум WinAPI
ветка " Second use of WaitForInputIdle".Скажите хотя бы возможно это или нет.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2002.07.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.006 c
1-58083
Guerrillero Che
2002-07-08 11:26
2002.07.18
Освобождение памяти ?


14-58286
SeF
2002-06-21 03:24
2002.07.18
ловля багов


14-58272
AlexPetrov
2002-06-20 11:27
2002.07.18
Улучшенный ScrollBox


1-58169
Valeris
2002-07-05 11:32
2002.07.18
Цвет кнопки


14-58261
Shadow
2002-06-20 10:45
2002.07.18
DMCP





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский