有的时候需要我们对鼠标和键盘的动作(鼠标的移动,键盘的点击)进行监听,比如按键记录,鼠标坐标记录等。
我们使用JNA来实现以上的操作
tips:JNA类库使用一个很小的本地类库sub 动态的调用本地代码。程序员只需要使用一个特定的java接口描述一下将要调用的本地代码的方法的结构和一些基本属性。这样就省了为了适配多个平台而大量的配置和编译代码。因为调用的都是JNA提供的公用jar 包中的接口。
首先我们实现监听鼠标的代码如下
package getInfo;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.sun.jna.Structure;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.examples.win32.User32;
import com.sun.jna.examples.win32.User32.HHOOK;
import com.sun.jna.examples.win32.User32.MSG;
import com.sun.jna.examples.win32.W32API.HMODULE;
import com.sun.jna.examples.win32.W32API.LRESULT;
import com.sun.jna.examples.win32.W32API.WPARAM;
import com.sun.jna.examples.win32.User32.HOOKPROC;
public class MouseHook implements Runnable{
public static final int WM_MOUSEMOVE = 512;
private static HHOOK hhk;
private static LowLevelMouseProc mouseHook;
final static User32 lib = User32.INSTANCE;
private boolean [] on_off=null;
public MouseHook(boolean [] on_off){
this.on_off = on_off;
}
public interface LowLevelMouseProc extends HOOKPROC {
LRESULT callback(int nCode, WPARAM wParam, MOUSEHOOKSTRUCT lParam);
}
public static class MOUSEHOOKSTRUCT extends Structure {
public static class ByReference extends MOUSEHOOKSTRUCT implements
Structure.ByReference {
};
public User32.POINT pt;
public int wHitTestCode;
public User32.ULONG_PTR dwExtraInfo;
}
public void run() {
HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
mouseHook = new LowLevelMouseProc() {
public LRESULT callback(int nCode, WPARAM wParam,
MOUSEHOOKSTRUCT info) {
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String fileName=df1.format(new Date());
String time=df2.format(new Date());
BufferedWriter bw1=null;
BufferedWriter bw2=null;
try {
bw1=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_Mouse.txt"),true));
bw2=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_Common.txt"),true));
} catch (IOException e) {
e.printStackTrace();
}
if (on_off[0] == false) {
System.exit(0);
}
if (nCode >= 0) {
switch (wParam.intValue()) {
case MouseHook.WM_MOUSEMOVE:
try {
bw1.write(time+" #### "+"x=" + info.pt.x
+ " y=" + info.pt.y+"\r\n");
bw2.write(time+" #### "+"x=" + info.pt.x
+ " y=" + info.pt.y+"\r\n");
bw1.flush();
bw2.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return lib
.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
}
};
hhk = lib.SetWindowsHookEx(User32.WH_MOUSE_LL, mouseHook, hMod, 0);
int result;
MSG msg = new MSG();
while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
if (result == -1) {
System.err.println("error in get message");
break;
} else {
System.err.println("got message");
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
}
lib.UnhookWindowsHookEx(hhk);
}
}
能够在鼠标移动的时候输出鼠标的坐标位置
接下来是监听键盘的代码
package getInfo;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.examples.win32.User32;
import com.sun.jna.examples.win32.User32.HHOOK;
import com.sun.jna.examples.win32.User32.KBDLLHOOKSTRUCT;
import com.sun.jna.examples.win32.User32.LowLevelKeyboardProc;
import com.sun.jna.examples.win32.User32.MSG;
import com.sun.jna.examples.win32.W32API.HMODULE;
import com.sun.jna.examples.win32.W32API.LRESULT;
import com.sun.jna.examples.win32.W32API.WPARAM;
public class KeyboardHook implements Runnable{
private static HHOOK hhk;
private static LowLevelKeyboardProc keyboardHook;
final static User32 lib = User32.INSTANCE;
private boolean [] on_off=null;
public KeyboardHook(boolean [] on_off){
this.on_off = on_off;
}
public void run() {
HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
keyboardHook = new LowLevelKeyboardProc() {
public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String fileName=df1.format(new Date());
String time=df2.format(new Date());
BufferedWriter bw1=null;
BufferedWriter bw2=null;
try {
bw1=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_Keyboard.txt"),true));
bw2=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_Common.txt"),true));
} catch (IOException e) {
e.printStackTrace();
}
if (on_off[0] == false) {
System.exit(0);
}
try {
bw1.write(time+" #### "+info.vkCode+"\r\n");
bw2.write(time+" #### "+info.vkCode+"\r\n");
bw1.flush();
bw2.flush();
} catch (IOException e) {
e.printStackTrace();
}
return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
}
};
hhk = lib.SetWindowsHookEx(User32.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
int result;
MSG msg = new MSG();
while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
if (result == -1) {
System.err.println("error in get message");
break;
} else {
System.err.println("got message");
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
}
lib.UnhookWindowsHookEx(hhk);
}
}
最后是获取进程信息的代码
package getInfo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ProcessInfo implements Runnable{
private boolean [] on_off=null;
public ProcessInfo(boolean [] on_off){
this.on_off = on_off;
}
public void run() {
BufferedReader input = null;
Process process = null;
BufferedWriter bw=null;
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String fileName=null;
String time=null;
try {
while(on_off[0]){
fileName=df1.format(new Date());
time=df2.format(new Date());
bw=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_ProcessInfo.txt"),true));
Thread.sleep(60000);
process = Runtime.getRuntime().exec("cmd.exe /c tasklist");
input =new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = " ";
int i=0;
input.readLine();
input.readLine();
input.readLine();
while ((line = input.readLine()) != null) {
bw.write(time+" #### "+line+"\r\n");
bw.flush();
i++;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
bw.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
开启上述线程的类
package getInfo;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Monitor {
public Monitor() {
boolean [] on_off={true};
new Thread(new ProcessInfo(on_off)).start();
new Thread(new KeyboardHook(on_off)).start();
new Thread(new MouseHook(on_off)).start();
final TrayIcon trayIcon;
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage(".//lib//monitor.png");
ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Exiting...");
System.exit(0);
}
};
PopupMenu popup = new PopupMenu();
MenuItem defaultItem = new MenuItem("Exit");
defaultItem.addActionListener(exitListener);
popup.add(defaultItem);
trayIcon = new TrayIcon(image, "monitor", popup);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
trayIcon.displayMessage("Action Event",
"An Action Event Has Been Peformed!",
TrayIcon.MessageType.INFO);
}
};
trayIcon.setImageAutoSize(true);
trayIcon.addActionListener(actionListener);
try {
tray.add(trayIcon);
} catch (AWTException e1) {
e1.printStackTrace();
}
}
}
public static void main(String[] args) {
new Monitor();
}
}
上面是一个鼠标监听的日志文件