1 место PM+WinApi или управление окнами любых других приложений

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
Всем доброго дня! Сегодня я бы хотел раскрыть такую крутую тему как WinApi функции, благодаря которым мы можем творить с окнами других приложений все что душе угодно.

Самый главный инструмент, который нам понадобится- это SPY++(прикрепил) , он позволяет отслеживать какие сообщения отправляются окну приложения для совершения с ним того или иного действия, следовательно наша задача сводится к тому чтобы правильно сформировать сообщение и отправить его нужному окну.

Итак, начинаем исследование, в качестве подопытного я выбрал клиент Viber'a для ПК, сделаем с вами авторассыльщик по списку номеров, погнали:

Для работы с WinApi из языка С# я выделил для себя три основных источника:
а) Это конечно же всеми любимый https://msdn.microsoft.com - там можно получить инструктаж для любой апишной функции, а так же необходимые для них значения констант. Документация для С++

б) http://www.firststeps.ru - на этом сайте можно посмотреть русскоязычное описание всех основных функций. Документация тоже для С++

в) http://www.pinvoke.net - на этом сайте через поиск можно найти любую WinApi функцию именно для С#, что нам и нужно

Первое что нам нужно сделать это получить хендл (уникальный идентификатор) окна вайбера, за это отвечает функция FindWindow, идем на pinvoke и находим ее:

Код:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
Куда же ее вставлять? Все просто:



Так же необходимо добавить директиву, как на скрине (именно туда, а не во вкладку Директивы using):

Код:
using System.Runtime.InteropServices;
Еще заметьте что саму функцию FindWindow я сделал публичной, чтобы к ней можно было обращаться из экшена "Свой С# код".

Как мы видим данная функция на вход получает имя класс и имя заголовка окна, со вторым все понятно, он всегда написан в верхней шапке окна, а где же взять имя класса? На помощь приходит наш spy++, качаем, запускаем его:

Как вы наверно уже догадались, он нам показывает все текущие открытые окна для того чтобы мы могли посмотреть какие сообщения система отправляет этим окнам для совершения манипуляций с ними. В нем есть прекрасный поиск окон при помощи прицела (его нужно перетащить на окно, которое собираемся атаковать):




После того как наведете прицел на нужное окно и отпустите его, у вас заполнятся поля Handle(уникальный идентификатор), Caption(заголовок окна) и искомое имя Class'a - копируем его и идем обратно в PM, теперь можно уже протестировать как работает наша функция:

Создаем экшен своего С# кода и вставляем туда:

Код:
IntPtr hwnd = CommonCode.FindWindow("Qt5QWindowIcon", null);

return hwnd;
Как видите второй параметр я поставил null, т.к. он не обязателен, и нужен только в тех случаях, когда присутствуют окна с таким же именем класса. Так же в некоторых случаях можно не указывать имя класса, но указать заголовок окна.

Отправляем результат в какую нибудь переменную и смотрим:



Работает!! К сожалению, зенка преобразовывает наш IntPtr сразу в тип string и мы не можем посмотреть его value, где это число будет именно в формате IntPtr, тогда бы мы смогли по поиску в spy++ сразу найти это окно и убедиться верно ли мы нашли идентификатор.

Хендл нужного окна получили, дальше нужно отправить ему какое нибудь сообщение, чтобы с ним что то произошло, для этого снова идем в spy++, снова прицелом находим окно viber' a и в этот раз после поиска жмем ОК, щелкаем ПКМ по выделенной строке и выбираем Messages, после этого нас перекидывает в новое пустое окно spy++, НО стоит нам навести мышью на окно вайбера, как тут же мы увидим как сыпятся сообщения:



Теперь все зависит от поставленных перед вами задач. Если мы делаем рассыльщик по вайберу, то в цикле мы должны будет делать следующие действия:



По нашему плану, нам первым делом нужно нажать на иконку с шариками, чтобы была возможность набора номера, смотрим в spy++ что для этого действия отправляется окну вайбера:



Среди всяких сообщений о передвижении мыши и установкой курсора (их названия говорят сами за себя) можно увидеть нажатия кнопки мыши по координатам окна, значит нужно определенно отправить эти два сообщения, а еще по своему опыту я скажу что нужно отправить WM_MOUSEMOVE на эти же координаты, т.к. без него клик может не сработать, давайте разбираться как это делается. Во- первых, сообщения окнам отправляются двумя способами это при помощи функций SendMessage и PostMessage, разница между ними только в том что первая ожидает ответа от приложения и чисто теоретически если приложение вайбера повиснет в момент отправки сообщения, то наше приложение тоже зависнет в ожидании, вторая функция ничего не ожидает, но я все равно буду юзать SendMessage =)

Идем на pinvoke.nеt и ищем эту функцию, я нашел:

Код:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
Пихаем ее в общий код в нашем проекте, так же делаем ее публичной для доступа из экшена.

Смотрим что эта функция принимает на вход, это хендл окна, которому отправляем сообщение (его мы находили выше), само сообщение в типе Uint32 - эту константу найдем на msdn, wParam - что это такое вообще тоже узнаем на msdn , lParam аналогично. Вбиваем в поисковик название нашего сообщения (WM_LBUTTONDOWN), попадаем на msdn и видим:



Это есть наше сообщение в типе UInt32, сразу закидываем его в общий код, снова делая публичным, вот так:

Код:
public static UInt32 WM_LBUTTONDOWN = 0x0201;
Дальше видим, что описываются интересующие нас параметры wParam в нашем случае нужен вот такой:



Если вы посмотрите на сообщение в spy++ вы поймете почему =)
Аналогичным способом добавляем ее в общий код

Код:
public static UInt32 MK_LBUTTON = 0x0001;
А вот с lParam не все так просто, мсдн нам говорит что он должен содержать low-order - координата Y и high-order - координата X:

Эти low и high ордеры еще называют младшим и старшим словом, т.е. нам нужно из двух этих параметров получить один в типе IntPtr, для этого есть функция MakelParam, на пинвоке ее нету, но я ее нашел в интернетах, держите:

Код:
   public static IntPtr MakeLParam(int LoWord, int HiWord)
        {
            return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
        }
Снова пихаем ее в общий код:



Если кому интересно что в ней происходит, то вам сюда ТЫК

Не забываем про WM_MOUSEMOVE и его тоже цепляем в общий код проекта:

Код:
public static UInt32 WM_MOUSEMOVE = 0x0200;
Ну вот, все данные для отправки сообщения мы наскребли, можем формировать вызов функции в нашем экшене:

Код:
CommonCode.SendMessage(hwnd /*хендл нужного окна (вайбера)*/, CommonCode.WM_MOUSEMOVE /* сам код сообщения*/, IntPtr.Zero /*wParam, spy++ показал что он заполнен нулями*/, CommonCode.MakeLParam(238, 78) /* сформированный из координатов для клика lParam */ );


Код:
CommonCode.SendMessage(hwnd /*хендл нужного окна (вайбера)*/, CommonCode.WM_LBUTTONDOWN /* сам код сообщения*/, (IntPtr)CommonCode.MK_LBUTTON /*wParam, с явным приведением к  IntPtr*/, CommonCode.MakeLParam(238, 78) /* сформированный из координатов для клика lParam */ );


По идее уже сейчас если запустить наш проект, то в spy++ мы увидим, в каком виде пришло наше сообщение окну вайбера:



Замечательно, сообщение о передвижении мыши на координаты и нажатии ЛКМ по этим координатам вайбера успешно отправилось, да еще и в правильном виде!

Давайте теперь отправим сообщение о том что ЛКМ отпустили в этих же координатах, т.е. отправим WM_LBUTTONUP.

Снова на msdn находим значение этого сообщения и добавляем в общий код:



И формируем вызов функции:

Код:
CommonCode.SendMessage(hwnd /*опять же нужный идентификатор нашего окна */, CommonCode.WM_LBUTTONUP /* само значение сообщения */, IntPtr.Zero /* если внимательно посмотреть в spy++ на это сообщение, то видно что wParam там заполнен нулями, я так и сделал */, CommonCode.MakeLParam(238, 78) /* по старой схеме формируем lParam из координатов*/);


В теории сейчас должна успешно нажаться кнопка для набора номера в вайбере, даже в свернутом состоянии окна, проверяем:



У меня все прекрасно сработало, даже в свернутом вайбере!

Не отступаем от нашего плана и следующим пунктом у нас стоит ввод номера телефона, но надо понимать, что в не активном окне скорее всего при переходе на номеронабератель каретка не будет в нужном месте, давайте ее туда поставим обычным кликом по полю набора номера, точно так же как мы только что выбрали номеронабиратель:

Код:
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(177, 155));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(177, 155));
Тут практика показала, что можно обойтись без WM_MOUSEMOVE.

Отлично, теперь можно набирать текст, лезем в spy++ и смотрим что отправляется окну вайбера при нажатии любой циферки:



Я выделил самое подходящее для нас сообщение о нажатии клавиши, однако, в некоторых случаях его может и не быть, тогда вам нужно будет смотреть на сообщения WM_KEYDOWN и WM_KEYUP.

Так вот, это сообщение говорит окну о том что пользователь нажал какой либо символ, значит мы должны сделать так же, в путь:

Сгугливаем значение WM_CHAR и кидаем в общий код:

Код:
public static UInt32 WM_CHAR = 0x0102;
Читаем на мсдн, что wParam - это есть char код символа, а lParam расписан вот так:



Это означает что придется немного поиграться с побитовыми операциями, юхууу!

Из всего этого списка нам нужно только лишь сформировать верный scan code клавиши и выполнить сдвиг на 16 бит влево и запихать туда единичку, т.к. в spy++ сказано что cRepeat: 1 - это мы и сделаем, но для получения scan code воспользуемся функцией:

Код:
 [DllImport("user32.dll")]
public static extern uint MapVirtualKey(uint uCode, uint uMapType);
Которую тоже нужно положить в общий код. Если вы загуглите что это за функция, то поймете что по сути она возвращает scan code клавиши, получая на входе ее virtual code и тип преобразования.

Формируем сообщение для нажатия клавиши 5 например:

Код:
CommonCode.SendMessage(hwnd, CommonCode.WM_CHAR, (IntPtr)'5' /*явное преобразование char в IntPtr*/, (IntPtr)(CommonCode.MapVirtualKey('5', 0)<<16|1) /*это и есть получение scan code клавиши , выполнение сдвига влево на 16 бит и запихивание туда 1*/ );
Но нам же нужно набрать целый номер, поэтому будем печатать посимвольно из всей строки по циклу:
Код:
string number = "500092511";

for(int i=0; i< number.Length ;i++)
CommonCode.SendMessage(hwnd, CommonCode.WM_CHAR, (IntPtr)number[i], (IntPtr)(CommonCode.MapVirtualKey('6', 0)<<16|1));
Правильней конечно было бы написать функцию, которая на вход получает любой текст и набирает его в нашем окне вайбера, ну да ладно, так нагляднее, проверяем:



Как видно, все работает, сообщения шлются, текст набирается, прекрасно! Осталось пару штрихов =)

По уже знакомой нам методике жмем кнопку, при помощи сообщений о нажатии ЛКМ, меняем только координаты:

Код:
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEMOVE, IntPtr.Zero, CommonCode.MakeLParam(190,503));
CommonCode.SendMessage(hwnd,
CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(190,503));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(190,503));
Пробуем иии, не работает :(
Но мы же не отчаиваемся и смотрим в spy++, скорее всего что то пропустили:



Попалась! Не хватает WM_MOUSEACTIVATE, давайте попробуем его добавить:

Код:
public static UInt32 WM_MOUSEACTIVATE = 0x0021;
Это в общий код. Так же на мсдн находим значение переменное HTCLIENT и она равна 1, поэтому я ее добавлять не буду, а запишу прямо в формировании сообщения:

Код:
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEACTIVATE, hwnd /*по документации msdn сказано что wParam это родительское окно, в нашем случае же это главное окно, поэтому сюда снова передаем hwnd*/, CommonCode.MakeLParam(1 /*это наша HTCLIENT*/, (int)CommonCode.WM_LBUTTONDOWN )/*так формируется lParam согласно инструкциям*/);
Важно понимать порядок передачи сообщений, т.е. сначала мы наводим курсор (WM_MOUSEMOVE), дальше активируется элемент (WM_MOUSEACTIVATE) потом идет нажатие мышкой (WM_LBUTTONDOWN), в коде это выглядит так:

Код:
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEMOVE, IntPtr.Zero, CommonCode.MakeLParam(190,503));
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEACTIVATE, hwnd, CommonCode.MakeLParam(1, (int)CommonCode.WM_LBUTTONDOWN));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(190,503));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(190,503));
Следующий пункт - это ввод текста сообщения для рассылки, опять же не забываем поставить каретку в нужное место, но как? Если вы еще не заметили, то до этого момента, пока мы работали с левой панелькой вайбера, мы могли спокойно забирать координаты из spy++ и пользоваться ими, т.к. элементы на этой панельке не меняют свои координаты относительно всего окна, в отличии от поля, в которое нужно вводить текст сообщения, если мы возьмем для него координаты, а потом небрежный пользователь изменит размеры окна вайбера, то все сломается, нужно это как то учесть...

Решение очевидно, исходя из расчета что относительно нижней границы окна поле для ввода сообщения никогда не поменяет свое положение по оси Y, ну а по оси X значение можно подобрать таким, чтобы клик всегда попадал по этому полю. Значит нам нужно получать текущие размеры окна и из его высоты отнимать определенное число, которое нужно подобрать, поехали:

В общий код кидаем вот эти функции:

Код:
    [DllImport("user32.dll")]
        static extern bool GetWindowRect(IntPtr hWnd, out Rectangle lpRect);

        [StructLayout(LayoutKind.Sequential)]
        public struct Rectangle
        {
            public readonly int Left;
            public readonly int Top;
            public readonly int Right;
            public readonly int Bottom;
            public readonly int Height;
            public readonly int Width;

            public Rectangle(int width, int height) : this()
            {
                this.Height = height;
                this.Width = width;
            }
        }

        public static Rectangle GetWindowRectEx(IntPtr hWnd)
        {
            if (IntPtr.Zero == hWnd) return default(Rectangle);

            Rectangle lprect;
            GetWindowRect(hWnd, out lprect);
            return new Rectangle(lprect.Right - lprect.Left, lprect.Bottom - lprect.Top);
        }
В этой статье я уже не буду мучать вас понятиями структур и как они работаю, так что если интересно узнать как это работает, то гуглите или пишите.

Теперь мы можем получить в своем коде размеры окна, вызвав функцию GetWindowRectEx:

Код:
var rect =  CommonCode.GetWindowRectEx(hwnd);
Из этой переменной нас интересует только высота, она достигает максимального значения на нижней границе окна вайбера, значит мы должны из нее отнимать примерно 100, чтобы всегда попадать кликом на поле ввода текста, координата X будет примерно 570, именно при таком размере щелчек всегда будет попадать, вот что получается:

Код:
var rect =  CommonCode.GetWindowRectEx(hwnd);
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(570,rect.Height-100));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(570,rect.Height-100));
И теперь это работает с любым размером окна, нештяк! =)

Вводим наш текст по старой схеме:

Код:
string text = "Это добрый спам по вайберу! Никакой рекламы, только добро! Всем добра!";
for(int i=0; i< text.Length ;i++)
CommonCode.SendMessage(hwnd, CommonCode.WM_CHAR, (IntPtr)text[i], (IntPtr)(CommonCode.MapVirtualKey(text[i], 0)<<16|1));
Все работает на УРА! Остался последний шаг - отправить сообщение, но так просто кликнуть на стрелочку мы опять не можем потому что у него каждый раз могут быть разные координаты относительно всего окна, по оси Y можно опять таким же макаром высчитать, но вот по оси X не получится, благо есть отправка по нажатию кнопки ENTER, действуем:

Сразу скажу что сообщение WM_CHAR с кодом кнопки enter вайбер видимо не обрабатывает, поэтому будем отправлять сообщение WM_KEYDOWN

Опять кидаем его значение в общий код:
Код:
public static UInt32 WM_KEYDOWN = 0x0100;
Гуглим эту функцию и видим, что wParam у нас виртуальный код клавиши, забираем нужный нам в исходный код:

Код:
public static UInt32 VK_RETURN = 0x0D;
lParam опять стряпаем из битов, не проблема, сделано:

Код:
CommonCode.SendMessage(hwnd, CommonCode.WM_KEYDOWN, (IntPtr)CommonCode.VK_RETURN, (IntPtr)(CommonCode.MapVirtualKey(CommonCode.VK_RETURN, 0)<<16|1));
Все по аналогии с примером на WM_CHAR.

Хотел уже сказать что все готово, но не тут то было)) Оказывается поле для ввода номера не отчищается автоматически, поэтому придется после каждого нажатия на номеронабиратель отчищать это поле, последний рывок:

В виду того что вайбер не хочет принимать сообщения нажатий Ctrl+A (хотя я уверен что это можно сделать, просто я уже туплю) я принял брутальное решение, просто 100 раз отправлю нажатие Backspace :D:

Код:
for(int i=0; i<100; i++)
CommonCode.SendMessage(hwnd, CommonCode.WM_KEYDOWN, (IntPtr)CommonCode.VK_BACK, (IntPtr)(CommonCode.MapVirtualKey(CommonCode.VK_BACK, 0)<<16|1));
И чисто и быстро =)

Остается только все скомпоновать и можно запускать нашу адскую машинку, полный листинг сниппета:

Код:
IntPtr hwnd = CommonCode.FindWindow("Qt5QWindowIcon", null); // получаем хендл окна вайбера
var all_number = project.Lists["Номера для рассылки"];// лист, в котором лежат номера для рассылки

foreach(string a in all_number) // идем по циклу по всем номерам
{
    //клик мышкой по номеронаберателю
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEMOVE, IntPtr.Zero, CommonCode.MakeLParam(243,76));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(238, 78));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(238, 78));
    //

    //клик по полю ввода номера (установка каретки)
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(177, 155));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(177, 155));
//
   
    //супер кастыль для отчищения поля от остатков предыдущего номера
for(int i=0; i<100; i++)
CommonCode.SendMessage(hwnd, CommonCode.WM_KEYDOWN, (IntPtr)CommonCode.VK_BACK, (IntPtr)(CommonCode.MapVirtualKey(CommonCode.VK_BACK, 0)<<16|1));
//

// текущую итерацию цикла складываем в переменную number и посимвольно отправляем соответствующие нажатия в окно вайбера
string number = a;
for(int i=0; i< number.Length ;i++)
CommonCode.SendMessage(hwnd, CommonCode.WM_CHAR, (IntPtr)number[i], (IntPtr)(CommonCode.MapVirtualKey(number[i], 0)<<16|1));
//

// Клик по кнопке перехода в чат с номером
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEMOVE, IntPtr.Zero, CommonCode.MakeLParam(190,503));
CommonCode.SendMessage(hwnd, CommonCode.WM_MOUSEACTIVATE, hwnd, CommonCode.MakeLParam(1, (int)CommonCode.WM_LBUTTONDOWN));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(190,503));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(190,503));
//

// Пауза для того чтобы вайбер успел прорисовать элементы после перехода в чат
Thread.Sleep(1000);
//получаем текущий размер окна
var rect =  CommonCode.GetWindowRectEx(hwnd);
//кликаем по полю ввода сообщения с учетом размеров окна
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONDOWN, (IntPtr)CommonCode.MK_LBUTTON, CommonCode.MakeLParam(570,rect.Height-100));
CommonCode.SendMessage(hwnd, CommonCode.WM_LBUTTONUP, IntPtr.Zero, CommonCode.MakeLParam(570,rect.Height-100));
//

//текст, который будет рассылаться
string text = "Это добрый спам по вайберу! Никакой рекламы, только добро! Всем добра!";
//по циклу печатаем каждый символ текста в окно вайбера
for(int i=0; i< text.Length ;i++)
CommonCode.SendMessage(hwnd, CommonCode.WM_CHAR, (IntPtr)text[i], (IntPtr)(CommonCode.MapVirtualKey(text[i], 0)<<16|1));
CommonCode.SendMessage(hwnd, CommonCode.WM_KEYDOWN, (IntPtr)CommonCode.VK_RETURN, (IntPtr)(CommonCode.MapVirtualKey(CommonCode.VK_RETURN, 0)<<16|1));
}

return hwnd;

Демонстрация этого чуда


Вообще область применения таких функций довольно таки обширная, не забывайте про эмуляторы Android, которыми так же без проблем можно управлять из PM...


Если у кого то возникнут вопросы, то пишите на почту [email protected]

Всем спасибо за внимание, надеюсь вы все разберетесь в этом нелегком направлении! =)
 
Номер конкурса статей
Пятый конкурс статей

Вложения

Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

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

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 287
Благодарностей
3 427
Баллы
113
О! Это тема. Многие просят такое в функционале Зенно.
Хотя, как мне кажется, каким-нибудь AutoIt или MouseRobot все это можно сделать намного проще и быстрее.
 
Последнее редактирование:
  • Спасибо
Реакции: MORENO

AlisaZ

Client
Регистрация
17.09.2014
Сообщения
139
Благодарностей
156
Баллы
43
Это ТВОРЕНИЕ заслуживает пристального внимания - автор НОВАТОР - свежее принёс на форум - ЛАЙКАЮ
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
Это ТВОРЕНИЕ заслуживает пристального внимания - автор НОВАТОР - свежее принёс на форум - ЛАЙКАЮ
Очень приятно! Я на самом деле был удивлен, что данная тема еще не была разобрана на этом форуме =)
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
О! Это тема. Многие просят такое в функционале Зенно.
Хотя, как мне кажется, каким-нибудь AutoIt или MouseRobot все это можно сделать намного проще и быстрее.
Чем меньше оберток на пути к результату, тем быстрее и красивее работает решение =)
 
  • Спасибо
Реакции: Oleg_M и sergodjan66

S16er1um

Client
Регистрация
14.04.2016
Сообщения
826
Благодарностей
239
Баллы
43
Просто круть. Реально возможности этого гайда безграничны)
 

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 287
Благодарностей
3 427
Баллы
113
Чем меньше оберток на пути к результату, тем быстрее и красивее работает решение =)
Хорошо сказано) Только оберток меньше именно в AutoIt.
Это не умаляет достоинств статьи. Методика хоть и сложная, но может использоваться во многих кейсах.
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
Просто круть. Реально возможности этого гайда безграничны)
Но это лишь малая часть базовой информации, для разных приложений понадобятся новые функции/ сообщения
 

burhanov88

Client
Регистрация
08.04.2015
Сообщения
67
Благодарностей
18
Баллы
8
Сильная заявка на победу). Аплодисменты)
 
  • Спасибо
Реакции: Gfoblin
Регистрация
08.07.2015
Сообщения
2 851
Благодарностей
708
Баллы
113
О! Это тема. Многие просят такое в функционале Зенно.
Хотя, как мне кажется, каким-нибудь AutoIt или MouseRobot все это можно сделать намного проще и быстрее.
Я так и делаю! Работаю в связке зенка+MouseRobot !
ТС молодеТС тема норм но для меня проще через MouseRobot. В С+ вообще тупой Я!
 
  • Спасибо
Реакции: MORENO

execut0r

Client
Регистрация
12.03.2014
Сообщения
254
Благодарностей
261
Баллы
63
Красота! Будет чем теперь заняться! =)
 

alex_shv

Client
Регистрация
31.03.2015
Сообщения
49
Благодарностей
20
Баллы
8
Революционно, однако...
Супер-комбайн получается!
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
508
Благодарностей
778
Баллы
93
Отличная статья.
Возможности применения реально безграничны.
Конечно попотеть придется работая со spy++, и не каждый осилит.
Но таким способом можно настроить взаимодействие с любой прогой, если других вариантов нет и очень надо.:-)
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
Отличная статья.
Возможности применения реально безграничны.
Конечно попотеть придется работая со spy++, и не каждый осилит.
Но таким способом можно настроить взаимодействие с любой прогой, если других вариантов нет и очень надо.:-)

Это не так сложно как кажется, просто нужно собраться с мыслями и действовать =)
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
508
Благодарностей
778
Баллы
93
Это не так сложно как кажется, просто нужно собраться с мыслями и действовать =)
Да для меня то это не сложно.))

Но на форуме есть люди, познания которых в кодинге заканчиваются тем, что скопировать откуда то кусок кода и чутка подредактировать под себя.
Тут же не форум программистов.
Все покупают зенку для автоматизации своих задач без кодинга - это основное направление.
Это уже потом, дальше, по мере освоения, приходит понимание, что какие то действия проще в коде написать.

А если использовать твой мануал, надо гуглить, читать msdn, ковыряться в WinApi функциях, тестить, пробовать.
В общем мозг нагружает основательно.:D

Конечно дорогу осилит идущий и нет ничего невозможного, было бы желание.;-)
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
Да для меня то это не сложно.))

Но на форуме есть люди, познания которых в кодинге заканчиваются тем, что скопировать откуда то кусок кода и чутка подредактировать под себя.
Тут же не форум программистов.
Все покупают зенку для автоматизации своих задач без кодинга - это основное направление.
Это уже потом, дальше, по мере освоения, приходит понимание, что какие то действия проще в коде написать.

А если использовать твой мануал, надо гуглить, читать msdn, ковыряться в WinApi функциях, тестить, пробовать.
В общем мозг нагружает основательно.:D

Конечно дорогу осилит идущий и нет ничего невозможного, было бы желание.;-)
Но в итоге игра будет стоить свеч :-)
 

7make

Moderator
Регистрация
25.06.2011
Сообщения
1 519
Благодарностей
1 253
Баллы
113
Статья не понятная как для меня.
Не понятна связь зенно +решения выше.
Библиотеки зенно не задействованы, с браузером не работаем....

С такми успехом можно было написать еще две функции , взять тел и текст из файла и оформить нейтив приложение
Сомнительна целесообразность использования кубика C# как IDE , когда экосистема кубика никак не задействована )

За кейс 5-, разобрался с хендлами, дескрипторами...
За выбор среды исполнения кода 2)

п.с. забыл закрыть хендл что не айс для винды, все что поломал, верни обратно)
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
Статья не понятная как для меня.
Не понятна связь зенно +решения выше.
Библиотеки зенно не задействованы, с браузером не работаем....

С такми успехом можно было написать еще две функции , взять тел и текст из файла и оформить нейтив приложение
Сомнительна целесообразность использования кубика C# как IDE , когда экосистема кубика никак не задействована )

За кейс 5-, разобрался с хендлами, дескрипторами...
За выбор среды исполнения кода 2)

п.с. забыл закрыть хендл что не айс для винды, все что поломал, верни обратно)
По поводу закрытия учтем)
С IDE понятно что все это должно делаться в вижаке на нормальном десктоп приложении, но конкурс проводит зенка и поэтому хотелось показать новые не открытые ее возможности
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
508
Благодарностей
778
Баллы
93
Статья не понятная как для меня.
Не понятна связь зенно +решения выше.
думаю для другой задачи можно будет связать и библиотеки и броузер
Могу даже предложить вариант где такое может пригодится.
К примеру есть сайты, где идет двух факторная аутентификация.
Надо вбить логин/пасс + пароль из мобильного приложения.
И под этот сайт надо бота. Как быть?
Если например портировали это приложение под винду на C# или сделали какой то аналог, то хорошо.
Можно покопаться в исходниках(если есть, или декомпильнуть), и вытащить что надо, перекинув в шаблон.
А если такой возможности нет, только через какой нибудь левый эмулятор. Или влом ковыряться в исходниках.
То тогда такой способ вполне подходит.
 

7make

Moderator
Регистрация
25.06.2011
Сообщения
1 519
Благодарностей
1 253
Баллы
113
Могу даже предложить вариант где такое может пригодится.
К примеру есть сайты, где идет двух факторная аутентификация.
...
С этим еще проще чем с хендлами))))
G=>rfc 6238 + c#

 
Последнее редактирование:

samsonnn

Client
Регистрация
02.06.2015
Сообщения
1 339
Благодарностей
989
Баллы
113
голосую за эту тему=) Автору респект и уважуха, и первго места в конкурсе=)
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
508
Благодарностей
778
Баллы
93
С этим еще проще чем с хендлами))))
G=>rfc 6238 + c#
Прикольно.))
Погуглил что за либы юзаются по using - ам.
В общем концепция понятна.
Не понятно как на винт попадат qr-код.
Ну как бы догадки есть, но это догадки.))

И еще название шаба интересное - 2StepAuthExample.))
Это спецом шаб сделал чтобы видос записать?
 

Serkser

Client
Регистрация
26.01.2015
Сообщения
90
Благодарностей
336
Баллы
53
голосую за эту тему=) Автору респект и уважуха, и первго места в конкурсе=)
Будет 1 место - будут новые статьи с еще большими возможностями зенки, материала за время фриланса накопилось огромное кол- во )))
 
  • Спасибо
Реакции: samsonnn и Gfoblin

Roman*

Client
Регистрация
25.09.2013
Сообщения
1 532
Благодарностей
567
Баллы
113
Работа, видно, проведена нехилая, спасибо за статью..сложно для обычного юзера, но главное маневры.
 
  • Спасибо
Реакции: Gfoblin и Serkser

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)