UPD: добавлен MCVE.Циклическая отправка сообщений в разные версии с помощью SendMessage()
Это образовательная задача. Я должен использовать SendMessage()
функции:
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd,
uint wMsg, UIntPtr wParam, IntPtr lParam);
я должен сделать два разных приложения с графическим интерфейсом communicationg сообщениями. После получения сообщения типа «старт» 1 app
должны начать посылать сообщение «Задавать значение» до 2 app
каждые 5 секунд. И 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
Референс:
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
не получают отложенное сообщение «Ask value», иногда 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' может быть правильным, но ваша подпись P/Invoke - все неправильно. Вы должны использовать 'IntPtr' для' hWnd' и 'lParam'. 'wParam' должен использовать тип' UIntPtr'. Аналогично, возвращаемое значение должно быть 'IntPtr'. Если вы хотите остаться CLS-совместимым, используйте 'IntPtr' для всего перечисленного. – IInspectable
@ Невозможно, спасибо! Я исправил это, но главная проблема все еще здесь. – InfernumDeus
Пожалуйста, сделайте MCVE. Остановите вызов RegisterWindowMessage более одного раза. Добавить проверку ошибок. Также, пожалуйста, подумайте над выполнением некоторой отладки. Попытка программы без отладки не является продуктивной. –