2011-08-18 10 views
6

किसी अन्य एप्लिकेशन की मोडल विंडो में आइटम जोड़ने का सबसे अच्छा तरीका क्या है?किसी अन्य एप्लिकेशन की मोडल विंडो में आइटम जोड़ने का सबसे अच्छा तरीका?

इस उदाहरण के लिए मैंने लिखा है कि सरल उदाहरण (अवधारणा के सबूत के रूप में) एक ऐसी विधि का उपयोग करता है जो मुझे संदेह है कि एक छोटी पृष्ठभूमि प्रक्रिया के लिए बहुत अधिक प्रोसेसर गहन है लेकिन मुझे एक विकल्प के साथ आने में परेशानी हो रही है।

उदाहरण के लिए, मान लीजिए कि आप चिकित्सक हैं जो डॉक्टर के पर्चे डेटा के साथ एक मोडल विंडो भर रहे हैं। आप इसे 11 दिनों के साथ 30 दिनों के लिए दर्ज करते हैं और फिर रोगी का कहना है कि वे 3 दिनों के साथ 90 दिन चाहते हैं। मूल एप्लिकेशन (जिसके लिए आपके पास स्रोत तक पहुंच नहीं है) में कोई आसान रूपांतरण नहीं है। मैंने एक छोटी सी उपयोगिता लिखी जो इस विशेष विंडो (टाइमर और फाइंडविंडो का उपयोग करके) के लिए देखता है और जब इसे पाता है, तो खुद को दृश्यमान बनाता है और लक्ष्य मोडल विंडो पर खाली जगह पर खुद को स्थान देता है। जब "30" बटन दबाया जाता है, तो आरएक्स को 11 दिनों के लिए 15 दिनों के लिए लिखा जाता है और जब "9 0" बटन दबाया जाता है, तो यह वही होता है जो आप उम्मीद करेंगे। यदि मोडल विंडो चलता है, तो 30 और 9 0 बटन इसके साथ आगे बढ़ते हैं। हालांकि यह काम करता है, मैं टाइमर पर बार-बार चलने में शामिल ओवरहेड के बारे में चिंतित हूं।

1) क्या कोई बेहतर तरीका है? 2) क्या मुझे इस बारे में चिंतित होने का अधिकार है? 3) क्या आप इस बात पर चिल्ला रहे हैं कि मेरे क्लेज कितने अक्षम हैं?

अग्रिम धन्यवाद - मैं यहां लोगों से बहुत प्रभावित हूं!

+4

मैं क्या रूप में एक वैकल्पिक और अधिक त्रुटियों की संभावना और समस्याग्रस्त एक वैश्विक सीबीटी हुक स्थापित करने के लिए, है के बारे में सोच सकते हैं, और यह बहुत ही मुफ्त के रूप में संसाधनों का संबंध है या तो नहीं है .. आप मतदान भी तेजी से नहीं कर रहे हैं, टाइमर अच्छा है मैं कहूंगा। –

+0

@Sertac: तो ... आप "बहुत तेजी से मतदान" होने पर क्या विचार करेंगे? मुझे 250 एमएमएस मतदान अंतराल के साथ सिस्टम प्रदर्शन में गिरावट या सीपीयू में वृद्धि (दोनों बहुत ही कच्चे उपायों, मुझे यकीन है) लेकिन यह सिर्फ "गलत लगता है" ... इससे धीमा कुछ भी बटन को फॉर्म का पालन करने से रोकता है सुचारू रूप से। –

+1

@ बी-पी आप खिड़की के लिए देखने के लिए 1 एस अंतराल का उपयोग कर सकते हैं और जब इसे चिकनी रखने के लिए 250 मिलीमीटर पर स्विच किया जाता है। इस तरह जब आप कोई लक्षित विंडो मौजूद नहीं होते हैं तो सिस्टम पर भी कम तनाव डालते हैं। – ain

उत्तर

1

सबसे अच्छा तरीका है ... डीएलएल इंजेक्शन।

// The DLL: 
library dll_inj; 

uses 
    ShareMem, 
    System.SysUtils, 
    System.Classes, Vcl.Dialogs, 
    windows, messages; 

{$R *.res} 

var 
    hWndMain, hDemoButton, hEdit, hNewButton, hWndEnter: THandle; 
    OldWndProc: TFarProc; 
    hBtnFont: hFont; 
    Times: integer; 
    dwThreadId: DWORD; 

function NewWndProc(hWnd: hWnd; Msg: UINT; wParam: wParam; lParam: lParam) 
    : Longint; stdcall; 
begin 
    if Times = 0 then 
    begin 
    Times := Times + 1; 
    hWndMain := FindWindowEx(0, 0, 'TForm1', 'Injection test'); 
    if hWndMain = 0 then 
     OutputDebugString('hWndMain is 0!'); 

    hNewButton := CreateWindow('button', 'NewBtn', WS_CHILD or WS_VISIBLE, 20, 
     20, 100, 24, hWndMain, 2000, GetWindowLong(hWndMain, GWL_HINSTANCE), nil); 
    if hNewButton = 0 then 
     OutputDebugString('CreateWindow failed!') 
    else 
    begin 
     hWndEnter := FindWindowEx(hWndMain, 0, 'TBitBtn', 'Enter'); 
     if hWndEnter <> 0 then 
     hBtnFont := SendMessage(hWndEnter, WM_GETFONT, 0, 0); 
     if hBtnFont <> 0 then 
     SendMessage(hNewButton, WM_SETFONT, hBtnFont, 1); 
    end; 

    hDemoButton := FindWindowEx(hWndMain, 0, 'TButton', 'Demo'); 
    if hDemoButton <> 0 then 
    begin 
     if not EnableWindow(hDemoButton, true) then 
     OutputDebugString('EnableWindow failed!'); 
    end 
    else 
     OutputDebugString('hDemoButton is 0!'); 

    hEdit := FindWindowEx(hWndMain, 0, 'TEdit', 'Serial'); 
    if hEdit = 0 then 
     OutputDebugString('hEdit is 0!') 
    else if not SetWindowText(hEdit, 'You have been hacked') then 
     OutputDebugString('SetWindowText failed!'); 
    end; 

    case Msg of 
    WM_COMMAND: 
     if (hNewButton <> 0) and (DWORD(lParam) = hNewButton) then 
     MessageBox(HWND_DESKTOP, 'You pressed a new button!', 'Yay!', MB_OK) 
     else if (hWndEnter <> 0) and (DWORD(lParam) = hWndEnter) then 
     begin 
     MessageBox(HWND_DESKTOP, 'This message is not default anymore!', 
      'Override!', MB_OK); 
     Exit(0); // Suppress default event completely 
     end; 
    end; 
    Result := CallWindowProc(OldWndProc, hWnd, Msg, wParam, lParam); 
end; 

procedure EntryPoint(Reason: integer); 
begin 
    hWndMain := FindWindowEx(0, 0, 'TForm1', 'Injection test'); 
    if hWndMain = 0 then 
    begin 
    OutputDebugString('hWndMain is 0!'); 
    Exit; 
    end; 

    OldWndProc := TFarProc(SetWindowLong(hWndMain, GWL_WNDPROC, 
    LONG(@NewWndProc))); 

    MessageBox(0, 'DLL Injected', 'OK', 0); 
end; 

begin 
    CreateThread(nil, 0, @EntryPoint, nil, 0, &dwThreadId); 

end. 

// The injector: 
program exe_inj2; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, windows, TLHelp32; 

Function EnumThreadProc(wnd: HWND; Var appHwnd: HWND): LongBool; stdcall; 
Var 
    buf: array [0 .. 256] of Char; 
Begin 
    Result := LongBool(1); 
    if GetClassname(wnd, buf, sizeof(buf)) > 0 then 
    If StrComp(buf, 'TApplication') = 0 Then 
    Begin 
     appHwnd := wnd; 
     Result := False; 
    End; 
End; 

Function FindApplicationWindow(forThreadID: DWORD): HWND; 
Begin 
    Result := 0; 
    EnumThreadWindows(forThreadID, @EnumThreadProc, lparam(@Result)); 
End; 

Function ProcessIDFromAppname32(appname: String): DWORD; 
{ Take only the application filename, not full path! } 
Var 
    snapshot: THandle; 
    processEntry: TProcessEntry32; 
Begin 
    Result := 0; 
    appname := UpperCase(appname); 
    snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
    If snapshot <> 0 Then 
    try 
     processEntry.dwSize := sizeof(processEntry); 
     If Process32First(snapshot, processEntry) Then 
     Repeat 
      If Pos(appname, 
      UpperCase(ExtractFilename(StrPas(processEntry.szExeFile)))) > 0 Then 
      Begin 
      Result := processEntry.th32ProcessID; 
      Break; 
      End; { If } 
     Until not Process32Next(snapshot, processEntry); 
    finally 
     CloseHandle(snapshot); 
    End; { try } 
End; 

function InjectDLL(dwPID: DWORD; DLLPath: PWideChar): integer; 
var 
    dwThreadID: Cardinal; 
    hProc, hThread, hKernel: THandle; 
    BytesToWrite, BytesWritten: SIZE_T; 
    pRemoteBuffer, pLoadLibrary: Pointer; 
begin 
    if not FileExists(DLLPath) then 
    begin 
    MessageBox(0, PWideChar('File ' + DLLPath + ' does not exist'), 'Error', 0); 
    Exit(0); 
    end; 

    hProc := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or 
    PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, False, dwPID); 
    if hProc = 0 then 
    Exit(0); 
    try 
    BytesToWrite := sizeof(WideChar) * (Length(DLLPath) + 1); 
    pRemoteBuffer := VirtualAllocEx(hProc, nil, BytesToWrite, MEM_COMMIT, 
     PAGE_READWRITE); 
    if pRemoteBuffer = nil then 
     Exit(0); 
    try 
     if not WriteProcessMemory(hProc, pRemoteBuffer, DLLPath, BytesToWrite, 
     BytesWritten) then 
     Exit(0); 
     hKernel := GetModuleHandle('kernel32.dll'); 
     pLoadLibrary := GetProcAddress(hKernel, 'LoadLibraryW'); 
     hThread := CreateRemoteThread(hProc, nil, 0, pLoadLibrary, pRemoteBuffer, 
     0, dwThreadID); 
     try 
     WaitForSingleObject(hThread, INFINITE); 
     finally 
     CloseHandle(hThread); 
     end; 
    finally 
     VirtualFreeEx(hProc, pRemoteBuffer, 0, MEM_RELEASE); 
    end; 
    finally 
    CloseHandle(hProc); 
    end; 
    Exit(1); 
end; 

const 
    PROCESS_NAME = 'Default_project.exe'; 

begin 
    try 
    { TODO -oUser -cConsole Main : Insert code here } 
    WriteLn(PROCESS_NAME + ' PID: ' + 
     IntToSTr(ProcessIDFromAppname32(PROCESS_NAME))); 
    InjectDLL(ProcessIDFromAppname32(PROCESS_NAME), 'dll_inj.dll'); 
    ReadLn; 
    except 
    on E: Exception do 
     WriteLn(E.ClassName, ': ', E.Message); 
    end; 

end. 
संबंधित मुद्दे

 संबंधित मुद्दे