Статьи по Assembler


Взаимодействие экземпляров приложения - часть 6


Пример реализации третьей стратегии, использующий только систему оконных сообщений, можно найти в приложении MyCall. Там используется регистрируемое глобальное сообщение, которое приложение передает в широковещательном режиме в надежде, что уже запущенный экземпляр ответит ему тем же сообщением. Если такой ответ получен, то делается вывод, что один экземпляр приложения уже запущен, и запускаемый экземпляр завершает работу. Но перед этим он извлекает из ответного сообщения дескриптор главного окна работающего экземпляра и выводит это окно на первый план, чтобы удовлетворить потребность пользователя в доступе к приложению.

Здесь мы приведем версию, выполняющую ту же задачу, но несколько отличную в реализации. По сути, она является гибридом из описанной выше и примененной в MyCall: для определения факта повторного запуска приложения используется mutex, а для передачи дескриптора окна работающего приложения вновь запускаемому - глобальное сообщение.

Это полностью работающее приложение. В его основу положен шаблон оконного приложения. Фрагменты, отвечающие за обеспечение уникальности экземпляра приложения и за вывод окна работающего приложения на первый план, выделены бледно-желтым фоном. Содержимое файла windows.inc не приводится (то, что он должен собой представлять, показано в предыдущем примере. Недостающие элементы следует добавить самостоятельно, по аналогии, пользуясь заголовочными файлами для C/C++).

.386 .Model flat,stdcall

include windows.inc ;заголовочный файл API

;///////////////////////////////////////////////////////////// WinMain EXIT_OK =0 ;коды выхода EXIT_ERROR =1 EXIT_ALREADY_EXIST =2

QUESTION_PRIME_HWND =1 ;запрос идентификатора окна ANSWER_PRIME_HWND =2 ;ответ идентификатора окна

.data? win_class WNDCLASSEXA{} ;структура класса главного окна main_window dd ? ;дескриптор главного окна check_inst_mutex dd ? ;дескриптор mutex'а second_instance dd ? ;признак второго экземпляра check_inst_message dd ? ;идентификатор регистрируемого сообщения loop_message MSG{} ;сообщение для цикла обработки .const app_name db "Single Instance Application",0 class_name db "Single Instance Application Class",0 check_inst_mutex_name db "Check Instant Mutex 0001",0 check_inst_message_name db "Check Instant Message 0001",0 .code ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::: WinMain PROC PUBLIC hinst,prev_hinst,command_line,cmd_show ;......................................................... регистрация класса окна mov win_class.cbSize,sizeof(WNDCLASSEXA) mov win_class.style,CS_HREDRAW OR CS_VREDRAW mov win_class.lpfnWndProc,offset win_procedure mov win_class.cbClsExtra,0 mov win_class.cbWndExtra,0 invoke GetModuleHandleA,NULL mov win_class.hInstance,eax invoke LoadIconA,NULL,IDI_APPLICATION mov win_class.hIcon,eax mov win_class.hIconSm,eax invoke LoadCursorA,NULL,IDC_ARROW mov win_class.hCursor,NULL mov win_class.hbrBackground,COLOR_WINDOWFRAME mov win_class.lpszMenuName,NULL mov win_class.lpszClassName,offset class_name invoke RegisterClassExA,offset win_class .if(!eax) jmp abort .endif ;......................................................... создание окна invoke CreateWindowExA,NULL,\ offset class_name,\ offset app_name,\ WS_OVERLAPPEDWINDOW,\ 100,100,300,200,\ NULL,\ NULL,\ win_class.hInstance,\ NULL .if(!eax) jmp abort .endif mov main_window,eax ;.............................................. зарегистрировать глобальное сообщение mov check_inst_message,0 invoke RegisterWindowMessageA,offset check_inst_message_name .if(eax) mov check_inst_message,eax .endif ;......................................................... проверить повторный запуск mov check_inst_mutex,0 invoke OpenMutexA,MUTEX_ALL_ACCESS,FALSE,offset check_inst_mutex_name .if(!eax) mov second_instance,FALSE invoke CreateMutexA,NULL,TRUE,offset check_inst_mutex_name mov check_inst_mutex,eax .else mov second_instance,TRUE .if(check_inst_message) invoke SendMessageA,HWND_BROADCAST,check_inst_message,QUESTION_PRIME_HWND,NULL




- Начало -  - Назад -  - Вперед -