2017-05-06 14 views
0

私はJNIにUser32Extメソッドを追加しています。私はGetModuleFileNameEx機能を追加したいJava JNAでLPTSTRの代わりに使用するものは?

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

:特に、私は、元UserExtクラスを拡張しました。

私はこのようにそれを記述します

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

しかしWinNT.LPTSTRが定義されていません。それは明らかにポインターであると思われています(私が推測するcharへ?)。だから、どうやってこれを終えるのですか?

+0

他の人の答えを調べるStringクラスを使用してください。@stackyflow.com/questions/5308655/jna-for-windows-api-function-getvolumepathnamesforvolumename – tommybee

+0

@tommybee文字列クラスは、コメントによって値を受け取ることができません。私は 'char []'を試みましたが、うまくいきませんでした。 –

+3

Unicodeインタフェースを呼び出すと、LPTSTRはwchar_t * –

答えて

2

まず第一に、私はだから

のための私の間違った答えのために申し訳ありませんが、私は再び右あなたの質問を受けた後、あなたのコードをテストしてみました。 私はこの問題のために自分のクラスを作る必要があります。

GetModuleFileNameはため GetModuleFileNameExのためではないのは、 GetModuleFileNameは

DWORD WINAPI GetModuleFileName(
    _In_opt_ HMODULE hModule, 
    _Out_ LPTSTR lpFilename, 
    _In_  DWORD nSize 
); 

あなたのプロトタイプの試作品を見てみましょう。 link

私が逃した主なポイントは、mutableオブジェクトでなければならないlpFilename引数です。

これは、パラメータの配列としてcharの配列やバイトの配列のような任意の変更可能なオブジェクトです。

クラスのため、Stringクラスをパラメーターとして使用できないと思います。

私は、GetModuleFileNameがmsdn siteのGetModuleFileNameExよりも推奨されると考えました。

あなたは彼らが言う記事の途中で見つけることができ、

To retrieve the name of a module in the current process, use the GetModuleFileName function. This is more efficient and more reliable than calling GetModuleFileNameEx with a handle to the current process

は、ここでは2つの条件があります。 まず、私のOSはWindows 7 Ultimate 64ビットです 第二に、あなたと私は異なる開発環境を持っています。

私は、元のsiteから最新のjna.jarJNA-platform.jarをダウンロードしました。

私は4つの異なる方法をテストしました。そのうちの1つが失敗しました。

私のエントリポイントは、ちょうどあなたに異なるアプローチで、いくつかのテキストファイルをコピーし

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

同じ関数を実装することによって、FunctionクラスのObject as parametersおよびinvokeメソッドが必要です。

次は、テストのプロセスIDを見つけることです。

画面に表示されている1つを選択するだけです。 便利な理由から、まずVirtualAllocExとVirtualFreeExという共通の機能を持つ2つのメソッドをテストしました。私は、次の2つの異なる方法...それは成功し

をテストし

、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); 
     } 


    } 

そして、

private static void testAllocFree2(final int processId) { 
     Function allocFunc = Function.getFunction("kernel32", "VirtualAllocEx"); 
     Function freeFunc = Function.getFunction("kernel32", "VirtualFreeEx"); 
     DWORD flAllocationType = new DWORD(Kernel32Me.MEM_RESERVE | Kernel32Me.MEM_COMMIT); 
     DWORD flProtect = new DWORD(Kernel32Me.PAGE_READWRITE); 
     SIZE_T dwSize = new SIZE_T(1024); 

     DWORD freeType = new DWORD(Kernel32Me.MEM_RELEASE); 
     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); 

     Pointer allocPoint = null; 

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

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

     Object[] inArgs = new Object[5]; 
     inArgs[0] = hProcess; 
     inArgs[1] = null; 
     inArgs[2] = dwSize; 
     inArgs[3] = flAllocationType; 
     inArgs[4] = flProtect; 

     allocPoint = (Pointer) allocFunc.invoke(Pointer.class, inArgs); 

     try 
     { 
      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) { 
       Object[] inArgs2 = new Object[4]; 
       inArgs2[0] = hProcess; 
       inArgs2[1] = allocPoint; 
       inArgs2[2] = new SIZE_T(0); 
       inArgs2[3] = freeType; 
       System.err.println("allocPoint ==> " + allocPoint.toString()); 
       freeFunc.invoke(inArgs2); 
      } 
     } 
     finally 
     { 
      Kernel32Me.INSTANCE.CloseHandle(hProcess); 
     } 
    } 

最後に、

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

下に試験GetModuleFileNameはとGetModuleFileNameA機能は私は2つのプロトタイプ、いずれかを有する配列バイトであり、他方はで使用される文字の配列でありますコード。私はなぜ知らない

DWORD GetModuleFileName(HMODULE hModule, char[] lpFilename, DWORD nSize); 
DWORD GetModuleFileName(HMODULE hModule, byte[] lpFilename, DWORD nSize); 

私はUnsatisfiedLinkErrorを私に言っ開始時に述べたように、第3の1が動作しませんでした.. ..

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


    } 

で.look。

Function allocFunc = Function.getFunction("kernel32", "GetModuleFileName"); 
Function allocFunc = Function.getFunction("kernel32", "GetModuleFileNameEx"); 

は、私は近い将来のある時点でこれらのエラーについてそれ以上を掘るする必要が

java.lang.UnsatisfiedLinkError: Error looking up function 'GetModuleFileName' java.lang.UnsatisfiedLinkError: Error looking up function 'GetModuleFileNameEx'

...私は見られない手順メッセージを表示します。

最終1 ...ここでの主プロトタイプクラスが

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(); 
    } 

で出力が文字エンコーディングの問題を回避バイトの配列よりも、あなたはcharの配列を使用する必要が

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 >>==> [email protected] 
allocPoint ==> [email protected] 
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': 

の下のようになります。 。

私のimport文は、あなたが順番に以下の方法を使用することができ、

import com.sun.jna.Function; 
import com.sun.jna.Native; 
import com.sun.jna.Pointer; 
import com.sun.jna.platform.win32.BaseTSD.SIZE_T; 
import com.sun.jna.platform.win32.Tlhelp32; 
import com.sun.jna.platform.win32.Tlhelp32.PROCESSENTRY32; 
import com.sun.jna.platform.win32.WinDef.DWORD; 
import com.sun.jna.platform.win32.WinDef.HMODULE; 
import com.sun.jna.platform.win32.WinNT.HANDLE; 
import com.sun.jna.win32.StdCallLibrary; 
import com.sun.jna.win32.W32APIOptions; 

です。

printProcesses(); testModuleFileName(PROCESSID);

private static final int PROCESSID = 3440; // the process id from printProcesses(); 
    public static void main(String[] args) { 
      printProcesses(); 
      testModuleFileName(PROCESSID); 
     } 

私はこれがあなた

P.S最後に

を助けることを願って、私はこの問題についての私自身の答えを持っています... ここに が私の最後の試験方法である... 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); 
    } 
} 

私はメモ帳を開いて、その後、そのプロセスID

を持って、私は、このメソッドを呼び出しました。

+1

まあ、短い答えは、 char [] 'を使うことができますが、このすべてを投稿していただきありがとうございます。私はwinapiを使用して、これらのすべての例のおかげで、これが将来私に役立つと確信しています! –

関連する問題