powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как корректно получить сообщение от SendMessage
12 сообщений из 12, страница 1 из 1
Как корректно получить сообщение от SendMessage
    #39831022
Не програмистъ. Сильно прошу не бить (если только чуть).
Кратко:
Не могу разобраться как получить сообщение от SendMessage;
Код почти полная копипаста:

Отправитель:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
procedure TForm1.Button1Click(Sender: TObject);
var
  CDS: TCopyDataStruct;
  str:string;
begin
  str := 'message1';

  CDS.dwData := 1;

  CDS.cbData := Length(str) + 1;

  GetMem(CDS.lpData, CDS.cbData);

  StrPCopy(CDS.lpData, AnsiString(str));

  SendMessage(FindWindow(nil, 'Receiver'),
                  WM_COPYDATA, Handle, Integer(@CDS));

  FreeMem(CDS.lpData, CDS.cbData);

 end;



Получатель:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure TForm1.WMCopyData(var MessageData: TWMCopyData);
var
  s:string;
begin
  if MessageData.CopyDataStruct.dwData = 1 then
  begin
    s := PAnsiChar((MessageData.CopyDataStruct.lpData));
    Label1.Caption:=s;
 //   ShowMessage(S);
    MessageData.Result := 123;
  end
  else
    MessageData.Result := -321;
end;



И получатель никак не реагирует, ничего не меняет, вообще не входит в данную процедуру.
Код: pascal
1.
FindWindow(nil, 'Receiver')


Работает корректно и находит нужное окно.
Например команды
Код: pascal
1.
2.
3.
    SendMessage(receiverHandle, WM_LBUTTONDOWN, 300,300);
    SendMessage(receiverHandle, WM_LBUTTONup, 300,300);
    SetWindowPos(receiverHandle, HWND_BOTTOM, 1, 1, 20, 20, swp_nosize);


Вполне себе успешно перемещают нужное окно получателя или кликают по нему.

Если чуть подробнее, может подскажите более корректное решение:
Есть программа (оболочка), которая запускает множество расчетных одинаковых подпрограмм (~100), но так сразу 100 положит любой компьютер, запускать надо по "N" штук, потому надо отслеживать сколько программ работает в текущий момент и запускать новые по мере закрытия старых, потому завершившие работы программы посылают сообщение с идентификатором (который получили при запуске) о окончании работы и закрываются.
С передачей сообщений никогда ранее дела не имел, потому - темный лес.
Можно, конечно, отслеживать количество запущенных программ, но это неудобно в случае если запустить расчетную программу вручную (что тоже бывает).
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831026
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
почему не потоки а процессы?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831031
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей Игоревич,

Код: pascal
1.
procedure WMCopyData(var MessageData: TWMCopyData); message WM_COPYDATA; //это есть?
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831079
Мимопроходящийпочему не потоки а процессы?

Возможно некорректно понял вопрос, но в основной программе естественно поток, который висит и последовательно запускает расчетные программы и отслеживает (будет отслеживать) их закрытие.

goldmi45Андрей Игоревич,

Код: pascal
1.
procedure WMCopyData(var MessageData: TWMCopyData); message WM_COPYDATA; //это есть?


Ааа...ааа... 3 часа сидел и тупил, вот как я мог прозевать, ведь вроде проверял, всё смотрел....
Всё, работает спасибо. Вот блин тупняк...
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831173
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SendMessage излишнее тут (и негибкое), если надо сообщать просто об окончании. Запускай процессы через CreateProcess, проверяй код завершения
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
var si: TStartupInfo;
    pi: TProcessInformation;
    ExitCode: DWORD;
begin
  Result := True;
  // запускаем проверку архива
  si := Default(TStartupInfo);
  if not CreateProcess(nil, PChar(string(AppPath)),
                       nil, nil, False, CREATE_NO_WINDOW, nil, nil, si, pi) then
    raise Err('Не удалось запустить');
  // и ждем, пока процесс отработает
  try
    repeat
      if WaitForSingleObject(pi.hProcess, 5*MSecsPerSec) = WAIT_TIMEOUT then
        begin TerminateProcess(pi.hProcess, 0); raise Err('Превышен срок ожидания'); end;
      if not GetExitCodeProcess(pi.hProcess, ExitCode) then Break;
    until ExitCode <> STILL_ACTIVE;
  finally
    CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
  end;
  // проверяем код завершения проги. 0 - ОК, иначе - ошибка
  Result := (ExitCode = 0);



Выдрано из рабочей функции, но могут быть артефакты вырезания лишнего
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831424
Василий 2SendMessage излишнее тут (и негибкое), если надо сообщать просто об окончании. Запускай процессы через CreateProcess, проверяй код завершения
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
var si: TStartupInfo;
    pi: TProcessInformation;
    ExitCode: DWORD;
begin
  Result := True;
  // запускаем проверку архива
  si := Default(TStartupInfo);
  if not CreateProcess(nil, PChar(string(AppPath)),
                       nil, nil, False, CREATE_NO_WINDOW, nil, nil, si, pi) then
    raise Err('Не удалось запустить');
  // и ждем, пока процесс отработает
  try
    repeat
      if WaitForSingleObject(pi.hProcess, 5*MSecsPerSec) = WAIT_TIMEOUT then
        begin TerminateProcess(pi.hProcess, 0); raise Err('Превышен срок ожидания'); end;
      if not GetExitCodeProcess(pi.hProcess, ExitCode) then Break;
    until ExitCode <> STILL_ACTIVE;
  finally
    CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
  end;
  // проверяем код завершения проги. 0 - ОК, иначе - ошибка
  Result := (ExitCode = 0);



Выдрано из рабочей функции, но могут быть артефакты вырезания лишнего
Однако не очень простая функция :). Но интересная.
Раз уж первый вопрос решился столь банально, не подскажете, как можно принудительно закрыть программы запущенные исключительно данной родительской программой (ну допустим запущенно две программы одновременно или вручную запущенна расчетная программа) у CreateProcess параметров какое-то безумное количество,способна ли она на такое?
Смысл - сделать кнопку в родительской программе "Остановить расчет": процесс запуска новых модулей остановить легко, но вот сами модули закрыть сложнее (не закрыв лишнего), стоит понимать, что средний расчет в одном расчетном модуле идет 4-6 часов (а весть расчет может идти около недели). Впихивать в расчетные модули что-то для прерывания крайне не хочется, к этому модулю достаточно суровые требования по коду и разрабатывается он не мной, обработкой параметров при запуске и сообщением при окончании хотелось бы ограничится.
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831488
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конечно, посмотри внимательнее, у меня есть закрытие процесса по таймеру
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831496
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичРаз уж первый вопрос решился столь банально, не подскажете, как можно принудительно закрыть программы запущенные исключительно данной родительской программой (ну допустим запущенно две программы одновременно или вручную запущенна расчетная программа) у CreateProcess параметров какое-то безумное количество,способна ли она на такое?
Смысл - сделать кнопку в родительской программе "Остановить расчет": процесс запуска новых модулей остановить легко, но вот сами модули закрыть сложнее (не закрыв лишнего), стоит понимать, что средний расчет в одном расчетном модуле идет 4-6 часов (а весть расчет может идти около недели). Впихивать в расчетные модули что-то для прерывания крайне не хочется, к этому модулю достаточно суровые требования по коду и разрабатывается он не мной, обработкой параметров при запуске и сообщением при окончании хотелось бы ограничится.
TerminateProcess() должен помочь. Хэндл процесса у вас уже есть из кода выше, разве что с правами могут возникнуть трудности, но, по-идее, не должны.
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831499
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Конечно, посмотри внимательнее, у меня есть закрытие процесса по таймеру
Код: pascal
1.
2.
if WaitForSingleObject(pi.hProcess, 5*MSecsPerSec) = WAIT_TIMEOUT then
        begin TerminateProcess(pi.hProcess, 0); raise Err('Превышен срок ожидания'); end;


Это вот жесть, с точки зрения читаемости кода, ИМХО.
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831679
Василий 2Конечно, посмотри внимательнее, у меня есть закрытие процесса по таймеру
Ага, спасибо. Всё отлично работает, открывает, закрывает, на удивление...

Из любопытства, понимаю что не про Делфи, но вдруг знаете чисто теоретически может ли Handle у программ повторятся? Ну например запомнил я все Handle всех запущенных программ, пользователь позакрывал часть руками, потом понаоткрывал новых всяких разных, а затем нажал "остановить расчет" - который убивает все процессы с запомненными Handle и дополнительно убил и ни в чем не повинные процессы? Надо ли такое отслеживать или шанс подобного пренебрежительно мал?

alekcvp TerminateProcess() должен помочь. Хэндл процесса у вас уже есть из кода выше, разве что с правами могут возникнуть трудности, но, по-идее, не должны.
Отлично работает, спасибо. Про права, если у пользователя нет прав админа будет ли работать?
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831682
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Андрей ИгоревичИз любопытства, понимаю что не про Делфи, но вдруг знаете чисто теоретически может ли Handle у программ повторятся? Ну например запомнил я все Handle всех запущенных программ, пользователь позакрывал часть руками, потом понаоткрывал новых всяких разных, а затем нажал "остановить расчет" - который убивает все процессы с запомненными Handle и дополнительно убил и ни в чем не повинные процессы? Надо ли такое отслеживать или шанс подобного пренебрежительно мал?
Может, но:
When a process terminates, its kernel object is not destroyed until all processes that have open handles to the process have released those handles.Т.е. пока все, у кого открыт этот процесс, не сделают CloseHandle() или не завершат работу - он будет валидным.
...
Рейтинг: 0 / 0
Как корректно получить сообщение от SendMessage
    #39831683
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
28.06.2019 14:41, Андрей Игоревич пишет:
> чисто теоретически может ли Handle у программ повторятся?

в рамках текущей сессии - НЕТ
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как корректно получить сообщение от SendMessage
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]