Пользователь
0,0
рейтинг
19 февраля 2013 в 23:04

Разработка → Как подключить сторонний браузер в приложении на C# tutorial recovery mode

C#*, .NET*
image

В определенный момент мне стало некомфортно использовать стандартный контрол WebBrowser, предлагаемый Visual Studio.
Причин было несколько:
1. Использовался IE-движок, что само по себе уже сильный аргумент.
2. Кривая работа с JS.
3. Отсутствие масштабирования.
4. Если запустить на машине, где стоит IE6, то все его «достоинства» переносятся на приложение.

В итоге был начат поиск альтернативных решений.
Было рассмотрено 2 SDK. xulrunner(Mozilla) и Awesomium(Chrome)

Подключение обоих происходит примерно одинаково, но на всякий случай опишу оба.


image
1. xulrunner
шаг 1
Идем на офицальный сайт http://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/
Выбираем подходящую нам версию.
Тут хотелось бы сделать маленькое отступление. Чем позднее версия, тем она тяжелее: к примеру, 1.9v весит 21Мб., а уже 19v весит 32Мб. Помимо этого каждая следующая версия требует все больше ресурсов. Забегая вперед скажу, что это и стало основной причиной отказа от этой SDK.

По данной ссылке заходим в папку с выбранной версией, далее sdk/xulrunner-X.X.en-US.win32.sdk.zip

шаг 2
Скачиваем и распаковываем содержимое. Нас интересует из архива только папочка bin. Копируем ее в папку с приложением и переименовываем в xulrunner. Имя можно и другое, но чтобы не было различий с моим описанием, лучше имя сделать такое.

шаг 3
Для работы с этой SDK нам потребуется библиотека Skybound.GeckoFX.bin.v1.9.1.0 Ее можно скачать тут http://code.google.com/p/geckofx/
Данная библиотека работает xulrunner версии 1.9.
Если вы решили использовать более позднюю версию, то нужно искать Skybound.GeckoFX 2.0, она подходит для версий 2.0 и выше.

шаг 4
В нашем приложении добавляем в References Skybound.Gecko.dll из скачанного архива

шаг 5
Правим класс Program:
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form2());
        }
    }


Инициализируем контрол браузера:
string path = "C:\\Program Files (x86)\\xulrunner\\";   //Путь к распакованной и переименованной папке bin из архива SDK
    Skybound.Gecko.Xpcom.Initialize(path);
    webBrowser1 = new Skybound.Gecko.GeckoWebBrowser();
    webBrowser1.Parent = this.panel1;
    webBrowser1.Dock = DockStyle.Fill;
    string u = "http://www.ya.ru";

    //Загрузка выбранной страницы
    webBrowser1.Navigate(u);


По данному коду родительской панелью будет panel1

шаг 6
Чтобы выполнить программно какой-либо JavaScript пришлось идти на ухищрения, т.к. то ли функции, которые для этого по идее предназначены не дописаны в этой версии, то ли что-то еще. Но выход я нашел только такой:

webBrowser1.Navigate("javascript:ImGecko()");


Минусом является то, что нельзя получить результат обработки, только в виде alert();
Данная проблема также стала причиной того, что я начал искать замену и пришел к Awesomium

image

2. Awesomium
шаг 1
Скачиваем SDK по ссылке http://awesomium.com/
На сайте имеется две версии — стабильная(1.6.5) и тестовая(1.7). Тестовая в целом работает лучше.
Для работы нам понадобятся файлы
Awesomium.Core.dll
Awesomium.dll
Awesomium.Windows.Controls.Design.dll
Awesomium.Windows.Controls.dll
Awesomium.Windows.Forms.dll

шаг 2
Подключаем к проекту библиотеки
Awesomium.Core.dll
Awesomium.Windows.Forms.dll

шаг 3
В Toolbox кликаем правой кнопкой и выбираем Choose Items. Далее жмем browse и подключаем Awesomium.Windows.Forms.dll, после этого у нас появится новые контролы WebControl, AddressBox и т.д. Нам в первую очередь важен WebControl

шаг 4
Размещаем контрол в дизайне

шаг 5
Примеры использования различных функций.

Открытие страниц
webControl1.LoadURL("http://ya.ru"); 


Загрузка Cookies
string cookie;  // Строка с cookie которые нужно подключить
string domen; // Домен 
string[] mascook;
mascook = cookie.Split(';');

Awesomium.Core.WebCore.ClearCookies();
foreach (string cook in mascook)
     Awesomium.Core.WebCore.SetCookie("http://" + domen, cook + "; domain=" + domen, true, true);


Получение значений переменных mx и my
            Awesomium.Core.JSValue x = webControl1.ExecuteJavascriptWithResult("mx", 500);
            Awesomium.Core.JSValue y = webControl1.ExecuteJavascriptWithResult("my", 500);


500 — это таймаут.

Вызов JS функции

webControl1.CallJavascriptFunction("", "al", new Awesomium.Core.JSValue[] {});


al — это имя функции
второй параметр передает значения в фунцию. В данном случае он пустой.

Приведенные примеры работают на Awesomium 1.6.5, в версии 1.7 немного изменена архитектура и некоторые методы могут отсутствовать или вызываться по другому.

Выводы
На текущий момент во всех проектах, где нужен браузер, использую Awesomium: он и работает стабильнее и функционал побогаче. Нагрузка от него небольшая. Единственный минус — это то, что не отрабатывает клик правой кнопкой по флешу, потому нельзя поменять необходимые параметры(возможно я просто не разобрался как). В остальном данная SDK меня во всем устроила.
Виталий @Violetdrug
карма
9,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (52)

  • +1
    Спасибо большое. А то я однажды искал webKit под C# по попадались только одни ужасы вида обёртки вокруг хромиума. Будем пробовать :)
  • +7
    Мы на работе используем CefSharp — тоже очень неплохо себя зарекомендовал.
  • +1
    Стоило посмотреть еще в сторону xilium.cefglue. Использовал в одном проекте, остался доволен.
    • 0
      Сколько весит библиотека?
      • 0
        Сейчас точно не скажу, но в комплекте с самим CEF3 емнип чуть меньше 60мб. Где-то 56мб — 58мб.
        • 0
          xulrunner весит около 10Мб
          Awesomium около 20Мб
          подразумеваю полный комплект для работы.
          Я специально выбирал по легче, т.к. программу скачивают в регионах где инет слабый.
          • +2
            Прошу прощения. Это я вместе с debug сборкой сказал. Сам CEF3 + xilium.cefglue весят около 35мб, но это с видео кодеками и поддержкой WebGL. Если попробовать собрать без всего этого, то будет меньше
    • 0
      Кстати автору xilium.cefglue, — т.е. мне — очень интересны отзывы, пожелания и прочее. :)
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Я когда с gecko на Awesomium перешел, не мог нарадоваться. И код приятный и мануал имеется.
      • НЛО прилетело и опубликовало эту надпись здесь
  • +8
    >В определенный момент мне стало некомфортно использовать стандартный контрол WebBrouser

    А я даже знаю почему — компилятор постоянно писал «класс не найден», да?
    • +3
      Уже все пошутили над этой опечаткой)
      Исправлено.
  • +1
    Из браузерных контролов пользовался OpenWebKitSharp

    Неплохо. Только много чего тянет — потому тяжёлый( + 50 m).

    И ещё Json Parser из коробки заменил на Newtonsoft
  • +2
    Не ожидал, что есть столько альтернатив стандартному контролу (один из тех постов, где комменты увеличивают его ценность). Спасибо за наводки! :)
  • 0
    Awesomium отличная штука, юзал его в дипломной работе.
    Проект был на WPF, так что кому актуально — есть и WPF-ная версия, с ней все отлично (но процесс «прикручивания» контрола, естественно, будет отличаться).
  • 0
    Право не знаю из какого нафталина вы достали скайбоунд и geckofx с гуглкода. А глядя на ваши муки с ними аж слезы наворачиваются. Оба этих проекта мертвы, сударь. А вот их логическое продолжение — bitbucket.org/geckofx/geckofx-18.0 они выходят примерно след в след за новыми версиями firefox/xulrunner. Проект живой и там есть и поддержка winforms для любителей античности и wpf для любителей ретро.

    Awesomium так себе, у него даже лицензия вражеская. А ведь есть такие проекты как Xilium.CefGlue (его уже упоминали).
    • 0
      Каждая следующая версия FF все тяжелее и тяжелее, как по нагрузке, так и по объему, а для меня очень важен был каждый Мб.
      На тот момент когда я от него отказался(примерно 1.5 года назад) самая стабильная была именно описанная версия.
      И если бы не проблемы обработки JS я бы на ней остался.

      К сравнению xulrunner 1.9v весил 10Мб и кушал оперативы около 20Мб
      А тот же Awesomium весит 20Мб и оперативы съедает около 60Мб

      В общем каждый сам решает, какие параметры при выборе ему важнее.
      • +1
        Не забывайте что в случае с ФФ и с Хромиумом с каждым выпуском прибавляются и багфиксы и исправления критических дыр безопасности. Встраивание браузера это конечно хорошо но не для критических приложений. Там еще есть одна большая проблема все движки браузеров поддерживают пока только х32 архитектуру есть найт билды под х64 но они остаются найтами.
    • 0
      я правильно понимаю, для этого компонента на клиентскую машину надо ставить FF? Если это так то не везде такое дадут сделать.
      • 0
        Нет, причем здесь FF когда речь идет о xulrunner, его вы должны иметь на машине жертвы, а его «ставить» не обязательно можно с собой прихватить.
  • 0
    Предупреждение 1 Несоответствие между архитектурой процессора проекта «MSIL», построение которого выполняется, и архитектурой процессора ссылки «Awesomium.Core, Version=1.7.0.3, Culture=neutral, PublicKeyToken=e1a0d7c8071a5214, processorArchitecture=x86», «x86». Это несоответствие может привести к ошибкам во время выполнения. Попробуйте изменить целевую архитектуру процессора для проекта с помощью диспетчера конфигураций, чтобы согласовать архитектуры процессоров для проекта и ссылок, или используйте зависимость от ссылок с архитектурой процессора, соответствующей целевой архитектуре процессора проекта. WindowsFormsApplication7

    Как выправить? Что не так? Делаю как описано…
    • 0
      В свойствах проекта выберите Build -> Platform target -> x86.
  • 0
    Еще не могу найти Awesomium.dll, где его брать?
    • 0
      в 1.7 версии Awesomium.dll лежит в build ->bin
      остальные wrappers->AwesomiumNET->Assemblies
      Еще хотел добавить, что в 1.7 немного отлечается архитектура, они ввели понятие сессий.
      Чуть позже допишу статью с пометкой для этой версии.
      • 0
        Было бы чудесно! Подскажите как просто загрузить страницу 1.7, а то LoadURL пишет устарел…
        • 0
          webControl1.Source = new Uri("http://www.google.com/ncr");
          в папке wrappers\AwesomiumNET\Samples\Windows Forms\CSharp\WinFormsSample
          есть пример, он реализован не через контрол, но в целом в нем есть, что подсмотреть.
          там же рядом лежит папка с примерами использования JS
  • 0
    Поздно написал… Sorry!
  • 0
    awesomium отличный контрол. Только вот с Proxy разобраться не получается. Для прокси нужно юзать сессии?
  • 0
    Почему так не работает?
    WebPreferences ds = new WebPreferences();
                ds.ProxyConfig = "myproxy:80";
                using (WebSession session = WebCore.CreateWebSession(ds))
                {
                    webControl1.Source = new Uri("http://google.com");
                    
                }
    


    Как правильно сделать?
    • 0
      Документации для 1.7 пока к сожалению нет. Все примеры для 1.6.3. Рискну предположить, раз это версия
      1.7 Final Release Candidate, возможно часть функционала там просто еще не работает. Я пока использую 1.6.3.
  • 0
    Немного попробовал Awesomium 1.7 для автоматизации действий на сложных страницах со скриптами, где просто парсить HTML и отправлять запросы сложно.

    Как-то не очень понравилось:
    1. Заполнение полей, кликанье кнопок и т.п. только через выполнение Javascript.
    2. (баг?) DocumentReady срабатывает когда документ еще не готов или как-то так. Он не null, но getElementById не находил на странице элементы, если Thread.Sleep(250), то ок. Решил так:
        WbAws.LoadingFrameCompleted += OnLoadingFrameCompleted;
        WbAws.Source = new Uri("http://google.com");
        
        private void OnLoadingFrameCompleted(...)
        { 
           if (webView == null || !webView.IsLive || webView.ParentView != null || !e.IsMainFrame)
             return;
    
            LoadingFrameCompleted -= OnLoadingFrameCompleted;
        }
    


    Еще столкнулся со странным багом в инсталлере: он почему-то закинул примеры (Samples) не в Documents\Visual Studio, как указано в ридми, а в корень совершенно другого диска, в папку VS10_PROJECTS (ее там не было), еле нашел, в вин8 еще и ярлык на них не создался на стартовом экране. Причем также и на виртуальной с машине.
  • 0
    А как у всех перечистенных обстоят дела с печатью? У WebBrowser есть одна проблема, а точнее у него нет нормальной программной возможности выбрать принтер и изменить его настройки для печати. Проблемы решаются подменой принтера по умолчанию и правкой реестра в случае необходимости изменить настройки принтера что является костылём. В принципе понятно почему (WebBrowser является только обёрткой вокруг ActiveX IE) но легче жить от этого не становится.

    п.с. когда столкнулся с этой проблемой глазам своим не поверил, на дворе 2013й .net 4.5 а контрол через который предполагается смотреть html и прочие документы не умеет толком программо работать с принтером.

    Кстати, посоветуйте, может есть решение такой проблемы.

    Спасибо
  • 0
    Спасибо!
    Попробую Awesomium. Возможно подойдет мне. Хочу удобную работу с элементами при помощи XPath.
    • 0
      Ну там нет XPath встроенного куда-либо, но можно через JS document.evaluate XPath использовать

      // returns Javascript XPath query string for getting a single element 
      public static string GetJsSingleXpathString(string xpath)
      {
          return
             String.Format(
      			"document.evaluate(\"{0}\", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue", xpath);
      }
      
      // returns Javascript XPath query string for getting a collection of elements
      public static string GetJsXpathString(string xpath)
      {
          return
          String.Format(
      			"document.evaluate(\"{0}\", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null)", xpath);
      }
      

      string linkJsXpath = GetJsSingleXpathString("//a[contains(@href, 'example.com')]");
       
      dynamic link = (JSObject) webControl.ExecuteJavascriptWithResult(linkJsXpath);
      if (link == null)
      {
          MessageBox.Show("No link found!");
          return;
      }
      
      // do something with the element
      string url = link.href;
      MessageBox.Show(url);
      
  • 0
    Awesomium не работает с https? Или я просто найти не могу?
    • 0
      С чего бы ему не работать?
      • 0
        У меня не открывает https:// сайт, может я конечно что то не то делаю?
        • 0
          Должно работать. Сайт-то какой?
          • 0
            локальный портал, на работе.
          • 0
            Видимо проблема в том что локальный ресурс настроен на работу по https но сертификата безопасности нет. Как это побороть?
            • 0
              А если в WebPreferences поставить WebSecurity в False? (там все ридонли, надо устанавливать либо при создании websession/webview, либо из XAML если WPF, либо из WebPreferencesProvider'a если WinForms)

              «не открывает» как именно? В событии LoadingFrameFailed какую-нибудь ошибку выдает?

              Еще там есть событие CertificateError и по идее можно сделать так:
                  void webControl1_CertificateError(object sender, CertificateErrorEventArgs e)
                  {
                      e.Ignore = true;
                      e.Handled = EventHandling.Modal;
                  }
              
              • 0
                Я на Visual Basic.NET учусь писать
                попробовал вот так:
                    Private Sub WebControl1_CertificateError(sender As Object, e As Awesomium.Core.CertificateErrorEventArgs) Handles WebControl1.CertificateError
                        e.Ignore = True
                        e.Handled = Awesomium.Core.EventHandling.Modal
                    End Sub
                

                Не получилось.
                • 0
                  Событие-то срабатывает вообще? Может не в этом дело вообще.

                  HTTPS сертификат просто самоподписанный или что? Я проверил, вроде бы работает с вышеописанной обработкой CertificateError.

                  LoadingFrameFailed (с IsMainFrame == true) срабатывает? В ErrorCode/Description есть что-то?
                  • 0
                    Очень странно, так как если перехожу на сайт допустим нажимая кнопку то отрабатывает нормально.
                        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
                            WebControl1.Source = New Uri("https://site.pru")
                        End Sub
                    


                    Если указываю site.pru как current url то не открывает.
                    • 0
                      эм… Current Url это где? В дизайнере формы что ли? Вроде нет нигде такого, переход через установку Source и есть стандартный способ для выполнения сего действия. Естественно не обязательно на кнопке, можно и в Form_Load, например.
                      • 0
                        Current Url это свойство Source WebControl1, то есть это страница которая загружается в момент загрузки формы. обычные сайты нормально открывает, а https не открывает.
                        • 0
                          Не вижу нигде такого свойства. Вы где это нашли?:)
                          • 0
                            Скриншот
                            image
                            • 0
                              А, и причем тут «current url»?
                              Ну у меня работает и так.
                              • 0
                                Странно у меня не работает, current url это я просто из описания свойства вычитал.
                                И еще небольшой вопрос, как программно заполнять textbox (авторизации допустим) захожу на сервер и всплывает окно то что для доступа нужна авторизация, с элементом из IE это решалось тем что IE просто запоминал логин и пароль.
                                • +1
                                  Тут answers.awesomium.com/index.html подобный вопрос почти каждый день задают :)
                                  answers.awesomium.com/questions/4168/enter-text-in-web-form-from-textbox.html
                                  answers.awesomium.com/questions/829/index.html

                                  Есть несколько способов.
                                  Можно просто Javascript выполнять:
                                  webControl.ExecuteJavascript("document.getElementById('passwordTextbox').value='password'");
                                  


                                  Но обычно (хотя для локального своего сайта может и все равно) лучше использовать что-то типа такого, чтобы можно было проверить, что элемент существует на странице и т.п.
                                  dynamic tbox = (JSObject) webControl.ExecuteJavascriptWithResult("document.getElementById('passwordTextbox')");
                                  
                                  if (tbox == null)
                                      выкинуть исключение об ошибке и т.д.
                                  
                                  tbox.value = "password";
                                  


                                  Или если в VB нет dynamic, то так:
                                  JSObject tbox = webControl.ExecuteJavascriptWithResult("document.getElementById('passwordTextbox')");
                                  
                                  if ((tbox == null) || !tbox.HasProperty("value"))
                                      выкинуть исключение об ошибке и т.д.
                                  
                                  tbox["value"] = "password";
                                  


                                  Аналогичным образом можно также нажать кнопку (через метод click() у нее) или отправить форму (через метод submit()), методы через Invoke вызываются у JSObject.

                                  Ловить завершение загрузки страницы можно в событии LoadingFrameCompleted (когда e.IsMainFrame == true)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.