Support Wikipedia Follow My Heart: JNA
显示标签为“JNA”的博文。显示所有博文
显示标签为“JNA”的博文。显示所有博文

2011年10月4日星期二

How to get Process Id in Windows?

For users, using WMIC.exe can easily solve the problem.

i.e. launch CMD.exe, then type in following sentence:

WMIC PROCESS get name,commandline,Processid


then press enter.
Now you can see three kinds of information for each running process:
  1. process caption (i.e. "notepad.exe"), 
  2. commandline (i.e. "C:\Windows\System32\notepad.exe"),
  3. process id (i.e. 1740)


You can also output the result into file by using the "/output" option.
You can type "WMIC /?" for help.

Also you can refer to this post or this post for more information.


For Java programmers, you can use JNA to do it. Otherwise you need to use native method to invoke local dll libraries.

The corresponding os-level method to get ProcessId in JNA is already wrapped in Kernel32.class.

What you need to do is just using the following code to do so. 

(import jna.jar
(import platform.jar)

private int getWindowsProcessId(Process proc) {
if (proc.getClass().getName().equals("java.lang.Win32Process")
|| proc.getClass().getName().equals("java.lang.ProcessImpl")) {
/* determine the pid on windows plattforms */
try {
Field f = proc.getClass().getDeclaredField("handle");
f.setAccessible(true);
long handl = f.getLong(proc);
Kernel32 kernel = Kernel32.INSTANCE;
                                        // be careful! If you use 3.3.0 version of JNA, you wil not found W32API.HANDLE. In stead, you should use WinNT.HANDLE 
W32API.HANDLE handle = new W32API.HANDLE(); 
                                // be careful for the security issue.
                                        // sometimes you need to open the rewrite lock and then invoke setPointer function.. For example, if you use 3.3.0 version of JNA, you need to reflect WinNT.HANDLE.immutable, which is a boolean variable. Set it to false before you setPointer
handle.setPointer(Pointer.createConstant(handl));
return kernel.GetProcessId(handle);
 
} catch (Throwable e) {
_log.error(e.getMessage());
}
}
return 0;
}


By the way, both jna.jar and platform.jar are released by JNA project. 
But jna.jar contains all mapping and specification, while platform.jar includes specific implementation. 
So if you do not want to import platform.jar, you need to write the following code by yourself.

Thanks to "Timothy Wall" who published the following code on internet as example.

/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.

* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.  
*/
public interface W32Errors {
   int NO_ERROR               = 0;
   int ERROR_INVALID_FUNCTION = 1;
   int ERROR_FILE_NOT_FOUND   = 2;
   int ERROR_PATH_NOT_FOUND   = 3;
}


public interface Kernel32 extends W32API {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32",
Kernel32.class, DEFAULT_OPTIONS);
/* http://msdn.microsoft.com/en-us/library/ms683179(VS.85).aspx */
HANDLE GetCurrentProcess();
/* http://msdn.microsoft.com/en-us/library/ms683215.aspx */
int GetProcessId(HANDLE Process);
int GetCurrentProcessId();
}

/** Base type for most W32 API libraries.  Provides standard options
 * for unicode/ASCII mappings.  Set the system property w32.ascii
 * to true to default to the ASCII mappings.
 */
public interface W32API extends StdCallLibrary, W32Errors {
 
    /** Standard options to use the unicode version of a w32 API. */
    Map UNICODE_OPTIONS = new HashMap() {
        /**
*
*/
private static final long serialVersionUID = 1L;
{
            put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
            put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
        }
    };
 
    /** Standard options to use the ASCII/MBCS version of a w32 API. */
    Map ASCII_OPTIONS = new HashMap() {
        /**
*
*/
private static final long serialVersionUID = 1L;
{
            put(OPTION_TYPE_MAPPER, W32APITypeMapper.ASCII);
            put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.ASCII);
        }
    };
    Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS;
 
    public class HANDLE extends PointerType {
        public Object fromNative(Object nativeValue, FromNativeContext context) {
            Object o = super.fromNative(nativeValue, context);
            if (INVALID_HANDLE_VALUE.equals(o))
                return INVALID_HANDLE_VALUE;
            return o;
        }
    }
    /** Constant value representing an invalid HANDLE. */
    HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
        { super.setPointer(Pointer.createConstant(-1)); }
        public void setPointer(Pointer p) {
            throw new UnsupportedOperationException("Immutable reference");
        }
    };
}







2011年10月2日星期日

Compatibility of JNA and Java Jdk (Version)

JNA (from GitHub) is already uploaded to Version 3.3.0

However, the WinNT.HANDLE in "platform" package is only compilable under JDK 1.5.0.22 (or above).

what a shame.
I need to find old release to meet my environment (JDK 1.4)


*******************************************************
不记得什么时候见过一句话,说如果所有中国写程序的人都坚持写博客,那么中国的IT技术水平肯定非常厉害!
嗯,认真反思一下,我确实应该写BLOG。不为别的,起码自己想找以前某个问题的解决方案的时候,不用去翻代码就好。
*******************************************************
JNA现在更新到3.3.0 版本,可是最新版需要jdk1.5来编译,faint.
如果还像我一样折腾jdk1.4的话,还是找老版本吧。