В Возможны ли какиелибо способы взаимодействия и обмен информацией между запущенными приложениями?
В. Возможны ли какие-либо способы взаимодействия и обмен информацией между запущенными приложениями?
Мы уже говорили о различных способах синхронизации, о разделяемой памяти. Есть еще один интересный подход, реализованный в Windows, - это анонимные каналы (pipes)46. Этот подход наиболее эффективен для обмена информацией с консольным процессом, порождаемым данным процессом. Представьте себе, что Вам необходимо, чтобы запускаемый Вами из приложения консольный процесс (например, какой-нибудь строковый компилятор) выводил информацию не в консоль, а в окно редактирования основного процесса. Пример такого приложения представлен на Рисунок 3.5.3.
Идея использования каналов очень проста. Канал - как труба: с одной стороны в него втекает информация, а с другой вытекает. Создавая процесс, можно передать ему в качестве дескриптора ввода или вывода соответствующий дескриптор канала. После этого можно обмениваться информацией между двумя процессами при помощи уже известных Вам функций WriteFile и ReadFile.
// файл pipe.rc // определение констант #define WS_SYSMENU 0x00080000L #define WS_VISIBLE 0x10000000L #define WS_TABSTOP 0x00010000L #define DS_3DLOOK 0x0004L #define ES_LEFT 0x0000L #define WS_CHILD 0x40000000L #define WS_BORDER 0x00800000L #define ES_MULTILINE 0x0004L #define WS_VSCROLL 0x00200000L #define WS_HSCROLL 0x00100000L
MENUP MENU { POPUP "&Запуск программы" { MENUITEM "&Запустить", 200 MENUITEM "Выход из &программы", 300 } }
// определение диалогового окна DIAL1 DIALOG 0, 0, 200, 140 STYLE WS_SYSMENU | DS_3DLOOK CAPTION "Пример использования PIPE" FONT 8, "Arial" { CONTROL "", 101, "edit", ES_LEFT | ES_MULTILINE | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL, 24, 20, 128, 70 }
; файл pipe.inc ; константы
SW_HIDE equ 0 SW_SHOWNORMAL equ 1 STARTF_USESHOWWINDOW equ 1h STARTF_USESTDHANDLES equ 100h STARTF_ADD = STARTF_USESHOWWINDOW + STARTF_USESTDHANDLES
; сообщение приходит при закрытии окна WM_CLOSE equ 10h WM_INITDIALOG equ 110h WM_COMMAND equ 111h EM_REPLACESEL equ 0C2h
; прототипы внешних процедур IFDEF MASM EXTERN ReadFile@20:NEAR EXTERN CloseHandle@4:NEAR EXTERN CreatePipe@16:NEAR EXTERN SetMenu@8:NEAR EXTERN LoadMenuA@8:NEAR EXTERN CreateProcessA@40:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN DialogBoxParamA@20:NEAR EXTERN EndDialog@8:NEAR EXTERN SendDlgItemMessageA@20:NEAR ELSE EXTERN ReadFile:NEAR EXTERN CloseHandle:NEAR EXTERN CreatePipe:NEAR EXTERN TerminateProcess:NEAR EXTERN WaitForSingieObject:NEAR EXTERN SetMenu:NEAR EXTERN LoadMenuA:NEAR EXTERN CreateProcessA:NEAR EXTERN ExitProcess:NEAR EXTERN GetModuleHandleA:NEAR EXTERN DialogBoxParamA:NEAR EXTERN EndDialog:NEAR EXTERN SendDlgItemMessageA:NEAR
ReadFile@20 = ReadFile CloseHandle@4 = CloseHandle CreatePipe@16 = CreatePipe TerminateProcess@8 = TerminateProcess WaitForSingleObject@8 = WaitForSingleObject SetMenu@8 = SetMenu LoadMenuA@8 = LoadMenuA CreateProcessA@40 = CreateProcessA ExitProcess@4 = ExitProcess GetModuleHandleA@4 = GetModuleHandleA DialogBoxParamA@20 = DialogBoxParamA EndDialog@8 = EndDialog SendDlgItemMessageA@20 = SendDlgItemMessageA ENDIF
; структуры ; структура сообщения MSGSTRUCT STRUC MSHWND DD ? MSMESSAGE DD ? MSWPARAM DD ? MSLPARAM DD ? MSTIME DD ? MSPT DD ? MSGSTRUCT ENDS
; структура для CreateProcess STARTUP STRUC cb DD 0 lpReserved DD 0 lpDesktop DD 0 lpTitle DD 0 dwX DD 0 dwY DD 0 dwXSize DD 0 dwYSize DD 0 dwXCountChars DD 0 dwYCountChars DD 0 dwFillAttribute DD 0 dwFlags DD 0 wShowWindow DW 0 cbReserved2 DW 0 lpReserved2 DD 0 hStdInput DD 0 hStdOutput DD 0 hStdError DD 0 STARTUP ENDS
; структура - информация о процессе PROCINF STRUC hProcess DD ? hThread DD ? Idproc DD ? idThr DD ? PROCINF ENDS
; файл pipe.asm .386P ; плоская модель .MODEL FLAT, stdcall include pipe.inc ; директивы компоновщику для подключения библиотек IFDEF MASM includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ELSE includelib c:\tasm32\lib\import32.lib ENDIF ;---------------------------------------- ; сегмент данных _DATA SEGMENT DWORD PUBLIC USE32 'DATA' STRUP STARTUP <?> INF PROCINF <?> MSG MSGSTRUCT <?> HINST DD 0 ; дескриптор приложения PA DB "DIAL1",0 CMD DB "c:\tasm32\bin\tlink32.exe",0 PMENU DB "MENUP",0 HW DD ? HR DD ? BUFER DB 3000 DUP (0) BYT DD ? _DATA ENDS
; сегмент кода _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; получить дескриптор приложения PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ;------------------------------------------- PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX,-1 JNE KOL ; сообщение об ошибке KOL: ;--------------------------------- PUSH 0 CALL ExitProcess@4 ;--------------------------------- ; процедура окна ; расположение параметров в стеке ; [EBP+014Н] ; LPARAM ; [EBP+10Н] ; WAPARAM ; [EBP+0CH] ; MES ; [EBP+8] ; HWND WNDPROC PROC PUSH EBP MOV EBP,ESP PUSH EBX PUSH ESI PUSH EDI ;------------------------ CMP DWORD PTR [EBP+0CH],WM_CLOSE JNE L1 L3: PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 JMP FINISH L1: CMP DWORD PTR [EBP+0CH],WM_INITDIALOG JNE L2 ; загрузить меню PUSH OFFSET PMENU PUSH [HINST] CALL LoadMenuA@8 ; установить меню PUSH EAX PUSH DWORD PTR [EBP+08H] CALL SetMenu@8 JMP FINISH L2: CMP DWORD PTR [EBP+0CH],WM_COMMAND JNE FINISH CMP WORD PTR [EBP+10H],300 JE L3 CMP WORD PTR [EBP+10H],200 JNE FINISH ; здесь запуск ; в начале PIPE PUSH 0 PUSH 0 PUSH OFFSET HW PUSH OFFSET HR CALL CreatePipe@16 MOV EAX,HW ; здесь запуск консольного приложения MOV STRUP.cb,68 MOV STRUP.lpReserved,0 MOV STRUP.lpDesktop,0 MOV STRUP.lpTitle,0 MOV STRUP.dwFlags,STARTF_ADD MOV STRUP.cbReserved2,0 MOV STRUP.lpReserved2,0 MOV STRUP.wShowWindow,SW_HIDE ; окно процесса невидимо MOV STRUP.hStdOutput,EAX MOV STRUP.hStdError,EAX ;---------------------------------------------------------- PUSH OFFSET INF PUSH OFFSET STRUP PUSH 0 PUSH 0 PUSH 0 PUSH 1 ; наследует дескрипторы PUSH 0 PUSH 0 PUSH OFFSET CMD PUSH 0 CALL CreateProcessA@40 ; здесь чтение информации PUSH 0 PUSH OFFSET BYT PUSH 3000 PUSH OFFSET BUFER PUSH HR CALL ReadFile@20 PUSH OFFSET BUFER PUSH 0 PUSH EM_REPLACESEL PUSH 101 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 ; закрыть HANDLE на запись PUSH HW CALL CloseHandle@4 ; закрыть HANDLE на чтение PUSH HR CALL CloseHandle@4 FINISH: MOV EAX,0 POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP _TEXT ENDS END START