How to inject a Javascript script into webpage using WebBrowser control? - c#

In my application I need to use a WebBrowser control to process user login. I use WPF and it's WebBrowser control. The problem is that I want to display a part of web page that is under certain div. I found a solution to this, I need to inject an javascript script into a loaded html page, but I have no clue how to do it :(
This is the script that I would like to inject into web.
function showHide() {
$('body >').hide();
$('#div').show().prependTo('body');
}
So i could later call it webbrowser1.InvokeScript("showHide");
I read a lot of posts on stack, but all of them refer to WindowsForms WebBrowser and it is not working with WPF one.
EDIT: I tried:
private void PageLoaded (object sender, NavigationEventArgs e)
{
var webBrowser = sender as WebBrowser;
webBrowser.Document.InvokeScript("execScript",
new object[] {"$('body >').hide(); $('#" + _div + "').show().prependTo('body');"});
}
But webBrowser.Document is type object and I cannot call InvokeScript on it, have no clue to what I should cast it.
Thanks for help.

Add a reference to mshtml
In whatever event you want to inject the JavaScript:
var doc = (mshtml.HTMLDocument)webBrowser1.Document;
var head = doc.getElementsByTagName("head").Cast<mshtml.HTMLHeadElement>().First();
var script = (mshtml.IHTMLScriptElement)doc.createElement("script");
script.text = "function myFunction() { alert(\"Hello!\");}";
head.appendChild((mshtml.IHTMLDOMNode)script);
In whatever event you want to invoke the JavaScript from:
webBrowser1.InvokeScript("myFunction");
Result:

Related

C# WebBrowser open new window and keep javascript object

I'm trying to design a multiple tab browser with webbrowser-control,
when my webrowser invoke the following javascript.
function myFunction() {
var myWindow = window.open("", "_blank");
// The website need do something to get url
myWindow.location.href = "https://www.google.com";
}
my webbrowser fire newWindow event first,
then i will open a new webbrowser,
in this case the url is "about:blank",
but the problem is how to bring "myWindow" to the new webbrowser and navigate to the correct url.
thanks a lot.
Use _parent instead of _blank in window.open.

Display portion of a Website into a Web Browser

i want to navigate to a specific website, and i want then to be displayed in the web browser only a portion of the website, which starts with:
<div id="dex1" ...... </div>
I know i need to get the element by id, but firstly i tried writing this:
string data = webBorwser.Document.Body.OuterHtml;
So from data i need to grab that content "id" and display it and the rest to be deleted.
Any idea on this?
webBrowser1.DocumentCompleted += (sender, e) =>
{
webBrowser1.DocumentText = webBrowser1.Document.GetElementById("dex1").OuterHtml;
};
On second thoughts, don't do that, setting the DocumentText property causes the DocumentCompleted event to fire again. So maybe do:
webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted;
webBrowser1.DocumentText = webBrowser1.Document.GetElementById("dex1").OuterHtml;
}
Although in most real world cases I'd expect you'd get better results injecting some javascript to do the DOM manipulation, a la Andrei's answer.
Edit: to just replace everything inside the body tag which might if you're lucky maintain all the required styling and scripts if they're all in the head don't reference any discarded context, you may have some joy with:
webBrowser1.Document.Body.InnerHtml = webBrowser1.Document.GetElementById("dex1").OuterHtml;
So, as you probably need a lot of external resources like scripts and images. You can add some custom javascript to modify the DOM however you like after you have loaded the document from your website. From How to update DOM content inside WebBrowser Control in C#? it would look something like this:
HtmlElement headElement = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptElement = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement domScriptElement = (IHTMLScriptElement)scriptElement.DomElement;
domScriptElement.text = "function applyChanges(){ $('body >').hide(); $('#dex1').show().prependTo('body');}";
headElement.AppendChild(scriptElement);
// Call the nextline whenever you want to execute your code
webBrowser1.Document.InvokeScript("applyChanges");
This is also assuming that jquery is available so you can do simple DOM manipulation.
The javascript code is just hiding all children on the body and then prepending the '#dex' div to the body so that it's at the top and visible.

Webbrowser, scripts and possible alternatives

I have a situation where a rather clever website updates the latest information on the site via Shockwave Flash through a TCP connection. The data received is then updated onto the page via JavaScript so in order to get the latest data a browser is required. If attempts are made to hit the website with continual requests then a) you get banned and b) you're not actually getting the latest data, only the last updated base framework.
So I need to run a browser with scripts enabled.
My first question is, using the standard WPF WebBrowser in .NET I get the following warnings which I don't get in standard IE, Chrome or Firefox. What is causing this and how do I supress/allow it but still allowing scripts for the site to be run?
My second question relates to is there a better way do to this or are there any better alternatives to the WebBrowser control that will
Allow scripts to run
can access the DOM or html and scripts returned in at least text format
is compatible with WPF
can hide the browser as I don't actually want it displayed.
So far I've looked into WebKit.NET which doesn't seem to allow access to the DOM and didn't like WPF windows when I tested and also Awesomium but again didn't appear to allow direct access to the DOM without javascript.
Are there any other options (apart from hacking their scripts)?
Thank you
set WebBrowser.ScriptErrorsSuppressed = true;
Ultimately I ended up keeping the WPF control and used this code to inject a JavaScript script to disable JavaScript errors. The Microsoft HTML Object Library needs to be added.
private const string DisableScriptError = #"function noError() { return true;} window.onerror = noError;";
private void webBrowser1_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
InjectDisableScript();
}
private void InjectDisableScript()
{
HTMLDocumentClass doc = webBrowser1.Document as HTMLDocumentClass;
HTMLDocument doc2 = webBrowser1.Document as HTMLDocument;
IHTMLScriptElement scriptErrorSuppressed = (IHTMLScriptElement)doc2.createElement("SCRIPT");
scriptErrorSuppressed.type = "text/javascript";
scriptErrorSuppressed.text = DisableScriptError;
IHTMLElementCollection nodes = doc.getElementsByTagName("head");
foreach (IHTMLElement elem in nodes)
{
HTMLHeadElementClass head = (HTMLHeadElementClass)elem;
head.appendChild((IHTMLDOMNode)scriptErrorSuppressed);
}
}
WPF WebBrowser does not have this property as the WinForms control.
You'd be better using a WindowsFormsHost in your WPF application and use the WinForms WebBrowser (so that you can use SuppressScriptErrors.) Make sure you run in full trust.

the usercontrol inside updatepanel problem

i have a usercontrol inside an updatepanel. when i click some button this usercontrol will be
loaded. and the usercontrol itself has anither button in it. the problem is that the
usercontrol code behind is never executed and when the button is clicked the usercontrol
disappears.
i know this is a common problem. but i have not found a good detailed solution.
i appreciate it.
In your user control, just use a standard HTML button like this:
<input type="button" id="myButton" onclick="clickTheButton();" value="Click Me"/>
this will invoke the javascript method "clickTheButton" which can look like this:
<script type="text/javascript">
function clickTheButton() {
var Sender = window.event.srcElement;
//here you can go gather any other values that you need to support the post back
var PostBackData = textboxCity.value + "|" + selectState.value
if(confirm("are you sure?"))
{
__doPostBack(Sender.ID, PostBackData)
}
}
</script>
So now you are going to invoke a postback from Javascript, identifying the Sender Control and command arguments. These values are passed with the post back as __EventTarget and __EventArgument and are available from the httpRequest in the page load like:
protected void Page_Load(object sender, EventArgs e)
{
string controlName = Request.Params.Get("__EVENTTARGET");
string[] commandArguments = Request.Params.Get("__EVENTARGUMENT").split('|')
}
Once you are in page load with whatever values you accumulated into commandArguments you should be capable of invoking whatever additional methods you desire.
This should get you pointed in the right direction.
Cheers,
CEC
Loading user-control dynamically in update-panel is tricky .
The Best solution is to save it in ViewState , Here is a tutorial and sample application .

Refreshing an iFrame in a Web Browser Control

C# Visual Studio 2010
I have a complex webpage that contains several iframes that I am loading into a web browser control. I'm trying to figure out a way to refresh one of the iframes when a user clicks a button on the windows form.
I can't find anything specific to refreshing a single iframe. Any ideas?
From within the DOM, you can just invoke:
document.getElementById([FrameID]).contentDocument.location.reload(true);
Using the WebBrowser control, you can execute javascript yourself, by using the InvokeScript method of Document:
browser.Document.InvokeScript([FunctionName], [Parameters]);
Put these two concepts together by writing your own function in the parent page:
function reloadFrame(frameId) {
document.getElementById(frameId).contentDocument.location.reload(true);
}
And invoke this in your C# code:
browser.Document.InvokeScript("reloadFrame", new[] { "myFrameId" });
How about using MSHTML and the reload method of the IHTMLLocation interface. You would add a reference to Microsoft.mshtml then try:
IHTMLDocument2 doc = webBrowser1.Document.Window.Frames["MyIFrame"].Document.DomDocument as IHTMLDocument2;
IHTMLLocation location = doc.location as IHTMLLocation;
if (location != null)
location.reload(true);
A value of true reloads the page from the server, while false retrieves it from the cache.

Categories

Resources