如何使用 JNA 运行 chrome?

发布于 2024-11-04 11:38:42 字数 2888 浏览 0 评论 0原文

我写了一些java代码。

如何在 Windows(32 位)中使用 JNA 运行 chrome。

然后我喜欢了解它的含义。

如您所知,FindWindow 是一个简单的解决方案,但如果 chrome 不运行,它就不起作用。

FindWindow 示例

下面的代码是否可行?

HWND hwnd = User32.CreateProcess(...);

下面的代码打开chrome。 但调整大小、最大化不起作用。


public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

    boolean CreateProcessA(
             String lpApplicationName
            , String lpCommandLine
            , Structure lpProcessAttributes
            , Structure lpThreadAttributes
            , boolean bInheritHandles
            , int dwCreationFlags
            , Structure lpEnvironment
            , String lpCurrentDirectory
            , Structure lpStartupInfo
            , Structure lpProcessInformation);
}

import com.sun.jna.Pointer;
import com.sun.jna.Structure;

public class ProcessInformation extends Structure {
    public Pointer hProcess;
    public Pointer hThread;
    public int dwProcessId;
    public int dwThreadId;
}

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;

public class StartupInfoA extends Structure {
    public int cb;
    public WString lpReserved;
    public WString lpDesktop;
    public WString lpTitle;
    public int dwX;
    public int dwY;
    public int dwXSize;
    public int dwYSize;
    public int dwXCountChars;
    public int dwYCountChars;
    public int dwFillAttribute;
    public int dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public Pointer lpReserved2;
    public Pointer hStdInput;
    public Pointer hStdOutput;
    public Pointer hStdError;
}

public class Test {
    public static void main(String[] args) {

        int STARTF_USEPOSITION = 0x00000004;
        int STARTF_USESIZE = 0x00000002;
        int STARTF_USESHOWWINDOW = 0x00000001;

        ProcessInformation processInformation = new ProcessInformation();
        StartupInfoA startupInfo = new StartupInfoA();
        startupInfo.dwX = 100;
        startupInfo.dwY = 100;
        startupInfo.dwXSize = 100;
        startupInfo.dwYSize = 100;    
        startupInfo.wShowWindow = (short) SW_MAXIMIZE;
        startupInfo.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;

        Kernel32.INSTANCE.CreateProcessA(new String("C:\\Users.....\\Google\\Chrome\\Application\\chrome.exe")
                , null
                , null
                , null
                , true
                , 0
                , null
                , null
                , startupInfo
                , processInformation);
    }
}

I wrote some java code.

how to run chrome using JNA in windows(32bit).

then I like to get the hwnd of it.

As you know, FindWindow is simple solution but if chrome doesn't running, it doesn't work.

FindWindow example

below like code is possible?

HWND hwnd = User32.CreateProcess(...);

below code open chrome.
but sizing, maxmizing doesn't work.


public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

    boolean CreateProcessA(
             String lpApplicationName
            , String lpCommandLine
            , Structure lpProcessAttributes
            , Structure lpThreadAttributes
            , boolean bInheritHandles
            , int dwCreationFlags
            , Structure lpEnvironment
            , String lpCurrentDirectory
            , Structure lpStartupInfo
            , Structure lpProcessInformation);
}

import com.sun.jna.Pointer;
import com.sun.jna.Structure;

public class ProcessInformation extends Structure {
    public Pointer hProcess;
    public Pointer hThread;
    public int dwProcessId;
    public int dwThreadId;
}

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;

public class StartupInfoA extends Structure {
    public int cb;
    public WString lpReserved;
    public WString lpDesktop;
    public WString lpTitle;
    public int dwX;
    public int dwY;
    public int dwXSize;
    public int dwYSize;
    public int dwXCountChars;
    public int dwYCountChars;
    public int dwFillAttribute;
    public int dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public Pointer lpReserved2;
    public Pointer hStdInput;
    public Pointer hStdOutput;
    public Pointer hStdError;
}

public class Test {
    public static void main(String[] args) {

        int STARTF_USEPOSITION = 0x00000004;
        int STARTF_USESIZE = 0x00000002;
        int STARTF_USESHOWWINDOW = 0x00000001;

        ProcessInformation processInformation = new ProcessInformation();
        StartupInfoA startupInfo = new StartupInfoA();
        startupInfo.dwX = 100;
        startupInfo.dwY = 100;
        startupInfo.dwXSize = 100;
        startupInfo.dwYSize = 100;    
        startupInfo.wShowWindow = (short) SW_MAXIMIZE;
        startupInfo.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;

        Kernel32.INSTANCE.CreateProcessA(new String("C:\\Users.....\\Google\\Chrome\\Application\\chrome.exe")
                , null
                , null
                , null
                , true
                , 0
                , null
                , null
                , startupInfo
                , processInformation);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨落星ぅ辰 2024-11-11 11:38:43

当然,如果 Chrome 没有运行,您就无法获取其窗口的句柄,因为这样的窗口不存在。您可能想要运行 Chrome,使用 ProcessBuilder 之类的东西,然后调用类似这样的东西:

user32.EnumWindows( new WndEnumProc()
{

    @SuppressWarnings ( "AssignmentToMethodParameter" )
    public boolean callback ( int hWnd, int lParam )
    {
        if ( user32.IsWindow( hWnd ) )
        {
            if ( user32.IsWindowVisible( hWnd ) )
            {
                RECT r = new RECT();
                user32.GetWindowRect( hWnd, r );
                // if (r.left > -32000) // is not minimized
                //{
                String windowTitle = getWindowParentName( hWnd );
                String windowClass = getWindowParentClassName( hWnd );
                hWnd = user32.GetAncestor( hWnd, 3 );
                if ( !windowTitle.toLowerCase().equals( "program manager" ) && !windowClass.toLowerCase().equals( "progman" ) && !windowTitle.equals( "" ) && !windowClass.toLowerCase().equals( "shell_traywnd" ) )
                {
                    listOfWindows.put( hWnd, getWindowParentRectangle( hWnd ) );
                }
                // }
            }
            return true;
        }
        else
        {
            return false;
        }
    }
}, 0 );

当然,这已经是工作代码,具有一些特定于我的应用程序的条件。但主要的想法是
使用 WndEnumProc() 调用 EnumWindows ,它将把它找到的所有窗口放入一个集合中(在我的例子中是一个 HashMap )。然后,在 EnumWindows 返回后,您的 listOfWindows 变量中将包含一个窗口集合,并且如果 Chrome 在调用 EnumWindows 期间正在运行,您将能够获取 Chrome 的 hwnd。

您应该在 user32 实例中定义 EnumWindows,如下所示:

/**
 * Enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function.
 * @param wndenumproc A pointer to an application-defined callback function.
 * @param lParam An application-defined value to be passed to the callback function.
 * @return if the function succeeded.
 * <a href="http://msdn.microsoft.com/en-us/library/ms633497(v=VS.85).aspx"> <b>Microsoft Reference</b></a><br>
 */
public boolean EnumWindows ( WndEnumProc wndenumproc, int lParam );

您还应该在类中定义 WndEnumProc 结构(我的名为 Structures),如下所示:

  public static interface WndEnumProc extends StdCallLibrary.StdCallCallback
    {

        boolean callback ( int hWnd, int lParam );
    }

希望有所帮助。请注意,当您执行所有这些操作时,Chrome 必须正在运行。正如我在开始时提到的,使用 ProcessBuilder 运行它应该相对简单,或者如果您不想太麻烦并且 Chrome 在您的路径中,您可以使用

System.getRuntime().exec("chrome .exe")

启动 Chrome。

If Chrome is not running, you can't get a handle of its window, of course, because such a window does not exist. You might want to run Chrome, using something like ProcessBuilder, then call something like this:

user32.EnumWindows( new WndEnumProc()
{

    @SuppressWarnings ( "AssignmentToMethodParameter" )
    public boolean callback ( int hWnd, int lParam )
    {
        if ( user32.IsWindow( hWnd ) )
        {
            if ( user32.IsWindowVisible( hWnd ) )
            {
                RECT r = new RECT();
                user32.GetWindowRect( hWnd, r );
                // if (r.left > -32000) // is not minimized
                //{
                String windowTitle = getWindowParentName( hWnd );
                String windowClass = getWindowParentClassName( hWnd );
                hWnd = user32.GetAncestor( hWnd, 3 );
                if ( !windowTitle.toLowerCase().equals( "program manager" ) && !windowClass.toLowerCase().equals( "progman" ) && !windowTitle.equals( "" ) && !windowClass.toLowerCase().equals( "shell_traywnd" ) )
                {
                    listOfWindows.put( hWnd, getWindowParentRectangle( hWnd ) );
                }
                // }
            }
            return true;
        }
        else
        {
            return false;
        }
    }
}, 0 );

Of course, this is already working code that has some conditions specific to my app. But the main idea is to
call EnumWindows with a WndEnumProc() that will put all windows it finds to a collection ( in my case an HashMap ). Then after the EnumWindows returns, you will have a collection of windows in your listOfWindows variable and you will be able to get the hwnd of Chrome if it was running during the time EnumWindows was called.

You should define EnumWindows in your user32 instance like this:

/**
 * Enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function.
 * @param wndenumproc A pointer to an application-defined callback function.
 * @param lParam An application-defined value to be passed to the callback function.
 * @return if the function succeeded.
 * <a href="http://msdn.microsoft.com/en-us/library/ms633497(v=VS.85).aspx"> <b>Microsoft Reference</b></a><br>
 */
public boolean EnumWindows ( WndEnumProc wndenumproc, int lParam );

You should also define your WndEnumProc structure in a class (mine was named Structures) something like this:

  public static interface WndEnumProc extends StdCallLibrary.StdCallCallback
    {

        boolean callback ( int hWnd, int lParam );
    }

Hope that helps. Please note that Chrome must be running while you are doing all that magic. Running it, as I noted in the beginning, should be relatively straightforward using a ProcessBuilder or if you don't want to bother much and Chrome is in your path, you can use

System.getRuntime().exec("chrome.exe")

to start Chrome.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文