Сейчас многие пользуются услугами онлайн банков чтобы воспользоватся этой услугой нужно просто зайти по нужной ссылке на сайт в нужных полях прописать логин и пароль и нажать ввод Подобные действия хоть и немного но всё равно отнимают определённое время Сейчас конечно существуют мобильные приложения установленные на телефоне которые смогут сделать подобную операцию в автоматическом режиме Но всё же некоторые в том числе и я пользуются услугами онлайн банков по старинке Я решил хоть не много автоматизировать этот процесс авторизации Синтаксис проекта это Ассемблер на макросах (masm32+) но интуитивно я думаю здесь всё будет понятно Код (ASM): ;--------------------------------------------------------------------- lib shell32 ;-------------------------------------------- global Login "Login" global Password "Password" global Url "https://online.sberbank.ru" ;-------------------------------------------- fun ShellExecute,0,"open","iexplore",&Url,0,SW_MAXIMIZE new 1024,Buffer1 fun lstrcpy,Buffer1,&Login new 1024,Buffer2 fun lstrcpy,Buffer2,&Password fun FunWrite ;-------------------------------------------- Exit ;--------------------------------------------------------------------- Fun FunWrite ;--------------------------------------------------------------------- fun Sleep,1000 mov eax,0 ;------------------------- while eax < 2 fun Sleep,10 fun GetAsyncKeyState,VK_LBUTTON endw ;------------------------- fun Sleep,100 fun OpenClipboard,0 fun EmptyClipboard fun SetClipboardData,CF_TEXT,Buffer1 fun CloseClipboard fun keybd_event,VK_CONTROL,0,0,0 fun keybd_event,VK_V,0,0,0 fun keybd_event,VK_CONTROL,0,KEYEVENTF_KEYUP,0 fun keybd_event,VK_V,0,KEYEVENTF_KEYUP,0 ;------------------------- fun Sleep,100 fun keybd_event,VK_TAB,0,0,0 fun keybd_event,VK_TAB,0,KEYEVENTF_KEYUP,0 fun Sleep,100 ;------------------------- fun OpenClipboard,0 fun EmptyClipboard fun SetClipboardData,CF_TEXT,Buffer2 fun CloseClipboard fun keybd_event,VK_CONTROL,0,0,0 fun keybd_event,VK_V,0,0,0 fun keybd_event,VK_CONTROL,0,KEYEVENTF_KEYUP,0 fun keybd_event,VK_V,0,KEYEVENTF_KEYUP,0 ;------------------------- fun Sleep,100 fun keybd_event,VK_RETURN,0,0,0 fun keybd_event,VK_RETURN,0,KEYEVENTF_KEYUP,0 ;------------------------- fun Sleep,100 fun OpenClipboard,0 fun EmptyClipboard fun CloseClipboard ;--------------------------------------------------------------------- End ;--------------------------------------------------------------------- End В глобальных переменных надо прописать нужные логин и пароль а также адрес страницы онлайн банка и после компиляции будет испольняемый файл который немного поможет избежать рутины авторизации Я конечно не могу поручится что эта фишка будет работать у всех но у меня она пока вроде бы работает Программа конечно не идеальная потому что нужно будет соблюсти одну условность Алгоритм работы исполняемого файла такой: Функция ShellExecute запускает браузер InternetExplorer а тот в свою очередь будет открывать страницу онлайн банка но так как отрытие страницы будет не быстрым всё зависит от того загружен InternetExplorer в оперативную память или нет вот тут то и нужно соблюсти одну условность а именно до открытия страницы не пользоватся левой кнопкой мышки но как только страница загрузится нужно в поле ввода логина (именно в поле логина) щёлкнуть левой кнопкой мышки и больше ничего не делать программа сама заполнит нужные поля и сама активирует ввод на этом программа закончит свою работу а вам нужно будет только дождатся когда откроется окно для ввода пароля который придёт вам на телефон Если щёлкнуть левой кнопкой мышки в другом месте то ничего страшного не произойдёт просто программа отработает в пустую а именно данные из буфера обмена не попадут в нужное место вот и всё например если вы видите что страница долго заружается нужно просто закрыть браузер и запустить исполняемый файл заново это не баг программы это скорее всего браузер запутался в протоколах данной сессии открытия веб страницы И так ещё раз про алгоритм программы так как функция ShellExecute будет работать асинхронно код после неё будет отрабатыватся сразу же а именно создадутся два динамических буфера для работы с буфером обмена так как буфер обмена не хочет работать просто с глобальной памятью сегмента данных в эти буфера при помощи функции lstrcpy поместятся логин и пароль и начнёт работать пользовательская функция - FunWrite В функции сначала отработает секундная задержка а потом заработает цикл отслеживания этот цикл будет работать до тех пор пока функция - GetAsyncKeyState не зафиксирует в системе действие с левой кнопкой мышки как только это произойдёт алгоритм выйдет из цикла и с определёнными задержками отработают пять этапов ------------------------------------------- 1 - в буфер обмена загрузится логин программно нажмутся и отпустятся кнопки - Ctrl + V имитируя вставку из буфера обмена ------------------------------------------- 2 - программно нажмётся и отпустится кнопка - Tab тем самым на веб странице активирутся следующее окошко то есть окошко для ввода пароля ------------------------------------------- 3 - в буфер обмена загрузится пароль программно нажмутся и отпустятся кнопки - Ctrl + V имитируя вставку из буфера обмена ------------------------------------------- 4 - программно нажмётся и отпустится кнопка - Enter тем самым браузер отправит данные на сервер ------------------------------------------- 5 - буфер обмена на всякий случай очищаем от наших данных ------------------------------------------- На этом программа заканчивает свою работу ------------------------------------------- Программа намеренно открывается на весь экран для того чтобы пользователь не смог случайно кликнуть левой кнопкой мышки на других приложениях как только вы кликнули мышкой то можно размеры окна уже устанавливать любые вам удобные для работы в окне К тоже если в функции не прописать параметр - SW_MAXIMIZE то браузер откроется по умолчанию с теми размерами и в том месте где он был активным в последний раз к тому же существует ничтожная вероятность того что в последний раз браузер был активным с небольшими размерами окна и соответственно он и откроется с теми же размерами в которых может не поместится поле ввода логина конечно это ерунда и можно просто расширить браузер но тогда алгоритм программы отработает в пустую и нужно будет закрыть браузер и запустить программу ещё раз или просто запустить программу ещё раз открыв тем самым ещё одно окно браузера Например можно ли программно открыть браузер InternetExplorer с нужными размерами и например в нужном месте даже если для этого нужен будет батник Кто в курсе подскажите пожалуйста как это сделать программно А может кто нибудь даст дельные советы по алгоритму программы в плане того что это можно сделать получше Да вот ещё что попробывал закрыть на выходе два динамических буфера так программа при работе на выходе стала выдавать ошибку честно говоря меня это удивило так и пришлось оставить динамические буфера не закрытыми надеюсь это не страшно и при закрытии программы на системе это не скажется
Ну кроме того, что IE уже безбожно устарел и для этого бы лучше использовать хотя бы Edge. Вообще через COM же доступен InternetExplorer.Application, который можно легко заскриптовать через интерфейс IDispatch. Ну и да, есть же Selenium, открывать окно IE и посылать ему нажатия клавиш - это как чесать правое ухо левой рукой через голову. Имхо канеш.
Я сам не пользуюсь InternetExplorer (как наверное и многие другие) и по поводу того что он устарел я соответственно даже не знаю смею только предположить что скорее всего да чем нет наверное это потому что в нём нет каких нибудь навороченных плагинов которые несомненно в определённых моментах помогают пользователям Но обычный серфинг на онлайн банк я думаю он сделает не хуже других А вот по поводу COM это конечно интересная тема для обсуждения Я сам изначально сделал открытие InternetExplorer через COM в нём даже можно указать место и размеры открываемого окна Код (ASM): ;-------------------------------------------- global Web IWebBrowser2 global Url u"https://online.sberbank.ru" global CLSID_InternetExplorer g"0002DF01-0000-0000-C000-000000000046" global IID_IWebBrowser2 g"D30C1661-CDAF-11D0-8A3E-00C04FC9E26E" ;-------------------------------------------- new 1024,Buffer1 fun lstrcpy,Buffer1,&Login ;-------------------------------------------- new 1024,Buffer2 fun lstrcpy,Buffer2,&Password ;-------------------------------------------- fun OleInitialize,0 fun CoCreateInstance,&CLSID_InternetExplorer,0,CLSCTX_LOCAL_SERVER,&IID_IWebBrowser2,&Web fun Web.put_Visible,VARIANT_TRUE fun Web.Navigate,&Url,0,0,0,0 ;-------------------------------------------- fun Web.put_Left,0 fun Web.put_Top,0 fun Web.put_Width,1000 fun Web.put_Height,800 fun Web.Release fun OleUninitialize ;-------------------------------------------- Но у подобной реализации есть один минус Открываемое окно имеет маленький приоритет и если в данный момент на месте предпологаемого открытия окна развёрнуто другое приложение то InternetExplorer откроется под ним что в данном случае не приемлемо Хотя может быть я что то не так сделал или не доделал подскажите пожалуйста
В MSDN написано, что у IWebBrowser2, а точнее у IWebBrowserApp, от которого первый наследуется, есть свойство HWND, что, логично предположить, является идентификатором его окна. Попробуй этот hwnd попихать во всякие функции типа SetForegroundWindow, SetWindowPos(... HWND_TOPMOST ...) и тд.
Большое спасибо Rel за подсказку Век живи век учись Функция - SetForegroundWindow тоже отлично отрабатывает но я думаю применение функции - SetWindowPos будет гораздо лучше Теперь не нужно определять через интерфейс положение и размеры а можно просто через интерфейс взять хендл окна и прописать эти параметры плюс z-последовательность окна через функцию - SetWindowPos Код (ASM): fun Web.get_HWND,&hWnd fun SetWindowPos,hWnd,HWND_TOPMOST,0,0,1200,800,SWP_SHOWWINDOW Параметр - HWND_TOPMOST конечно самый крутой но для этой реализации я думаю будет самое то В конце первого поста я писал что попробывал закрыть на выходе два динамических буфера но программа на выходе стала выдавать ошибку так и пришлось оставить динамические буфера не закрытыми Не в курсе почему так происходит что система или конкретно буфер обмена не хотят закрытия выделенной динамической области
Эмм, ты про Buffer1 и Buffer2? Ну давай начнем с того, для чего они тебе нужны в принципе, почему не достаточно их держать в секции константных данных? Потом продолжим тем, что не особо понятно, что делает макрос new конкретно? И потом еще нужно посмотреть, как ты ее освобождаешь и какая ошибка происходит? Ну и весь код, который приводит к ошибке тоже не помешает привести.
Я бы рад был бы прописать логин и пароль в глобальном сегменте данных я об этом уже писал в первом посте но буфер обмена почему то не хочет работать с этим сегментом я сам удивлён но ему подавай именно динамическую память А макрос - new 1024,Buffer1 под капотом прописывает банальное выделение памяти из кучи Код (ASM): .data? Buffer1 dd ? .code push 1024 push 0 push hHeap call HeapAlloc mov Buffer1,eax и если я пропишу в конце макрос - delete Buffer1 под капотом пропишется Код (ASM): push Buffer1 push 0 push hHeap call HeapFree программа отработает нормально просто на выходе выдаст ошибку Код исключения: c0000374 Смещение исключения: 000ce753 Я попробывал выделить память функцией - LocalAlloc с разными флагами программа работает без проблем но как только я прописывал в конце вроде бы логичное закрытие функцией - LocalFree то ещё раз повторюсь программа выполняла свою функцию но в конце вылетала точно такая же ошибка
c0000374 - это heap corruption же? Откуда в этих макросах берется hHeap? Exit что делает (ExitProcess(0) или что-то другое)? --- Сообщение объединено, 11 авг 2020 --- Ну разобраться в проблеме надо, но чисто технически в данном контексте тебе освобождать память на куче не обязательно, процесс завершится и уже как бы до этих 2048 байт на куче никакого дела нет. Вон dmd компилятор намеренно старается не освобождать память, чтобы не тратить на это время, тк обычно 2гб памяти вполне хватает, чтобы и так скомпилить подавляющее большинство программ. --- Сообщение объединено, 11 авг 2020 --- А, я похоже нашел проблему:
У меня в проектах под капотом в начале кода всегда прописывается Код (ASM): .data? hInstance dd ? hHeap dd ? .code call GetModuleHandleA mov hInstance,eax call GetProcessHeap mov hHeap,eax Отсюда и берётся это значение - hHeap а под капотом макроса - Exit банальное завершение Код (ASM): push 0 call ExitProcess Прочитав вольный перевод я так понял что после вставки в буфер обмена система владеет объектом Вот по этому мне и не удалось сделать одну память сначала использовать её для логина а потом для пароля по этому и пришлось делать два объекта памяти и наверное по этому системе не пондравилось когда попытались закрыть то чем владеет она Может и есть какой нибудь способ забрать этот объект у системы Интересно было бы узнать как но наверное в данном случае эта реализация (овчинка выделки будет не стоить)
Так а зачем тебе ее забирать, если система должна гарантировать, что она сама освободит эту память, когда посчитает нужным?