Proccess ID vs. Tasklist Windows Handle [erledigt]

Fragen rund um diverse Windows-Versionen, ihr Verhalten unter Xbase++ und den Umgang mit der API

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Proccess ID vs. Tasklist Windows Handle [erledigt]

Beitrag von AUGE_OHR »

moin,

ich möchte aus meinem Xbase++ OSK Events an externe Windows Apps senden.
dazu benutze ich die VK_* Konstanten (virtual Keyboard).
nun muss ich den Empfänger bzw. das Fenster auswählen an das es gehen soll.

wenn ich die Processliste abfrage erhalte ich Name des EXE und die PID.
wenn ich die Tastliste abfrage erhalte ich Title des Fenster und das Handle des Fenster.

eigentlich sollte die PID mit SetActiveWindow() ausreichen ... aber ich musste das Fenster erst "nach vorne" holen damit es klappt :roll:
nun ist der Titel des Fenster aber nicht gleich dem *.EXE dessen PID ich habe :^o

also meine Frage : wie bekomme ich noch das Empfänger Fenster "nach vorne" :idea:
Zuletzt geändert von AUGE_OHR am Do, 06. Dez 2018 3:55, insgesamt 1-mal geändert.
gruss by OHR
Jimmy
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von Herbert »

Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von AUGE_OHR »

hi,
Herbert hat geschrieben: Di, 04. Dez 2018 10:30 Vielleicht hilft das hier?
https://www.xbaseforum.de/viewtopic.php ... exe#p90168
Danke für den Hinweis, den Code muss ich mir noch mal genauer ansehen.
allerdings ist von WildFindWindow() die Rede ... das finde ich ja auch über die Tasklist.

mit SendMessageA() hatte ich es auch versucht aber das klappt nicht mit ALLEN Tasten.
bei Marcus Lösung kann der Empfänger auf WM_USER_4096 reagieren.
Rudolf macht es mit WM_COPYDATA und einer eigenen wndproc() Method.
den Code von DelUser01 mit BAP wird wohl ähnlich sein da ich auch dort nach einem Title suche aber nicht nach der dazu gehörigen EXE.

bei den VK_* Konstanten, gesendet mit keybd_event(), kann ich jede (sichtbare) App erreichen aber es sind 2 Sachen

Code: Alles auswählen

   CASE cSeek = "WINWORD.EXE"  ; cSeek := "Microsoft Word"
   CASE cSeek = "TOTALCMD.EXE" ; cSeek := "Total Commander"
   // German
   CASE cSeek = "CMD.EXE"      ; cSeek := "Eingabeaufforderung"
   CASE cSeek = "NOTEPAD.EXE"  ; cSeek := "Editor"
die Processlist gibt mir die PID für das EXE aber das Fenster hat in der Titlebar nicht den Namen des EXE sondern was anderes.

Code: Alles auswählen

   nPosi := ASCAN( aTasklist, { | x | UPPER( cSeek ) $ UPPER( x ) } )
   IF nPosi > 0
      ::hWndApp := VAL( SUBSTR( aTasklist[ nPosi ], 1, 8 ) ) 
ich suche nun nach dem Teil-String um es in der Tasklist zu finden.
während WINWORD.EXE verschiedene Instanzen erstellt wird NOTEPAD.EXE mehrfach gestartet mit verschiedener PID. dummerweise findet er im Taskmanager ( und WildFindWindow() ) jeweils das erste Fenster mit "- Editor" ...

wie schon gesagt kann ich die externen Apps nicht ändern. z.Z. funktioniert das OSK nur bei solchen Einträgen.
ich möchte wissen welche PID (EXE) welches Fenster (Handle) kontrolliert damit diese Code immer funktioniert.

Code: Alles auswählen

METHOD DXE_KbWin:SetTheFocus()
   SetActiveWindow( ::hProcess )   // Proccess ID (PID)
   SLEEP( 1 )
   
   IF !EMPTY( ::hWndApp )   // Windows Handle from Tasklist
      SetForegroundWindow( ::hWndApp )
      BringWindowToTop( ::hWndApp )
      ShowWindow( ::hWndApp, 1 )
      UpdateWindow( ::hWndApp )
      SLEEP( 1 )
   ENDIF
   
   SetActiveWindow( ::hProcess )
   SLEEP( 1 )
RETURN
Zuletzt geändert von AUGE_OHR am Mi, 05. Dez 2018 9:45, insgesamt 1-mal geändert.
gruss by OHR
Jimmy
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von Werner_Bayern »

Ich mach das über

Code: Alles auswählen

ShowWindow
Sleep(10)
SetForegroundWindow
jeweils per Fensterhandle.

Code: Alles auswählen

EXTERN INTEGER ShowWindow(hWnd AS UINTEGER, nCmdShow AS INTEGER) IN USER32
EXTERN LONG SetForegroundWindow(hWnd AS UINTEGER) IN USER32
Hab da sehr lange rumgetüftelt und probiert. So läuft es einwandfrei!
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von AUGE_OHR »

hi,
Werner_Bayern hat geschrieben: Di, 04. Dez 2018 15:27 Ich mach das über

Code: Alles auswählen

ShowWindow
Sleep(10)
SetForegroundWindow
jeweils per Fensterhandle.
ich habe ja keine Probleme ein Fenster nach vorne zu holen ... wenn ich den Title habe.
nun kann ich aber an das Windows Handle kein keybd_event() schicken, dazu brauche ich die Proccess ID.

die PID ist das EXE z.b. Notepad.EXE und das Fenster heisst "Unbekannt - Editor" also wie bekomme ich "das" zusammen :?:
gruss by OHR
Jimmy
Benutzeravatar
HaPe
1000 working lines a day
1000 working lines a day
Beiträge: 995
Registriert: So, 15. Nov 2015 17:44
Wohnort: 71665 Vaihingen-Enz
Hat sich bedankt: 17 Mal
Danksagung erhalten: 15 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von HaPe »

Hallo Jimmy !
nun kann ich aber an das Windows Handle kein keybd_event() schicken, dazu brauche ich die Proccess ID.
Mit GetWindowThreadProcessId kannst du das rausbekommen.
C-Quellcode:
DWORD dwProcessID = 0x01;
hProcessWindow = whMyWindowHandle;
dwThreadProcessID = GetWindowThreadProcessId( hProcessWindow, &dwProcessID );
In dwProcessID hast du eine Proccess ID 8)

https://docs.microsoft.com/en-us/window ... dprocessid
--
Hans-Peter
Benutzeravatar
mikehoffmann
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 133
Registriert: Mo, 21. Sep 2015 16:22
Hat sich bedankt: 1 Mal
Danksagung erhalten: 18 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von mikehoffmann »

Auauauauauaua.

Was heißt "nach vorne holen"?

Auf "Nach-Vorne-Holen" steht übrigens die Todesstrafe.

Die ProcessID nützt Dir nix. Keybd_event kann sie gar nicht gebrauchen. Ach ja, keybd_event sollte man gar nicht mehr nutzen, meint Frau MSDN.

Reihenfolge beachten: (1) Erst verstehen, (2) dann rumschweinzen. Aber nur, wenn nach (1) wirklich nötig.

(1a): Wer bekommt denn die Keyboard Events? Soll das denn nicht genau der sein, den der mächtige Herr User bereits gewählt hat?
(1b): Ist das Problem nicht eher, dass Dein Tastaturfenster den Focus bekommt, wenn der mächtige Herr User reinklickt, um eine Taste zu drücken?

(2): Nach Berücksichtigung von (1a) und (1b) nicht mehr erforderlich.
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von Werner_Bayern »

mikehoffmann hat geschrieben: Mi, 05. Dez 2018 11:58 Auauauauauaua.

Was heißt "nach vorne holen"?

Auf "Nach-Vorne-Holen" steht übrigens die Todesstrafe.
Dann bin ich des mehrfachen - ja was eigentlich - schuldig! Von Dir zum Tode verurteilt.
(1a): Wer bekommt denn die Keyboard Events? Soll das denn nicht genau der sein, den der mächtige Herr User bereits gewählt hat?
(1b): Ist das Problem nicht eher, dass Dein Tastaturfenster den Focus bekommt, wenn der mächtige Herr User reinklickt, um eine Taste zu drücken?

(2): Nach Berücksichtigung von (1a) und (1b) nicht mehr erforderlich.
1a: Nein, soll er nicht! Ein Anwendungsfall bei uns ist z. B., dass wir ein externes Programm des Kunden starten, die PID ermitteln, dieses dann in den Vordergrund holen und dann über sendkey Tastatureingaben simulieren und damit dem Kunden einiges an Handarbeit und Fehleranfälligkeit abnehmen.
1b: Nein, er ist ja in unserer Xbase++-Anwendung, die alles weitere für ihn erledigt.

Muss ich jetzt mein Testament machen?
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von AUGE_OHR »

hi,
HaPe hat geschrieben: Mi, 05. Dez 2018 11:19 Mit GetWindowThreadProcessId kannst du das rausbekommen.
C-Quellcode:
DWORD dwProcessID = 0x01;
hProcessWindow = whMyWindowHandle;
dwThreadProcessID = GetWindowThreadProcessId( hProcessWindow, &dwProcessID );
In dwProcessID hast du eine Proccess ID 8)
https://docs.microsoft.com/en-us/window ... dprocessid
habe nun das probiert und bekomme mit GetWindowThreadProcessId() nicht gewünschtes Resultat :(

den ersten Parameter hWnd entnehme ich der Tasklist.
beim 2nd Parameter, als Referenz, hab ich es mit 0, 1, -1 und hProccess versucht

Code: Alles auswählen

METHOD DXE_KbWin:GetWindowThreadProcessId(aTasklist, hProcess )
LOCAL nRet  := 0
LOCAL nPID  := 0
LOCAL cSeek := ""
LOCAL hWnd
LOCAL i,iMax := LEN(aTasklist)

   FOR i := 1 TO iMax
      hWnd := VAL(SUBSTR(aTasklist[i],1,8))
      nPID := 0 // -1, 1, hProcess
      nRet := GetWindowThreadProcessId(hWnd, @nPID)

      IF nPID = hProcess .or. nRet = hProcess
         cSeek := TRIM(STRTRAN(SUBSTR(aTasklist[i],9),CHR(0),""))
         EXIT
      ENDIF
   NEXT
RETURN cSeek
bei -1, 1, hProcess crashed er mit "Interne Datenstrukturen beschädigt".
mit 0 läuft er zwar durch aber ohne Ergebnis

hm ... der 2nd Parameter ist Type: LPDWORD
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von AUGE_OHR »

hi Mike,

das wir uns nicht falsch verstehen : das OSK ist für Xbase++ Apps mit Touch-Screen gedacht und funktioniert.

nun gibt es aber nicht für alle Tasten eine XbeK_* Konstante also habe ich dann VK_* Konstanten verwendet.

dabei kam mir der Gedanke das man VK_* Konstanten auch an externe Apps schicken könnte ...
damit der Empfänger richtig eingestellt ist verwenden die Jungs in ihren Demo Code SetActiveWindow(hPID) ... aber das reicht für Xbase++ nicht :shock:

also weiter mit

Code: Alles auswählen

   SetForegroundWindow( ::hWndApp )
   BringWindowToTop( ::hWndApp )
   ShowWindow( ::hWndApp, 1 )
   UpdateWindow( ::hWndApp )
   SLEEP( 1 )
   SetActiveWindow(hPID)
   SLEEP( 1 ) 
und damit klappt es dann =D>

ich brauche also beides

Code: Alles auswählen

PID  : Proccess ID des EXE -> Notepad.EXE
hWnd : Handle des Fenster  -> "Unbenannt - Editor"
ich habe die Proccesslist und Tasklist als Array ... die Frage ist wie bekomme ich das zusammen :idea:

---

wie du schon sagtest ist keybd_event() eigentlich veraltet.
ich habe auch schon die SendInput() Function mit der Input Structure.

Code: Alles auswählen

FUNCTION Print_Window( nWindow )
LOCAL oInput := INPUT() :New()
LOCAL nSize  := oInput:_sizeof_()
LOCAL nRet   := 0

   nWindow := IIF( EMPTY( nWindow ), 0, 1 ) // 0 is entire screen, 1 is active window
   sleep( 1 )
   
   // old function 
   // keybd_Event( VK_SNAPSHOT,nWindow,0,0)

   oInput:type := INPUT_KEYBOARD
   oInput:ki:wVk := VK_SNAPSHOT
   oInput:ki:wScan := nWindow
   oInput:ki:dwFlags := 0
   oInput:ki:dwExtraInfo := 0

   nRet := @user32:SendInput( 1, oInput, nSize )
RETURN nRet
nun ist das OSK pure Xbase++ also keine 3PP wie ot4xb und deshalb verwende ich es in diesem Fall nicht.
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Proccess ID vs. Tasklist Windows Handle

Beitrag von AUGE_OHR »

so nun hab ich das sammeln der Taskleiste erweitert und sehe das (natürlich) weiter Informationen vorhanden sind ausser Handle und Title

Code: Alles auswählen

   aInfo[1] := hWnd
   c := ChrR(0,n)
   @user32:GetWindowTextA(hWnd,@c,Len(c)+1)
   aInfo[2] := c
   n := 0
   aInfo[3] := @user32:GetWindowThreadProcessId(hWnd,@n)
   aInfo[4] := n
   c := ChrR(0,260)
   aInfo[5] := cPid2ModName(aInfo[4] )
neu sind also
aInfo[3] -> Thread ID
aInfo[4] -> PID
aInfo[5] -> EXE Name
ich habe beim sammeln der Taskliste also alle Informationen über ein Fenster und brauche keine weitere Verknüpfung :D
gruss by OHR
Jimmy
Benutzeravatar
HaPe
1000 working lines a day
1000 working lines a day
Beiträge: 995
Registriert: So, 15. Nov 2015 17:44
Wohnort: 71665 Vaihingen-Enz
Hat sich bedankt: 17 Mal
Danksagung erhalten: 15 Mal

Re: Proccess ID vs. Tasklist Windows Handle [erledigt]

Beitrag von HaPe »

Hallo Jimmy !
ich habe beim sammeln der Taskliste also alle Informationen über ein Fenster und brauche keine weitere Verknüpfung
Geht mit GetWindowThreadProcessId. 8)

Sag ich doch :blob8:
--
Hans-Peter
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Proccess ID vs. Tasklist Windows Handle [erledigt]

Beitrag von AUGE_OHR »

HaPe hat geschrieben: Do, 06. Dez 2018 10:01 Sag ich doch :blob8:
Ja, Danke =D>
gruss by OHR
Jimmy
Benutzeravatar
mikehoffmann
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 133
Registriert: Mo, 21. Sep 2015 16:22
Hat sich bedankt: 1 Mal
Danksagung erhalten: 18 Mal

Re: Proccess ID vs. Tasklist Windows Handle [erledigt]

Beitrag von mikehoffmann »

Nochmal zum Mitschrieben: Fenster "nach vorne knallen" ist ein absolutes No-Go, vor allem dann nicht, wenn man nicht wirklich weiß, was man tut und warum es manchmal doch nicht geht. Einen kleinen Einstieg in den Hintergrund gibt es z.B. hier:

https://blogs.msdn.microsoft.com/oldnew ... 0/?p=21393

Man muss dazu noch wissen, dass das Xbase++ GUI komplett andes funktioniert, als dies normalerweise der Fall ist, weil die Fensterlein (oder besser Teilchen) in einem anderen Thread ticken als die eigentliche Anwendung und da beginnt ja schon der ganze Ärger. Von da dann noch SetForegroundWindow() und SetActiveWindow()-Calls ins Blaue zu machen, oh bitte nicht.

Es mag Ausnahmen geben für das Einkloppen von Daten in andere Anwendungen aber selbst da ist es nicht nötig (und manchmal reicht es auch nicht), die bekloppte Anwendung "nach vorne" zu knallen. Ich mache so ein Zeug auch und eben weil ich es nicht sicher schaffe, die Anwendung SAP-Client im SAP-Portal im Browser um siebzehn Ecken und noch dazu mit Terminal Server in einen ordentlichen Empfangsmodus zu bringen, lasse ich dies den Anwender tun und dann eine magische Taste (sozusagen F13) drücken. Dann ist der Focus (auch ein Nicht-Windows-Focus!) garantiert an der richtigen Stelle und ich kann die Tastendrücke auf die Reise schicken, ohne den User zu bevormunden.

Wie gesagt, Ausnahmen mag es geben, aber vorher wirklich erst mal das Testament machen oder noch viel besser: Verstehen wie das mit den aktiven, vordergründigen und scharfen Licheinfallsöffnungen funktioniert.

Was die Tastatur von Jimmy angeht, die korrekte Lösung benötigt keinen Focuswechsel, würde ich tippen. Die Tastatur muss die Tastendrücke an die Anwendung schicken, die der User gerade als Empfänger gewählt hat.
Antworten