Viper029
@Viper029
Программирую за печенье

Как считывать данные из сторонней программы?

Всем привет! Есть задача, считывать данные со сторонней программы. Данные выводятся в лейбл на одной из форм.

1. Изначально пробовал через память. Нахожу нужное мне значение в регионе памяти и считываю его. Но, проблема в том, что считывать нужно 10 раз в секунду, значение постоянно меняется. Плюсом ко всему, прыгает каждое свое обновление по памяти. Нашел устойчивую сигнатуру, но это не помогает. Моя функция поиска работает на много дольше, чем прыжки по памяти нужного мне значения. Соответственно, не вариант ее таким образом считывать.

2. Решил подойти к проблеме с другой стороны, считывать данные через WinAPI. С помощью утилит нашел нужный мне контрол, но по функции получения текста из контрола(WM_GETTEXT = 0x000D) выдает пустое поле. Оно вполне понятно, через программы по типу Control Viewer или подобных, конкретно у этого контрола поле Text пустое. Каким-то образом мне нужно у этого контрола вытащить данные из лейбла(возможно и не из лейбла, я хз как в нём реализован вывод текста).
Вот короткий код программы. Перебирает все контролы приложения и собирает из них текст:
[System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        static void Main(string[] args)
        {
            Process[] App = Process.GetProcessesByName("EXE NAME"); // тут я считываю процесс с нужным именем в массив
            if (App.Length == 0)// проверяю запущено ли приложение, если массив пустой, то процесс не запущен
            {
                Console.WriteLine("Программа *EXE NAME* не запущена!");
            }

            else if (App[0] != null)
            {
                SetForegroundWindow(App[0].MainWindowHandle);// перевожу фокус на окно приложения
                string NewText, CurrText;

                var allChildWindows = new WindowHandleInfo(App[0].MainWindowHandle).GetAllChildHandles();// считываю все возможные контролы из приложения
                foreach (IntPtr hWnd in allChildWindows) // перебираю контролы и вытаскиваю из них текст
                {
                    var gt = new GetText().GetControlText(hWnd); // нахожу нужный мне текст               
                }
            }
        }

Вот класс GetText
public class GetText
    {

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SendMessage(int hWnd, int Msg, int wparam, int lparam);

        const int WM_GETTEXT = 0x000D;
        const int WM_GETTEXTLENGTH = 0x000E;
        const int MN_GETHMENU = 0x01E1;

        public string GetControlText(IntPtr hWnd)
        {

            // Get the size of the string required to hold the window title (including trailing null.) 
            Int32 titleSize = SendMessage((int)hWnd, WM_GETTEXTLENGTH, 0, 0).ToInt32();

            // If titleSize is 0, there is no title so return an empty string (or null)
            if (titleSize == 0)
                return String.Empty;

            StringBuilder title = new StringBuilder(titleSize + 1);

            SendMessage(hWnd, (int)WM_GETTEXT, title.Capacity, title);

            return title.ToString();
        }
    }


Сам я в первый раз такое делаю, опыта мало, подскажите, пожалуйста, возможно есть какие-то библиотеки для вытаскивания нужного мне значения, или вообще, в какую сторону копать. :)
  • Вопрос задан
  • 2181 просмотр
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы