Страницы

Поиск по вопросам

Показаны сообщения с ярлыком webbrowser. Показать все сообщения
Показаны сообщения с ярлыком webbrowser. Показать все сообщения

воскресенье, 8 марта 2020 г.

C# webbrowser как двигать скрол?

#c_sharp #webbrowser


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


Ответы

Ответ 1



Еще способы: WebBrowser.Document.Window.ScrollTo(int x, int y); WebBrowser.Navigate("javascript:window.scroll(...);");

Ответ 2



Доброго времени суток. Для управления скролом на веб странице вам надо смотреть в сторону Js (jQuery). Вот ряд статей которые могут вам помочь: [событие scroll][1] jQuery.ScrollTo статьи не самые новые, но дадут вам отправную точку). удачи

понедельник, 24 февраля 2020 г.

Шутки браузеров: криво работает php валидация?

#php #webbrowser #opera


Я тестирую в основном сайт в Google Chrome (посл. версия), и только что заметил,
что Opera (последняя версия) позволяет обойти ОБЯЗАТЕЛЬНОЕ ТРЕБОВАНИЕ заполнить возраст.
Просто игнорирует это поле и даже успешно отправляется форма и тп.

Ссылка на форму

А также наверно какие-то старые браузеры умудряются еще регать людей с НЕВОЗМОЖНЫМ
значением пола, например.

Т.е. Опера в данном случае игнорит и JS, и PHP валидацию. Это вообще законна такая
работа PHP и браузеров?

Использую rules:

$rules[] = array( 'gender', 'required', 'message' => 'Укажите пол' );
$rules[] = array( 'birthYear', 'required', 'message' => 'Укажите год рождения' );
$rules[] = array('gender', 'in', 'range' => array("f", "m", "?"), 'message' => 'Укажите
пол.');


Обновление

Добавил еще правило:

$rules[] = array( 'birthYear',
            'length',
            'min'=>$AGE_START,
            'max'=>$AGE_END,
            'tooShort' => 'Укажите год рождения',
            'tooLong' => 'Укажите год рождения',
        );


Опера перестала глючить.
    


Ответы

Ответ 1



К вам на сервер от клиента (в данном случае браузер) могут прийти какие угодно данные. Валидация данных всегда должна быть на сервере помимо JS. Если у вас регистрация проходит даже без обязательных полей, значит у вас некорректный PHP код с валидацией. UPD Лучше не обращаться к массиву $_POST напрямую. К тому же, в вашем выпадающем списке есть пустое значение. Один браузер его вам посылает, другой нет. Получается при обращении к $_POST['Form']['gender'] у вас в одном случае строка пустая, в другом случае null (не факт, это моё предположение). Проверьте $_POST массив в контроллере в разных браузерах: var_dump($_POST); die(); Вам может помочь либо метод saveAttributes(), либо как минимум проверка на пустое значение: if(isset($_POST['Form']['gender']) && $_POST['Form']['gender'] != '') { $form->gender = $_POST['Form']['gender']; }

Исключение при попытке закрыть форму с браузером

#c_sharp #net #winforms #webbrowser


Есть форма с единственным контролом типа WebBrowser.
Для обработки нажатия Ecs используется переопределение ProcessCmdKey.
При загрузке формы выполняется открытие стараницы в webBrowser1.

Вот код:

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
  {
    if (keyData == Keys.Escape)
    {
      this.Close();
      return true;
    }

    return base.ProcessCmdKey(ref msg, keyData);
  }

  private void Form1_Load(object sender, EventArgs e)
  {
    webBrowser1.Navigate("about:blank");
  }
}


Проблема в том, что при нажатии Esc форма закрывается, но приложение падает:


  RaceOnRCWCleanup occurred
  
  Message: Managed Debugging Assistant 'RaceOnRCWCleanup' has detected a problem
in 'C:\Тут был путь к проекту\bin\Release\Test - Close by Esc with WebBrowser.vshost.exe'.
  
  Additional information: Была предпринята попытка освободить RCW, находящийся в
использовании. RCW используется активным потоком или другим потоком. Попытка освободить
RCW, находящийся в использовании, может привести к повреждению или потере данных.


Стектрейс показывается такой:

    mscorlib.dll!System.__ComObject.FinalReleaseSelf()  Unknown
    mscorlib.dll!System.Runtime.InteropServices.Marshal.FinalReleaseComObject(object
o) Unknown
    System.Windows.Forms.dll!System.Windows.Forms.WebBrowserBase.TransitionFromLoadedToPassive()
   Unknown
    System.Windows.Forms.dll!System.Windows.Forms.WebBrowserBase.TransitionDownTo(System.Windows.Forms.WebBrowserHelper.AXState
state)  Unknown
    System.Windows.Forms.dll!System.Windows.Forms.WebBrowser.Dispose(bool disposing)
   Unknown
    System.dll!System.ComponentModel.Component.Dispose()    Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.Dispose(bool disposing)
  Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Form.Dispose(bool disposing)  Unknown
>   Test - Close by Esc with WebBrowser.exe!Test___Close_by_Esc_with_WebBrowser.Form1.Dispose(bool
disposing) Line 21   C#
    System.Windows.Forms.dll!System.Windows.Forms.Form.WmClose(ref System.Windows.Forms.Message
m)  Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message
m)  Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref
System.Windows.Forms.Message m) Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref
System.Windows.Forms.Message m)   Unknown
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr
hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam)  Unknown
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.Control.SendMessage(int msg, int
wparam, int lparam)  Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Form.Close()  Unknown
    Test - Close by Esc with WebBrowser.exe!Test___Close_by_Esc_with_WebBrowser.Form1.ProcessCmdKey(ref
System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) Line 25    C#
    System.Windows.Forms.dll!System.Windows.Forms.Control.ProcessCmdKey(ref System.Windows.Forms.Message
msg, System.Windows.Forms.Keys keyData)    Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessMessage(ref System.Windows.Forms.Message
msg)   Unknown
    System.Windows.Forms.dll!System.Windows.Forms.WebBrowserBase.PreProcessMessage(ref
System.Windows.Forms.Message msg)    Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessControlMessageInternal(System.Windows.Forms.Control
target, ref System.Windows.Forms.Message msg)   Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessControlMessage(ref
System.Windows.Forms.Message msg)    Unknown
    System.Windows.Forms.dll!System.Windows.Forms.WebBrowserSiteBase.System.Windows.Forms.UnsafeNativeMethods.IOleControlSite.TranslateAccelerator(ref
System.Windows.Forms.NativeMethods.MSG pMsg, int grfModifiers)   Unknown
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.WebBrowserBase.PreProcessMessage(ref
System.Windows.Forms.Message msg)    Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessControlMessageInternal(System.Windows.Forms.Control
target, ref System.Windows.Forms.Message msg)   Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(ref
System.Windows.Forms.NativeMethods.MSG msg) Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage(ref
System.Windows.Forms.NativeMethods.MSG msg) Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr
dwComponentID, int reason, int pvLoopData)  Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int
reason, System.Windows.Forms.ApplicationContext context)    Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int
reason, System.Windows.Forms.ApplicationContext context) Unknown
    System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form
mainForm)   Unknown
    Test - Close by Esc with WebBrowser.exe!Test___Close_by_Esc_with_WebBrowser.Program.Main()
Line 20  C#
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence
assemblySecurity, string[] args) Unknown
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
  Unknown
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state)
   Unknown
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext
executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
  Unknown
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext
executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
  Unknown
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext
executionContext, System.Threading.ContextCallback callback, object state) Unknown
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()    Unknown


Что можно сделать?
    


Ответы

Ответ 1



Это не ошибка, это лишь предупреждение, выдаваемое Managed Debugging Assistant'ом (это такое расширение отладчика), которому кажется, что с вашим кодом что-то не так. Вы используете Runtime Callable Wrapper, специальную обёртку для COM-контролов (WebBrowser по сути является COM-контролом). Когда вы пытаетесь закрыть форму, расширение отладчика бросается на амбразуру и заявляет вам, что браузер ещё используется, а вы убиваете его до того, как его текущая функция полностью отработает. Такое может по идее привести к реальным проблемам лишь если ваш код многопоточный. Проблема воспроизводится в обычном коде при использовании CancelProperty у кнопки, или DialogResult. Или в вашем случае, когда у вас есть особая реакция на Esc. Фокус находится на WebBrowser'е, он получает нажатие Esc. Обвязка ActiveX собирается сообщить контейнеру о нажатии, чтобы он мог на него отреагировать. (Это нужно, например, для поддержки клавиатурных шорткатов, Tab'а, Enter/Escape для активизации кнопок и тому подобного.) Если при этом нажатие на клавишу закрывает форму (как в вашем случае), отладчик видит, что на WebBrowser'е вызывается Dispose в то время как код его RCW ещё выполняется. Опасность заключается в том, что когда код вернётся в RCW, он имеет право работать с COM-объектом (он же не знает, что у него из под носа этот самый объект увели), и произойдёт вылет — это не такой уж и редкий сценарий. Окей, в конкретно данном случае вылет вроде бы не воспроизводится так просто. Но по идее проблема может произойти если финализирующий поток доберётся до COM-объекта до того, как произойдёт возврат из обработчика Esc. Так что у нач возможна гонка между UI-потоком и потоком финализатора. В качестве заплатки можно отложить реальное закрытие на момент, когда код обвязки ActiveX закончит работу. Например, вызывая закрытие асинхронно: if (keyData == Keys.Escape) { this.BeginInvoke((Action)this.Close); return true; } Вольный перевод этого ответа с en.SO

Ответ 2



Возможный вариант решения - подписаться на PreviewKeyDown самого WebBrowserа: private void webBrowser1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { this.Close(); } Обращаю внимание, что подписка на нажатие клавиши на форме не работает, независимо от значения свойства KeyPreview. Нужно именно на браузер.

Ответ 3



Базовый метод ProcessCmdKey надо вызывать до вызова Close. protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { var res = base.ProcessCmdKey(ref msg, keyData); if (keyData == Keys.Escape) { this.Close(); res = true; } return res; } Иначе, если base.ProcessCmdKey вызывается после закрытия формы, то надо удалять браузер перед закрытием. protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == Keys.Escape) { this.Controls.Remove(wb); // ДОБАВИТЬ ЭТУ СТРОКУ this.Close(); return true; } return base.ProcessCmdKey(ref msg, keyData); } Проверил в Visual Studio Community 2015, C# Interactive // Microsoft (R) Roslyn C# Compiler version 1.1.0.51204 #r "System.WIndows.Forms" using System.Windows.Forms; public class Form1 : Form { WebBrowser wb; public Form1() { wb = new WebBrowser() { Dock = DockStyle.Fill, Parent = this }; wb.Navigating += (s, e) => Console.WriteLine("Navigating " + e.Url); wb.Navigated += (s, e) => Console.WriteLine("Navigated " + e.Url); wb.DocumentCompleted += delegate { Console.WriteLine("DocumentCompleted"); }; } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == Keys.Escape) { this.Controls.Remove(wb); // ДОБАВИТЬ ЭТУ СТРОКУ this.Close(); return true; } return base.ProcessCmdKey(ref msg, keyData); } protected override void OnLoad(EventArgs e) { wb.Navigate("about:blank"); } } var f = new Form1(); f.Activated += delegate { SendKeys.Send("{ESC}"); }; f.ShowDialog(); Работает нормально, закрывается при нажатии Esc и выводит Navigating about:blank Navigated about:blank DocumentCompleted

пятница, 14 февраля 2020 г.

Корректное удаление файлов C#

#c_sharp #winforms #файлы #webbrowser


Написал такой метод для удаления файлов 

public static void deleteFile(params string[] fileName)
{
    foreach (string f in fileName)
    {
        if (File.Exists(Properties.Settings.Default.diskString + f)) File.Delete(Properties.Settings.Default.diskString
+ f);
    }
}


Вызываю так:

HelpClass.deleteFile("poster.jpg", "1.jpg", "2.jpg", "3.jpg", "4.jpg", downloadFileName);


Вот эти файлы, перечисленные в аргументах метода, предварительно вставляются в поля
сайта через webbrowser. Соответственно, при запуске метода файлы якобы удаляются, но
на самом деле остаются до полного закрытия программы. Прикрепил скрин, как они на диске
выглядят после этого. Если попытаться их открыть, то пишет, что отсутствует разрешение
на доступ к расположению файла.
Если же в webbrowser их не вставлять, то все хорошо удаляется.
Пытался очищать память при закрытии второй формы (событие FormClosed), на которой
находится webbrowser, двумя способами:

this.Dispose();


и

GG.Collect();


результата нет. Один раз сработал второй способ, но больше почему-то не работает))

Файлы в поля на сайте вставляются следующим образом:

Populate().ContinueWith((_) =>
        {

        }, TaskScheduler.FromCurrentSynchronizationContext());

async Task PopulateInputFile_poster(HtmlElement file_poster)
{
    file_poster.Focus();
    dialog show up
    var sendKeyTask = Task.Delay(500).ContinueWith((_) =>
        {
            SendKeys.Send(Properties.Settings.Default.diskString + "" + "poster.jpg"
+ "{ENTER}");
        }, TaskScheduler.FromCurrentSynchronizationContext());

    file_poster.InvokeMember("Click"); 

    await sendKeyTask;

    await Task.Delay(500);
}

async Task Populate()
{
    var elements = webBrowser1.Document.GetElementsByTagName("input");


    //постер
    foreach (HtmlElement file_poster in elements)
    {
        if (file_poster.GetAttribute("name") == "screen")
        {
            file_poster.Focus();
            await PopulateInputFile_poster(file_poster);
        }
    }
}


Подскажите, что не так?

    


Ответы

Ответ 1



Нашел похожую проблему вот тут Там говорится, что если перейти на произвольный адрес, например, http://localhost/ , то ресурсы освобождаются и могут быть удалены. В этом вопросе так же сталкиваются с этой проблемой и предлагают такое же решение: webBrowser.Navigate("about:blank"); while (webBrowser.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents(); File.Delete(fileName); Если это не поможет, то можно подойти радикально, используя AppDomain: Создаете класс наследник от MarshalByRefObject Оборачиваете этот класс вокруг webbrowser Создаете новый домен В этом домене создаете объект вашего класса Взаимодействуете с браузером через него Когда хотите удалить файлы, выгружаете домен целиком Как вариант, еще можно попробовать стороннюю библиотеку CefSharp . Она является альтернативой webbrowser на хромиуме.

понедельник, 3 февраля 2020 г.

Ищу аналог функции WebBrowser из WindowsForms (С#) в Intellij Idea, в Swing редакторе

#java #c_sharp #swing #webbrowser


Ищу аналог функции WebBrowser из WindowsForms (С#) в Intellij Idea (Java), в Swing
редакторе, из предустановленных ничего нет, вот я думаю может есть какие-нибудь модуль
расширения для этого, в частности мне нужно создать форму содержащее информацию из
интернета. Ядро любое можно (не только IE6 как там ^_^), просто не могу найти подобного
в сети, плохо ищу, может кто-нибудь посоветует?)
    


Ответы

Ответ 1



Например: JxBrowser (на движке Chromium) Браузер из состава DJProject

Ответ 2



Тоже советую насчет DJProject, в отличие от JxBrowser, они бесплатны. И легко вставляются в swing приложение: JWerBrowser webBrowser = new JWebBrowser(); webBrowser.navigate(WebServer.getDefaultWebServer().getClassPathResourceURL(getClass().getName(), "start.html")); webBrowser.setBarsVisible(false); add(webBrowser, BorderLayout.CENTER); Если будут проблемы с js - для таких случаев есть Rhino.

Ответ 3



Как вариант, в JavaFX есть WebView. Вот ссылка на хабр, где довольно подробно показаны примеры его использования. Входит в Java SE.

среда, 22 января 2020 г.

Как получить событие LoadCompleted контрола WebBrowser, не вставляя данный контрол в XAML?

#c_sharp #wpf #webbrowser


У меня нет потребности использовать WebBrowser в XAML, мне он нужен всего лишь для
того что бы иметь возможность вызвать событие Click на одном из тегов загруженной HTML
страницы. 

Я не могу вызывать событие Click на нужном мне теге, до того как загрузиться страница.
Для того что бы получить уведомление о загрузке страницы мне нужно подписаться на событие
LoadCompleted. Но, судя из того что я вижу событие LoadCompleted не генерируется пока
WebBrowser не будет добавлен в XAML.

По причине того что я хочу осуществлять загрузку множества HTML страниц параллельно,
перспектива постоянно добавлять WebBrowser контрол в разметку XAML до загрузки одной
из множества страниц и удаление его из этой разметки после загрузки нужной страницы
выглядит не очень удобно. 

Моя цель получить доступ к вызову события Click на загруженной HTML странице без
возни с ХАМL.

Можно ли получить доступ к событию LoadCompleted контрола  WebBrowser без его привязки
к XAML. Возможно ли это? Может быть есть какой то другой путь?

Код отражающий суть проблемы (WebBrowser в XAML не добавлялся)

public partial class SettingsWindow : Window
{
    private WebBrowser browser = new WebBrowser();

    public SettingsWindow()
    {
        InitializeComponent();

        this.browser.LoadCompleted += Browser_LoadCompleted;
        this.browser.Source         = new Uri(@"https://www.google.com.ua/");
        //this.browser.Navigate(path); <-- пробовал загружать страницу и этим способом.
    }

    private void Browser_LoadCompleted(object sender, NavigationEventArgs e)
    {
        // Этот обработчик никогда не вызывается если объект WebBrowser не 
        // добавлен в XAML или не добавлен программным путем в качестве 
        // дочернего компонента к одному из существующих контролов окна.
    }        
}

    


Ответы

Ответ 1



Действительно, событие LoadCompleted для WPF WebBrowser не вызывается до тех пор, пока он не добавлен в какое-либо отображаемое окно или элемент управления, это известная проблема. Причина ее в том, как WebBrowser осуществляет инициализацию своего внутреннего ActiveX-элемента Internet Explorer, который и занимается загрузкой страницы. Это можно понять, посмотрев в его исходный код на Reference Source. Для корректной работы события DocumentCompleted внутреннего ActiveX-объекта класс ActiveXHost должен быть переведен в состояние ActiveXState.InPlaceActive. По умолчанию он находится в ActiveXState.Running (см. инициализацию свойства), переход в состояние InPlaceActive происходит при вызове метода BuildWindowCore, который вызывается только при отображении родительского окна элемента. Это поведение отличается от аналогичного элемента в WinForms, который сразу переводится в InPlaceActive при инициализации, см. здесь). Решение 1 - Использование WinForms WebBrowser Элемент WebBrowser в WinForms избавлен от этой проблемы (аналогичное событие DocumentCompleted всегда вызывается), и функционально ни в чем не уступает элементу из WPF. Можно просто добавить ссылку на System.Windows.Forms и использовать его. Решение 2 - Использование окна за пределами экрана Для вызова BuildWindowCore требуется видимое окно, однако никто не запрещает сделать координаты отрицательными и поместить окно за пределы экрана: Window wnd = new Window(); wnd.Content = browser; wnd.ShowInTaskbar = false; wnd.Top = -1000; wnd.Left = -1000; wnd.Width = 0; wnd.Height = 0; wnd.Show(); Решение 3 - Грязный хак с использованием отражения Просто вызвать внутренний метод TransitionUpTo, передав в качества аргумента константу InPlaceActive (4): using System.Reflection; const int InPlaceActive = 4; //... var method = browser.GetType().GetMethod("TransitionUpTo",BindingFlags.NonPublic | BindingFlags.Instance); method.Invoke(browser, new object[] {InPlaceActive});

суббота, 28 декабря 2019 г.

Самый быстрый (короткий) способ крашнуть вкладку [закрыт]

#javascript #jquery #framework #webbrowser #браузер


        
             
                
                    
                        
                            Закрыт. На этот вопрос невозможно дать объективный ответ.
Ответы на него в данный момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Update the question so it
can be answered with facts and citations by editing this post.
                        
                        Закрыт 6 месяцев назад.
                                                                                
           
                
        
Как, используя минимум символов, уронить вкладку браузера / уйти в вечный цикл или
рекурсию или что-то в этом духе?

Предлагайте свои варианты на чистом js или с использованием фреймворков.
    


Ответы

Ответ 1



Или такой цикл например :D while(1);

Ответ 2



Один из самых коротких способов открыл для себя недавно. Он на jquery. $($) *Спасибо всем, кто принял участие. Очень занятно было наблюдать за комментариями.

Ответ 3



19 символов for(let a;;a+=" ");

Ответ 4



Немного поигрался в консоли, написал банальное зацикливание. Пару секунд и страница мертвая. Я так понимаю заканчивается слишком большой объект получается. function crash(){ let i = 1; let a = {}; while (i > 0){ a[i] = i++; console.log(a); } } crash()

Ответ 5



Столько вариантов, предложу и я интересный) while(true) { window.open(); } for(;;) {}

воскресенье, 15 декабря 2019 г.

Почему поток с компонентом WebBrowser в цикле приводит к неработоспособности и росту памяти

#c_sharp #webbrowser


Поток с WebBrowser после определённой итерации зависает в ожидании примерно на 5
минут в коде потока:

while (wb.ReadyState != WebBrowserReadyState.Complete) 
  { System.Windows.Forms.Application.DoEvents(); }


где значение состояния равно: 

wb.ReadyState == Uninitialized или Interactive


в итоге возвращает страницу "Navigation canceled" - либо  возвращает её уже с 5 минутными
задержками.


Почему компонент WebBrowser использует IE как 7-ой версии, если у меня в системе
стоит IE8? 
Почему компонент WebBrowser перестаёт отдавать страницы?
Почему объём память растёт приложения и в итоге занимает около 800 мб?


У меня стоит задача сохранить отображение страницы на жёсткий диск, используя консольное
приложение. Возможно можно как-то в pdf или ещё в какой формат сохранить, чтобы можно
было увидеть содержимое HTML странцы.

Я задавал вопрос здесь но ненашёл где написать продолжение:)

Буду рад любому ценному комментарию.

    class Program
    {
    static string url = "http://www.whatbrowser.org";
    static int width = 960, height = 1380;
    static int count = 0;

    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("hi");

        try
        {
            int number = 1000;
            for (int i = 0; i < number; i++)
            {
                var th = new Thread(obj => RunGenerateScreenshotThread((string)obj));
                th.SetApartmentState(ApartmentState.STA);
                th.Start(url);
                th.Join();

                count++;
            }

            Console.WriteLine("All successfully completed!");
            Console.ReadKey(true);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: {0}", ex.ToString());
        }
    }

    static void RunGenerateScreenshotThread(string url)
    {
        try
        {
            using (WebBrowser wb = new WebBrowser())
            {
                // Set the size of the WebBrowser control
                wb.Width = width;
                wb.Height = height;

                //wb.DocumentCompleted += GenerateScreenshotCompleted;
                wb.Navigate(url);

                while (wb.ReadyState != WebBrowserReadyState.Complete) 
                  { System.Windows.Forms.Application.DoEvents(); }

                if (wb.DocumentTitle == "Navigation Canceled")
                    Console.WriteLine("Natigated ERROR {0}", count);
                else
                    Console.WriteLine("Natigated OK {0}", count);
                }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: {0}", ex.ToString());
        }
        finally
        {
            Application.ExitThread();   // Stops the thread
        }
    }
}

    


Ответы

Ответ 1



1) нужно явно включить использования для своего приложения, прописав в реестре ключик. 2) что третий вопрос является ответом на второй. 3) а вот это сложный вопрос. сейчас практически все браузеры кушают очень много. upd Как бы я сделал. Отдельное приложение, которое получает два параметра - урл и куда сохранить (можно через параметры, можно через пайп). Его задача проста - загрузил, заскриншотил и отдал. Второе приложение в цикле запускает первое, передавая ему параметры (на первых порах это может быть обычный батник). плюсы: очень легко получается сделать для разных версий IE - просто два приложения, для одного прописан правильный webbrowser падения "скриншотерра" безопасно для основного приложения. так как приложение закрывается каждый раз, то это такой "костыль" против утечек. минусы: возможно некое падение скорости (но это ещё нужно проверить) нужно следить за дочерними процессами

Ответ 2



Браузер можно запускать в отдельном Thread + Task. Работает в WinForms и Console Application using System; using System.Windows.Forms; using System.Threading; using System.Threading.Tasks; static Task Navigate(Uri url, Func callback) { var ts = new TaskCompletionSource(); var t = new Thread(() => { var wb = new WebBrowser() { AllowNavigation=true, ScriptErrorsSuppressed=true }; wb.DocumentCompleted += (s, e) => ts.SetResult(callback(wb.Document)); wb.Navigate(url); while (!ts.Task.IsCompleted) Application.DoEvents(); }); t.TrySetApartmentState(ApartmentState.STA); t.Start(); return ts.Task; } var t = Navigate(Uri("http://ru.stackoverflow.com"), doc => { return doc.Body.InnerHtml; // передается в t.Result });

Ответ 3



Есть еще одна проблема вот в этих строчках. while (wb.ReadyState != WebBrowserReadyState.Complete) { System.Windows.Forms.Application.DoEvents(); } В нормальном состоянии, при отсутствии событий программа засыпает и не расходует время процессора. Но ваш цикл так делать не умеет. Цикл обработки событий надо "крутить" через Application.Run, обязательно передав ему любую форму - тогда с процессорным временем все будет в порядке. Должно получиться примерно так: static void RunGenerateScreenshotThread(string url) { try { using (WebBrowser wb = new WebBrowser()) { // Set the size of the WebBrowser control wb.Width = width; wb.Height = height; wb.DocumentCompleted += (o, e) => Application.ExitThread(); wb.Navigate(url); Application.Run(new Form { Visible = false }); if (wb.DocumentTitle == "Navigation Canceled") Console.WriteLine("Natigated ERROR {0}", count); else Console.WriteLine("Natigated OK {0}", count); } } catch (Exception ex) { Console.WriteLine("Error: {0}", ex.ToString()); } } Наличие формы предотвращает немедленной выход из цикла обработки сообщений.

среда, 11 декабря 2019 г.

Посоветуйте маленький Linux в который можно установить браузер? [закрыт]

#linux #webbrowser #virtualbox


        
             
                
                    
                        
                            Closed. This question is opinion-based. It is not currently
accepting answers.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Want to improve this question? Update the question so
it can be answered with facts and citations by editing this post.
                        
                        Closed 3 года назад.
                                                                                
           
                
        
Занимаюсь веб-разработкой. Хочу иметь виртуальную машину в VirtualBox маленького
размера в которой будет только браузер Firefox/Chrome/etc. Всё остальное не нужно.
Ubuntu занимает гигабайты и тянет много лишнего. Мне нужна крайне компактная и оперативная
ВМ. На чем будет GUI не важно. Не нужны увесистые GNOME, KDE... Главное чтобы современный
браузер работал.
    


Ответы

Ответ 1



Как вариант легковесного Linux-а - это использование собственного docker-образа на базе Ubuntu с установленным браузером. Он не будет содержать ничего лишнего, кроме того, что вам необходимо. Для сборки docker-образа c установленным браузером firefox выполните следующее: Создайте Dockerfile FROM ubuntu:16.04 RUN apt-get update && apt-get install -y firefox # Replace 1000 with your user / group id RUN export uid=1000 gid=1000 && \ mkdir -p /home/developer && \ echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \ echo "developer:x:${uid}:" >> /etc/group && \ echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \ chmod 0440 /etc/sudoers.d/developer && \ chown ${uid}:${gid} -R /home/developer USER developer ENV HOME /home/developer CMD /usr/bin/firefox Из папки, где создали файл, выполните сборку образа docker build -t firefox . Запустите контейнер docker run -ti --rm \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ firefox После запуска контейнера у вас должен на экране запуститься firefox-браузер. Также в общедоступном репозитории docker-образов имеется готовый образ с предустановленным firefox-браузером. Можно воспользоваться им. Перейдя по ссылке, вы найдете параметры для запуска данного контейнера. https://hub.docker.com/r/chrisdaish/firefox/

Ответ 2



BrowserLinux - 93MB. Запускать следует из ISO-файла (т.н. LiveCD). Следовательно, после создания гостевой системы в VMWare - из ее оборудования нужно удалить все ненужное, в том числе и HDD. По поводу свежести версии браузера Данная Live-версия линукса позволяет произвести обновление FireFox в два этапа. В окошке "About" проверяем обновление и обновляемся с версии 5.0 до 12.0, повторяем те же самые действия и обновляемся с версии 12.0 до 45.0.2. Дальше браузер не обновляется, и дает линк на объяснения "почему". На момент написания этого сообщение - последняя версия FireFox 49.0.2 Учитывая, что данный дистрибутив Live-версии - единственный способ использования такой обновленной версии под управлением VMWare, это приостановка гостевой системы, и последующее ее возобновление. Иначе, понятное дело, все обновления пропадут.

Ответ 3



Поставь Arch linux.Он довольно легкий и сам по себе отличный.Цитата с википедии «легковесный», простой и гибкий дистрибутив Linux, оптимизированный для архитектур i686 и x86-64, использующий последние стабильные версии программ и дополняемый поддерживаемым сообществом репозиторием AUR. Arch «будет тем, что вы из него сделаете», и рассчитан не на новичков, а на более опытных пользователей.

четверг, 11 июля 2019 г.

Web vs. периферия

Дано: Web сервер и клиентское устройство. На клиентском устройстве имеются порты (COM, USB и тп.) через которые устройство получает данные от периферии (датчики, сенсоры и пр. оборудование) На устройстве доступен браузер, любые плагины к нему и, в принципе, возможно установить любое доп. п.о. Клиентских устройств много. Их кол-во заранее не известно.
Вопрос: С помощью каких технологий возможно реализовать первичную обработку и отображение данных с периферийных устройств в браузере на клиентской машине. Ну и передачу данных на сервер ? Дополнение: Есть ли что-то подходящее в .Net?
В качестве примера: Есть, скажем, датчики температуры, давления и влажности. Подключены к ПК по USB, COM и Ethernet. Я на данном пк открываю в браузере некоторую страницу на моём сервере и хочу чтобы на сервере по данным с датчиков был рассчитан, скажем, прогноз погоды на ближайший час или данные просто были занесены в БД для дальнейшей обработки и, при этом, не хочу ручками забивать показания датчиков в форму для отправки на сервер.


Ответ

Вам нужно разрабатывать кроссплатформенное ПО для ваших устройств. Технологий тьма что-то конкретное советовать сложно, нужно знать требования по архитектуре и производительности. (С++ Qt/Poco, Python, NodeJS..., если win можно и .net ) Софт этот будет вести сбор данных и передавать на удаленный сервер(HTTP-REST или Websocket). Браузер я вобще не понял зачем тут. На вашем удаленном сервере необходимо организовать бекенд для веб-сервера который будет вести пост обработку. Тут что-то советовать по технологиям, тоже сложно. Не понятно под какой ос сервер и какие требования по произоводительности.

среда, 10 июля 2019 г.

Приложение убирает фокус

Написал небольшого бота, который переходит по ссылкам. Добавил возможность сворачивать в трей, дабы не мешалось. Так вот, когда приложение находится в трее и совершает клик, то с других окон снимается фокус, это доставляет дискомфорт. Сижу, например, в браузере, что-то печатаю, и тут бах - с браузера снимается фокус и нужно заново нажимать на текстовое поле. Если просто свернуть приложение, то такого не происходит. Есть ли способ избавиться от этого?
Клик осуществляется так: element.InvokeMember("Click");


Ответ

WebBrowser действительно может похищать фокус, когда URL загружается.
Для предотвращения этого, перез загрузкой следует устанавливать свойство Enabled родительского для браузера контрола в значение false;. А после её завершения, в событии DocumentCompleted, обратно устанавливать в значение true

понедельник, 17 июня 2019 г.

Как правильно перехватывать нажатия клавиш в Windows Forms (C++)?

На Form есть DataGridView (в нём показывается одна строка) и WebBrowser
У Form на Event keyDown есть обработчик, который срабатывает на нажатие F2, который записывает слово в определенную ячейку. Этот же обработчик привязан к DataGridView
private: System::Void CSV_WViewForm_KeyDown( System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) { if (e->KeyCode == Keys::F2) /*Do something*/; }
Необходимо, чтобы нажатие на F2 срабатывало всегда и сразу (с первого раза). Для этого я воспользовался свойством KeyPreview = false; (пробовал устанавливать его в true - не помогало).
protected: virtual bool ProcessCmdKey(Message% msg, Keys keyData) override { if (keyData == Keys::F2) { this->dataGridView1->Focus(); return Form::ProcessCmdKey(msg, keyData); } return Form::ProcessCmdKey(msg, keyData); }
Но когда Focus находится в WebBrowser, F2 не всегда срабатывает (иногда приходится нажимать F2 дважды). Как это победить?
Проект Windows Forms (C++, Visual Studio 2015)


Ответ

Если уж перехватываете ввод пользователя на уровне формы, то там его и обрабатывайте. Простой тестовый проект с эквивалентным кодом на C# показал следующее:
Если элемент в фокусе, все отрабатывает как надо. Если элемент не в фокусе и мы предварительно на уровне формы переключаем фокус на другой элемент, то событие о нажатой клавише уходит тому элементу, который был в фокусе во время нажатия на клавишу, что в принципе логично. Отсюда и необходимость второго нажатия на клавишу, т.к. первое нажатие отрабатывает только передачу фокуса и уходит предыдущему владельцу фокуса.
Что делать?
Перенести всю обработку клавиш, которые перехватываются на уровне формы, в код перехвата (в ProcessCmdKey), чтобы не загромождать код, сделать это в виде вызова отдельных методов для каждой перехватываемой клавиши.
Изменить ваш код можно так:
virtual bool ProcessCmdKey(Message% msg, Keys keyData) override { if (keyData == Keys::F2) { this->dataGridView1->Focus();
//do somthing for F2-key
return true; } return Form::ProcessCmdKey(msg, keyData); }
или через switch - case если клавиш много. И не забываем удалить лишние обработчики или исключить из них обработку клавиш, перехватываемых на уровне формы.

понедельник, 10 июня 2019 г.

Ни с одного браузера не скачивается файл

Знаю, это напрямую не связано с программированием, тем не менее, проблема есть. https://2appstudio.com/journey/ Вот с этого сайта не могу скачать ни 32-, ни 64-битную версию для Windows. Тоже самое и в Firefox, примерно. Помогите, пожалуйста. Программа уж больно понравилась. Спасибо заранее.


Ответ

Настроить хром так, чтобы он не удалял подозрительные файлы самостоятельно: https://superuser.com/questions/387724/how-to-disable-download-scanning-protection-of-new-chrome-17 Выбрать сохранение скачанного файла в следующем запросе:

четверг, 30 мая 2019 г.

C# webbrowser как двигать скрол?

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


Ответ

Еще способы:
WebBrowser.Document.Window.ScrollTo(int x, int y); WebBrowser.Navigate("javascript:window.scroll(...);");

среда, 8 мая 2019 г.

Шутки браузеров: криво работает php валидация?

Я тестирую в основном сайт в Google Chrome (посл. версия), и только что заметил, что Opera (последняя версия) позволяет обойти ОБЯЗАТЕЛЬНОЕ ТРЕБОВАНИЕ заполнить возраст. Просто игнорирует это поле и даже успешно отправляется форма и тп.
Ссылка на форму
А также наверно какие-то старые браузеры умудряются еще регать людей с НЕВОЗМОЖНЫМ значением пола, например.
Т.е. Опера в данном случае игнорит и JS, и PHP валидацию. Это вообще законна такая работа PHP и браузеров?
Использую rules:
$rules[] = array( 'gender', 'required', 'message' => 'Укажите пол' ); $rules[] = array( 'birthYear', 'required', 'message' => 'Укажите год рождения' ); $rules[] = array('gender', 'in', 'range' => array("f", "m", "?"), 'message' => 'Укажите пол.');
Обновление
Добавил еще правило:
$rules[] = array( 'birthYear', 'length', 'min'=>$AGE_START, 'max'=>$AGE_END, 'tooShort' => 'Укажите год рождения', 'tooLong' => 'Укажите год рождения', );
Опера перестала глючить.


Ответ

К вам на сервер от клиента (в данном случае браузер) могут прийти какие угодно данные. Валидация данных всегда должна быть на сервере помимо JS. Если у вас регистрация проходит даже без обязательных полей, значит у вас некорректный PHP код с валидацией.
UPD
Лучше не обращаться к массиву $_POST напрямую. К тому же, в вашем выпадающем списке есть пустое значение. Один браузер его вам посылает, другой нет. Получается при обращении к $_POST['Form']['gender'] у вас в одном случае строка пустая, в другом случае null (не факт, это моё предположение).
Проверьте $_POST массив в контроллере в разных браузерах:
var_dump($_POST); die();
Вам может помочь либо метод saveAttributes(), либо как минимум проверка на пустое значение:
if(isset($_POST['Form']['gender']) && $_POST['Form']['gender'] != '') { $form->gender = $_POST['Form']['gender']; }

вторник, 12 марта 2019 г.

Как получить событие LoadCompleted контрола WebBrowser, не вставляя данный контрол в XAML?

У меня нет потребности использовать WebBrowser в XAML, мне он нужен всего лишь для того что бы иметь возможность вызвать событие Click на одном из тегов загруженной HTML страницы.
Я не могу вызывать событие Click на нужном мне теге, до того как загрузиться страница. Для того что бы получить уведомление о загрузке страницы мне нужно подписаться на событие LoadCompleted. Но, судя из того что я вижу событие LoadCompleted не генерируется пока WebBrowser не будет добавлен в XAML.
По причине того что я хочу осуществлять загрузку множества HTML страниц параллельно, перспектива постоянно добавлять WebBrowser контрол в разметку XAML до загрузки одной из множества страниц и удаление его из этой разметки после загрузки нужной страницы выглядит не очень удобно.
Моя цель получить доступ к вызову события Click на загруженной HTML странице без возни с ХАМL.
Можно ли получить доступ к событию LoadCompleted контрола WebBrowser без его привязки к XAML. Возможно ли это? Может быть есть какой то другой путь?
Код отражающий суть проблемы (WebBrowser в XAML не добавлялся)
public partial class SettingsWindow : Window { private WebBrowser browser = new WebBrowser();
public SettingsWindow() { InitializeComponent();
this.browser.LoadCompleted += Browser_LoadCompleted; this.browser.Source = new Uri(@"https://www.google.com.ua/"); //this.browser.Navigate(path); <-- пробовал загружать страницу и этим способом. }
private void Browser_LoadCompleted(object sender, NavigationEventArgs e) { // Этот обработчик никогда не вызывается если объект WebBrowser не // добавлен в XAML или не добавлен программным путем в качестве // дочернего компонента к одному из существующих контролов окна. } }


Ответ

Действительно, событие LoadCompleted для WPF WebBrowser не вызывается до тех пор, пока он не добавлен в какое-либо отображаемое окно или элемент управления, это известная проблема. Причина ее в том, как WebBrowser осуществляет инициализацию своего внутреннего ActiveX-элемента Internet Explorer, который и занимается загрузкой страницы. Это можно понять, посмотрев в его исходный код на Reference Source.
Для корректной работы события DocumentCompleted внутреннего ActiveX-объекта класс ActiveXHost должен быть переведен в состояние ActiveXState.InPlaceActive. По умолчанию он находится в ActiveXState.Running (см. инициализацию свойства), переход в состояние InPlaceActive происходит при вызове метода BuildWindowCore, который вызывается только при отображении родительского окна элемента. Это поведение отличается от аналогичного элемента в WinForms, который сразу переводится в InPlaceActive при инициализации, см. здесь)
Решение 1 - Использование WinForms WebBrowser
Элемент WebBrowser в WinForms избавлен от этой проблемы (аналогичное событие DocumentCompleted всегда вызывается), и функционально ни в чем не уступает элементу из WPF. Можно просто добавить ссылку на System.Windows.Forms и использовать его.
Решение 2 - Использование окна за пределами экрана
Для вызова BuildWindowCore требуется видимое окно, однако никто не запрещает сделать координаты отрицательными и поместить окно за пределы экрана:
Window wnd = new Window(); wnd.Content = browser; wnd.ShowInTaskbar = false; wnd.Top = -1000; wnd.Left = -1000; wnd.Width = 0; wnd.Height = 0; wnd.Show();
Решение 3 - Грязный хак с использованием отражения
Просто вызвать внутренний метод TransitionUpTo, передав в качества аргумента константу InPlaceActive (4):
using System.Reflection; const int InPlaceActive = 4;
//...
var method = browser.GetType().GetMethod("TransitionUpTo",BindingFlags.NonPublic | BindingFlags.Instance); method.Invoke(browser, new object[] {InPlaceActive});