C # WebBrowser operations and precautions

Source: Internet
Author: User

1. To use WebBrowser in Winform, add some things to Form1.cs:
1.1 Add:

Copy codeThe Code is as follows: [PermissionSet (SecurityAction. Demand, Name = "FullTrust")]
[System. Runtime. InteropServices. ComVisibleAttribute (true)]

1.2 In the Shown event of Form1, add:

Copy codeThe Code is as follows: this. UI_webBrowser.ObjectForScripting = this;

2. because WebBrowser is placed in the Winform interface, it is managed by the interface thread (main thread), and rendering execution is also the main thread. Therefore, you should open another thread instead of putting the business logic in the main thread, execute the business logic. And use Invoke to interact with WebBrowser.

Example:

Copy codeThe Code is as follows: private void Form1_Shown (object sender, EventArgs e)
{
This. _ thread_mainLogic = new Thread (this. ThreadFunction_MainLogic );
This. _ thread_mainLogic.Start ();
}

Private void ThreadFunction_MainLogic ()
{
Debugger. Log (0, "", "\ r \ n start to execute business logic \ r \ n ");
This. Invoke (new Action () => {this. webBrowser. Navigate ("http://www.baidu.com") ;}); // interacts with webBrowser through Invoke
.....
}

3. Browse the specified URL. Note: This method is asynchronous and needs to be synchronized manually.

Copy codeThe Code is as follows: // The following method is not a thread security method.
Private AutoResetEvent _ threadControlEvent_Tool_webBrowser_Navigate = null;

Private void Tool_webBrowser_Navigate (string arg_URL)
{
This. _ threadControlEvent_Tool_webBrowser_Navigate = new AutoResetEvent (false );
This. Invoke (new Action () =>
{
This. webBrowser. DocumentCompleted + = webBrowser_DocumentCompleted_Tool_webBrowser_Navigate;
This. webBrowser. Navigate (arg_URL );
}));
This. _ threadControlEvent_Tool_webBrowser_Navigate.WaitOne ();
This. _ threadControlEvent_Tool_webBrowser_Navigate.Close ();
This. _ threadControlEvent_Tool_webBrowser_Navigate.Dispose ();
}

Void webBrowser_DocumentCompleted_Tool_webBrowser_Navigate (object sender, WebBrowserDocumentCompletedEventArgs e)
{
This. webBrowser. DocumentCompleted-= webBrowser_DocumentCompleted_Tool_webBrowser_Navigate;
This. _ threadControlEvent_Tool_webBrowser_Navigate.Set ();
}

4. Obtain the button Based on the ID and click it: (it can also act on the URL link in the webpage)

Copy codeThe Code is as follows: // assume that the button in the webpage is ID "btn"
HtmlElement element_btn = null;
This. Invoke (new Action () => {element_btn = this. UI_webBrowser.Document.All ["btn"] ;})); // get
Element_btn.InvokeMember ("Click"); // Click. This method is synchronous and can be safely used.

5. Obtain the input box based on the ID and enter the content.

Copy codeThe Code is as follows: // assume that the input box in the webpage has the ID of "input"
HtmlElement input = null;
This. Invoke (new Action () => {input = this. UI_webBrowser.Document.All ["input"] ;})); // get
Input. InnerText = "123"; // enter "123 ". This method is not a synchronous method. You need to use the Wait_SafeMode method below.
Tool_Wait_SafeMode (); // The implementation is as follows:

6. Obtain the form based on the ID and submit (submit)

Copy codeThe Code is as follows: // assume that the form in the webpage has the ID of "form2"
HtmlElement form2 = null;
This. Invoke (new Action () => {form2 = this. UI_webBrowser.Document.Forms ["form2"] ;})); // get
Form_submit.InvokeMember ("submit"); // submit the content in form2. This method is synchronous and can be used safely.

7. Get the CheckBox according to the ID and set it to Checked)

Copy codeThe Code is as follows: // assume the CheckBox in the webpage with the ID "checkbox5"
HtmlElement checkBox5 = null;
This. Invoke (new Action () => {checkBox5 = this. UI_webBrowser.Document.All ["checkbox5"] ;})); // get
CheckBox5.SetAttribute ("Checked", "true"); // set it to selected. This method is synchronous and can be used safely.

8. Find the element based on its known attributes.

Copy codeThe Code is as follows: // assume that there is only one element in the webpage: it has an attribute named "value" and the attribute value is "12345"
Bool isFind = false;
HtmlElementCollection htmlElementCollection = null;
This. Invoke (new Action () =>{ htmlElementCollection = this. webBrowser. Document. All;}); // gets the set
HtmlElement resultElement = null;

Foreach (HtmlElement currentElement in htmlElementCollection) // traverses all elements in the collection to find
{
If (currentElement. GetAttribute ("value") = "12345 ")
{
IsFind = true;
ResultElement = currentElement;
Break;
}
}

If (! IsFind)
{
Handle situations that cannot be found;
}

9. Set ComboBox in the webpage. Note: Please do not use the following code. Because SetAttribute is an API that does not respond, we recommend that you set it using js. Next, let WebBrowser execute js Code, and callback can be implemented.

Copy codeThe Code is as follows: // assume that a ComboBox with the ID "comboBox123" exists in the webpage. The drop-down menu has two items:
// The ID of the first item is 1, and the value is "apple"
// The ID of the second item is 2, and the value is "watermelon"
HtmlElement element_comboBox = null;
This. Invoke (new Action () => {element_comboBox = this. webBrowser. Document. All ["comboBox123"] ;})); // get
Tool_Wait_SafeMode ();
This. Invoke (new Action () => {element_combox.setattribute ("value", "2") ;}); // set it to "watermelon", that is, value = 2
Tool_Wait_SafeMode ();

10. Tool_Wait_SafeMode

Copy codeThe Code is as follows: private void Tool_Wait_SafeMode ()
{
Bool isError = false;
Bool isBusy = false;
Do
{
This. Invoke (new Action () =>
{
Try
{
IsBusy = this. webBrowser. IsBusy;
}
Catch (System. Exception ex)
{
IsError = true;
}
}));
If (isError)
{
Thread. Sleep (errorWaitTime); // we recommend that you set it to more than 2 seconds. This time must be set based on the machine performance.
}
Else
{
If (isBusy)
{
Thread. Sleep (arg_waitTime); // we recommend that you set this parameter to more than 0.1 seconds. This time should be set according to the machine performance, and can be set to a shorter value.
}
}
}
While (isError | isBusy );
}

11. Execute js Code on the webpage

WebBrowser execution of js is an asynchronous process and callback is required. Therefore, this function is complicated. This is encapsulated into a synchronization process for ease of use:

Copy codeThe Code is as follows: # region private void Tool_webBrowser_ExecUserJSScript (string arg_jsCodes)
Private AutoResetEvent _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Init = null;
Private AutoResetEvent _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Exec = null;
Private object _ returnObj_Tool_webBrowser_ExecUserJSScript = null;

/// <Summary>
/// Use WebBrowser to execute JS custom statements.
/// 1: Define a js method. The method name should be as special as possible to avoid duplicate names with existing js methods in html. At the end of this method, you must use window. external. yycsharpcomplete (msg); To notify CSharp after js execution is complete. Pass this method to the arg_jsFunctionDefineCodes parameter.
/// 2: Pass the method name of this method to the parameter arg_jsFunctionName.
/// 3: Pass the parameters required for this method to arg_functionArgs. If you do not need to input a parameter, you do not need to assign a value to this field, or assign a value to null, or assign a value to new object [] {}.
/// 4: If js does not need to return parameters when calling C #, use window in the js method. external. notifyCSharpComplete (null); if any parameter is returned, it can be changed to window. external. notifyCSharpComplete (parameter variable );
// Example: js method: function jsFunctionTest (arg1, arg2) {var arg3 = arg1 + arg2; window. external. policycsharpcomplete ("Operation Result:" + arg3 );}
/// Then arg_jsFunctionDefineCodes = "function jsFunctionTest (arg1, arg2) {var arg3 = arg1 + arg2; window. external. yycsharpcomplete (\ "Operation Result: \" + arg3 );}";
/// Arg_jsFunctionName = jsFunctionTest
/// If the parameters to be passed are 123 and 456, arg_functionArgs = new object [] {123,456}
/// Return value, which is returned through object. If the object is of another type, convert it by yourself. For example, stirng result = (string) Tool_webBrowser_ExecUserJSScript (...);
/// </Summary>
/// <Param name = "arg_jsFunctionDefineCodes"> js method. Note that the total length cannot exceed 1991 (the total length cannot exceed 2048, and some content is added to the program .) </Param>
/// <Param name = "arg_jsFunctionName"> Method name of the js method </param>
/// <Param name = "arg_functionArgs"> list of parameters of the js method. If you do not need to input a parameter, you do not need to assign a value to this field, or assign a value to null, or assign a value to new object [] {}</param>
/// <Returns> returns the execution result. Note: The Return parameter is used by default. If no response is returned, modify the js method and change NotifyCSharpComplete (msg) to NotifyCSharpComplete (null) </returns>
Private object Tool_webBrowser_ExecUserJSScript (string arg_jsFunctionDefineCodes, string arg_jsFunctionName, object [] arg_functionArgs = null)
{
This. _ returnObj_Tool_webBrowser_ExecUserJSScript = null;
If (arg_jsFunctionDefineCodes.Length> 1991)
{
Throw new Exception ("error: the js method definition length exceeds 1991. ");
}
// 1. Write the js method.
Arg_jsFunctionDefineCodes = "javascript:" + arg_jsFunctionDefineCodes + "; window. external. policycsharpcompleteinit ();";
If (arg_jsFunctionDefineCodes.Length> = 2048)
{
Throw new Exception ("error: the total length of the js method definition exceeds 2048 (original method + added content ). ");
}
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Init = new AutoResetEvent (false );
This. Invoke (new Action () =>
{
This. webBrowser. Navigate (arg_jsFunctionDefineCodes );
}));
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Init.WaitOne ();
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Init.Close ();
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Init.Dispose ();
// 2. Execute the js method
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Exec = new AutoResetEvent (false );
This. Invoke (new Action () =>
{
This. webBrowser. Document. InvokeScript (arg_jsFunctionName, arg_functionArgs );
}));
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Exec.WaitOne ();
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Exec.Close ();
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Exec.Dispose ();
// 3. Response parameters
Return this. _ returnObj_Tool_webBrowser_ExecUserJSScript;
}

Public void policycsharpcompleteinit ()
{
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Init.Set ();
}

Public void policycsharpcomplete (object arg_obj)
{
This. _ returnObj_Tool_webBrowser_ExecUserJSScript = arg_obj;
This. _ threadControlEvent_Tool_webBrowser_ExecUserJSScript_Exec.Set ();
}
# Endregion

Example 1:

Copy codeThe Code is as follows: string jsCmdTest = "function testFunction (msg) {setTimeout (\" window. external. policycsharpcomplete (\\\ "Returned content \\\") ;\", 5000 );};";
Object returnObj = this. Tool_webBrowser_ExecUserJSScript (jsCmdTest, "testFunction", new object [] {"input parameter "});
String returnStr = returnObj as string;

Example 2:

Copy codeThe Code is as follows: string jsCmdTest = "function testFunction () {var a = 122; var B = 244; var c = a + B; window. external. notifyCSharpComplete (c );};";
Object returnObj = this. Tool_webBrowser_ExecUserJSScript (jsCmdTest, "testFunction", null );
Int returnInt = (int) returnObj;

Example 3:

Copy codeCode: string jsCmdTest = "function testFunction () {window. external. policycsharpcomplete (null );};";
Object returnObj = this. Tool_webBrowser_ExecUserJSScript (jsCmdTest, "testFunction", null );
String result = "js execution completed ";

Summary: two major problems with WebBrowser:

1. WebBrowser is used to call IE on the machine. Therefore, the version and rendering program depend on the IE version and the Renderer program.

2. WebBrowser executes js and many other operations asynchronously without event responses. You can only estimate the execution time and wait for it. And the wait time must be later than the actual execution time of js, otherwise there will be problems with the subsequent code.

3. Currently, JavaScript Execution can only be performed through the address bar of the browser. The address bar has a length limit.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.