Как нажатие на кнопку из .NET в хитром нативном окне?
От: StarLancer  
Дата: 08.07.11 09:41
Оценка:
Здравствуйте!

Переду сразу к делу, столкнулся с такой проблемой:
Как правильно нажать на кнопку в радной программе "Удаленный помощник" из Windows7.
Пытаюсь ее нажать следующим образом:
Освновной код:
namespace ConsoleFindWindows {
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading;

    internal sealed class Program {


        static void Main(string[] args) {
            Process[] ms = Process.GetProcessesByName("msra");
            Process msra = ms.Length > 0 ? ms[0] : Process.Start("msra", "/offerra");

            //Дожидаемся запуска
            Thread.Sleep(300);
            IntPtr hWndParent = msra.MainWindowHandle;

            #region Тут отрабатывает нажатие на кнопку Обзор в открытом окне Выполнить, если заранее его открыть

            IntPtr runWindowHandle = WinApi.FindWindow(null, "Выполнить");
            if (runWindowHandle != IntPtr.Zero) {
                IntPtr hButton = WinApi.FindWindowEx(runWindowHandle, IntPtr.Zero, "Button", "Об&зор...");
                PushButton(hButton);
            }

            #endregion

            //Получение списка всех handle-ов процесса
            List<IntPtr> handles = WinApi.GetChildWindows(hWndParent);

            //Перебераем список в поиска нужного handle
            foreach (IntPtr intPtr in handles) {
                //Поиска handle нужной кнопки
                IntPtr hWndChild = WinApi.FindWindowEx(intPtr, IntPtr.Zero, "Button", "Отмена");

                //Нашли нужный нам handle
                if (hWndChild != IntPtr.Zero) {
                    WinApi.SetForegroundWindow(hWndChild);

                    //Отправляем сообщение о нажатие кнопки
                    PushButton(hWndChild);
                }
            }

            Console.WriteLine("Нажмите любую клавишу для закрытия процесса");
            Console.ReadKey();
        }

        private static void PushButton(IntPtr handle) {
            //Переводим фокус на кнопку
            WinApi.SetFocus(handle);

            WinApi.PostMessage((Int32)handle, (int)WinApi.ButtonControlMessages.BM_CLICK, 0, IntPtr.Zero);
        }
    }
}


Вспомогательный код:
namespace ConsoleFindWindows {
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    public static class WinApi {
        #region Delegates

        public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

        #endregion

        #region Enums

        public enum ButtonControlMessages : uint {
            BM_GETCHECK = 0x00F0,
            BM_SETCHECK = 0x00F1,
            BM_GETSTATE = 0x00F2,
            BM_SETSTATE = 0x00F3,
            BM_SETSTYLE = 0x00F4,
            BM_CLICK = 0x00F5,
            BM_GETIMAGE = 0x00F6,
            BM_SETIMAGE = 0x00F7
        }

        public enum GetWindow_Cmd : uint {
            GW_HWNDFIRST = 0,
            GW_HWNDLAST = 1,
            GW_HWNDNEXT = 2,
            GW_HWNDPREV = 3,
            GW_OWNER = 4,
            GW_CHILD = 5,
            GW_ENABLEDPOPUP = 6
        }

        public enum WindowsMessage : uint {
            WM_KEYDOWN = 256,
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205,
            WM_SETFOCUS = 0x0007,
            WM_ACTIVATE = 0x0006,
            WM_ENABLE = 0x000A
        }

        #endregion

        #region Public Methods

        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(
            IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        public static List<IntPtr> GetChildWindows(IntPtr parent) {
            var result = new List<IntPtr>();
            GCHandle listHandle = GCHandle.Alloc(result);
            try {
                EnumWindowProc childProc = EnumWindow;
                EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
            }
            finally {
                if (listHandle.IsAllocated) {
                    listHandle.Free();
                }
            }
            return result;
        }

        [DllImport("user32.dll", SetLastError = true)]
        public static extern int PostMessage(int hWnd, int msg, int wParam, IntPtr lParam);

        [DllImport("user32.dll")] //, CharSet = CharSet.Auto)]
        public static extern int SendMessage(int hWnd, UInt32 msg, Int32 wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern IntPtr SetFocus(IntPtr hWnd);

        [DllImport("user32.dll")]
        public static extern int SetForegroundWindow(IntPtr hWnd);

        #endregion

        #region Methods

        private static bool EnumWindow(IntPtr handle, IntPtr pointer) {
            GCHandle gch = GCHandle.FromIntPtr(pointer);
            var list = gch.Target as List<IntPtr>;
            if (list == null) {
                throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
            }
            list.Add(handle);
            //  You can modify this to check to see if you want to cancel the operation, then return a null here
            return true;
        }

        #endregion
    }
}


В чем может быть нюанс при отправке события о нажатии кнопки в "Удаленном помощнике"?
Re: Как нажатие на кнопку из .NET в хитром нативном окне?
От: Spinifex Россия https://architecture-cleaning.ru/
Дата: 08.07.11 09:48
Оценка:
Точно не скажу, но может нужно WM_LBUTTONDOWN отсылать?
Попробуйте послушать через утилиту Spy++ (входит в состав Visual Studio) какие сообщения приходят к кнопке и отошлите ей те же самые события.
Re: Как нажатие на кнопку из .NET в хитром нативном окне?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.07.11 10:05
Оценка:
Здравствуйте, StarLancer, Вы писали:

В свое время для КПК шника делал
http://rsdn.ru/forum/pda/2953653.aspx
Автор: Serginio1
Дата: 16.05.08


Попробуй нажатие через паузу. И поищи в гугле "Не срабатывает SendMessage кнопка"
Например http://www.delphisources.ru/forum/showthread.php?t=6815
и солнце б утром не вставало, когда бы не было меня
Re[2]: Как нажатие на кнопку из .NET в хитром нативном окне?
От: StarLancer  
Дата: 08.07.11 11:34
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, StarLancer, Вы писали:


S>В свое время для КПК шника делал

S>http://rsdn.ru/forum/pda/2953653.aspx
Автор: Serginio1
Дата: 16.05.08


S>Попробуй нажатие через паузу. И поищи в гугле "Не срабатывает SendMessage кнопка"

S>Например http://www.delphisources.ru/forum/showthread.php?t=6815


Пробывал по разному отправлять сообщения, и через KEYDOWN, KYEUP не доходит он в очередь и все....SPY++ не показывает.
В других программ работает а тут нет.....может влият отправка сообщений, если у родительского окна много дочерних окон, в котором и находится эта кнопка? Или должно быть побарабану, т.к. имею ее handle?

Ссылки посмотрю
Re[3]: Как нажатие на кнопку из .NET в хитром нативном окне?
От: StarLancer  
Дата: 08.07.11 11:54
Оценка:
Код заработал....НО только с АДМИНИСКИМИ ПРАВАМИ, отсюда соответсвенно вопрос, как проделать этот фокус из под пользователя?

ОСь Windows 7 x64....почему для нажатия это вшивой кнопки нужны админские права?
Если после вызова воспользоваться GetLastError, то под пользователем получаем код ошибки Access Denied....че за бред??
Re[4]: Как нажатие на кнопку из .NET в хитром нативном окне?
От: Аноним  
Дата: 11.07.11 04:36
Оценка: +2
Здравствуйте, StarLancer, Вы писали:

SL>ОСь Windows 7 x64....почему для нажатия это вшивой кнопки нужны админские права?


Потому что нельзя за пользователя делать то что он не просил...
Re[5]: Как нажатие на кнопку из .NET в хитром нативном окне?
От: Аноним  
Дата: 12.07.11 07:20
Оценка:
Делать вирус — делать плохо!
Microsoft о нас заботиться!
Re[6]: Как нажатие на кнопку из .NET в хитром нативном окне?
От: StarLancer  
Дата: 12.07.11 07:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Делать вирус — делать плохо!

А>Microsoft о нас заботиться!

Причем тут вирус?
Код хорошо, себя ведет при нажатии на кнопку в других приложения, и без проблем.
А тут такая засада..
Если microsoft сделала для доменов политику в которой не надо было дожидаться явного ответа от пользователя, так бы не извращался...сторонние ПО здесь не рассматриваются
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.