JavaのJNAは、デスクトップ項目の位置を取得します

Pieter12345:

ゴール

デスクトップ項目/アイコンのデスクトップ座標を取得します。

試み

私が使用して、デスクトップのアイコンが含まれているSysListView32のウィンドウハンドルを取得しています:

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");

私は、デスクトップの項目数を取得しています:

LRESULT result = User32.INSTANCE.SendMessage(hWnd_SysListView32, LVM_GETITEMCOUNT, new WPARAM(), new LPARAM());
long desktopIconCount = result.longValue();

私は(SysListView32は、デスクトップ項目の右側のリストビューであることを確認する)デスクトップ項目の位置を設定しています。渡されたx、y座標は、デスクトップ項目の左上隅に私の一番左のモニターの左上からのオフセットに対応していました。コード:

int itemIndex = 0; // Allows 0 to desktopIconCount - 1.
int x = ...;
int y = ...;
LRESULT res = User32.INSTANCE.SendMessage(hWnd_SysListView32, LVM_SETITEMPOSITION, new WPARAM(itemIndex), new LPARAM((x & 0xFFFF) | (y << 16)));

さて、1つのニーズを送信するには、デスクトップ項目の位置を取得しLVM_GETITEMPOSITIONSysListView32にし、それが位置を書き込むことができますアドレスへのポインタが含まれています。しかし、このポインタはSysListView32に属するプロセスのメモリ内の有効なアドレスである必要があります。だから、私は何をしようとしたことにあります。

  • SysListView32に属するプロセスを取得します。
  • そのプロセスでメモリを割り当てます。
  • 書き込みPOINT(項目位置のために使用される)、このメモリ内のオブジェクトを。
  • 送るLVM_GETITEMPOSITIONこの割り当てられたメモリへのポインタでSysListView32に。
  • この読みPOINTメモリからオブジェクトを。この時点で、プロセスは、デスクトップ項目の位置を書かれているはずです。

私は、次のコードでこれを試してみました:

// 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 = Native.getNativeSize(POINT.class)); // 8 bytes.
LPVOID pMem = MyKernel32.INSTANCE.VirtualAllocEx(procHandle, new LPVOID(), new SIZE_T(pointSize),
        MyKernel32.MEM_COMMIT, MyKernel32.PAGE_READWRITE);

// Put some POINT-sized object in the process its memory.
boolean success = Kernel32.INSTANCE.WriteProcessMemory(
        procHandle, pMem.getPointer(), pMem.getPointer(), pointSize, null);
if(!success) {
    System.out.println("Write error = " + Kernel32.INSTANCE.GetLastError());
    System.exit(1);
}

// Send the LVM_GETITEMPOSITION message to the SysListView32.
int itemIndex = 0; // Allows 0 to desktopIconCount - 1.
LRESULT res = MyUser32.INSTANCE.SendMessage(
        hWnd_SysListView32, LVM_GETITEMPOSITION, new WPARAM(itemIndex), pMem.getPointer());
System.out.println("Message result = " + res.longValue());

// Read the earlier POINT-sized written memory.
POINT point = new POINT();
success = Kernel32.INSTANCE.ReadProcessMemory(
        procHandle, pMem.getPointer(), point.getPointer(), pointSize, null);
if(!success) {
    System.out.println("Read error = " + Kernel32.INSTANCE.GetLastError());
    System.exit(1);
}
System.out.println("Point found: x=" + pos.x + ", y=" + pos.y);

ここでは、MyUser32次のように作成されます。

interface MyUser32 extends User32 {
    static MyUser32 INSTANCE =
        (MyUser32) Native.load("user32", MyUser32.class, W32APIOptions.DEFAULT_OPTIONS);
    LRESULT SendMessage(HWND hWnd, int msg, WPARAM wParam, Pointer pointer);
}

そしてMyKernel32、次のように作成されます。

interface MyKernel32 extends Kernel32 {
    static final MyKernel32 INSTANCE =
            (MyKernel32) Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
    static int MEM_COMMIT = 0x1000;
    static int PAGE_READWRITE = 0x04;
    LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, int flAllocationType, int flProtect);
}

完全なものにするには、次の追加の静的値が使用されます。

static final int LVM_FIRST = 0x1000;
static final int LVM_GETITEMCOUNT = LVM_FIRST + 4;
static final int LVM_SETITEMPOSITION = LVM_FIRST + 15;
static final int LVM_GETITEMPOSITION = LVM_FIRST + 16;

問題

WriteProcessMemory呼び出しは、多くの場合、エラーコード299で失敗ERROR_PARTIAL_COPYし、それが失敗していない場合でも、返されるポイントは常に(0,0)です。私はこの問題は、いずれかであることを期待SendMessage/ VirtualAllocExでメソッド宣言MyUser32MyKernel32、あるいは私がオブジェクト/ポインタがに渡すためにどの正しく理解していませんVirtualAllocExWriteProcessMemory

私は多くの研究を行って、それはC / C ++で動作するはずです方法を考え出したが、私は私の場合のためにJNAを使用して、任意の作業のコード例を見つけることができませんでしたしました。

関心を示し、あなたがすべての方法私のメッセージを通してそれを作った場合、ヘルプしようとしていただきありがとうございます。

マティアスBläsing:

問題があるということcom.sun.jna.Native.getNativeSize(クラス)は、この場合に使用する権利の機能ではありません。32ビットJVMを使用する場合に問題が表示され、(それがA 64ビットVM見えません)。

構造について上述した機能は、それらが参照(構造体へのポインタ)によって渡されることを前提とし、したがって、関数がの値を返しNative.POINTER_SIZEを64 - VM上で、これは運でのサイズと一致するPOINTの構造を。32ビットVM上Native.POINTER_SIZE 4バイトであるので結果のみ構造の一部を保持することができます。

最も関連性の高いパーツ:構造#サイズの機能を使用し、JNAに構造体のサイズを決定します。この場合、最終的なパラメータを使用することも有用であるReadProcessMemoryを関数は差を読み取って示したバイト数(8対4)を返します。

さらにコメント:あなたが割り当てられたメモリを解放しても受信にプロセスハンドルを閉じることを忘れないでください。

ここでは、完全な実行可能なサンプル(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);
    }
}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=191114&siteId=1