我需要使用 Java 应用程序的窗口消息传递与 C# 应用程序进行通信。我从我的应用程序中注册用于通信的消息。我能够成功获取 C# 应用程序的窗口句柄并注册消息。 C# 应用程序通过发送 WM_COPYDATA 响应消息来响应消息。 我可以达到接收 WM_COPYDATA 的程度。但我不知道如何从响应消息中提取消息内容。
如果我能得到一个使用 jniwrap 和 winpack 库从 java 应用程序读取 WM_COPYDATA 消息内容的示例代码,那真的很有帮助。如果lParam的内容是Structure类型会更有帮助。
我必须编辑代码才能删除敏感数据
以下代码通过窗口名称获取其他应用程序的窗口句柄,注册请求和响应消息,然后发送内容为空的请求消息。
private Library user32;
private long appHandle;
public void sendRequest() {
long requestMsgId = (int)this.registerWindowMessage("WM_TBD_SN_REQEST");
long responseMsgId = (int)this.registerWindowMessage("WM_TBD_SN_RESPONSE");
long tbdHandle = findWindow(null, "TestApp");
this.sendWindowsMessage(new Handle(tbdHandle), new Int(requestMsgId), new Handle(this.appHandle), new Pointer.Void());
}
public long sendWindowsMessage(final Parameter... args) {
final Function sendMessage = this.user32.getFunction("SendMessageA");
LongInt longInt = new LongInt();
sendMessage.invoke(longInt, args);
return longInt.getValue();
}
public long findWindow(final String classname, final String windowName) {
final Function findWindow = this.user32.getFunction("FindWindowA");
Parameter cName = null;
if (classname == null || classname.equals("")) {
cName = new Pointer.Void();
}
else {
cName = new AnsiString(classname);
}
LongInt longInt = new LongInt();
findWindow.invoke(longInt, cName, new AnsiString(windowName));
return longInt.getValue();
}
public long registerWindowMessage(String message) {
final Function findWindow = this.user32.getFunction("RegisterWindowMessageA");
LongInt longInt = new LongInt();
findWindow.invoke(longInt, new AnsiString(message));
return longInt.getValue();
}
这是自定义窗口过程,它将取代我的应用程序窗口的 native 过程
public class MyWindowProc extends WindowProc {
@Override
public void callback() {
if (this._msg.getValue() == Msg.WM_COPYDATA) {
// I can get to this point, but not sure how I can get the information from the message
// The WM_TBD_SN_RESPONSE structure consists of four fields
// 1. hWnd Field --- window handle of the calling application...
// 2. msg Field --- WM_COPYDATA message code
// 3. wData Field --- TDB application's window handle
// 4. pData Field --- contains a CopyDataStruct
// CopyDataStruct.pData – contains the Serial Number ----> how to extract this?
// CopyDataStruct.dwData – contains the message code for WM_TBD_SN_RESPONSE (this should match responseMsgId)
}
else {
super.callback();
}
}
}
请帮忙。提前致谢。
最佳答案
首先,我不是 Java 开发人员,也没有测试过下面的代码,但我确实了解 WM_COPYDATA,因此我可以对您的问题做出合理的回答。
WM_COPYDATA消息发送一个指针到(即a的地址)COPYDATASTRUCT Windows 定义为:
struct COPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
}
在 Java 中,您必须使用 sun.misc.Unsafe class 中的方法手动阅读此内容。 。我所说的手动是指您必须自己计算内存地址。
dwData
是应用程序可用于自身的整数值。 lpData
是一个指向缓冲区的指针,该缓冲区保存应用程序想要传递的数据。 cbData
是 lpData
包含的缓冲区中的字节数。
在 Windows 中,ULONG_PTR
在 32 位系统上为 4 个字节,在 64 位系统上为 8 个字节。 DWORD
始终为 4 个字节。 PVOID 是一个指针(即内存地址),在 32 位系统上为 4 字节,在 64 位系统上为 8 字节。
因此,在 32 位系统上,dwData
位于偏移量 0,cbData
位于偏移量 4,lpData
位于偏移量 8。在 64 位系统上位系统 dwData
仍位于偏移量 0,但 cbData
位于偏移量 8,lpData
位于偏移量 16。
import sun.misc;
final int dwDataOffset = 0;
final int cbDataOffset = 4; // Change to 8 for 64 bit
final int lpDataOffset = 8; // Change to 16 for 64 bit
int cpDataAddr = this._pData.getValue(); // This will return the address of the struct (I assume this syntax is correct) - change to long for 64 bit
int messageCode= Unsafe.getInt(cpDataAddr+dwDataOffset); // Change to getLong for 64 bit
int dataSize = Unsafe.getInt(cbDataAddr+cbDataOffset);
int dataAddress = Unsafe.GetInt(cbDataAddr+lpDataOffset); // Change to getLong for 64 bit
// Create a buffer to hold the data from lpData
byte[] data = new byte[dataSize];
for (int i = 0; i < dataSize; i++)
data[i] = Unsafe.getByte(dataAddress+i);
一旦您完成的数据将包含应用程序传入的原始数据,在您的情况下就是许可证。如果许可证是字符串,您应该能够将字节数组传递给 String 构造函数。如果它是一个更复杂的数据结构,您将必须使用 Unsafe
方法来读取它,就像我们对 COPYDATASTRUCT
关于c# - 使用窗口消息传递在 JAVA 和 C# 之间进行应用程序间通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6968325/