Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
找出Java中关注的应用程序(窗口)_Java_Windows - Fatal编程技术网

找出Java中关注的应用程序(窗口)

找出Java中关注的应用程序(窗口),java,windows,Java,Windows,我想知道如何编写一个Java程序,知道哪个Windows应用程序是重点。我可以打开许多窗口,但我想知道正在使用的窗口(就像我现在输入的Google Chrome) 我不需要更改窗口或应用程序中的任何内容,只需要知道它的名称。恐怕没有java api。JVM对它不管理的窗口一无所知。您可能需要使用JNI并调用此函数 [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); 还有一个GetWindowText函数,

我想知道如何编写一个Java程序,知道哪个Windows应用程序是重点。我可以打开许多窗口,但我想知道正在使用的窗口(就像我现在输入的Google Chrome)


我不需要更改窗口或应用程序中的任何内容,只需要知道它的名称。

恐怕没有java api。JVM对它不管理的窗口一无所知。您可能需要使用JNI并调用此函数

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

还有一个
GetWindowText
函数,如果您需要获取窗口的标题,可能需要使用该函数


有可能对您有所帮助的JNI示例。

正如装满鳗鱼的气垫船所说,这是您最好的选择。与JNI不同,您不必为它编译任何C代码

要获取进程名称,请执行以下操作:

  • 调用以获取窗口句柄
  • 调用以确定是哪个进程拥有它
  • 调用以获取进程句柄(使用
    process\u QUERY\u INFORMATION | process\u VM\u READ
  • 调用以从句柄获取进程名称。您也可以只调用模块名而不调用完整路径
  • 中提供了完整的示例


    可以找到C代码。

    其他人已经指出,在所有平台上都没有可移植的方法来实现这一点。但更糟糕的是:微软Windows上甚至没有一个一致的方法。我将提供一些代码来解决不同平台的问题,并指出其局限性。使用时请自行承担风险,因为安全原因,代码可能会提供错误的结果或根本无法运行。如果它在您的机器上运行,并不意味着它在其他机器上也能同样好地运行

    代码使用JNA。在我的实验中,我遇到了不同版本的JNA和JNA平台库的问题。最好自己编译,这样您就有了一个一致的环境

    窗户 kichik提供的答案在当时是正确的,但并非在所有情况下都适用于Windows 8。问题是,它无法正确处理Metro应用程序。不幸的是,目前没有稳定的API来获取当前运行的Metro应用程序的名称。我已经在代码中插入了一些提示,但最好等到Microsoft为您提供API

    在Windows上,特权应用程序和UAC对话框也会出现问题。所以你不会总是得到正确的答案

    public interface Psapi extends StdCallLibrary {
        Psapi INSTANCE = (Psapi) Native.loadLibrary("Psapi", Psapi.class);
    
        WinDef.DWORD GetModuleBaseNameW(Pointer hProcess, Pointer hModule, byte[] lpBaseName, int nSize);
    }
        if (Platform.isWindows()) {
            final int PROCESS_VM_READ=0x0010;
            final int PROCESS_QUERY_INFORMATION=0x0400;
            final User32 user32 = User32.INSTANCE;
            final Kernel32 kernel32=Kernel32.INSTANCE;
            final Psapi psapi = Psapi.INSTANCE;
            WinDef.HWND windowHandle=user32.GetForegroundWindow();
            IntByReference pid= new IntByReference();
            user32.GetWindowThreadProcessId(windowHandle, pid);
            WinNT.HANDLE processHandle=kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, true, pid.getValue());
    
            byte[] filename = new byte[512];
            Psapi.INSTANCE.GetModuleBaseNameW(processHandle.getPointer(), Pointer.NULL, filename, filename.length);
            String name=new String(filename);
            System.out.println(name);
            if (name.endsWith("wwahost.exe")) { // Metro App
                // There is no stable API to get the current Metro app
                // But you can guestimate the name form the current directory of the process
                // To query this, see:
                // http://stackoverflow.com/questions/16110936/read-other-process-current-directory-in-c-sharp
            }
    
        if(Platform.isMac()) {
            final String script="tell application \"System Events\"\n" +
                    "\tname of application processes whose frontmost is tru\n" +
                    "end";
            ScriptEngine appleScript=new ScriptEngineManager().getEngineByName("AppleScript");
            String result=(String)appleScript.eval(script);
            System.out.println(result);
        }
    
    Linux/Unix/X11 对于X11,我们有三个问题:

  • 由于网络透明性,来自完全不同机器的多个窗口可能混合在同一个X11中。因此,在您查询的机器上,属于窗口的进程的名称和PID可能都没有意义
  • 大多数windows管理器都有多个桌面。在每个桌面上,前台可以有不同的应用程序
  • 平铺窗口管理器(如)没有前景窗口的概念。它们以某种方式排列所有窗口,因此每个窗口同时位于前景中
  • 在X11上,查询当前具有焦点的窗口更有意义

    public interface XLib extends StdCallLibrary {
        XLib INSTANCE = (XLib) Native.loadLibrary("XLib", Psapi.class);
    
        int XGetInputFocus(X11.Display display, X11.Window focus_return, Pointer revert_to_return);
    }
    
    if(Platform.isLinux()) {  // Possibly most of the Unix systems will work here too, e.g. FreeBSD
            final X11 x11 = X11.INSTANCE;
            final XLib xlib= XLib.INSTANCE;
            X11.Display display = x11.XOpenDisplay(null);
            X11.Window window=new X11.Window();
            xlib.XGetInputFocus(display, window,Pointer.NULL);
            X11.XTextProperty name=new X11.XTextProperty();
            x11.XGetWMName(display, window, name);
            System.out.println(name.toString());
        }
    
    MacOSX MacOSX的重点不是windows,而是应用程序。因此,请求当前活动的应用程序是有意义的。旧版本的Mac OS X提供多个台式机。较新版本可以同时打开多个全屏应用程序。所以你可能不会总是得到正确的答案

    public interface Psapi extends StdCallLibrary {
        Psapi INSTANCE = (Psapi) Native.loadLibrary("Psapi", Psapi.class);
    
        WinDef.DWORD GetModuleBaseNameW(Pointer hProcess, Pointer hModule, byte[] lpBaseName, int nSize);
    }
        if (Platform.isWindows()) {
            final int PROCESS_VM_READ=0x0010;
            final int PROCESS_QUERY_INFORMATION=0x0400;
            final User32 user32 = User32.INSTANCE;
            final Kernel32 kernel32=Kernel32.INSTANCE;
            final Psapi psapi = Psapi.INSTANCE;
            WinDef.HWND windowHandle=user32.GetForegroundWindow();
            IntByReference pid= new IntByReference();
            user32.GetWindowThreadProcessId(windowHandle, pid);
            WinNT.HANDLE processHandle=kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, true, pid.getValue());
    
            byte[] filename = new byte[512];
            Psapi.INSTANCE.GetModuleBaseNameW(processHandle.getPointer(), Pointer.NULL, filename, filename.length);
            String name=new String(filename);
            System.out.println(name);
            if (name.endsWith("wwahost.exe")) { // Metro App
                // There is no stable API to get the current Metro app
                // But you can guestimate the name form the current directory of the process
                // To query this, see:
                // http://stackoverflow.com/questions/16110936/read-other-process-current-directory-in-c-sharp
            }
    
        if(Platform.isMac()) {
            final String script="tell application \"System Events\"\n" +
                    "\tname of application processes whose frontmost is tru\n" +
                    "end";
            ScriptEngine appleScript=new ScriptEngineManager().getEngineByName("AppleScript");
            String result=(String)appleScript.eval(script);
            System.out.println(result);
        }
    
    结论 当我使用这段代码时,它在最基本的情况下工作。但是,如果你想让这段代码运行可靠,你就必须进行大量的润色。自己决定是否值得

    为了使代码完整,下面是我使用的导入部分:

        import com.sun.jna.Native;
        import com.sun.jna.Platform;
        import com.sun.jna.Pointer;
        import com.sun.jna.platform.unix.X11;
        import com.sun.jna.platform.win32.Kernel32;
        import com.sun.jna.platform.win32.User32;
        import com.sun.jna.platform.win32.WinDef;
        import com.sun.jna.platform.win32.WinNT;
        import com.sun.jna.ptr.IntByReference;
        import com.sun.jna.win32.StdCallLibrary;
    
        import javax.script.ScriptEngine;
        import javax.script.ScriptEngineManager;
        import javax.script.ScriptException;
    

    当然,您必须重新排列代码的各个部分。我在一开始使用了一个带有接口的大类,然后在一个大的main方法中使用了其余的类。

    您想用这个窗口做什么?也许你只能在JNI上找到它。如果可能的话,能有一个答案说明如何在所有3个主要平台,即windows、mac和linux上做到这一点,那就太好了。DllImport?看起来像是C语言。@Hovercraft充满了EEL有一些库可以让你在java中绑定DLL。虽然这个语法可能是C#,但是语法来自C#。我只是想显示dll和函数签名。这似乎是一个不错的选择!我以前从未听说过JNI,似乎有点困惑。我可以请您指定我必须导入/调用什么才能在java类中工作吗?如果您可以编写一个实现GetWindowText函数的简单类,那就更好了。Thnx!就我的2美分而言,我认为使用JNA比使用JNI要好得多。它是基于JNI的,但使用起来要简单得多(我认为)。好吧,最初的问题是针对Windows的,但同样的方法应该适用于其他任何东西。对于MacOSX,您可以尝试移植它。它应该可以让您开始调用哪些函数。悬赏是如此的希望linux/mac能够找到答案。不过,感谢您迄今为止的帮助。:)@ClickUpvote在这个网站上还有其他答案可以告诉你如何用python在Mac和Linux上实现它;您只需要将代码移植到JavaScrible,非常有用。嗨,Stefan,在Linux/Unix代码示例中,您正在加载带有“Psapi.class”的XLib。我不明白为什么要用“Psapi.class”加载,而不是用自己的“XLib.class”接口加载。你能解释一下吗?