Как я могу зарегистрировать время появления сообщения от стороннего приложения? - PullRequest
3 голосов
/ 18 октября 2010

Вот ситуация:

У нас есть стороннее приложение, которое периодически отображает сообщение об ошибке.Обычно ошибка возникает, когда в офисе никого нет, поэтому мы не знаем точно, в какое время появляется окно сообщения.Мы работаем с нашими поставщиками, чтобы определить причину проблемы, и они хотят точно знать, когда происходит ошибка, чтобы мы могли сообщить им о состоянии сети и т. Д. Во время ошибки.Сообщение об ошибке нигде не регистрируется приложением, поэтому мне было поручено каким-то образом регистрировать его, когда это происходит.

У меня 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;
    }
}
}

Ответы [ 3 ]

1 голос
/ 18 октября 2010

Они толкают вас, прекрасно понимая, что это не так легко осуществить. Добавить запись в журнал для них совершенно тривиально, они должны были это сделать, если их приложение чувствительно к условиям сети. Наиболее позитивный взгляд на эту просьбу состоит в том, что они будут надеяться, что вы сами это поймете, если попытаетесь сделать эту работу. Могло случиться. Поговорите со своим руководителем и укажите на это.

0 голосов
/ 19 октября 2010

Если вы можете подключить отладчик, он должен быть довольно тривиальным:)

0 голосов
/ 18 октября 2010

Как насчет этого простого подхода: создавать снимок экрана каждые 2 минуты и просто проверять файлы изображений на следующий день?

...