Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.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
在JavaJNA中使用什么来代替LPTSTR?_Java_C++_Winapi_Java Native Interface_Jna - Fatal编程技术网

在JavaJNA中使用什么来代替LPTSTR?

在JavaJNA中使用什么来代替LPTSTR?,java,c++,winapi,java-native-interface,jna,Java,C++,Winapi,Java Native Interface,Jna,我正在向JNI添加User32Ext方法。特别是,我扩展了原始的UserExt类: package sirius.core; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinDef; import com.sun.jna.platform.win32.WinNT

我正在向JNI添加User32Ext方法。特别是,我扩展了原始的UserExt类:

 package sirius.core;

 import com.sun.jna.Native;
 import com.sun.jna.Pointer;
 import com.sun.jna.platform.win32.Kernel32;
 import com.sun.jna.platform.win32.WinDef;
 import com.sun.jna.platform.win32.WinNT;
 import com.sun.jna.win32.W32APIOptions;

 public abstract interface Kernel32Ext
   extends Kernel32
 {
   public static final Kernel32Ext INSTANCE = (Kernel32Ext)Native.loadLibrary("kernel32.dll", Kernel32Ext.class, W32APIOptions.DEFAULT_OPTIONS);

   public abstract Pointer VirtualAllocEx(WinNT.HANDLE paramHANDLE, Pointer paramPointer, int paramInt, WinDef.DWORD paramDWORD1, WinDef.DWORD paramDWORD2);
   public abstract boolean VirtualFreeEx(WinNT.HANDLE paramHANDLE, Pointer paramPointer, int paramInt, WinDef.DWORD paramDWORD);
 }
我想添加这个函数

我会这样写:

public abstract DWORD getModuleFileName(WinNT.HANDLE hProcess, WinNT.HMODULE hModule, WinNT.LPTSTR pathString, WinNT.DWORD pathStringLength);

但是未定义
WinNT.LPTSTR
。它显然应该是一个指针(我猜是指向char的?)。那么,我该如何完成这项工作呢?

首先,很抱歉我给你的回答不正确

所以,在再次收到您的问题后,我已经测试了您的代码。 我必须为这个问题制作自己的课程

让我们看看GetModuleFileName的原型

DWORD WINAPI GetModuleFileName(
  _In_opt_ HMODULE hModule,
  _Out_    LPTSTR  lpFilename,
  _In_     DWORD   nSize
);
您的原型适用于GetModuleFileName而不是GetModuleFileName

我遗漏的主要一点是lpFilename参数,它必须是muttable对象

它可以是任何可咕哝的对象,如字符数组或作为参数的字节数组

我认为我们不能使用String类作为参数,因为它是一个不可变的

我认为建议使用GetModuleFileName,而不是msdn中的GetModuleFileName

你可以在他们说的文章中间找到

要检索当前进程中模块的名称,请使用 GetModuleFileName函数。这是更有效和更可靠的 而不是使用当前进程的句柄调用GetModuleFileNameEx

这里有两个条件。 首先,我的操作系统是Windows 7 Ultimate 64位 第二,你和我有一个不同的开发环境

我从原始版本下载了最新的jna.jarjna platform.jar

我测试了四种不同的方法,其中一种失败了

我的切入点如下

public static void main(String[] args) {
        testCopyFile();
                printProcesses();
        testAllocFree(PROCESSID);
        testAllocFree2(PROCESSID);
        testModuleFileName(PROCESSID);
        testModuleFileName2(PROCESSID);
    }
testCopyFile方法只是用不同的方法复制一些文本文件

private static void testCopyFile() {
        Function copyFunc = Function.getFunction("kernel32", "CopyFileA");
        Object[] params = new Object[3];
        params[0] = "C:\\DEV\\temp\\_info.txt";
        params[1] = "C:\\DEV\\temp\\_info2.txt";
        params[2] = false;
        copyFunc.invoke(params);
    }
实现相同的函数需要函数类、作为参数的对象和函数类的调用方法

下一步是查找测试的进程id

private static void printProcesses()
    {
        Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();

        HANDLE snapshot = Kernel32Me.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS,
                new DWORD(0));
        try {
            while (Kernel32Me.INSTANCE.Process32Next(snapshot, processEntry)) {
                System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile));
            }
        } finally {
            Kernel32Me.INSTANCE.CloseHandle(snapshot);
        }
    }
只需选择屏幕上显示的其中一个。 为了方便起见,我首先测试了两种常用函数的方法,VirtualAllocEx和VirtualFreeEx

我测试成功了

以下两种不同的方法testAllocFree和testAllocFree2函数产生相同的输出

private static void testAllocFree(final int processId) {
        SIZE_T dwSize = new SIZE_T(1024);

        DWORD  flAllocationType = new DWORD(Kernel32Me.MEM_RESERVE | Kernel32Me.MEM_COMMIT);
        DWORD  flProtect = new DWORD(Kernel32Me.PAGE_READWRITE);
        Pointer allocPoint = null;
        boolean ret = false;
        DWORD options 
            = new DWORD(
                Kernel32Me.PROCESS_VM_OPERATION | 
                Kernel32Me.PROCESS_VM_WRITE | 
                Kernel32Me.PROCESS_VM_READ | 
                Kernel32Me.PROCESS_CREATE_THREAD | 
                Kernel32Me.PROCESS_QUERY_INFORMATION);

        DWORD procs = new DWORD(processId);

        HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options, false, procs);

        if(null == hProcess)
        {
            System.err.println("Can't have a handle for you..sorry");
            return;
        }

        try
        {
            allocPoint = Kernel32Me.INSTANCE.VirtualAllocEx(hProcess, null, dwSize, flAllocationType, flProtect);

            if(allocPoint==null)
            {
                System.err.println("Can't get a memory resource for you..sorry");
                int c = Kernel32Me.INSTANCE.GetLastError();
                System.out.println("\t>>" + c);
                //c = Native.getLastError();
                //System.out.println("\t" + c);
            }

            if (allocPoint != null) {
                dwSize = new SIZE_T(0);
                DWORD freeType = new DWORD(Kernel32Me.MEM_RELEASE);
                System.err.println("allocPoint >>==> " + allocPoint.toString());
                ret = Kernel32Me.INSTANCE.VirtualFreeEx(hProcess, allocPoint, dwSize, freeType);

                if(!ret)
                {
                    int c = Kernel32Me.INSTANCE.GetLastError();
                    System.out.println("\t" + c);
                    c = Native.getLastError();
                    System.out.println("\t" + c);
                }
                else
                {
                    System.out.println("\t Free success");
                }
            }
        }
        finally
        {
            Kernel32Me.INSTANCE.CloseHandle(hProcess);
        }


    }
以及

最后,下面测试GetModuleFileName和GetModuleFileName函数

private static void testModuleFileName(final int processId)
    {
        DWORD nSize = new DWORD(256);
        char lpFilename[] = new char[256];
        byte bFilename[] = new byte[256];
        String strFileName = new String();
        DWORD options = new DWORD(Kernel32Me.PROCESS_VM_READ | Kernel32Me.PROCESS_QUERY_INFORMATION);
        DWORD procs = new DWORD(processId);

        HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options,false, procs);

        if(null == hProcess)
        {
            System.err.println("Can't have a handle for you..sorry");
            return;
        }

        try
        {
            Kernel32Me.INSTANCE.GetModuleFileName(null, lpFilename, nSize);
            System.err.println("module path is " + new String(lpFilename));

            Kernel32Me.INSTANCE.GetModuleFileName(null, bFilename, nSize);
            System.err.println("module path is " + new String(bFilename));

            Kernel32Me.INSTANCE.GetModuleFileNameEx(hProcess, null, strFileName, nSize);
            System.err.println("module path is " + strFileName);

        }
        finally
        {
            Kernel32Me.INSTANCE.CloseHandle(hProcess);
        }
    }
我有两个原型,一个是数组字节,另一个是代码中使用的字符数组

DWORD GetModuleFileName(HMODULE hModule, char[] lpFilename, DWORD nSize);
DWORD GetModuleFileName(HMODULE hModule, byte[] lpFilename, DWORD nSize);
第三个没有像我在开始时提到的那样工作,这告诉我不满意的链接错误。。 我不知道为什么

DWORD GetModuleFileNameEx(HANDLE hProcess, HMODULE hModule, String lpFilename, DWORD nSize);
另一个实现也是一样的..看看代码

private static void testModuleFileName2(final int processId)
    {
        Function allocFunc = Function.getFunction("kernel32", "GetModuleFileName");

        DWORD nSize = new DWORD(256);
        char[] lpFilename = new char[256];

        DWORD procs = new DWORD(processId);
        DWORD options 
            = new DWORD(
                Kernel32Me.PROCESS_VM_READ | 
                Kernel32Me.PROCESS_QUERY_INFORMATION);

        HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options, false, procs);

        if(null == hProcess)
        {
            System.err.println("Can't have a handle for you..sorry");
            return;
        }

        try
        {
            Object[] inArgs = new Object[3];
            inArgs[0] = null;
            inArgs[1] = lpFilename;
            inArgs[2] = nSize;
            allocFunc.invoke(inArgs);
            System.err.println("module path is " + new String(lpFilename));
        }
        finally
        {
            Kernel32Me.INSTANCE.CloseHandle(hProcess);
        }


    }
最后我发现两种方法都不管用

Function allocFunc = Function.getFunction("kernel32", "GetModuleFileName");
Function allocFunc = Function.getFunction("kernel32", "GetModuleFileNameEx");
显示未找到的过程消息

java.lang.UnsatifiedLinkError:查找函数时出错 'GetModuleFileName'java.lang.UnsatisfiedLinkError:查找时出错 函数“GetModuleFileNameEx”

在不久的将来,我必须对这些错误进行更多的挖掘

最后一个…这里是一个主要的原型类

public interface Kernel32Me extends StdCallLibrary {
        final Kernel32Me INSTANCE 
            = (Kernel32Me) Native.loadLibrary("kernel32.dll", Kernel32Me.class, W32APIOptions.DEFAULT_OPTIONS);

        //https://msdn.microsoft.com/en-us/library/windows/desktop/aa366890(v=vs.85).aspx
        int PROCESS_CREATE_THREAD = 0x0002;
        int PAGE_EXECUTE_READWRITE = 0x40;
        int PROCESS_QUERY_INFORMATION = 0x0400;
        int PROCESS_VM_OPERATION = 0x0008;
        int PROCESS_VM_WRITE = 0x0020;
        int PROCESS_VM_READ = 0x0010;
        int PAGE_READWRITE = 0x04;
        int MEM_RESERVE = 0x00002000;
        int MEM_COMMIT = 0x00001000;
        int MEM_RESET = 0x00080000;
        int MEM_DECOMMIT = 0x4000;
        int MEM_RELEASE = 0x8000;


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

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

        DWORD GetModuleFileName(HMODULE hModule, char[] lpFilename, DWORD nSize);
        DWORD GetModuleFileName(HMODULE hModule, byte[] lpFilename, DWORD nSize);
        DWORD GetModuleFileNameEx(HANDLE hProcess, HMODULE hModule, String lpFilename, DWORD nSize);

        HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);

        boolean Process32First(HANDLE hSnapshot, PROCESSENTRY32 lppe);

        boolean Process32Next(HANDLE hSnapshot, PROCESSENTRY32 lppe);

        HANDLE OpenProcess(DWORD dwDesiredAccess, boolean bInheritHandle, DWORD dwProcessId);

        boolean CloseHandle(HANDLE hObject);

        int GetLastError();
    }
输出可能如下所示

0   [System Process]
4   System
280 smss.exe
444 csrss.exe
536 wininit.exe
544 csrss.exe
7860    chrome.exe
8132    chrome.exe
7808    chrome.exe
7516    chrome.exe
6176    chrome.exe
8156    chrome.exe
7120    chrome.exe
7476    chrome.exe
8016    chrome.exe
5616    devmonsrv.exe
1644    chrome.exe
6548    chrome.exe
5960    chrome.exe
5636    chrome.exe
8260    chrome.exe
3440    notepad.exe
8844    chrome.exe
9416    chrome.exe
6744    chrome.exe
6032    chrome.exe
9724    javaw.exe
     Free success
allocPoint >>==> native@0x34d0000
allocPoint ==> native@0x34d0000
module path is C:\DEV\COMP\Java\jdk1.7\bin\javaw.exe
module path is C.... <== The output is strange...
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'GetModuleFileNameEx':
您可以依次使用下面的方法

printprocess();testModuleFileName(进程ID)

我希望这能对你有所帮助

附言

最后,我对这个问题有了自己的答案。。。 它可以通过Psapi接口完成。。。 这是我最后的测试方法

private static void testModuleFileName2(final int processId) {
    DWORD nSize = new DWORD(260);
    char lpFilename[] = new char[260];
    byte bFilename[] = new byte[260];

    DWORD options = new DWORD(Kernel32Me.PROCESS_VM_READ | Kernel32Me.PROCESS_QUERY_INFORMATION);
    DWORD procs = new DWORD(processId);

    HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options, false, procs);

    if (null == hProcess) {
        System.err.println("Can't have a handle for you..sorry");
        return;
    }

    HMODULE handle = Kernel32.INSTANCE.GetModuleHandle("kernel32.dll");

    if (null == handle) {
        System.err.println("Can't have a handle for you..sorry");
        return;
    }

    try {
        Kernel32Me.INSTANCE.GetModuleFileName(handle, lpFilename, nSize);
        System.err.println("2> module path is " + new String(lpFilename));

        Psapi.INSTANCE.GetModuleFileNameExA(hProcess, handle, bFilename, 260);
        System.err.println("2> module path is " + new String(bFilename));

        Psapi.INSTANCE.GetModuleFileNameExW(hProcess, null, lpFilename, 260);
        System.err.println("2> module path is " + new String(lpFilename));

    } finally {
        Kernel32Me.INSTANCE.CloseHandle(hProcess);
    }
}
我打开了一个notepad.exe,得到了它的进程id


然后,我调用了这个方法。

首先,我为我的错误回答向您道歉

所以,在再次收到您的问题后,我已经测试了您的代码。 我必须为这个问题制作自己的课程

让我们看看GetModuleFileName的原型

DWORD WINAPI GetModuleFileName(
  _In_opt_ HMODULE hModule,
  _Out_    LPTSTR  lpFilename,
  _In_     DWORD   nSize
);
您的原型适用于GetModuleFileName而不是GetModuleFileName

我遗漏的主要一点是lpFilename参数,它必须是muttable对象

它可以是任何可咕哝的对象,如字符数组或作为参数的字节数组

我认为我们不能使用String类作为参数,因为它是一个不可变的

我认为建议使用GetModuleFileName,而不是msdn中的GetModuleFileName

你可以在他们说的文章中间找到

要检索当前进程中模块的名称,请使用 GetModuleFileName函数。这是更有效和更可靠的 而不是使用当前进程的句柄调用GetModuleFileNameEx

这里有两个条件。 首先,我的操作系统是Windows 7 Ultimate 64位 第二,你和我有一个不同的开发环境

我从原始版本下载了最新的jna.jarjna platform.jar

我测试了四种不同的方法,其中一种失败了

我的切入点如下

public static void main(String[] args) {
        testCopyFile();
                printProcesses();
        testAllocFree(PROCESSID);
        testAllocFree2(PROCESSID);
        testModuleFileName(PROCESSID);
        testModuleFileName2(PROCESSID);
    }
testCopyFile方法只是用不同的方法复制一些文本文件

private static void testCopyFile() {
        Function copyFunc = Function.getFunction("kernel32", "CopyFileA");
        Object[] params = new Object[3];
        params[0] = "C:\\DEV\\temp\\_info.txt";
        params[1] = "C:\\DEV\\temp\\_info2.txt";
        params[2] = false;
        copyFunc.invoke(params);
    }
实现相同的函数需要函数类、作为参数的对象和函数类的调用方法

下一步是查找测试的进程id

private static void printProcesses()
    {
        Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();

        HANDLE snapshot = Kernel32Me.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS,
                new DWORD(0));
        try {
            while (Kernel32Me.INSTANCE.Process32Next(snapshot, processEntry)) {
                System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile));
            }
        } finally {
            Kernel32Me.INSTANCE.CloseHandle(snapshot);
        }
    }
只需选择屏幕上显示的其中一个。 为了方便起见,我首先测试了两种常用函数的方法,VirtualAllocEx和VirtualFreeEx

我测试成功了

以下两种不同的方法testAllocFree和testAllocFree2函数产生相同的输出

private static void testAllocFree(final int processId) {
        SIZE_T dwSize = new SIZE_T(1024);

        DWORD  flAllocationType = new DWORD(Kernel32Me.MEM_RESERVE | Kernel32Me.MEM_COMMIT);
        DWORD  flProtect = new DWORD(Kernel32Me.PAGE_READWRITE);
        Pointer allocPoint = null;
        boolean ret = false;
        DWORD options 
            = new DWORD(
                Kernel32Me.PROCESS_VM_OPERATION | 
                Kernel32Me.PROCESS_VM_WRITE | 
                Kernel32Me.PROCESS_VM_READ | 
                Kernel32Me.PROCESS_CREATE_THREAD | 
                Kernel32Me.PROCESS_QUERY_INFORMATION);

        DWORD procs = new DWORD(processId);

        HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options, false, procs);

        if(null == hProcess)
        {
            System.err.println("Can't have a handle for you..sorry");
            return;
        }

        try
        {
            allocPoint = Kernel32Me.INSTANCE.VirtualAllocEx(hProcess, null, dwSize, flAllocationType, flProtect);

            if(allocPoint==null)
            {
                System.err.println("Can't get a memory resource for you..sorry");
                int c = Kernel32Me.INSTANCE.GetLastError();
                System.out.println("\t>>" + c);
                //c = Native.getLastError();
                //System.out.println("\t" + c);
            }

            if (allocPoint != null) {
                dwSize = new SIZE_T(0);
                DWORD freeType = new DWORD(Kernel32Me.MEM_RELEASE);
                System.err.println("allocPoint >>==> " + allocPoint.toString());
                ret = Kernel32Me.INSTANCE.VirtualFreeEx(hProcess, allocPoint, dwSize, freeType);

                if(!ret)
                {
                    int c = Kernel32Me.INSTANCE.GetLastError();
                    System.out.println("\t" + c);
                    c = Native.getLastError();
                    System.out.println("\t" + c);
                }
                else
                {
                    System.out.println("\t Free success");
                }
            }
        }
        finally
        {
            Kernel32Me.INSTANCE.CloseHandle(hProcess);
        }


    }
以及

最后,下面测试GetModuleFileName和GetModuleFileName函数

private static void testModuleFileName(final int processId)
    {
        DWORD nSize = new DWORD(256);
        char lpFilename[] = new char[256];
        byte bFilename[] = new byte[256];
        String strFileName = new String();
        DWORD options = new DWORD(Kernel32Me.PROCESS_VM_READ | Kernel32Me.PROCESS_QUERY_INFORMATION);
        DWORD procs = new DWORD(processId);

        HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options,false, procs);

        if(null == hProcess)
        {
            System.err.println("Can't have a handle for you..sorry");
            return;
        }

        try
        {
            Kernel32Me.INSTANCE.GetModuleFileName(null, lpFilename, nSize);
            System.err.println("module path is " + new String(lpFilename));

            Kernel32Me.INSTANCE.GetModuleFileName(null, bFilename, nSize);
            System.err.println("module path is " + new String(bFilename));

            Kernel32Me.INSTANCE.GetModuleFileNameEx(hProcess, null, strFileName, nSize);
            System.err.println("module path is " + strFileName);

        }
        finally
        {
            Kernel32Me.INSTANCE.CloseHandle(hProcess);
        }
    }
我有两个原型,一个是数组字节,另一个是代码中使用的字符数组

DWORD GetModuleFileName(HMODULE hModule, char[] lpFilename, DWORD nSize);
DWORD GetModuleFileName(HMODULE hModule, byte[] lpFilename, DWORD nSize);
第三个没有像我在开始时提到的那样工作,这告诉我不满意的链接错误。。 我不知道为什么

DWORD GetModuleFileNameEx(HANDLE hProcess, HMODULE hModule, String lpFilename, DWORD nSize);
另一个实现也是一样的..看看代码

private static void testModuleFileName2(final int processId)
    {
        Function allocFunc = Function.getFunction("kernel32", "GetModuleFileName");

        DWORD nSize = new DWORD(256);
        char[] lpFilename = new char[256];

        DWORD procs = new DWORD(processId);
        DWORD options 
            = new DWORD(
                Kernel32Me.PROCESS_VM_READ | 
                Kernel32Me.PROCESS_QUERY_INFORMATION);

        HANDLE hProcess = Kernel32Me.INSTANCE.OpenProcess(options, false, procs);

        if(null == hProcess)
        {
            System.err.println("Can't have a handle for you..sorry");
            return;
        }

        try
        {
            Object[] inArgs = new Object[3];
            inArgs[0] = null;
            inArgs[1] = lpFilename;
            inArgs[2] = nSize;
            allocFunc.invoke(inArgs);
            System.err.println("module path is " + new String(lpFilename));
        }
        finally
        {
            Kernel32Me.INSTANCE.CloseHandle(hProcess);
        }


    }
最后我发现两种方法都不管用

Function allocFunc = Function.getFunction("kernel32", "GetModuleFileName");
Function allocFunc = Function.getFunction("kernel32", "GetModuleFileNameEx");
给我看未找到的文件