UPD:添加了MCVE。使用SendMessage將消息循環發送到不同的procces()
這是一項教育任務。我必須使用SendMessage()
功能:
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd,
uint wMsg, UIntPtr wParam, IntPtr lParam);
我有信息,以與GUI communicationg兩個不同的應用。在得到諸如「開始」1 app
之類的消息之後,必須每5秒開始發送消息「請求值」至2 app
。並且2 app
發送到1 app
消息「發送值」與一些數據。
1 app
是的WinForms方案:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Oven_Monitor
{
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetCurrentProcessId();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);
private uint askMessageID = RegisterWindowMessage("Ask value");
private uint dataMessageID = RegisterWindowMessage("Send value");
private uint registerMessageID = RegisterWindowMessage("Register sensor");
public Form1() {
InitializeComponent();
this.Text = "Really rare title";
}
public void checkSensors() {
while (true) {
SendMessage(secondAppHWnd, askMessageID, (UIntPtr)0, (IntPtr)0);
System.Threading.Thread.Sleep(500);
}
}
private IntPtr secondAppHWnd;
protected override void WndProc(ref Message m) {
if (m.Msg == registerMessageID) {
secondAppHWnd = m.LParam;
Thread tr = new Thread(checkSensors);
tr.Start();
} else if (m.Msg == dataMessageID) {
//do some stuff
}
base.WndProc(ref m);
}
}
}
2 app
是控制檯項目,但它需要System.Windows.Forms
referens:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace HeatSensor
{
class Program
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static void Main(string[] args)
{
IntPtr mainAppHandle = FindWindow(null, "Really rare title");
while (mainAppHandle == IntPtr.Zero)
{
Console.ReadKey();
mainAppHandle = FindWindow(null, "Really rare title");
}
HiddenForm form = new HiddenForm(mainAppHandle);
while (true) //it's actually not infinit
{
//do some stuff
}
}
}
}
及隱藏表單類:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace HeatSensor
{
public partial class HiddenForm : Form
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
static private IntPtr mainAppHandle;
public HiddenForm(IntPtr mainAppHWnd)
{
InitializeComponent();
mainAppHandle = mainAppHWnd;
string title = System.DateTime.Now.ToLongDateString();
title += System.DateTime.Now.ToLongTimeString();
title += System.DateTime.Now.Ticks.ToString();
this.Text = title;
this.CreateHandle();
int currentWindowHandle = (int)FindWindow(null, title);
SendMessage(mainAppHandle, RegisterWindowMessage("Register sensor"),
(UIntPtr)0, currentWindowHandle);
}
private uint askMessageID = RegisterWindowMessage("Ask value");
private uint dataMessageID = RegisterWindowMessage("Send value");
private uint registerMessageID = RegisterWindowMessage("Register sensor");
protected override void WndProc(ref Message m)
{
if (m.Msg == askMessageID)
{
SendMessage(mainAppHandle, dataMessageID, (UIntPtr)1, (IntPtr)1);
}
base.WndProc(ref m);
}
}
}
出於某種原因,這個程序行爲很奇怪。幾乎每次2 app
都沒有收到「詢問價值」消息,有時checkSensors()
發送1-3條消息並停止。
有什麼不對?
這兩個HWnd都是正確的。
更新:我試圖檢查錯誤的位置:
public void checkSensors() {
while (true) {
SendMessage(secondAppHWnd, askMessageID, (UIntPtr)0, (IntPtr)0);
int error = Marshal.GetLastWin32Error();
System.Threading.Thread.Sleep(500);
}
}
看看。當SendMessage
被執行時,這個線程被阻塞了(什麼意思,SendMessage
沒有被弄錯,當我關閉2 app
之後,線程被解除了阻塞,並且我得到了164個錯誤(ERROR_MAX_THRDS_REACHED:系統中沒有更多的線程可以被創建)。 ?意味着
此外,補充說:
protected override void WndProc(ref Message m)
{
//here is all message checks
int erro2r = Marshal.GetLastWin32Error();
if (erro2r != 0) {
int j; //stop to debug here
}
base.WndProc(ref m);
}
它只是不斷地返回1400 ERROR_INVALID_WINDOW_HANDLE(我沒有在那一刻發送任何消息)
因此,它看起來完全以我不清楚
。更新2:如果我從WndProc()
調用它,一切正常:
SendMessage(secondAppHWnd, askMessageID, (UIntPtr)0, (IntPtr)0);
,但我需要從不同的線程發送此消息每5秒。
'HWND's可能是正確的,但你的P/Invoke簽名是全部錯誤的。你必須爲'hWnd'和'lParam'使用'IntPtr'。 'wParam'應該使用'UIntPtr'類型。同樣,返回值應該是'IntPtr'。如果你想保持CLS兼容,所有的上述內容使用'IntPtr'。 – IInspectable
@IInspectable,謝謝!我解決了這個問題,但主要問題仍然存在。 – InfernumDeus
請製作一個MCVE。不止一次地停止調用RegisterWindowMessage。添加錯誤檢查。也請考慮做一些調試。試圖在不進行調試的情況下進行編程並不有效。 –