AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Undokumentierter Sendmessage-Befehl
Thema durchsuchen
Ansicht
Themen-Optionen

Undokumentierter Sendmessage-Befehl

Ein Thema von PinkFloydFan · begonnen am 4. Sep 2011 · letzter Beitrag vom 6. Sep 2011
Antwort Antwort
Seite 1 von 2  1 2      
EWeiss
(Gast)

n/a Beiträge
 
#1

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 01:04
Zitat:
aus ner beliebigen Form auslesen kann
Dir ist aber schon klar das diese Sendmessage wenn überhaupt nur mit VB6 Formen (HWND) funktioniert?
"ThunderRT6FormDC"

Code:
'Make sure we are working with a VB Form hWnd
sClass = Space(256)
lRet = GetClassName(hwnd, sClass, 255)
sClass = Left(sClass, lRet)

    If Not sClass = "ThunderRT6FormDC" Then
        MsgBox "This function only works on VB RunTime 6 Forms ThunderFormRT6DC"
        Exit Sub
    End If
gruss

Geändert von EWeiss ( 5. Sep 2011 um 02:22 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von PinkFloydFan
PinkFloydFan

Registriert seit: 4. Dez 2007
Ort: Straubing
54 Beiträge
 
Delphi 2010 Architect
 
#2

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 07:02
Guten Morgen!

@ EWeiss:
Das war mir schon klar.. Ich bin eben sehr optimistisch und hoffte, das man das auch für ne Delphi-Form verwenden könnte.. Aber so wie's aussieht kann ich das auch vergessen..


Hintergrund des Ganzen ist, dass wir in der Firma ein Hypersuperoberwichtiges Programm am Laufen haben, dessen Quellcode leider von einem ehemaligen Mitarbeiter mutwillig zerstört wurde und somit nicht mehr verfügbar ist, auch nicht in Code-Fragmenten. Das Proggi tut ja seinen Dienst, und nun sollten einige Erweiterungen dazu geschrieben werden, um das Handling dieses Proggs etwas zu erleichtern. Allerdings sind alle Text-Ausgaben, die das Programm tätigt, nicht in Edits oder Memos (Leider, denn dann wär's ja ein Leichtes) sondern in Labels...

Und das ist das Problem. Um die Sache "fernzusteuern" muss ich den Inhalt dieser Labels kennen.


Ich habe auch die Vorschläge in http://www.delphipraxis.net/86561-zu...wendung-2.html durchprobiert, was ja an sich auch funktioniert. Nur kenne ich die Namen der Labels nicht. Label1, Label2 usw sinds jedenfalls nicht. Die können ja jeden X-beliebigen Namen haben, zB LblIrgendwas oder ArtikelNrLabel oder sonst was...

Die grosse Frage lautet also:

Wie komme ich also an die Captions diese Label??

Geändert von PinkFloydFan ( 5. Sep 2011 um 07:36 Uhr) Grund: Linksschreibfehler ausgepessrt :-)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.666 Beiträge
 
Delphi 12 Athens
 
#3

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 07:03
Wenn es wirklich Labels sind, sieht es schlecht aus. Bei StaticText gäbe es noch die Möglichkeit, die Fensterhandles zu ermitteln und zu schauen, was da was ist.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von PinkFloydFan
PinkFloydFan

Registriert seit: 4. Dez 2007
Ort: Straubing
54 Beiträge
 
Delphi 2010 Architect
 
#4

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 07:22
Guten Morgen DeddyH!

Static Labels sind auf keinen Fall.
Mit z.B. Winspy erhalte ich keine Handles. Einzig für ein TPanel,
welches die übergeordnete Komponente dieser 14 Labels darstellt.

Vielleicht gibts über das TPanel nen Ansatz??

Hab mal spasseshalber einen Memory-Dump dieses Programms erzeugt. Die Captions dieser Label sind da schon enthalten, aber immer an anderen Offsets. ( Und auch die vorherigen Captions.. also fast schon wie ne History..)
Irgendwo muss Windows ja mitgeteilt werden, welcher Text wo zu malen ist..

Geändert von PinkFloydFan ( 5. Sep 2011 um 07:37 Uhr)
  Mit Zitat antworten Zitat
Morphie

Registriert seit: 27. Apr 2008
Ort: Rahden
630 Beiträge
 
#5

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 07:47
Ich habe auch die Vorschläge in http://www.delphipraxis.net/86561-zu...wendung-2.html durchprobiert, was ja an sich auch funktioniert. Nur kenne ich die Namen der Labels nicht. Label1, Label2 usw sinds jedenfalls nicht. Die können ja jeden X-beliebigen Namen haben, zB LblIrgendwas oder ArtikelNrLabel oder sonst was...
An die Namen kommst du z.B. ganz leicht mittels ResHacker ran.
Angehängte Grafiken
Dateityp: png labels.png (32,1 KB, 32x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.666 Beiträge
 
Delphi 12 Athens
 
#6

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 07:52
Aber wie kommt man von außen an die Beschriftung? WM_GETTEXT usw. scheiden ja mangels Fensterhandle aus.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von PinkFloydFan
PinkFloydFan

Registriert seit: 4. Dez 2007
Ort: Straubing
54 Beiträge
 
Delphi 2010 Architect
 
#7

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 08:02
Moin Morphie!

jo!! Das sieht gut aus!! Werde ich dann gleich versuchen, wenn ich in der Maloche bin..

Melde mich wenn ich ein Ergebnis habe..


@DeddyH:

so kommt man dran: (Source von Sirius, Link weiter oben)

Delphi-Quellcode:
unit U_getImage;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;


const mymsg=WM_User+1;

type TSearchtype=(sClassName,sName,sCaption);
type PMemory=^TMemory;
     TMemory=packed record
       Thread:array[0..1023] of char;
       Postmessage:function(wnd:hwnd;msg,wparam,lparam:cardinal):bool;stdcall;
       exitthread:procedure(exitcode:integer);stdcall;
       getwindowlong:function(wnd:hwnd;index:integer):cardinal;stdcall;
       watchwnd:hwnd;
       backwnd:hwnd;
       backmsg:integer;
       count:integer;
       SearchType:TSearchtype;
       vgl:array[0..31] of char;
       vgllength:integer;
     end;



type
  TForm1 = class(TForm)
    Image1: TImage;
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Label1: TLabel;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure GetMyMsg(var msg:TMessage);message mymsg;
    procedure GetMyCaption(var msg:TMessage);message mymsg+1;
    procedure Button3Click(Sender: TObject);
  private
    { Private-Deklarationen }
    myhandle:hwnd;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


function injectThread(memory:Pmemory):integer; stdcall;
{Diese Funktion landet nachher in einem fremden Process.
Deswegen dürfen hier keine Funktionen von Delphi benutzt werden
(inkl. Stringoperationen, VCL, etc.).}

var pi,p,pm:ppointer;
    i,a:integer;
    c:pchar;
    left,top,width,height:smallint;
    same:boolean;
    wparam,lparam:cardinal;
begin
  wparam:=0;
  lparam:=0;
  p:=pointer(memory^.getwindowlong(memory^.watchwnd,gwl_wndproc)+9);


  pm:=pointer(integer(p^)+16);

  for a:=0 to pinteger(integer(pm^)+8)^-1 do begin //von 0 bis componentcount

    p:=pointer(integer(pm^)+4);
    p:=pointer(integer(p^)+4*a);
    pi:=p; //pi^ ist Zeiger auf ein Objekt

    if memory^.SearchType=sClassname then begin
      p:=p^;
      p:=pointer(integer(p^)-44);
    end else
      p:=pointer(integer(p^)+8);

    p:=p^;

    c:=pchar(p);
    if (pbyte(p)^=memory^.vgllength)or(memory^.SearchType in[sName,sCaption]) then begin
      if memory^.SearchType=sClassName then inc(c);
      same:=false;
      for i:=1 to memory^.vgllength do begin
        if memory^.vgl[i-1]<>c^ then break;
        same:=i=memory^.vgllength;
        inc(c);
      end;
      if same then begin
        dec(memory^.count);
        if (memory^.count=0)or(memory^.SearchType in [sName,sCaption]) then begin
          if memory^.SearchType=sCaption then begin
            p:=pointer(integer(pi^)+$64);
            wparam:=cardinal(p^);
            c:=pchar(p^);
            while c^<>#0 do begin
              inc(c);
              inc(lparam);
            end;
            inc(memory^.backmsg);
          end else begin
            left:=pinteger(integer(pi^)+$40)^;
            top:=pinteger(integer(pi^)+$44)^;
            width:=pinteger(integer(pi^)+$48)^;
            height:=pinteger(integer(pi^)+$4C)^;
            //4 Zahlen in 2*32Bit kopieren
            wparam:=left*65536+top;
            lparam:=width*65536+height;
          end;
          break;
        end;
      end;
    end;

  end;

  //Ergebnis Nach Hause senden
  memory^.Postmessage(memory^.backwnd,memory^.backmsg,wparam,lparam);
  result:=0;
  //Thread beenden
  memory^.exitthread(0);
end;
procedure endpoint;
//ohne Funktion nur zum finden des Address-endes von injcetThread
asm
nop
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  close;
end;

procedure TForm1.Button1Click(Sender: TObject);
var mem:TMemory;
    lib:THandle;
    size:integer;
    process:cardinal;
    processid:cardinal;
    procmem:PMemory;
    tmp:cardinal;
    threadID:cardinal;
    thread:THandle;
begin
  memo1.clear;
  myhandle:=findwindow(nil,'PImage'); //Beispielprogramm finden
  if myhandle=0 then exit;

  //mem ist der Record der nachher in den anderen Process kopiert wird
  mem.backwnd:=self.Handle; //Handle, damit wir Nachrichten zurückschicken können
  mem.backmsg:=mymsg; //Message-Nr., damit wir unsere Message wiederfinden
  mem.watchwnd:=myhandle; //Das Handle für getwindowlong
  mem.count:=6; //welches TControl (=mem.vgl)? (nur für Searchtype=sClassName)
  mem.vgl:='Label2'; //der Vergleichsstring <-------------------------------------------------------------------------------------------- HIER
  mem.vgllength:=6; //Länge des Vergleichsstrings
  mem.SearchType:=sCaption; //vgl vergleichen mit Classname oder Name oder Caption zurücksenden
  //kopieren der funktion injectthread in den Record
  size:=integer(@endpoint)-integer(@injectThread);
  move(injectthread,mem.thread,size);
  //EinsprungAdresse von 3 WinAPI-funktionen, die nacher benötigt werden
  //Die Adressen sind in jedem Process gleich
  lib:=getmodulehandle('user32.dll');
  mem.Postmessage:=getprocaddress(lib,'PostMessageA');
  mem.getwindowlong:=getprocaddress(lib,'GetWindowLongA');
  lib:=getmodulehandle('kernel32.dll');
  mem.exitthread:=getprocaddress(lib,'ExitThread');

  //Thread-Record in anderen Process kopieren und mem.Thread starten
  getwindowthreadprocessid(myhandle,@processid);
  process:=openprocess(PROCESS_ALL_ACCESS,false,processid);
  //Speicher reservieren
  procmem:=virtualallocex(process,nil,sizeof(Tmemory),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  //Kopieren
  writeprocessmemory(process,procmem,@mem,sizeof(TMemory),tmp);
  //Starten
  thread:=createremotethread(process,nil,0,@procmem.thread,procmem,0,threadid);
  //Warten bis injectthread beendet ist

  waitforsingleobject(thread,infinite);
  //Speicher wieder freigeben
  closehandle(thread);
  virtualfreeex(process,procmem,0,mem_decommit);
  closehandle(process);

end;
procedure TForm1.GetMyMsg(var msg:TMessage);
begin
  memo1.Lines.add(inttostr(msg.WParamlo));
  memo1.Lines.add(inttostr(msg.WParamhi));
  memo1.Lines.add(inttostr(msg.lParamlo));
  memo1.Lines.add(inttostr(msg.lParamhi));
end;
procedure TForm1.GetMyCaption(var msg:TMessage);
var process,processID,tmp:cardinal;
    s:string;
begin
  if myhandle=0 then exit;

  //in msg.wparam steht der Pointer auf das TLabel.caption im anderen Process
  //in msg.lparam die Länge des TCaption

  getwindowthreadprocessid(myhandle,@processid);
  process:=openprocess(PROCESS_VM_READ,false,processid);
  setlength(s,msg.LParam);
  readprocessmemory(process,pointer(msg.wparam),@s[1],msg.lparam,tmp);
  closehandle(process);
  memo1.Lines.add(s);
end;

end.
Natürlich muss dieser Source noch entsprechend aufbereitet werden und einige Sachen entfallen, aber das Prinzip funktioniert..
  Mit Zitat antworten Zitat
Morphie

Registriert seit: 27. Apr 2008
Ort: Rahden
630 Beiträge
 
#8

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 08:12
das hier sollte wohl auch schon reichen:
Delphi-Quellcode:
function GetLabelText(ParentHandle: HWND; LabelName: string): string;
var
  pi, p, pm: ppointer;
  a: integer;
  obj: tPersistent;
  myhandle: hwnd;
begin
  Result := '';
  myhandle := ParentHandle;
  p := pointer(getwindowlong(myhandle, gwl_wndproc) + 9);
  pm := p;
  pm := pointer(integer(pm^) + 16);
  for a := 0 to pinteger(integer(pm^) + 8)^ - 1 do
  begin //von 0 bis componentcount
    p := pointer(integer(pm^) + 4);
    p := pointer(integer(p^) + 4 * a);
    pi := p; //pi^ ist Zeiger auf ein Objekt
    obj := tPersistent(pi^);
    if obj is TLabel then
    begin
      if (TLabel(obj).Name = LabelName) then
      begin
        Result := TLabel(obj).Caption;
        break;
      end;
    end;
  end;
end;
ParentHandle = Handle der Form, auf der sich das Label befindet
LabelName = Name des Label-Controls
  Mit Zitat antworten Zitat
Benutzerbild von PinkFloydFan
PinkFloydFan

Registriert seit: 4. Dez 2007
Ort: Straubing
54 Beiträge
 
Delphi 2010 Architect
 
#9

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 08:16
Nu wirds aber richtig interessant!!

Werde ich gleich mal antesten!!

Sollte es doch noch eine Lösung geben?? *freu*
  Mit Zitat antworten Zitat
Benutzerbild von PinkFloydFan
PinkFloydFan

Registriert seit: 4. Dez 2007
Ort: Straubing
54 Beiträge
 
Delphi 2010 Architect
 
#10

AW: Undokumentierter Sendmessage-Befehl

  Alt 5. Sep 2011, 08:28
@Morphie:

Danke für deinen Vorschlag!!
Liest sich soweit gut, aaaber:

hier bekomme ich eine Zugriffsverletzung:

pm := pointer(integer(pm^) + 16);


"Lesen von Adresse 00000009"

Dieser Code scheint nur bei der eigenen Anwendung zu funktionieren.
Sobald man das Handle einer fremden Anwendung angibt, erhält man die Zugriffs-Verletzung

Edit: Ers ma Kaffee zubereiten...

Geändert von PinkFloydFan ( 5. Sep 2011 um 08:31 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:37 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz