Модификация браузера от Mozilla в C#
Если в своих проектах на C# вы используете браузер, основанный на движке от Mozilla Gecko, то вы наверняка заметили что его стандартные возможности, желают оставлять лучшего. Имеется в виду, что если вы используете чистую, а не модифицированную библиотеку Skybound.GeckoFX. Конечно следует выразить благодарность разработчикам этого движка и этой библиотеки. Ведь лучше иметь немного, чем не иметь ничего. Но на этой библиотеке далеко не “уедешь” (хотя смотря у кого какие цели). Потому что она имеет самый минимально необходимый функционал. Но ее можно расширить до колоссального перечня различных возможностей. Если вы хотите управлять программно некоторыми операциями, то необходимо объявить необходимые интерфейсы и описать реализацию нужных вам методов. В этой статье я продемонстрирую, как расширить функциональные особенности библиотеки Skybound.GeckoFX.
Помните, что после каждой модификации библиотеки, необходимо в вашем проекте заменять ссылку, на новую пересобранную версию.
Удаление cookie
Возможность удаления cookie, является одной из самых необходимых особенностей браузера. Для того чтобы иметь возможность удалять cookie в разрабатываемом браузере, необходимо в модуль nsInterfaces.cs, добавить описание следующего интерфейса:
[Guid("AAAB6710-0F2C-11d5-A53B-0010A401EB10"), ComImport, InterfaceType( ComInterfaceType.InterfaceIsIUnknown)] interface nsICookieManager { void RemoveAll(); nsISimpleEnumerator Enumerator(); void Remove(AUTF8String aDomain, nsACString aName, AUTF8String aPath, bool aBlocked); }
Интерфейс имеет два метода по работе с cookie: RemoveAll и Remove. Мы реализуем метод по удалению всех cookie сразу, для этого нам необходимо описать реализацию метода RemoveAll. Описание методов по реализации дополнительных возможностей я предлагаю выносить в модуль GeckoWebBrowser.cs. Сейчас добавьте в модуль следующий код:
public void DeleteCookie() { nsICookieManager CookieMan; CookieMan = Xpcom.GetService("@mozilla.org/cookiemanager;1"); CookieMan = Xpcom.QueryInterface(CookieMan); CookieMan.RemoveAll(); }
Теперь в вашем проекте, при необходимости удаления cookie, вы должны вызывать метод компонента GeckoWebBrowser – DeleteCookie().
geckoWebBrowser.DeleteCookie();
Настройка прокси-сервера
Также не менее важной особенностью браузера является возможность работы через прокси-сервер. Настроить использование прокси-сервера просто. Но если понадобиться сделать и автоматическую авторизацию, то здесь необходимо уже применить смекалку. Сначала необходимо указать стандартные настройки (хост и порт) прокси-сервера. Для этого нужно добавить в проект следующий код:
Указываем, что мы настраиваем прокси-сервер вручную:
GeckoPreferences.User["network.proxy.type"] = 1;
Указываем используемый нами хост:
GeckoPreferences.User["network.proxy.http"] = "88.78.4.77";
Ну и соответственно номер порта:
GeckoPreferences.User["network.proxy.http_port"] = 80;
Если для прокси-сервера указание хоста и порта не является достаточным и он требует авторизацию по логину и паролю, то здесь ситуация меняется не в лучшую для нас с вами сторону. Потому что без явного указания логина и пароля, нас будет ждать разочарование в виде появляющегося такого диалогового окна с предложением введения логина и пароля.
Для того чтобы указать недостающие настройки в самом проекте, а не вводить каждый раз логин и пароль вручную, придется вновь внести изменения в библиотеку. Поскольку стандартные возможности для указания логина и пароля в коде проекта, у самой этой библиотеки отсутствуют. К счастью, не все так печально как может показаться на первый взгляд. Здесь даже нет необходимости объявлять новый интерфейс. Все, что необходимо сделать, это открыть модуль PromptService.cs. Найти в нем метод PromptAuth и заменить его на ниже приведенный код:
public bool PromptAuth(nsIDOMWindow aParent, IntPtr aChannel, int level, nsIAuthInformation authInfo, string checkboxLabel, IntPtr aCheckValue) { Object login = GeckoPreferences.User["network.proxy.login"]; Object password = GeckoPreferences.User["network.proxy.password"]; if (login != null) nsString.Set(authInfo.SetUsername, login.ToString()); if (password != null) nsString.Set(authInfo.SetPassword, password.ToString()); return true; }
Далее в коде проекта, в нужном вам месте необходимо добавить следующие две строки:
GeckoPreferences.User["network.proxy.login"] = "login"; GeckoPreferences.User["network.proxy.password"] = "password";
Все, теперь браузер будет корректно проходить авторизацию, если в этом конечно будет необходимость.
Эмуляция событий
Эмулировать события от мыши или клавиатуры так же является одной из самых важных необходимостей браузера. Особенно сейчас, когда многое количество различного рода защит реализованных с помощью JavaScript (от накрутки, спама и т.д.) требуют некого действия пользователя. То кликнуть мышью, то подвести курсор и так далее в этом же стиле. Вот здесь собственно и возникает необходимость в эмуляции некого рода действий пользователя. Для того чтобы получить возможность эмулировать события в нашем проекте, нам потребуется снова в модуль nsInterfaces.cs, добавить следующие интерфейсы:
[Guid("1acdb2ba-1dd2-11b2-95bc-9542495d2569"), ComImport, InterfaceType( ComInterfaceType.InterfaceIsIUnknown)] internal interface nsIDOMDocumentView { nsIDOMAbstractView GetDefaultView(); } [Guid("f51ebade-8b1a-11d3-aae7-0010830123b4"), ComImport, InterfaceType( ComInterfaceType.InterfaceIsIUnknown)] interface nsIDOMAbstractView { nsIDOMDocumentView GetDocument(); } [Guid("46b91d66-28e2-11d4-ab1e-0010830123b4"), ComImport, InterfaceType( ComInterfaceType.InterfaceIsIUnknown)] interface nsIDOMDocumentEvent { nsIDOMEvent CreateEvent(nsAString eventType); } [Guid("028e0e6e-8b01-11d3-aae7-0010838a3123"), ComImport, InterfaceType( ComInterfaceType.InterfaceIsIUnknown)] interface nsIDOMKeyEvent : nsIDOMUIEvent { // nsIDOMEvent: new void GetType(nsAString aType); new nsIDOMEventTarget GetTarget(); new nsIDOMEventTarget GetCurrentTarget(); new ushort GetEventPhase(); new bool GetBubbles(); new bool GetCancelable(); new IntPtr GetTimeStamp(); // DOMTimeStamp new void StopPropagation(); new void PreventDefault(); new void InitEvent(nsACString eventTypeArg, bool canBubbleArg, bool cancelableArg); // nsIDOMUIEvent: new IntPtr GetView(); // nsIDOMAbstractView new int GetDetail(); new void InitUIEvent(nsAString typeArg, bool canBubbleArg, bool cancelableArg, nsIDOMAbstractView viewArg, int detailArg); // nsIDOMKeyEvent: uint GetCharCode(); uint GetKeyCode(); bool GetAltKey(); bool GetCtrlKey(); bool GetShiftKey(); bool GetMetaKey(); void InitKeyEvent(nsAString typeArg, bool canBubbleArg, bool cancelableArg, nsIDOMAbstractView viewArg, bool ctrlKeyArg, bool altKeyArg, bool shiftKeyArg, bool metaKeyArg, uint keyCodeArg, uint charCodeArg); } [Guid("ff751edc-8b02-aae7-0010-8301838a3123"), ComImport, InterfaceType( ComInterfaceType.InterfaceIsIUnknown)] interface nsIDOMMouseEvent : nsIDOMUIEvent { // nsIDOMEvent: new void GetType(nsAString aType); new nsIDOMEventTarget GetTarget(); new nsIDOMEventTarget GetCurrentTarget(); new ushort GetEventPhase(); new bool GetBubbles(); new bool GetCancelable(); new UInt64 GetTimeStamp(); // DOMTimeStamp new void StopPropagation(); new void PreventDefault(); new void InitEvent(nsACString eventTypeArg, bool canBubbleArg, bool cancelableArg); // nsIDOMUIEvent: new IntPtr GetView(); // nsIDOMAbstractView new int GetDetail(); new void InitUIEvent(nsAString typeArg, bool canBubbleArg, bool cancelableArg, nsIDOMAbstractView viewArg, int detailArg); // nsIDOMMouseEvent: int GetScreenX(); int GetScreenY(); int GetClientX(); int GetClientY(); bool GetCtrlKey(); bool GetShiftKey(); bool GetAltKey(); int GetMetaKey(); ushort GetButton(); nsIDOMEventTarget GetRelatedTarget(); void InitMouseEvent(nsAString typeArg, bool canBubbleArg, bool cancelableArg, nsIDOMAbstractView viewArg, int detailArg, int screenXArg, int screenYArg, int clientXArg, int clientYArg, bool ctrlKeyArg, bool altKeyArg, bool shiftKeyArg, bool metaKeyArg, ushort buttonArg, nsIDOMEventTarget relatedTargetArg); }
После того как мы добавили недостающие нам интерфейсы, необходимо в уже знакомый нам модуль GeckoWebBrowser.cs добавить два метода для реализации эмуляции события от мыши и клавиатуры:
public void EmulationMouseEvent(GeckoElement Element, string ATypeEvent, int screenX, int screenY, int clientX, int clientY) { nsIDOMEventTarget Target = Xpcom.QueryInterface<nsIDOMEventTarget> (Element.DomObject); nsIDOMEvent evt = ((nsIDOMDocumentEvent)this.Document.DomObject ).CreateEvent(new nsAString("MouseEvents")); nsIDOMMouseEvent MouseEvent = (nsIDOMMouseEvent)evt; nsIDOMAbstractView Window = Xpcom.QueryInterface<nsIDOMAbstractView> (this.Window.DomWindow); nsAString TypeEvent = new nsAString(ATypeEvent); MouseEvent.InitMouseEvent(TypeEvent, true, true, Window, 0, screenX, screenY, clientX, clientY, false, false, false, false, 0, null); Target.DispatchEvent(MouseEvent); TypeEvent.Dispose(); } public void EmulationKeyboardEvent(GeckoElement Element, string ATypeEvent, uint KeyCode) { nsIDOMEventTarget Target = Xpcom.QueryInterface<nsIDOMEventTarget> (Element.DomObject); nsIDOMEvent evt = ((nsIDOMDocumentEvent)this.Document.DomObject ).CreateEvent(new nsAString("KeyboardEvent")); nsIDOMKeyEvent Keyboard = (nsIDOMKeyEvent)evt; nsIDOMAbstractView Window = Xpcom.QueryInterface<nsIDOMAbstractView> (this.Window.DomWindow); nsAString TypeEvent = new nsAString(ATypeEvent); Keyboard.InitKeyEvent(TypeEvent, true, true, Window, false, false, false, false, KeyCode, 0); Target.DispatchEvent(Keyboard); TypeEvent.Dispose(); }
Сейчас у нас все готово и необходимо перекомпилировать библиотеку, а затем ее будет можно подключать к проекту. В качестве примера эмуляции клика рассмотрим следующий код:
geckoWebBrowser.EmulationMouseEvent(element, "click", 0, 0, 0, 0);
В результате выполнения этого кода сгенерируется событие “onclick”, для некого элемента в координатах left = 0, top = 0, width = 0 и height = 0.
Vlad
18.04.2014 @ 11:08 пп
Hello,
I do not know russian, but maybe you can help me (please).
How can I implement the PromptAuth method? Can I do this WITHOUT rebuilding the entire geckofx source? I mean can I do it by simply adding the required .dll files + adding this piece of code like an extension?
Please let me know how I can implement this, I have been looking for a solution for over 1 month, and you are the first one where I seen it.
Thanks!
Vlad
admin
30.04.2014 @ 1:00 дп
Hello!
Do you want have automatic proxy authorization or no?
Кирил
05.08.2014 @ 7:30 пп
Помогите как добавить интерфейсы nsInterfaces.cs и GeckoWebBrowser.cs. а то я не шарю помогите тормозу.
admin
05.08.2014 @ 8:37 пп
Добрый день!
Интерфейс «nsInterfaces» уже присутствует и его добавлять никуда не надо. Что вы хотите?
Кирил
06.08.2014 @ 12:04 дп
Доброе время суток!
Спасибо вам что откликнулись. Я так понял dll-ка Skybound.Gecko.dll включает в себя эти интерфейсы то есть чтобы добавить удаление cookie
мне нужно исходники этой dll-ки и вставить фрагмент
кода приведенный выше в nsInterfaces.cs и GeckoWebBrowser.cs и
собрать библиотеку я правильно понял.
admin
06.08.2014 @ 12:12 пп
Добрый день!
Да вы все правильно поняли, нужно пересобрать библиотеку.
Кирил
06.08.2014 @ 1:48 пп
Доброе время суток!
Вот я нашел http://rghost.ru/57316145 теперь мне вместимое папки Skybound.Gecko добавить в библиотеку классов на С#-пе, извините что переспрашиваю инструкцы не нашел как собирать подобную библиотеку.
admin
06.08.2014 @ 5:12 пп
Это вы нашли исходник библиотеки. Компилируете и затем добавляете в ваш проект созданную библиотеку.
Кирил
06.08.2014 @ 6:36 пп
Дак я тут и спрашиваю компилировать в Visual Studio 2012 проект на C#-пе библиотека классов и все туда или по другому както ее собрать нужно.
Извините что вас достаю я просто пока новичок в программировании но коечто знаю. Я думаю ети коментарии будут полезны тем кто непонял как добавить удаления cookie.
admin
07.08.2014 @ 2:27 пп
Вся библиотека это отдельный проект (те исходники. что вы скачали). И собирается все отдельным проектом.
Кирил
07.08.2014 @ 5:36 пп
Я разобрался, если вам нетрудно вы добавьте инструкцию для подобных мне пользователей дабы небыло таких вопросов в будущем, а но все новички не поймут что к чему как я. Вам огромное спасибо что объяснили мне дураку.
Спасибо большое я так и понял просто в какой именно проект добавить не знал толи в библиотеку классов толи в переносную библиотеку
Никита
07.08.2014 @ 8:40 пп
При сборке библиотеки у меня выдает ошибку ругается на AUTF8String
Ошибка 1 Не удалось найти имя типа или пространства имен «AUTF8String» (пропущена директива using или ссылка на сборку?) C:\Users\XXXX\Desktop\src\Skybound.Gecko\nsInterfaces.cs 53 21 Skybound.Gecko
admin
07.08.2014 @ 10:35 пп
Добрый вечер!
Возможно в сборке, которую вы скачали, отсутствует модуль AUTF8String.cs. Я с подобным тоже сталкивался.
Никита
07.08.2014 @ 11:19 пп
Я понял буду искать нормальную спасибки 🙂
Никита
08.08.2014 @ 7:47 пп
Извините но я не могу найти такую сборку, можете дать ссылку пожалуста.
admin
08.08.2014 @ 8:01 пп
Я же вам отправил модуль на указанный вами email.
Никита
08.08.2014 @ 10:42 пп
Извините почту не проверял я прошу прощения надо было написать что вы отправили. Oчень вам благодарен :):):).
Никита
08.08.2014 @ 11:32 пп
Блин вопросов стало больше чем было описано метод выдал две ошыбки первая неявное приобразования типа и нужно явно указать аргумент. Ошибка 1 Неявное преобразование типа «object» в
«Skybound.Gecko.nsICookieManager» невозможно. Существует явное преобразование (возможно, отсутствует приведение) C:\Users\Никита\Desktop\src — копия\Skybound.Gecko\GeckoWebBrowser.cs 114 25 Skybound.Gecko
———————————————————————————
Ошибка 2 Невозможно получить аргумент типа для метода «Skybound.Gecko.Xpcom.QueryInterface(object)» из данных использования. Попробуйте указать аргументы типа явным образом. C:\Users\Никита\Desktop\src — копия\Skybound.Gecko\GeckoWebBrowser.cs 115 25 Skybound.Gecko
Придется код переписывать.
admin
09.08.2014 @ 12:14 дп
Я отправил вам на email оригинальную сборку.
Саша
10.08.2014 @ 8:12 пп
У меня такая проблема не могу загрузить сайт пишет ошибку с сертификатами как отключить их проверку Ошибка Error code: sec_error_expired_issuer_certificate ПОМОГИТЕ!!!!!!!!!
admin
11.08.2014 @ 3:21 пп
Добрый день! С таким я не сталкивался.
Саша
11.08.2014 @ 8:50 пп
Я решил проблему решения простое скачал сборку движка xulrunner-1.9.0.3.en-US.win32.sdk а была до этого xulrunner-1.9.0.1.en-US.win32.sdk . Поновее сборка нужна хотя саму причину почему в старых ошибку выдавало непонял.
Саша
11.08.2014 @ 8:53 пп
У меня возник такой вопрос можно на сайте например отключить подгрузку картинок рекламы и т д ненужных елементов какимто методом или нет. Подскажите очень нужная штука!!!
admin
12.08.2014 @ 1:53 дп
Вот так: GeckoPreferences.User[«permissions.default.image»] = 1;. А вот другие настройки.
Саша
12.08.2014 @ 3:46 пп
Безмерно благодарен за помощь и на сайте данном вами можно найти метод который отключает проверку сертификатов в старых сборках движка вы супер.
Frenki
31.03.2016 @ 11:31 дп
метод который отключает проверку сертификатов??
как???
admin
31.03.2016 @ 1:14 пп
Я не сталкивался с таким.
Алексей
12.08.2014 @ 4:35 пп
Добрый день. Подскажите мне такую вещь можно ли например подгрузить форму входа в почту в данном браузере или нет всю страницу неохота грузить и тем более из прокси они тупят, я просто пишу прогу она будет рассылать моим знакомым подобные письма с заданиями и мне нужно сделать подгрузку формы в GeckoWebBrowser и передать в textBox-сы самой формы логин и пароль из dataGridView ну или из переменной я там сам допишу как надо.
admin
12.08.2014 @ 7:01 пп
Нет, такого насколько я знаю сделать нельзя. Так как вы получается все равно весь html код.
Алексей
12.08.2014 @ 6:52 пп
И я вот вспомнил в обычном встроеном браузере в Visual Studio есть такой метод geckoWebBrowser1.Document.GetElementById(«здесь id кнопки»).InvokeMember(«Click»); для нажатия кнопки на странице но в данном браузере не пашет есть альтернатива.
admin
12.08.2014 @ 7:08 пп
1) Обращаться к элементам по идентификатору или имени тоже можно.
Вот пример поиска элемента c идентификатором («id-2»):
GeckoElement node = this.Mozilla.Document.GetElementById ("id-2");
2) Эмулировать события конечно можно. Но не в стандартной библиотеке. Нужно добавлять интерфейс и дописывать код в самом проекте с библиотекой. И здесь я вам не смогу объяснить как это происходит, так как это на целую статью «тянет».
Алексей
12.08.2014 @ 9:28 пп
Про эмуляцию событий есть где то толковая инфа дайте мне плиз и может както можно типа webBrowser1.DocumentText = «Авторизацыя» + «Your / Email Address» + «Password «; и как то придумать сделать пост запрос или я не знаю но всю форму с рекламой грузить и с кучей текста ненужного чуш какаято.
———————————————————————————
Может как то так и потом придумать как пост запрос сформировать а то грузить весь ненужный текст и рекламу через прокси ето убийственно долго webBrowser1.DocumentText = «Авторизацыя» + «Your / Email Address» +»Password «; .И где можно найти инфу про события дайте мне наводочку или сайтик толковый.
———————————————————————————
Вот нашел про имитацию событий http://www.webprogrammingblog.com/link-click-geckofx/ правда не все понятно добавьте подобную статью думаю она будет полезной а я ща буду разбираться чо к чему.
admin
13.08.2014 @ 3:35 пп
1) У вас неверно указан ваш email. Хотел вам сбросить модули с примером эмуляции событий.
2) Я видел тот способ, который вы нашли. Ресурс, где я в свое время брал информация о работе с движком, я уже и не помню. Несколько лет прошло.
Алексей
13.08.2014 @ 9:44 пп
Отправьте мне на silver.mark@yandex.ru и я так понял мне понадобится для моего задания другой метод чтобы не грузить всю страницу мне понадобится библиотека xNet и самому сформировать запрос к серверу, потом загрузить капчу в Webrover или picturebox ну вообщем чтобы было все быстро и прокси полчаса не грузил все, но вы отправьте мне на почту вдруг пригодится
———————————————————————————
Спасибо за помощь и извините что украл у вас немного времени.Буду разбираться как имитировать события ввода в форму данных на сайте.
Федя
22.01.2016 @ 7:33 дп
Скажите как создать ряд действий симуляции не только по координатам (Х) и (У) мыши но и клик по тексту, или ссылкам добавлять тайм аут между кликами. Управлять разными списками кликов (чик и радио бутонами). Где найти такую информацию с примерами написания кода, и всего необходимого.
admin
24.01.2016 @ 6:12 пп
По координатам (Х) и (У) в статье приведен пример клика по координатам элемента
По таймеру прочтите в книге по C#
Находите все ссылки и выбираете рандомно для клика, также и с другими элементами.
Информация как таковая отсутствует (может только на англоязычных сайтах). Все необходимое вам есть в статье (кроме таймера).
Федя
13.02.2017 @ 2:24 дп
я спрашивал как сделать чтоб НЕ по координатам клик шел а по тексту- строке кнопке button иконке. на подобе плагина iMacros
Самое важное первый этап в три строки не могу пройти пишет мазила не существует. можно увидеть весь код? куда я что не то ни туда пишу?
admin
14.02.2017 @ 5:35 пп
1. У меня возможности проверить нет, но вроде бы у объектов класса GeckoElement, должен быть метод Click().
2. Какой код?
Алекс
31.03.2016 @ 8:20 пп
Добрый день!
Подскажите — как проверить работоспособность прокси. А то если прокси не рабочий, получаю такое: Proxy Server Refused Connection…..
Как можно обработать автоматически это? чтобы поставить другой прокси. А то бывают рабочие прокси, то все ок работает. А если не рабочий, то все останавливается.
admin
04.04.2016 @ 2:17 дп
Доброй ночи!
В теории конечно возможность определения должна быть. Ведь есть возможности куда более серьезные. Но мне не приходилось сталкиваться с подобными вещами. Единственное что могу на данный момент предложить, так это ориентироваться на страницу с текстом «The proxy server is refusing connections».
Дмитрий
17.04.2016 @ 10:17 пп
Добрый день. В GeckoWebBrowser.cs вставил
public void EmulationMouseEvent( …..
….
…
пошли ошибки типа:
Ошибка 1 Наиболее подходящий перегруженный метод для «Skybound.Gecko.nsIDOMMouseEvent.InitMouseEvent(Skybound.Gecko.nsAString, bool, bool, System.IntPtr, int, int, int, int, int, bool, bool, bool, bool, ushort, Skybound.Gecko.nsIDOMEventTarget)» имеет несколько недопустимых аргументов C:\Libs\C#\SuperGecko\Skybound.Gecko\GeckoWebBrowser.cs 1936 13 Skybound.Gecko
Ошибка 2 Аргумент «4»: преобразование типа из «Skybound.Gecko.nsIDOMAbstractView» в «System.IntPtr» невозможно C:\Libs\C#\SuperGecko\Skybound.Gecko\GeckoWebBrowser.cs 1936 62 Skybound.Gecko
Gecko брал отсюда http://howtofix.pro/using-skybound-gecko-fx-on-net-application/
— может там чтото не так…
Поможете? если что на почту можете прислать работающий модуль, исходники?
admin
18.04.2016 @ 9:14 пп
Добрый день!
Чистая версия:
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/geckofx/Skybound.GeckoFX.src.v1.9.0.0.zip
SDK (xulrunner):
http://ftp.mozilla.org/pub/xulrunner/releases/1.9.0.0/
И отправил на почту свою модифицированную библиотеку.
Алексей
02.07.2016 @ 11:36 пп
Спасибо за статью.
Я выбрал xulrunner, потому что мне нужно открывать браузер под прокси, а мои прокси — сокс5 с авторизацией по логину и паролю. Пробовал стандартный webBrowser и awesomium, но ничего не получилось, т.к. я совсем не опытный. А xulrunner кажется простым для реализации моей задачи.
Только вот я не могу скомпилировать эту библиотеку на VS 2015. Даже открывая чистую имею несколько ошибок из-за того что VS изменяет файлы старых версий (как я понял), а когда добавляю туда этот код количество ошибок кратно возрастает.
Отправьте пожалуйста на почту модифицированную библиотеку.
И если есть какой-то проект использующий xulrunner, а еще лучше работающий с куками, пожалуйста поделитесь =)
Спасибо!
admin
04.07.2016 @ 12:09 дп
Добрый вечер!
Отправил вам на почту. Версия собрана в среде VS 2010.
Простого рабочего проекта нет. Однако вы можете собрать очень просто браузер: https://swblog.ru/articles/programming/brauzer-ot-mozilla-v-proekte-na-c.html.
softbob
30.10.2018 @ 4:41 дп
Уважаемый автор , в IE есть возможность растягивать мышкой «,» … если есть бордюры , есть ли такая возможность у geckofx , может есть что-то в настройках ?