Вот ситуация:
У нас есть стороннее приложение, которое периодически отображает сообщение об ошибке.Обычно ошибка возникает, когда в офисе никого нет, поэтому мы не знаем точно, в какое время появляется окно сообщения.Мы работаем с нашими поставщиками, чтобы определить причину проблемы, и они хотят точно знать, когда происходит ошибка, чтобы мы могли сообщить им о состоянии сети и т. Д. Во время ошибки.Сообщение об ошибке нигде не регистрируется приложением, поэтому мне было поручено каким-то образом регистрировать его, когда это происходит.
У меня C # .NET в качестве инструмента.До сих пор самыми близкими вещами, которые я нашел к решению, являются FindWindow и EnumChildWindows или подключение к сообщениям Windows.Я недавно закончил колледж и только начал свою работу, поэтому оба эти маршрута будут довольно сложными для меня.Прежде чем тратить много времени на изучение того, что мне нужно, чтобы заставить один из этих методов работать, я хотел проверить здесь и посмотреть, не было ли более простого решения.
На самом деле все, что мне нужно, это войти в систему.когда появляется окно сообщения и некоторая идентифицирующая информация о окне сообщения.Нет необходимости регистрировать только сообщения из рассматриваемого приложения.
Спасибо за помощь.Пожалуйста, дайте мне знать, если мне нужно что-то уточнить.
РЕДАКТИРОВАТЬ:
Я пытался что-то кодировать с предложениями и ссылками Ганса.Я довольно сильно полагался на его пример кода.Прямо сейчас у меня есть форма, которая будет принимать имя процесса.Нажатие на кнопку создаст экземпляр следующего класса.Я провел некоторое тестирование с помощью Блокнота, но он просто перебирал метод findMessageBox, даже когда у меня было открыто диалоговое окно.Я попытался использовать EnumChildWindows вместо EnumThreadWindows, и произошло то же самое.Я подтвердил, что программа имела правильный PID с Spy ++.Буду признателен за любые предложения о том, что мне нужно исправить.
РЕДАКТИРОВАТЬ:
Это работает сейчас.Спасибо большое за вашу помощь.Я передал неправильное значение из GetWindowProcessThreadId в EnumThreadWindows.Я все еще буду работать над этим, так как я могу кое-что почистить, и я не хочу, чтобы открытый диалог фиксировался постоянно, но это тривиальные вещи.Я разместил код, который у меня сейчас есть, с основной функцией на тот случай, если кому-то еще придется сделать подобное в будущем:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
namespace LogDialog
{
class DialogLogger
{
TextWriter log = new StreamWriter(@"C:\ErrorLog\ErrorLog.txt");
private Timer mTimer;
private uint lpdwProcessId;
private IntPtr mhwnd;
uint threadID;
//*************P/Invoke Declarations*************//
private delegate bool EnumThreadWndProc(IntPtr hwnd, IntPtr lp);
private delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lp);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadWndProc callback, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hwnd, StringBuilder buffer, int buflen);
//Retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);
//***********************************************//
//Constructor; initiates timer
public DialogLogger(string processName)
{
setWindowProcessID(processName); //set process ID
mTimer = new Timer(); //create timer for logging
mTimer.Interval = 50; //set interval
mTimer.Enabled = true; //enable
mTimer.Tick += new EventHandler(findMessageBox); //set event handler
}
private void setWindowProcessID(string processName)
{
mhwnd = Process.GetProcessesByName(processName)[0].MainWindowHandle;
threadID = GetWindowThreadProcessId(mhwnd, out lpdwProcessId);
}
//Enumerates windows to find a message box
private void findMessageBox(object sender, EventArgs e)
{
EnumThreadWndProc callback = new EnumThreadWndProc(checkDialogWindow);
EnumThreadWindows((int)threadID, callback, IntPtr.Zero);
GC.KeepAlive(callback);
}
//Checks if hwnd is a dialog
private bool checkDialogWindow(IntPtr hwnd, IntPtr lp)
{
StringBuilder sb = new StringBuilder(260);
GetClassName(hwnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
log.WriteLine("Error Logged: {0}", DateTime.Now.ToLongTimeString());
return false;
}
}
}