How to get Internet Explorer loaded web page text - c#

I am using .NET 4.8 WebBrowser component, while using web page that creates new window on submit, it creates new Internet Explorer process with a Tab of this new window.
This is a problem for me as what I need, is the content of this new window.
I tried using NewWindow event on WebBrowser, to e.Cancel this event and redirect WebBrowser component to desired NewWindow URL, but it does not work, as this webSite uses some form of App PostBack that returns only one time resutls.
Then I tried to use
AutoItX.WinGetText("Window Title"); //Of course I changed this to real window title
But it does not show one thing and that is content of the TabPage
Is there any way to read content of Internet Explorer tab please ?
I have tried:
AutoItX.WinGetText("Window Title"); //Of course I changed this to real window title
and also
private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
{
e.Cancel = true;
webBrowser1.Navigate("url");
}
WebPage: cica.vugk.sk , Navigate to 'vlastnik spravca', fill 'prvé písmeno priezviska' to A, click 'Vytvor LV', it creates popup that I need content of and I did not find any solution how to access it using WebBrowser, or WebView2.

C# WebBrowser is forced to open in this window, and prohibited to open in a new window.
Use the load complete event to change the target value of all links and forms to "_self":
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
foreach (HtmlElement archor in this.webBrowser.Document.Links)
{
archor.SetAttribute("target", "_self");
}
foreach (HtmlElement form in this.webBrowser.Document.Forms)
{
form.SetAttribute("target", "_self");
}
}
Cancel the new window event:
private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
{
e.Cancel = true;
}
WebBrowser property settings:
Set AllowWebBrowserDrop of WebBrowser to false (no drag and drop)
Set WebBrowserShortcutsEnabled of WebBrowser to false (disable shortcut keys)
Set WebBrowser's IsWebBrowserContextMenuEnabled to false (disable right-click context menu)

Related

Triggering onbeforeunload in WebView2

This answer shows how to trigger the onbeforeunload event in a WebBrowser control in the following way:
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (!this.formsWebBrowser.IsDisposed)
{
//// Generate SHDocVw.dll: Visual Studio Developer Command Prompt "tlbimp.exe ieframe.dll /out: C:\temp\SHDocVw.dll",
var activeX = this.formsWebBrowser.ActiveXInstance;
var input = Type.Missing;
object leavePage = true;
((SHDocVw.WebBrowser)activeX).ExecWB(
SHDocVw.OLECMDID.OLECMDID_ONUNLOAD,
SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT,
ref input,
ref leavePage);
if (!(bool)leavePage)
{
e.Cancel = true;
return;
}
}
base.OnFormClosing(e);
}
But now trying to move away from IE11 (as used by WebBrowser) to Edge Chromium with the WebView2 control, I can't figure out how to do the same thing in WebView2.
The dialog shows correctly when navigating the WebView2 to another page.
The problem comes when the user closes the application or the window containing the WebView2.
It then just closes without showing any dialog.
That's what the code above does for the WebBrowser control, when closing the application the (on)beforeonload event is triggered in the IE11 browser and a bool is returned. True if the user pressed "Leave" or there isn't an beforeonload event active and false if the user pressed "Stay on the page".
Short of calling ExecuteScriptAsync("onbeforeunload();") (which doesn't work when setting the event with window.addEventListener("beforeunload", function(event) { ... });) how can the same be done in WebView2?
Edit:
The problem is that I don't want to show the dialog always when closing, unless I really have to.
I only want to show it if the page has unsaved changes (and it communicates that in the beforeunload event in JavaScript).
The only way I know how handle that in the C#-code is by triggering the built in onunload event showing the beforeunload dialog in the browser.
That is exactly what the ActiveXInstance.ExecWB(OLECMDID_ONUNLOAD) does for the WebBrowser control and IE11.
It may simply not be possible to trigger that event in WebView2/Chromium in the same way? That's really what I'm asking.
I've tried calling JavaScripts in the FormClosing event, but the application just closes w/o waiting for the response.
I guess the only other option is to remove the x-close button and use a custom close button that can do the needed checks and then close the application.
This is working for me. You can combine it with a form closing or something. Don't forget to properly detach events / dispose where proper. This is just a sample.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
DoWork();
}
private async Task DoWork()
{
await webView21.EnsureCoreWebView2Async();
webView21.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
webView21.CoreWebView2.ScriptDialogOpening += CoreWebView2_ScriptDialogOpening;
await webView21.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.addEventListener('beforeunload', function(e) { return event.returnValue = 'prompt';});");
webView21.Source = new Uri("https://www.google.com");
}
private void CoreWebView2_ScriptDialogOpening(object sender, Microsoft.Web.WebView2.Core.CoreWebView2ScriptDialogOpeningEventArgs e)
{
if (MessageBox.Show("do you want to leave", "Leave?", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
e.Accept();
}
else
{
e.GetDeferral();
}
}

Waiting for webBrowser control to load before filling textbox and clicking

I'm using Visual Studio Community in C# (.Net 4.5).
I have a simple form, with one button and one webBrowser control.
I want to check if "tremblay jean" has a trademark registered in his name in Canada (I know he has two).
So when I click my button I load the trademarks search page in my webBrowser control, I wait for it to be complete, then I insert his name in their textbox and click their button.
If I pause the program using a MessageBox.Show after loading the page, it works, there's two documents found.
But if I don't pause the program using a MessageBox it doesn't work. It gives me 500 results, unrelated to "tremblay jean".
So the line of code waiting for the ReadyState to be Complete doen't seem to work.
Does anyone know why?
private void button1_Click(object sender, EventArgs e)
{
string website = "http://www.ic.gc.ca/app/opic-cipo/trdmrks/srch/home?lang=eng";
webBrowser1.Navigate(website);
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
MessageBox.Show(webBrowser1.ReadyState.ToString()); // to pause the program
webBrowser1.Document.GetElementById("search-crit-1").SetAttribute("value", "tremblay jean");
HtmlElementCollection elc = webBrowser1.Document.GetElementsByTagName("button");
foreach (HtmlElement el in elc)
{
if (el.GetAttribute("type").Equals("submit"))
{
if (el.InnerText == " Search ")
{
el.InvokeMember("Click"); //comment this line to see if textbox is filled
break;
}
}
}
}
The first thing to do, when you're using a WebBrowser control, is to initialize it with this html string:
<meta http-equiv='x-ua-compatible' content='IE=edge,chrome=1'>
This allows to set the compatibility mode of the control's underlying activex (Internet Explorer) to the most recent locally available version.
With webBrowser1.ScriptErrorsSuppressed = true;, the scripting error popup is disabled.It's a just in case measure.
Then, subscribe the DocumentCompleted event, that will raise when the page has been loaded. As already noted in the comments, this event might be raised more than once, because of the interaction of Scripting and IFrame.
The WebBrowser.ReadyState is used to verify that page is indeed completed.
It's true that, sometimes, the inner scripting can cause some trouble
here, but since this is not the case, I'll leave it as a side
note.
One other thing you'll notice is that the DocumentCompleted event is unsubscribed after the WebForm button is clicked. This is done to avoid further notifications from the WebBrowser, as the needed action is already been performed and no further action is required on other pages.
So, the event will be active only when you'll be requesting new results to the server (e.g. clicking your UI Search button).
Here, the private string SearchName; is a placeholder for a procedure the defines the new search criteria.
private string SearchName;
private void button1_Click(object sender, EventArgs e)
{
SearchName = "tremblay jean";
webBrowser1.ScriptErrorsSuppressed = true;
webBrowser1.Navigate("");
webBrowser1.Document.Write("<!DOCTYPE html><head><meta http-equiv='x-ua-compatible' content='IE=edge,chrome=1'></head>");
webBrowser1.Navigate("http://www.ic.gc.ca/app/opic-cipo/trdmrks/srch/home?lang=eng");
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(this.WBDocCompleted);
}
protected void WBDocCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = ((WebBrowser)sender);
if (browser.ReadyState == WebBrowserReadyState.Complete)
{
if (browser.Document != null)
{
browser.Document.GetElementById("search-crit-1").SetAttribute("value", this.SearchName);
foreach (HtmlElement button in browser.Document.GetElementsByTagName("button"))
{
if (button.GetAttribute("type") == "submit" && button.Name == "")
{
browser.DocumentCompleted -= this.WBDocCompleted;
button.InvokeMember("click");
break;
}
}
}
}
}

Prevent to close parent window if child windows are active

I am developing multiple instance WPF application. Application has a grid in a main screen and on double click of grid row, it opens child window. It has also functionality to open multiple child windows on double click of grid row from main screen.
Can anybody help me to prevent parent window to be close if child windows are active? So user can not able to close main window if child windows are active.
Set Owner property for those childs to Main Windows:
private void Button_Click(object sender, RoutedEventArgs e)
{
var wnd = new Window();
wnd.Owner = this;
wnd.Show();
}
Then in Main Window closing event handler:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (this.OwnedWindows.Count > 0)
{
MessageBox.Show("Child windows exists, you have to close'em first");
e.Cancel = true;
}
}
As a final point it could be helpful for you to know that you can get from anywhere in your code the app main windows with this:
System.Windows.Application.Current.MainWindow
So if you are using MVVM the above will help you in setting the Owner property.
You have two options:
1- You can use ShowDialog() to open the child window, but user can't interact with the parent window till the child is closed.
2- You can check all windows that are currently opened by checking
Application.Current.Windows
and then you can determine whether you want to close your window or not
Edit:
add the following event handler to your Parent.Closing event
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach (var item in Application.Current.Windows)
{
Window window = item as Window;
if (window.Title == "YourChildWindowTitle")
{
// show some message for user to close childWindows
e.Cancel = true;
break;
}
}
}
In window closing command pass that if the child window is open disable closing functionality.
Or
you what you can do is make canexecute = false when a pop up is open and closing command is triggered.
Attach a function to the main window's 'Closing' event, and check to see if the child window is open. if it is, set
e.cancel = true;

block a popup visual studio

I am using the below code in visual studio to make an auto login software . The software is working fine, But the page that is displayed after login has a popup script. This forces the opening of popup url in internet explorer. I want to block the internet explorer getting opened. Can i solve this ?
private void webBrowser1_DocumentCompleted_1(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Navigate("https://mwcp-ekm-04.adlkerala.com:8001/");
webBrowser1.Document.GetElementById("name").InnerText = "name";
webBrowser1.Document.GetElementById("id").InnerText = "66491";
webBrowser1.Document.GetElementById("accept").InvokeMember("click");
}
You can prevent the opening of a new window (popup) by subscribing to the NewWindow event and then cancel the event itself:
private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
{
e.Cancel = true;
}

How to show "page setup" and "printer setup" as modeless forms?

Is possible to show "page setup" and "printer setup" as modeless forms? I used code as follows, but that forms display as modal forms:
// page setup
private void btnPageSetup_Click(object sender, EventArgs e)
{
this.pageSetupDialog1.PageSettings = new PageSettings();
this.pageSetupDialog1.PrinterSettings = this.printDocument1.PrinterSettings;
this.pageSetupDialog1.ShowDialog();
if (this.pageSetupDialog1.PageSettings != null)
{
this.printDocument1.DefaultPageSettings = this.pageSetupDialog1.PageSettings;
}
}
// print setup
private void btnPrintSetup_Click(object sender, EventArgs e)
{
this.pageSetupDialog1.Document = this.printDocument1;
if (this.pageSetupDialog1.ShowDialog() == DialogResult.OK)
{
this.printDocument1.Print();
}
}
You can show a form as non-modal by calling Show rather than ShowDialog.
However, you'll also have to shuffle your code around, because your main form will no longer sit and wait for one of the subforms to close in order to check what the user did.
For example, you'll have to change the Print Setup code such that your PageSetupDialog prints the document itself when the user clicks OK, rather than relying on the main form to act when the user has clicked OK.
Similarly, you'll need to change the Page Setup code such that your PageSetupDialog sets Document.DefaultPageSettings itself, rather than "returning" settings in the PageSettings property and relying on the main form handling them.

Categories