Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.9.170] |
|
Сообщ.
#1
,
|
|
|
Каков будет код для передачи пользовательского сообщения другому приложению о котором первому известно только название исполняемого файла?И каков будет код получения и обработки принимающим приложением?То есть стоит задача передать сообщение от одного приложения другому и зафиксировать прием сообщения отображением MessageBox(сообщение полученоMB_OK).
|
Сообщ.
#2
,
|
|
|
Это системное программирование, IPC
|
Сообщ.
#3
,
|
|
|
Насколько я вижу ветка называется и win API.А вызов функции sendmessage или postmessage это и есть windows api.И в чем я заблуждаюсь?
|
Сообщ.
#4
,
|
|
|
CreateToolhelp32Snapshot() + Process32First()/Process32Next() + OpenProcess() + QueryFullProcessImageName()
Ну и не забыть про CloseHandle() |
Сообщ.
#5
,
|
|
|
Джеффри Рихтер расписал способы межпроцессного общения
Цитата Взаимодействие между процессами Потоки одного процесса не имеют доступа к адресному пространству другого процесса. Однако существуют механизмы для передачи данных между процессами. http://library.tsilikin.ru/%D0%A2%D0%B5%D1...2%20Windows.pdf Тебе, очевидно, более подойдёт инфа на стр 14. Цитата Сообщения в Windows (оконные сообщения) |
Сообщ.
#6
,
|
|
|
Пусть ТС сначала определится, что ему надо. Как связать имя исполняемого файла с процессом, объяснено. Перечислить нитки процесса из того же снапшота CreateToolhelp32Snapshot() дело двух кликов мышью по справочнику Process32First(). За посылку сообщений в нить говорилось в соседней теме.
Если же нужно окно, то искать процесс вообще не нужно, нужно искать окно. Перечислить все окна верхнего уровня EnumWindows(), в каллбаке которого EnumWindowsProc сравнивать нитку-владельца с результатом GetWindowThreadProcessId(). Как вариант – перебрать все окна нитки EnumThreadWindows(). Как удобнее, ябеспонятия. ИМХО искать окна неблагодарное занятие, если о них ничего не известно. |
Сообщ.
#7
,
|
|
|
Цитата izumov @ Каков будет код для передачи пользовательского сообщения другому приложению о котором первому известно только название исполняемого файла?И каков будет код получения и обработки принимающим приложением? Оба приложения твои? Что конкретно нужно передать? WM_-сообщение или бинарные данные? Или просто дёрнуть логику "отдал-принял" любым событием? В последнем случае подойдёт самый обычный Event: https://learn.microsoft.com/en-us/windows/w...pi-createeventa Цитата DrUnkard @ Джеффри Рихтер расписал способы межпроцессного общения Майкрософт их расписал, полагаю, много раньше Рихтера: https://learn.microsoft.com/en-us/windows/w...synchronization |
Сообщ.
#8
,
|
|
|
Цитата B.V. @ Майкрософт их расписал, полагаю, много раньше Рихтера И чо? Рихтер сам консультировал Микрософт. Я дал человеку текст на русском языке, шо, заведомо, читабельнее. |
Сообщ.
#9
,
|
|
|
Цитата DrUnkard @ Я дал человеку текст на русском языке, шо, заведомо, читабельнее. Согласен. К тому же межпроцессное взаимодействие будет еще и более православным! |
Сообщ.
#10
,
|
|
|
Нате на нитках. Ожидающее приложение:
#include <windows.h> #include <iostream> #include <functional> #include <stdexcept> #include <thread> #include <mutex> UINT usrMsg; MSG msg; DWORD msgThread = 0; class Guard { std::function<void(void)> fn; public: Guard(const std::function<void(void)>& f): fn(f) {} ~Guard() { fn(); } }; std::mutex modal; void wndProc(UINT uMsg, WPARAM, LPARAM lParam) { if (uMsg == usrMsg) modal.lock(), MessageBox(NULL, "сообщение получено", "threadClient", MB_OK), modal.unlock(); if (lParam == 1) PostQuitMessage(0); } using namespace std::literals; void workThread(void) try { msgThread = GetCurrentThreadId(); HMODULE kernel(LoadLibrary("KernelBase.dll")); Guard freeKernel([&]{ FreeLibrary(kernel); }); HRESULT (*SetThreadDescription)(HANDLE, PCWSTR) = nullptr; if (kernel == NULL) throw std::runtime_error("KernelBase.dll isn't load"s); SetThreadDescription = reinterpret_cast<HRESULT (*)(HANDLE, PCWSTR)>(GetProcAddress(kernel, "SetThreadDescription")); if (SetThreadDescription == nullptr)throw std::runtime_error("SetThreadDescription() isn't found"s); if (FAILED(SetThreadDescription(GetCurrentThread(), L"working message thread"))) throw std::runtime_error("SetThreadDescription() fails"s); while (GetMessage(&msg, reinterpret_cast<HWND>(-1), 0, 0)) wndProc(msg.message, msg.wParam, msg.lParam); } catch(const std::exception& exc) { std::cerr << exc.what() << std::endl; } int main() { usrMsg = RegisterWindowMessage("Message for client"); if (usrMsg == 0) return std::cout << "RegisterWindowMessage() fails", 1; INPUT_RECORD inp; DWORD readed; std::thread working(workThread); for (;;) { if (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &inp, 1, &readed) == 0) break; if (inp.EventType == KEY_EVENT && inp.Event.KeyEvent.bKeyDown == TRUE && inp.Event.KeyEvent.uChar.AsciiChar == '\x1B' && (inp.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED| RIGHT_CTRL_PRESSED| ENHANCED_KEY | SHIFT_PRESSED)) == 0) break; } while (msgThread == 0 || !modal.try_lock()) Sleep(0); PostThreadMessage(msgThread, WM_COMMAND, 0, 1); modal.unlock(); working.join(); return 0; } #include <windows.h> #include <tlhelp32.h> #include <stdexcept> #include <iostream> using namespace std::literals; template <typename H, HANDLE Inv = NULL> class Resource { H handle; public: explicit Resource(H h): handle(h) { if (handle == Inv) throw std::runtime_error("NULL handle"s); } Resource(const Resource&) = delete; void operator=(const Resource&) = delete; operator H() const { return handle; } protected: ~Resource() {} }; template <HANDLE Inv = NULL> class Handle: public Resource<HANDLE, Inv> { public: explicit Handle(HANDLE h): Resource(h) {} ~Handle() { CloseHandle(*this); } }; class Hmodule: public Resource<HMODULE> { public: explicit Hmodule(HMODULE h): Resource(h) {} ~Hmodule() { FreeLibrary(*this); } }; class Wchar: public Resource<wchar_t*> { public: explicit Wchar(wchar_t *h): Resource(h) {} ~Wchar() { LocalFree(*this); } }; int main() try { UINT usrMsg = RegisterWindowMessage("Message for client"); if (usrMsg == 0) return std::cout << "RegisterWindowMessage() fails", 1; Handle<INVALID_HANDLE_VALUE> snapShot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0)); PROCESSENTRY32 proc = { sizeof(proc) }; DWORD procId = 0; Hmodule kernel(LoadLibrary("KernelBase.dll")); HRESULT (*GetThreadDescription)(HANDLE, PWSTR*) = nullptr; if (kernel == NULL) throw std::runtime_error("KernelBase.dll isn't load"s); GetThreadDescription = reinterpret_cast<HRESULT (*)(HANDLE, PWSTR*)>(GetProcAddress(kernel, "GetThreadDescription")); if (GetThreadDescription == nullptr)throw std::runtime_error("GetThreadDescription() isn't found"s); if (Process32First(snapShot, &proc) != FALSE) do if (proc.szExeFile == "threadClient.exe"s) { procId = proc.th32ProcessID; break; } while (Process32Next(snapShot, &proc) != FALSE); if (procId == 0) throw std::runtime_error("threadClient.exe not found"s); THREADENTRY32 thread = { sizeof(thread) } ; DWORD threadId = 0; if (Thread32First(snapShot, &thread) != FALSE) do { if (thread.th32OwnerProcessID != procId) continue; Handle<> threadClient(OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, thread.th32ThreadID)); Wchar buffer([&]{ wchar_t *buffer; GetThreadDescription(threadClient, &buffer); return buffer; }()); if (std::wstring(buffer) == L"working message thread"s) { threadId = thread.th32ThreadID; break; } } while (Thread32Next(snapShot, &thread) != FALSE); if (threadId == 0) throw std::runtime_error("working message thread of threadClient.exe not found"s); PostThreadMessage(threadId, usrMsg, 0, 0); } catch(const std::exception& exc) { std::cerr << exc.what() << std::endl; } Как найду время, напишу и запосчу на окнах. Добавлено P.S. Забыл пояснить. По идее ожидающее называется threadClient.exe. Если это не так, то переименуйте или измените искомое посылающим имя. Добавлено Нате на окнах. Ожидающее приложение: #include <windows.h> #define IDM_QUIT 101 #define ICON_ID 1 WNDCLASS wndClass; MSG msg; HWND hWnd; UINT usrMsg, trayMsg; HMENU hMenu; BOOL CreateOwnMenu() { if ((hMenu = CreatePopupMenu()) == NULL) return FALSE; if (!AppendMenu(hMenu, MF_STRING, IDM_QUIT, "stop it")) return DestroyMenu(hMenu), FALSE; return TRUE; } NOTIFYICONDATA nid; LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { POINT curPos; switch (uMsg) { case WM_CREATE: usrMsg = RegisterWindowMessage("Message for client"); trayMsg= RegisterWindowMessage("Notyfy message"); if (usrMsg == 0) return -1; if (trayMsg== 0) return -1; if (!CreateOwnMenu()) return -1; nid.cbSize = sizeof(nid); nid.hWnd = hWnd; nid.uID = ICON_ID; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = trayMsg; nid.hIcon = LoadIcon(NULL, IDI_WARNING); strcpy(nid.szTip, "appClient"); Shell_NotifyIcon(NIM_ADD, &nid); return 0; case WM_CLOSE: DestroyMenu(hMenu); Shell_NotifyIcon(NIM_DELETE, &nid); DestroyWindow(hWnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: if (uMsg == usrMsg) MessageBox(NULL, "сообщение получено", "appClient", MB_OK); if (uMsg == trayMsg) switch(lParam) { DWORD retCmd; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: GetCursorPos(&curPos); SetForegroundWindow(hWnd); retCmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, curPos.x, curPos.y, 0, hWnd, NULL); switch(retCmd) { case IDM_QUIT: PostMessage(hWnd, WM_CLOSE, 0, 0); break; default: break; } } return DefWindowProc(hWnd, uMsg, wParam, lParam); } } int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) { wndClass.lpfnWndProc = wndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = GetModuleHandle(NULL); wndClass.hIcon = LoadIcon (NULL, IDI_WARNING); wndClass.hCursor = LoadCursor (NULL, IDC_ARROW); wndClass.hbrBackground= reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); wndClass.lpszMenuName = NULL; wndClass.lpszClassName= "appClient class window"; if (RegisterClass(&wndClass) == 0) return 1; if ((hWnd = CreateWindow(wndClass.lpszClassName, "appClient", WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL)) == NULL) return 1; ShowWindow(hWnd, SW_HIDE); while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } #include <windows.h> #include <iostream> int main() { HWND hWnd = FindWindow("appClient class window", "appClient"); UINT usrMsg = RegisterWindowMessage("Message for client"); if (hWnd == NULL) return std::cout << "appClient window not found", 1; if (usrMsg == 0) return std::cout << "RegisterWindowMessage() fails", 1; SendMessage(hWnd, usrMsg, 0, 0); return 0; } |
Сообщ.
#11
,
|
|
|
Цитата Qraizer @ P.S. То же, прочем и для threadClient.exe. Если запустите несколько экземпляров ожидающего, окна будут дублированы. |
Сообщ.
#12
,
|
|
|
Мое затруднение состоит в том что я не могу определить место нахождения wndProc в моем проекте сделанном в visual studio по шаблону CppCLR_WinForms_GUI.
Могли бы Вы мне подсказать в каком месте проекта я могу увидеть эту функцию и скорректировать ее? |
Сообщ.
#13
,
|
|
|
А просто повесить на окно дополнительную функцию-фильтр не катит?
oldWindowProc = SetWindowLongPtr(hWnd, GWL_WNDPROC, &newWndProc); //Вместо return DefWindowProc(hWnd, uMsg, wPar, lPar); return CallWindowProc(oldWindowProc, hWnd, uMsg, wPar, lPar); |