Как использовать AxWebBrowser в консольном приложении

Я хочу использовать AxWebBrowser в консольном приложении, но это дает мне следующее исключение:

Возникло исключение типа «System.Windows.Forms.AxHost+InvalidActiveXStateException».

кто-нибудь, пожалуйста, помогите мне в этом любым примером кода для использования AxWebBrowser в консольном приложении С# без каких-либо исключений...


person mohsen asfia    schedule 24.01.2010    source источник
comment
Создайте свой проект для x86 вместо x64.   -  person Lieven Cardoen    schedule 05.02.2010


Ответы (4)


Да, атрибут [STAThread] необходим в вашем методе Main(), чтобы COM правильно инициализировался, чтобы сделать основной поток однопоточным апартаментом. Это еще не все, вам также нужно будет прокачать цикл сообщений. Это требование для STA. Без него WebBrowser не может обновлять свое состояние или запускать обработчики событий, например, вы никогда не получите событие DocumentCompleted. Вы можете получить цикл сообщений с помощью Application.Run().

Ваше консольное приложение теперь неотличимо от приложения Windows Forms. На самом деле проще сделать все правильно, начав новый проект с шаблоном проекта приложения Windows Forms, затем Project + Properties, Output type = Console Application. Отредактируйте вызов Application.Run() в Program.cs, чтобы он не создавал форму. Это не упростит работу с Application.Run(), рассмотрите Timer для запуска кода.

person Hans Passant    schedule 24.01.2010

Добавьте атрибут STAThread к методу Main.

Однако не следует использовать «сырой» элемент управления ActiveX.

Вместо этого добавьте ссылку на System.Windows.Forms.dll и используйте WebBrowser. (Да, вы можете сделать это в консольном приложении)


Кроме того, автоматизация IE не идеальна. Вам следует рассмотреть возможность использования класса WebCLient.

person SLaks    schedule 24.01.2010
comment
Спасибо, но на самом деле у меня есть класс с именем Browse, который программа консольного приложения вызывает свой метод StartBrowse с входным параметром url, и в этой функции я должен просматривать этот url, выполнять некоторую обработку и возвращать некоторые результаты, поэтому куда я должен поместить атрибут [STAThread]? Я поместил его перед методом StartBrowse, но он дает мне то же исключение во время выполнения! - person mohsen asfia; 24.01.2010
comment
Вам нужно применить его к методу Main. - person SLaks; 24.01.2010

Мой класс такой, как показано ниже, но во время выполнения он дает мне System.Windows.Forms.AxHost+InvalidActiveXStateException:

public class Browse
{

    private static AxWebBrowser wBrowser;         
    public static Result StartBrowse(string url)
    {
        var validUri = (url.Contains("http://") ? url : "http://" + url);
        wBrowser = new AxWebBrowser();

        System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(AxWebBrowser));

        ((ISupportInitialize) (wBrowser)).BeginInit();
        wBrowser.OcxState = ((AxHost.State)(resources.GetObject("wBrowser.OcxState")));

        wBrowser.NewWindow2 += wBrowser_NewWindow2;
        wBrowser.NewWindow3 += wBrowser_NewWindow3;
        wBrowser.DocumentComplete += wBrowser_DocumentComplete;
        wBrowser.DownloadComplete += wBrowser_DownloadComplete;
        if (string.IsNullOrEmpty(html) || validUri != url)
        {
            object empty = System.Reflection.Missing.Value;
            wBrowser.Silent = true;
            wBrowser.Navigate(validUri, ref empty, ref empty, ref empty, ref empty);
        }
        return null;
    }

    static void wBrowser_DownloadComplete(object sender, EventArgs e)
    {
        doAlgorithm();
    }

    static void wBrowser_DocumentComplete(object sender, DWebBrowserEvents2_DocumentCompleteEvent e)
    {
        doAlgorithm();
    }

    static void wBrowser_NewWindow3(object sender, DWebBrowserEvents2_NewWindow3Event e)
    {
        e.cancel = true;
    }

    static void wBrowser_NewWindow2(object sender, DWebBrowserEvents2_NewWindow2Event e)
    {
        e.cancel = true;
    }
}
person mohsen asfia    schedule 24.01.2010

Во-первых, поток, в котором размещен элемент управления, должен находиться в однопоточном апартаменте, вы можете либо поместить STAThread в метод Main, либо создать отдельный поток следующим образом:

var thread = new Thread(() =>
{
   //My code
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join(); //Wait for thread termination

Во-вторых, вы должны запустить цикл сообщений:

while (true) //Put some exit condition
    System.Windows.Forms.Application.DoEvents();

В-третьих, элемент управления должен быть размещен в видимой форме. Форма должна быть видна только один раз, поэтому, чтобы избежать «мерцания», вы можете написать этот код:

var browser = new AxWebBrowser();
var hostForm = new Form();
//Set form 0 size, without any control box / title / icon
hostForm.Width = 0;
hostForm.Height = 0;
hostForm.ShowInTaskbar = false;
hostForm.ControlBox = false;
hostForm.ShowIcon = false;
hostForm.MinimizeBox = false;
hostForm.MaximizeBox = false;
//Add browser control
hostForm.Controls.Add(browser);
//Show and immediately hide
hostForm.Show();
hostForm.Hide();

Наконец, вы можете отключить звук щелчка (Как отключить щелчок звук в WebBrowser Control)

Окончательный код:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        URLSecurityZoneAPI.InternetSetFeatureEnabled(URLSecurityZoneAPI.InternetFeaturelist.DISABLE_NAVIGATION_SOUNDS, URLSecurityZoneAPI.SetFeatureOn.PROCESS, true);

        var browser = new AxWebBrowser();
        var hostForm = new Form();
        hostForm.Width = 0;
        hostForm.Height = 0;
        hostForm.ShowInTaskbar = false;
        hostForm.ControlBox = false;
        hostForm.ShowIcon = false;
        hostForm.MinimizeBox = false;
        hostForm.MaximizeBox = false;
        hostForm.Controls.Add(browser);
        hostForm.Show();
        hostForm.Hide();

        browser.DocumentComplete += delegate(object sender, DWebBrowserEvents2_DocumentCompleteEvent e)
        {
            var doc = (IHTMLDocument3)browser.Document;
            Console.WriteLine(doc.documentElement.innerHTML);
        };

        browser.Navigate("www.google.com");

        while (true) 
            System.Windows.Forms.Application.DoEvents();
    }
}
person Andrea Guerrieri    schedule 22.02.2014