java使用jna修改桌面_java - Java JNA获取桌面项目位置 - 堆栈内存溢出

这篇博客展示了如何使用Java的JNA库在32位和64位JVM中读取桌面图标的坐标。通过查找桌面窗口句柄,发送消息获取图标的当前位置,并使用VirtualAllocEx和ReadProcessMemory等函数进行内存操作。示例代码详细解释了整个过程,包括内存分配、读取和释放。
摘要由CSDN通过智能技术生成

问题是com.sun.jna.Native.getNativeSize(Class)不是在这种情况下使用的正确函数。 使用32位JVM时,问题是可见的(64位虚拟机不可见)。

对于结构,上面提到的函数假​​定它们通过引用传递(指向结构的指针),因此函数返回Native.POINTER_SIZE的值。 在64位虚拟机上,运气匹配POINT结构的大小。 在32位VM上, Native.POINTER_SIZE是4字节,因此只能保存结果结构的一部分。

最相关的部分:要确定JNA中结构的大小,请使用Structure#size函数。 在这种情况下,使用ReadProcessMemory的最终参数也很有帮助。 该函数返回读取的字节数并显示差异(4对8)。

进一步的评论:记得释放你分配的内存,并关闭收到的进程句柄。

这是完整的可运行样本(仅缺少导入,使用JNA 5.2测试):

public class Test {

private interface Kernel32 extends com.sun.jna.platform.win32.Kernel32 {

Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, W32APIOptions.DEFAULT_OPTIONS);

public Pointer VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize, int flAllocationType, int flProtect);

public boolean VirtualFreeEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize, int dwFreeType);

int MEM_COMMIT = 0x00001000;

int MEM_RESERVE = 0x00002000;

int MEM_RESET = 0x00080000;

int MEM_RESET_UNDO = 0x1000000;

int MEM_LARGE_PAGES = 0x20000000;

int MEM_PHYSICAL = 0x00400000;

int MEM_TOP_DOWN = 0x00100000;

int MEM_COALESCE_PLACEHOLDERS = 0x00000001;

int MEM_PRESERVE_PLACEHOLDER = 0x00000002;

int MEM_DECOMMIT = 0x4000;

int MEM_RELEASE = 0x8000;

}

private static final int LVM_FIRST = 0x1000;

private static final int LVM_GETITEMCOUNT = LVM_FIRST + 4;

private static final int LVM_GETITEMPOSITION = LVM_FIRST + 16;

public static void main(String[] args) throws IOException, InterruptedException {

// Find the HWND for the "desktop" list view

HWND hWnd_Progman = User32.INSTANCE.FindWindow("Progman", "Program Manager");

HWND hWnd_SHELLDLL_DefView = User32.INSTANCE.FindWindowEx(hWnd_Progman, null, "SHELLDLL_DefView", null);

HWND hWnd_SysListView32 = User32.INSTANCE.FindWindowEx(hWnd_SHELLDLL_DefView, null, "SysListView32", "FolderView");

// Fetch the icon count

int itemCount = User32.INSTANCE.SendMessage(hWnd_SysListView32, LVM_GETITEMCOUNT, new WPARAM(), new LPARAM()).intValue();

System.out.println("Desktop Icons: " + itemCount);

// Get the SysListView32 process handle.

IntByReference processIdRef = new IntByReference();

User32.INSTANCE.GetWindowThreadProcessId(hWnd_SysListView32, processIdRef);

HANDLE procHandle = Kernel32.INSTANCE.OpenProcess(

Kernel32.PROCESS_VM_OPERATION | Kernel32.PROCESS_VM_WRITE | Kernel32.PROCESS_VM_READ,

false, processIdRef.getValue());

// Allocate memory in the SysView32 process.

int pointSize = new POINT().size(); // 8 bytes.

Pointer pMem = Kernel32.INSTANCE.VirtualAllocEx(procHandle, null, new SIZE_T(pointSize),

Kernel32.MEM_COMMIT, Kernel32.PAGE_READWRITE);

for (int i = 0; i < itemCount; i++) {

// Send the LVM_GETITEMPOSITION message to the SysListView32.

LRESULT res = User32.INSTANCE.SendMessage(

hWnd_SysListView32, LVM_GETITEMPOSITION, new WPARAM(i), new LPARAM(Pointer.nativeValue(pMem)));

if(res.intValue() != 1) {

throw new IllegalStateException("Message sending failed");

}

// Read the earlier POINT-sized written memory.

POINT point = new POINT();

IntByReference read = new IntByReference();

boolean success = Kernel32.INSTANCE.ReadProcessMemory(

procHandle, pMem, point.getPointer(), pointSize, read);

if (!success) {

System.out.println("Read error = " + Kernel32.INSTANCE.GetLastError());

System.exit(1);

}

point.read();

System.out.println("Point found: x=" + point.x + ", y=" + point.y);

}

// Release allocated memory

Kernel32.INSTANCE.VirtualFreeEx(procHandle, pMem, new SIZE_T(0), Kernel32.MEM_RELEASE);

// Close Process Handle

Kernel32.INSTANCE.CloseHandle(procHandle);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值