我想在控制台应用程序上使用 AxWebBrowser,但它给了我以下异常:
引发了“System.Windows.Forms.AxHost+InvalidActiveXStateException”类型的异常。
任何人请通过任何示例代码帮助我在控制台应用程序 c# 中使用 AxWebBrowser 没有任何异常...
我想在控制台应用程序上使用 AxWebBrowser,但它给了我以下异常:
引发了“System.Windows.Forms.AxHost+InvalidActiveXStateException”类型的异常。
任何人请通过任何示例代码帮助我在控制台应用程序 c# 中使用 AxWebBrowser 没有任何异常...
是的,您的 Main() 方法需要 [STAThread] 属性,以便正确初始化 COM 以使主线程成为单线程单元。但这还不是全部,您还需要泵送消息循环。这是对 STA 的要求。没有它,WebBrowser 将无法更新其状态或运行其事件处理程序,例如,您将永远无法获得 DocumentCompleted 事件。您可以使用 Application.Run() 获得消息循环。
您的控制台应用程序现在与 Windows 窗体应用程序没有区别。通过使用 Windows 窗体应用程序项目模板开始一个新项目,然后是项目 + 属性,输出类型 = 控制台应用程序,实际上更容易得到正确的结果。编辑 Program.cs 中的 Application.Run() 调用,使其不会创建表单。它不会使处理 Application.Run() 变得更容易,考虑一个 Timer 来运行代码。
将STAThread
属性添加到您的Main
方法中。
但是,您不应该使用“原始”ActiveX 控件。
相反,添加对 System.Windows.Forms.dll 的引用并使用WebBrowser
该类。(是的,您可以在控制台应用程序中执行此操作)
此外,自动化 IE 并不理想。您应该考虑使用WebCLient
该类。
我的课程如下,但在运行时它给了我 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;
}
}
首先,托管控件的线程必须在单线程单元中,您可以将其放在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();
}
}