Name des aktuellen Programms

grafsoft

Mitglied
Ich fange Tastatureingaben ab und würde gerne wissen, in was für einem Programm (Anwendung, app ...) der Benutzer gerade ist, z.B. Word, Notepad ...

Was ich bekomme sind sich ständig ändernde Werte wie z.B. "[C@2b40eb52".

Ich habe gesucht und nicht gefunden.

Mein Code:

Java:
public String getActiveWindowText() {
            User32 OS = (User32) User32.INSTANCE;
            HWND h = OS.GetForegroundWindow();
            int length = OS.GetWindowTextLength(h);
            char[] buffer = new char[512];
            OS.GetWindowText(h, buffer, length + 1);
            String s = buffer.toString();
            return (s);
        }
 
Das ist halt das, was bei einem Char Array heraus kommt. Auf Arrays toString() aufzurufen ergibt die typische Ausgabe von Object. Streng genommen haben Arrays eine kleine Sonderrolle, aber der Typ wird da dann mit einem "[" + einem Kürzel des Typs (hier C für char) angegeben.

Wenn Du aus einem char Array ein String machen willst, dann solltest Du einmal die Klasse String ansehen. Da dürftest Du dann einen Konstruktor und eine valueOf Methode finden.

Und du musst Dir die Dokumentation genauer ansehen" GetWindowText gibt die Anzahl der Zeichen zurück. Das musst Du natürlich mit verwenden, denn Du willst da ja nicht den ganzen Buffer nutzen!
 
Das ist halt das, was bei einem Char Array heraus kommt. Auf Arrays toString() aufzurufen ergibt die typische Ausgabe von Object. Streng genommen haben Arrays eine kleine Sonderrolle, aber der Typ wird da dann mit einem "[" + einem Kürzel des Typs (hier C für char) angegeben.

Wenn Du aus einem char Array ein String machen willst, dann solltest Du einmal die Klasse String ansehen. Da dürftest Du dann einen Konstruktor und eine valueOf Methode finden.

Und du musst Dir die Dokumentation genauer ansehen" GetWindowText gibt die Anzahl der Zeichen zurück. Das musst Du natürlich mit verwenden, denn Du willst da ja nicht den ganzen Buffer nutzen!
Danke, wieder was gelernt! Auch Beispiele bei Stackoverflow u.a. können Fehler enthalten.
 
Nur um es noch einmal etwas genauer zu machen:

Wenn man sich die JNA Dinge anschaut, dann macht es Sinn:
a) die Größe des Buffers zuerst abzufragen
b) dann Native.toString() zu nutzen, denn das Encoding muss nicht dem in Java entsprechen und so.

Der Code sieht dann so aus:
Java:
  final int requiredLength = User32.INSTANCE.GetWindowTextLength(hwnd) + 1;
  final char[] title = new char[requiredLength];
  final int length = User32.INSTANCE.[URL='https://www.tabnine.com/code/java/methods/com.sun.jna.platform.win32.User32/GetWindowText']GetWindowText[/URL](hwnd, title, title.length);
  return Native.toString(Arrays.copyOfRange(title, 0, length));
 
Das Beispiel scheint grundasetzlich ein biszchen komisch zu sein wenn man sich die Dokumentation ansieht.

Korrekter wird es in etwa so sein:

Java:
User32 user32 = (User32) User32.INSTANCE;

HWND foregroundWindowHandle = user32.GetForegroundWindow();

char[] foregroundWindowTextBuffer = new char[512];

int foregroundWindowTextLength = user32.GetWindowText(
        foregroundWindowHandle,
        foregroundWindowTextBuffer,
        foregroundWindowTextBuffer.length);
        
String foregroundWindowText = new String(
        foregroundWindowTextBuffer,
        0,
        foregroundWindowTextLength);

return foregroundWindowText;

@KonradN Die Groesze des Buffers vorher abzufragen ist eine gute Idee, aber dann hast du da eine Race-Condition falls sich der Fenstertitel in der Zwischenzeit aendert. Mit einem fixen (zu groszen) Buffer bekommst du immer den ganzen (vorrausgesetzt der ist nicht zu lange, ja).
 
@KonradN Die Groesze des Buffers vorher abzufragen ist eine gute Idee, aber dann hast du da eine Race-Condition falls sich der Fenstertitel in der Zwischenzeit aendert. Mit einem fixen (zu groszen) Buffer bekommst du immer den ganzen (vorrausgesetzt der ist nicht zu lange, ja).
Das Risiko ist natürlich da. Aber hier muss man keine Angst haben, dass dies zu einem Overflow führt. Der eigentliche Aufruf, der da statt findet, dürfte
GetWindowTextA function (winuser.h) - Win32 apps | Microsoft Learn
sein. (Evtl. gibt es auch eine Ex Variante oder so. Ich habe da jetzt nicht mehr im Detail hinein geschaut.)

Aber es wird klar, wie hier die API aufgebaut wurde von Microsoft: Es wird nicht nur ein Buffer übergeben sondern auch die Größe des Buffers.

Wenn man das als Problem ansieht, dann sollte man ggf. hin gehen und überlegen, ob man mehr Tests macht. Man könnte also z.B. die Länge abfragen, dann einen Buffer mit +2 Größe erstellen (Also einmal für das 0-Byte und dann ein Reserve Byte) und dann prüfen, ob die Länge die zurück gegeben wurde kleiner oder gleich der abgefragten Länge ist.

Die andere Alternative wäre, dass man halt für eine Länge x Platz reserviert und nur Längen < x akzeptiert. Wenn als Länge x Zurück kommt, dann wird der Buffer (x) verdoppelt. Dann würde man auch immer den ganzen Titel bekommen. Sprich: Man nimmt die 512 char, wenn nicht weniger als 511 Zeichen zurück kommen, dann nimmt man 1024 Zeichen und erwartet weniger als 1023 Zeichen ... u.s.w.

Aber ich denke, damit schießt man mit Kanonen auf Spatzen. Dein Hinweis ist aber auf jeden Fall gerechtfertigt und wichtig!
 
Das Risiko ist natürlich da. Aber hier muss man keine Angst haben, dass dies zu einem Overflow führt.

Nein nein, ich dachte da wirklich nur an die "Gefahr" das man einen gekuerzten Titel bekommt beziehungsweise nicht den ganzen Titel bekommt (weil er in der Zwischenzeit laenger geworden ist). Deswegen fixe Buffergroesze damit man da nicht hineinlaufen kann oder zumindest weisz dass man Titel mit Groesze X oder groszer nicht bekommen wird). Der Ueberlauf sollte ja von der API her gar nicht auftreten (oder man bekommt -1 zurueck, oder so, was aber in dem Fall nicht der Fall ist).
 
Ja, mir war klar, dass dies dein Hauptanliegen war, aber ich dachte, dass andere da ggf. eine größere Angst haben. Buffer Overflow und so wird der eine oder Andere ja gehört haben und da kommen ggf. Ängste auf. Daher meine Ausführung. Hätte ich evtl. deutlicher schreiben müssen.
 

Zurück
Oben