在 WebBrowser 中打开多个页面并向所有页面发送命令
Open multiple pages in WebBrowser and send a command to all of them
我有一个具有以下功能的 winform 应用程序:
- 有一个 多行文本框 每行包含一个 URL - 大约 30 URL 秒(每个 URL 是不同的,但网页相同(只是域不同);
- 我有另一个文本框,我可以在其中编写一个命令和一个按钮,用于将该命令发送到来自网页的输入字段 .
- 我有一个 WebBrowser 控制器(我想在 一个 控制器中做所有事情)
该网页由一个文本框和一个按钮组成,我希望在该文本框中插入命令后单击该按钮。
到目前为止我的代码:
//get path for the text file to import the URLs to my textbox to see them
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fbd1 = new OpenFileDialog();
fbd1.Title = "Open Dictionary(only .txt)";
fbd1.Filter = "TXT files|*.txt";
fbd1.InitialDirectory = @"M:\";
if (fbd1.ShowDialog(this) == DialogResult.OK)
path = fbd1.FileName;
}
//import the content of .txt to my textbox
private void button2_Click(object sender, EventArgs e)
{
textBox1.Lines = File.ReadAllLines(path);
}
//click the button from webpage
private void button3_Click(object sender, EventArgs e)
{
this.webBrowser1.Document.GetElementById("_act").InvokeMember("click");
}
//parse the value of the textbox and press the button from the webpage
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
newValue = textBox2.Text;
HtmlDocument doc = this.webBrowser1.Document;
doc.GetElementById("_cmd").SetAttribute("Value", newValue);
}
现在,我如何将我的文本框中的所有这 30 URL 添加到同一个网络控制器中,以便我可以将相同的命令发送到所有网页中的所有文本框,然后按下按钮全部 ?
//编辑 1
所以,我采用了@Setsu 方法并创建了以下内容:
public IEnumerable<string> GetUrlList()
{
string f = File.ReadAllText(path); ;
List<string> lines = new List<string>();
using (StreamReader r = new StreamReader(f))
{
string line;
while ((line = r.ReadLine()) != null)
lines.Add(line);
}
return lines;
}
现在,为了解析每个 URL,这是 return 它应该 return 的内容吗?
如果您只想继续使用 1 个 WebBrowser 控件,则必须按顺序导航到每个 URL。但是请注意,WebBrowser class 的 Navigate
方法是异步的,因此您不能天真地在循环中调用它。您最好的选择是实施此答案 here.
中详述的 async/await 模式
或者,您可以拥有 30 个 WebBrowser 控件并让每个控件独立导航;这大致相当于在现代浏览器中打开 30 个选项卡。由于每个 WebBrowser 都在做相同的工作,您可以只编写 1 DocumentCompleted
事件来处理单个 WebBrowser,然后将其他事件连接到同一事件。请注意 WebBrowser 控件有一个错误,会导致它逐渐泄漏内存,解决此问题的唯一方法是重新启动应用程序。因此,我建议使用 async/await 解决方案。
更新:
这是一个简短的代码示例,说明如何使用 30 个 WebBrowsers 方式(未经测试,因为我现在无法访问 VS):
List<WebBrowser> myBrowsers = new List<WebBrowser>();
public void btnDoWork(object sender, EventArgs e)
{
//This method starts navigation.
//It will call a helper function that gives us a list
//of URLs to work with, and naively create as many
//WebBrowsers as necessary to navigate all of them
IEnumerable<string> urlList = GetUrlList();
//note: be sure to sanitize the URLs in this method call
foreach (string url in urlList)
{
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += webBrowserDocumentCompleted;
browser.Navigate(url);
myBrowsers.Add(browser);
}
}
private void webBrowserDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//check that the full document is finished
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
//get our browser reference
WebBrowser browser = sender as WebBrowser;
//get the string command from form TextBox
string command = textBox2.Text;
//enter the command string
browser.Document.GetElementById("_cmd").SetAttribute("Value", command);
//invoke click
browser.Document.GetElementById("_act").InvokeMember("click");
//detach the event handler from the browser
//note: necessary to stop endlessly setting strings and clicking buttons
browser.DocumentCompleted -= webBrowserDocumentCompleted;
//attach second DocumentCompleted event handler to destroy browser
browser.DocumentCompleted += webBrowserDestroyOnCompletion;
}
private void webBrowserDestroyOnCompletion(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//check that the full document is finished
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
//I just destroy the WebBrowser, but you might want to do something
//with the newly navigated page
WebBrowser browser = sender as WebBrowser;
browser.Dispose();
myBrowsers.Remove(browser);
}
我有一个具有以下功能的 winform 应用程序:
- 有一个 多行文本框 每行包含一个 URL - 大约 30 URL 秒(每个 URL 是不同的,但网页相同(只是域不同);
- 我有另一个文本框,我可以在其中编写一个命令和一个按钮,用于将该命令发送到来自网页的输入字段 .
- 我有一个 WebBrowser 控制器(我想在 一个 控制器中做所有事情)
该网页由一个文本框和一个按钮组成,我希望在该文本框中插入命令后单击该按钮。
到目前为止我的代码:
//get path for the text file to import the URLs to my textbox to see them
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fbd1 = new OpenFileDialog();
fbd1.Title = "Open Dictionary(only .txt)";
fbd1.Filter = "TXT files|*.txt";
fbd1.InitialDirectory = @"M:\";
if (fbd1.ShowDialog(this) == DialogResult.OK)
path = fbd1.FileName;
}
//import the content of .txt to my textbox
private void button2_Click(object sender, EventArgs e)
{
textBox1.Lines = File.ReadAllLines(path);
}
//click the button from webpage
private void button3_Click(object sender, EventArgs e)
{
this.webBrowser1.Document.GetElementById("_act").InvokeMember("click");
}
//parse the value of the textbox and press the button from the webpage
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
newValue = textBox2.Text;
HtmlDocument doc = this.webBrowser1.Document;
doc.GetElementById("_cmd").SetAttribute("Value", newValue);
}
现在,我如何将我的文本框中的所有这 30 URL 添加到同一个网络控制器中,以便我可以将相同的命令发送到所有网页中的所有文本框,然后按下按钮全部 ?
//编辑 1 所以,我采用了@Setsu 方法并创建了以下内容:
public IEnumerable<string> GetUrlList()
{
string f = File.ReadAllText(path); ;
List<string> lines = new List<string>();
using (StreamReader r = new StreamReader(f))
{
string line;
while ((line = r.ReadLine()) != null)
lines.Add(line);
}
return lines;
}
现在,为了解析每个 URL,这是 return 它应该 return 的内容吗?
如果您只想继续使用 1 个 WebBrowser 控件,则必须按顺序导航到每个 URL。但是请注意,WebBrowser class 的 Navigate
方法是异步的,因此您不能天真地在循环中调用它。您最好的选择是实施此答案 here.
或者,您可以拥有 30 个 WebBrowser 控件并让每个控件独立导航;这大致相当于在现代浏览器中打开 30 个选项卡。由于每个 WebBrowser 都在做相同的工作,您可以只编写 1 DocumentCompleted
事件来处理单个 WebBrowser,然后将其他事件连接到同一事件。请注意 WebBrowser 控件有一个错误,会导致它逐渐泄漏内存,解决此问题的唯一方法是重新启动应用程序。因此,我建议使用 async/await 解决方案。
更新:
这是一个简短的代码示例,说明如何使用 30 个 WebBrowsers 方式(未经测试,因为我现在无法访问 VS):
List<WebBrowser> myBrowsers = new List<WebBrowser>();
public void btnDoWork(object sender, EventArgs e)
{
//This method starts navigation.
//It will call a helper function that gives us a list
//of URLs to work with, and naively create as many
//WebBrowsers as necessary to navigate all of them
IEnumerable<string> urlList = GetUrlList();
//note: be sure to sanitize the URLs in this method call
foreach (string url in urlList)
{
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += webBrowserDocumentCompleted;
browser.Navigate(url);
myBrowsers.Add(browser);
}
}
private void webBrowserDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//check that the full document is finished
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
//get our browser reference
WebBrowser browser = sender as WebBrowser;
//get the string command from form TextBox
string command = textBox2.Text;
//enter the command string
browser.Document.GetElementById("_cmd").SetAttribute("Value", command);
//invoke click
browser.Document.GetElementById("_act").InvokeMember("click");
//detach the event handler from the browser
//note: necessary to stop endlessly setting strings and clicking buttons
browser.DocumentCompleted -= webBrowserDocumentCompleted;
//attach second DocumentCompleted event handler to destroy browser
browser.DocumentCompleted += webBrowserDestroyOnCompletion;
}
private void webBrowserDestroyOnCompletion(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//check that the full document is finished
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
//I just destroy the WebBrowser, but you might want to do something
//with the newly navigated page
WebBrowser browser = sender as WebBrowser;
browser.Dispose();
myBrowsers.Remove(browser);
}