C# 使用 SendMessage,WM_COPYDATA 问题
我花了几天(或更长时间)试图让它发挥作用。
手头的应用程序是 FTPRush
,我知道有一个名为 rush_cmdline.exe
的命令行应用程序,它使用 SendMessage
向 发送请求>FTPRush
。
通过调试rush_cmdline.exe
,我可以看到lParam
、wParam
、Message
和hWnd
。
我的代码如下(使用 SendMessage,而不是 SendMessageW):
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("USER32.DLL", EntryPoint= "SendMessage")]
public static extern IntPtr SendMessage(int hWnd, int Msg, int wParam, IntPtr lParam);
我也尝试了另一个规范:
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
句柄(hWnd
)不是问题,因为这有效:
int ftprush = FindWindow("TfmRush", null);
ShowWindow(ftprush, 8);
哪个(我没有粘贴 dllimport,因为它在这里并不重要。如果您想查看它,请告诉我)将窗口置于前面。另外,我通过调试rush_cmdline.exe进行了检查。所以手柄是一样的。
两次尝试都失败了(默默地):
public const Int32 WM_COPYDATA = 0x4A;
string msg = "RushApp.FTP.Login('backup','',0); ";
// 1
byte[] array = Encoding.UTF8.GetBytes((string)msg);
int size = Marshal.SizeOf(array[0]) * array.Length + Marshal.SizeOf(array[0]);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(array, 0, ptr, array.Length);
Marshal.WriteByte(ptr, size - 1, 0);
SendMessage(ftprush, WM_COPYDATA, 0, ptr);
// 2
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = msg;
cds.cbData = sarr.Length + 1;
SendMessage(ftprush, WM_COPYDATA, 0, ref cds);
我希望至少第二个解决方案能够工作,因为它与此非常匹配: perl 示例
非常感谢任何启发!
谢谢,
- 弗兰克
更新:
string msg = "RushApp.FTP.Login('backup','',0);\0";
var cds = new COPYDATASTRUCT
{
dwData = new IntPtr(3),
cbData = msg.Length + 1,
lpData = msg
};
IntPtr ftprush = FindWindow("TfmRush", null);
SendMessage(ftprush, WM_COPYDATA, IntPtr.Zero, ref cds);
I've been spending a few days (or more) trying to get this to work.
The application at hand is FTPRush
, and I know there is a cmd line application called rush_cmdline.exe
which uses SendMessage
to send requests to FTPRush
.
From debugging the rush_cmdline.exe
I can see lParam
, wParam
, Message
and hWnd
.
My code is as follows (using SendMessage, not SendMessageW):
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("USER32.DLL", EntryPoint= "SendMessage")]
public static extern IntPtr SendMessage(int hWnd, int Msg, int wParam, IntPtr lParam);
And I've tried a another specification also:
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
The handle (hWnd
) is not the problem, as this works:
int ftprush = FindWindow("TfmRush", null);
ShowWindow(ftprush, 8);
Which (I didn't paste the dllimport as it's not important here. Let me know if you wish to see it) brings the window to front. Also, I checked by debugging rush_cmdline.exe
. So the handle is the same.
Two attempts which both fail (silently):
public const Int32 WM_COPYDATA = 0x4A;
string msg = "RushApp.FTP.Login('backup','',0); ";
// 1
byte[] array = Encoding.UTF8.GetBytes((string)msg);
int size = Marshal.SizeOf(array[0]) * array.Length + Marshal.SizeOf(array[0]);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(array, 0, ptr, array.Length);
Marshal.WriteByte(ptr, size - 1, 0);
SendMessage(ftprush, WM_COPYDATA, 0, ptr);
// 2
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = msg;
cds.cbData = sarr.Length + 1;
SendMessage(ftprush, WM_COPYDATA, 0, ref cds);
I would expect at least the 2nd solution to work, as it matches up pretty well with this: perl example
Any enlightenment is GREATLY appreciated!
Thanks,
- Frank
UPDATE:
string msg = "RushApp.FTP.Login('backup','',0);\0";
var cds = new COPYDATASTRUCT
{
dwData = new IntPtr(3),
cbData = msg.Length + 1,
lpData = msg
};
IntPtr ftprush = FindWindow("TfmRush", null);
SendMessage(ftprush, WM_COPYDATA, IntPtr.Zero, ref cds);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的定义
当然,请确保 str 以 null 结尾“\0”
或者由 PInvoke 给出的定义。 NET 是
My Definitions have
Of course, make sure that str is null terminated "\0"
Alternatively a definition given by PInvoke.NET is
在上面的两个答案之间,我拼凑了一个工作示例。 Bryce Wagner 的类有效,因此我添加了一个方法来使用 SendMessageTimeout 发送数据。它是一个静态方法,因此您只需调用它来发送数据即可。这实际上不是我的工作,只是粘合在一起并分享回来。
使用方法:
使用默认的 1 秒超时。
Between the 2 answers above I cobbled together a working example. Bryce Wagner's class works, so I added a method to use SendMessageTimeout to send the data. it's a static method, so you just call it to send data. This isn't really my work, just gluing together and sharing back.
To use it:
That uses the default 1 second timeout.
COPYDATASTRUCT 中参数的顺序至关重要,而 Bob Vale 的回答却将它们的顺序弄错了。 http://msdn.microsoft。 com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx 应该按这个顺序:
我还没有得到
MarshalAs(UnmanagedType.LPStr)] public string lpData
可以工作。我只是通过自己进行编组才使其工作:The order of arguments in the COPYDATASTRUCT are critically important, and Bob Vale's answer has them in the wrong order. http://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx It should be in this order:
I haven't gotten the
MarshalAs(UnmanagedType.LPStr)] public string lpData
to work either. I've only gotten it to work by doing the marshalling myself: