是否可以将 VM_CHAR 消息发送到 ProcessBuilder 启动的控制台程序? (windows 平台)
Is possible to send VM_CHAR message to a console program launch by ProcessBuilder? (windows platform)
我想模拟VK_ENTER
到控制台程序。
当我通过cmd.exe
手动启动程序时,我可以post VK_ENTER
成功发送消息。
未找到 ProcessBuilder
启动的控制台程序的 hwnd。
@Test
public void testGetPid(){
ProcessBuilder pb = new ProcessBuilder("test.exe"); // not work
// ProcessBuilder pb = new ProcessBuilder("notepad.exe"); // work
Process p = null;
try {
p = pb.start();
//"handle"
System.out.println(p);
Field f = p.getClass().getDeclaredField( "handle");
f.setAccessible( true);
long procHandle = f.getLong( p);
System.out.println("Handle: " + procHandle);
//Kernel32.INSTANCE.
HANDLE handle = new HANDLE();
handle.setPointer(Pointer.createConstant(procHandle));
final int pid = Kernel32.INSTANCE.GetProcessId(handle);
System.out.println("Pid: " + pid);
ThreadUtil.sleep(5*1000);
sendKeyToProcess(pid);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
ThreadUtil.sleep(60*1000);
if( p != null )
p.destroy();
}
}
private void sendKeyToProcess(final int pid) {
final User32 user32Lib = User32.INSTANCE;
final int WM_KEYDOWN = 0x0100;
final int WM_KEYUP = 0x0101;
final int WM_CHAR = 0x0102;
user32Lib.EnumWindows(new WinUser.WNDENUMPROC() {
@Override
public boolean callback(HWND paramHWND, Pointer paramPointer) {
IntByReference intRef = new IntByReference();
user32Lib.GetWindowThreadProcessId(paramHWND, intRef);
if( pid == intRef.getValue() ){
// final WPARAM wPARAM = new WPARAM(13); // enter
final WPARAM wPARAM = new WPARAM(48); // '0'
final LPARAM lPARAM = new LPARAM(0);
System.out.println("Match hwnd: " + paramHWND.toString());
user32Lib.PostMessage(paramHWND,
WM_KEYDOWN, wPARAM, lPARAM);
User32.INSTANCE.EnumChildWindows(paramHWND,
new WinUser.WNDENUMPROC() {
@Override
public boolean callback(HWND childParamHWND,
Pointer paramPointer) {
System.out.println("send");
user32Lib.PostMessage(childParamHWND,
WM_KEYDOWN, wPARAM, lPARAM);
return true;
}
}, null);
//return false;
}
return true;
}
}, null);
}
它对我有用:(所有 JNA 解决方案)
- 使用 STARTF_USESHOWWINDOW 和 CREATE_NEW_CONSOLE 标志创建进程
- EnumWindows with PROCESS_INFORMATION dwProcessId 查找进程 window id
(GetWindowThreadProcessId)
- PostMessage 与进程 window id 发送进入
我想模拟VK_ENTER
到控制台程序。
当我通过cmd.exe
手动启动程序时,我可以post VK_ENTER
成功发送消息。
未找到 ProcessBuilder
启动的控制台程序的 hwnd。
@Test
public void testGetPid(){
ProcessBuilder pb = new ProcessBuilder("test.exe"); // not work
// ProcessBuilder pb = new ProcessBuilder("notepad.exe"); // work
Process p = null;
try {
p = pb.start();
//"handle"
System.out.println(p);
Field f = p.getClass().getDeclaredField( "handle");
f.setAccessible( true);
long procHandle = f.getLong( p);
System.out.println("Handle: " + procHandle);
//Kernel32.INSTANCE.
HANDLE handle = new HANDLE();
handle.setPointer(Pointer.createConstant(procHandle));
final int pid = Kernel32.INSTANCE.GetProcessId(handle);
System.out.println("Pid: " + pid);
ThreadUtil.sleep(5*1000);
sendKeyToProcess(pid);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
ThreadUtil.sleep(60*1000);
if( p != null )
p.destroy();
}
}
private void sendKeyToProcess(final int pid) {
final User32 user32Lib = User32.INSTANCE;
final int WM_KEYDOWN = 0x0100;
final int WM_KEYUP = 0x0101;
final int WM_CHAR = 0x0102;
user32Lib.EnumWindows(new WinUser.WNDENUMPROC() {
@Override
public boolean callback(HWND paramHWND, Pointer paramPointer) {
IntByReference intRef = new IntByReference();
user32Lib.GetWindowThreadProcessId(paramHWND, intRef);
if( pid == intRef.getValue() ){
// final WPARAM wPARAM = new WPARAM(13); // enter
final WPARAM wPARAM = new WPARAM(48); // '0'
final LPARAM lPARAM = new LPARAM(0);
System.out.println("Match hwnd: " + paramHWND.toString());
user32Lib.PostMessage(paramHWND,
WM_KEYDOWN, wPARAM, lPARAM);
User32.INSTANCE.EnumChildWindows(paramHWND,
new WinUser.WNDENUMPROC() {
@Override
public boolean callback(HWND childParamHWND,
Pointer paramPointer) {
System.out.println("send");
user32Lib.PostMessage(childParamHWND,
WM_KEYDOWN, wPARAM, lPARAM);
return true;
}
}, null);
//return false;
}
return true;
}
}, null);
}
它对我有用:(所有 JNA 解决方案)
- 使用 STARTF_USESHOWWINDOW 和 CREATE_NEW_CONSOLE 标志创建进程
- EnumWindows with PROCESS_INFORMATION dwProcessId 查找进程 window id (GetWindowThreadProcessId)
- PostMessage 与进程 window id 发送进入