Hello and thank you for looking.
Problem Description:
I have implemented a c# WinForm application with the browser control embedded and have implemented IInternetSecurityManager to perform the tasks we need in order to allow cross-domain access in iframes with our locally installed web pages.
All things are working as expected with IInternetSecurityManager, IOleClientSite, IDocHostShowUI and IDocHostUIHandler. In other words, we are being called by the browser control for all of our implementations.
The problem is when the web page loaded in the browser control has script that calls window.showModalDialog(): The browser control instance that is being used no longer communicates with our client site. Absolutely no QueryInterface calls or any other methods are called in any of the interfaces mentioned above.
The document in the dialog is not using our security manager implementation I am assuming because the web browser control in the dialog that IE displays is not the same one we called SetClientSite() on.
Question:
How do we talk to this new browser control? We need to be able to give the browser control in the dialog that is shown by IE, our IInternetSecurityManager implementation. But, we never get the opportunity to tell it about our client site to make the hook up, so to speak. In other words, there is no communication from IE that tells us via an interface that says, "I am a new browser control created by IE and here is my IUnknown interface. This your chance to set my client site, etc." We would be golden if there was such a notification coming from IE.
The result is two different security contexts are being used and our applicaiton fails any time we are in a dialog using an iframe, because our IInternetSecurityManager implementation is not in use.
Example Source Code:
I have chiseled away at source code to protect the innocent :) and have reduced down to something I think you can work with in its own Visual Studio 2010 solution.
Please read the ReadMe.txt file for information on the problem, repro steps, etc.
The test web pages I wrote display information and steps to guide you through the use of the sample.
Please let me know if you have questions about what I am trying to accomplish or if the sample isn’t clear enough.
Please advise. Thank you.
http://home.comcast.net/~lowrider2112/bin/TestIEHost.rar
You can override the web-browser's control method CreateWebBrowserSiteBase.
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
and implement ExtendedWebBrowserSite like this:
class ExtendedWebBrowserSite : WebBrowser.WebBrowserSite,
IDocHostShowUI,
IfacesEnumsStructsClasses.IServiceProvider,
IInternetSecurityManager
...
That can call the class IInternetSecurityManager.
One option would be to create your own dialog form (in C#) with another custom-security WebBrowser control on it. Then you can call from Javascript to C# to open the form instead of using showModalDialog.
Related
After reading Dianyang Wu article and this excellent post I managed to build a small .net app (almost a C&P from Wu source code) to automatize tests (let's call it protoTestApp). My final goal is to open a dozen small windows and in each simulate a different user interacting with a web app to stress it.
It works for some extend but after I logon on the web app (let's call it InternalTestSubject) it calls a external url (let's call it ExternalTestSubject) and injects it's content on a iFrame. This particular external url is another web app and it ill look up for the parent window to get some parameters. Opening ExternalTestSubject directly is not a option.
My problem is at my protoTestApp I want to also interact with that ExternalTestSubject (find a button by id, click it, etc) but at my CompletedEvent handler the iFrame is still empty.
The WebBrowser shows both web apps full loaded and working, so I suppose the handler is just not waiting for the iFrame content to load since it's done by a Ajax async call.
Any advice to acomplish it?
I think I explained this in the answer you linked (and in more details in another related answer). AJAX pages are non-determinustic, so there is no generic approach.
Use periodic asynchronous polling to watch the page's current HTML snapshot or DOM for changes, the linked post illustrates how to do that. You can poll the frame's content in the same way.
I can imagine the frame reports to be ready but it actually does not. For instance, the frame contains frames, you have no way to know whether all these frames are loaded by using DocumentCompleted event.
In short: Using a frame to load external stuff and do the testing is not a good approach. Even if you use a timer to check the loading status manually. But according to security considerations, you will have many problems to access the DOM.
I have two suggestions for you:
Create a WebBrowser instance and open external test subject into it. You will have a very good chance to know, whether document (and its frames) have been loaded completely. You still have the full control to access any elements of the WebBrowser or cookies or click elements or change elements.
Use 3rd tool such as Selenium as test driver.
Update 1:
As the questioner does not want any 3rd tool, I'd suggest let the internal test subject query the loading completeness of the target frame periodically. Possible code can be check document.readyState == 'complete'.
So far as I know, as the external test subject is embedded as frame, due to security consideration, you might not able to access the DOM of the frame. In other words, you cannot do mouse clicks, etc., unless you change the security settings for the Webbrowser control first.
Background:
I am creating a Windows Form App that automates order entry on a intranet Web Application. We have a large amount of order entry that needs to be done that will cost us a lot of money so I volenteered to automate the task.
Problem:
I am using the webbrowser class to navigate the web app. I have gotten very far but reached a road block. There is a part in the app that opens a web dialog page. How do I interact with the web dialog. My instance of the webbrowser class is still with the parent page. I am hoping someone can point me in the right direction.
You've got a number of options. To expand on the answers from others and add a new idea...
Do it using the webbrowser control: This is technically possible by either injecting javascript into the target page as demonstrated here or creating a JavaScript object and using it as a bridge via the webbrowser.objectforscripting property. This is very fragile - something as simple as the website changing an element's Id could break it. You also need to make sure your code doesn't interfere with the functioning of the form (clashing function names, etc...)
Do it using a postback: Monitor the communications between the web browser and the server (I personally prefer Firfox/Firebug but ie/Fiddler or Chrome/F12 are both good too). As long as you can replicate the actions of the browser exactly, the server can't know the difference. The problem here is that browsers are complex and the more secure a form is, the more demanding servers are. This means you may have to fake a login, get cookies, send them back on subsequnt requests, Handle Viewstate data and xss prevention variables. It's possible and it's far more robust than the first option but can be a pain to get working. If it's not a highly secure form,, this is your best bet. More information here
Do it by browser automation: Selenium is probably the best option here (as mentioned by others) but suffers from a similar flaw to the webbrowser control in that it's sensitive to changes on the form itself (But not as mcuh so as the webbrowser control).
Incidentally, if you have Visual Studio Ultimate/Test edition (and some others, not sure which), it includes a suite of testing tools including an excellent engine to automate load testing a website. This is also superb for tracking down what exactly a form does as you can see every step of the emulation.
Hope this helps
You have two choices depending of the level of complexity you need:
Use a HTTP Debugger like Fiddler to find out the POST data you
need to send to each page and mimic it via a HttpWebRequest.
Use a Browser Automation Tool like Selenium and do the job.
NOTE: Your action may be considered as spamming by the website so be ready for IP blocking, CAPTCHA...
You could give Selenium a go: http://seleniumhq.org/
UI automation is a far more intuitive approach to these types of tasks.
Let me rephrase the question...
Here's the scenario: As an insurance agent you are constantly working with multiple insurance websites. For each website I need to login and pull up a client. I am looking to automate this process.
I currently have a solution built for iMacros but that requires a download/installation.
I'm looking for a solution using the .NET framework that will allow the user to provide their login credentials and information about a client and I will be able to automate this process for them.
This will involve knowledge of each specific website which is fine, I will have all of that information.
I would like for this process to be able to happen in the background and then launch the website to the user once the action is performed.
You could try the following tools:
StoryTestIQ
Selenium
Watir
Windmill Testing Framework
Visual Studio Web Tests
They are automated testing tools/frameworks that allow you to write automated tests from a UI perspective and verify the results.
Use Watin. It's an open source .NET library to automate IE and Firefox. It's a lot easier than manipulating raw HTTP requests or hacking the WebBrowser control to do what you want, and you can run it from a console app or service, since you mentioned this wouldn't be a WinForms app.
You can also make the browser window invisible if needed, since you mentioned only showing this to the user at a certain point.
I've done this in the past using the WebBrowser control inside a winforms app that i execute on the server. The WebBrowser control will allow you to access the html elements on the page, input information, click buttons/links, etc. It should allow you to accomplish your goal.
There are ways to do this without the WebBrowser control, look at the HTML Agility Pack.
Assuming that you are talking about filling and submitting a form or forms using a bot of some sort then scraping the response to display to the user.
Use HttpWebRequest(?) to create a form post containing the relevant form fields and data from your model and submit the request.
Retrieve and analyse the response, store any cookies as you will need to resubmit the cookie on the next request.
Formulate the next request based on the results of the first request ( remembering to attach cookies as necessary ) and submit it.
Retrieve the response and display or parse and display ( depending on what you are hoping to achieve ).
You say this is not a client app - therefore I will assume a web app. The downside of this is that once you start proxying requests for the user, you will have to always proxy those requests as there is no way for you to transfer any session cookies from the target site to the user and there is no ( simple / easy / logical ) way for the user to log in to the target site and then transfer the cookie to you.
Usually when trying to do this sort of integration, people will use some form of published API for interacting with the companies / systems in question as they are designed for the type of interactions that you are referring to.
It is not clear to me what difficulty you want to communicate when you wrote:
I currently have a solution built for
iMacros but that requires a
download/installation.
I think here lies some your requirements about which you are not explicit. You certainly need to "download/install" your .Net program on your client's machines. So, what's the difference?
Anyway, Crowbar seems promising:
Crowbar is a web scraping environment
based on the use of a server-side
headless mozilla-based browser.
Its purpose is to allow running
javascript scrapers against a DOM to
automate web sites scraping but
avoiding all the syntax normalization
issues.
For people not familiar with this terminology: "javascript scrapers" here means something like an iMacros' macro, used to extract information from a web site (in the end is a Javascript program, for what purpose you use it I do not think makes a difference).
Design
Crowbar is implemented as a (rather
simple, in fact) XULRunner application
that provides an HTTP RESTful web
service implemented in javascript
(basically turning a web browser into
a web server!) that you can use to
'remotely control' the browser.
I don't know if this headless browser can be extended with add-ons like a normal Firefox installation. In such case you can even think to use yours iMacros' macros (or use CoScripter) with appropriate packaging.
The more I think about this, more I feel that this is a convoluted solution for what you wrote you want to achieve. So, please, clarify.
How to create a open a webpage as a popup using c# and need to run a function when the popup window is closed. my intention is to create a web login/logout and run a function after successful completion of the event
Well you've not given much away, but if I'm guessing that your architecture is ASP.NET, then you should have events on the server in your page's codebehind that can process that event. If you expand a bit on your requirements we can help you out a bit more.
Just for completeness, you should know that you can't just run C# code in a browser with html/javascript. You could run a Silverlight application but I don't think that's what you're after.
To summarise, make a web request and respond to it on the server. Popups are just webpages, so the architecture there is the same. When the request comes back, you can then run JS to close the popup and make the main browser window do something.
Personally I'd just have the main browser do the login, popups are cumbersome for users in web apps.
If you are using jQuery, I would strongly suggest using ThickBox http://jquery.com/demo/thickbox/ We use it in every single projects we do and it work very weel and it's easy to modify to have it do what you want.
You can use it to load another aspx page where your login code would reside and then pay particual attention to
function tb_remove() {
Which is called on close. This is where we added our code to return data to the page.
The short answer is, you can't. C# runs on the server and opening a popup window is a client side action. You will need to have JavaScript in your rendered markup to open the popup window when appropriate, or an anchor tag with target="_blank".
However, I agree with the other answers that popup windows are more of a pain than they are worth, they annoy users and lead to window management issues that are not always easy to solve especially when popup blockers are involved. A DOM based modal dialog is almost always a better solution.
I would go with Neil... Sorry to say this but you are exactly the type of person Jeff Atwood was talking about when he wrote this article...
http://www.codinghorror.com/blog/archives/001296.html
I would suggest you take the time to learn the difference between client and server functionality, languages and technology.
I would also suggest you listen to Neil, your usability skills also need serious work.
LOL - and if you think I'm being cruel, think how cruel you're being to your users... login in a pop up window... bah
i wish to interact with my browser window may be IE great if it works on Firefox too, using C#.
I want to make a software which can fill the entries in a webform automatically. In old times there was gator now is roboform, where it can fill in the values automatically.
I actually have users who are comfortable working on an old windows forms application, so i want to make a solution where they can still enter the data in their windows application and it actually fills in the entries at the web form and acts as if the request had generated from the browser itself.
I know i can merge both the databases, since it is a legacy application re writing the database for windows app is a trouble..
Any suggestion?
WatiN is designed to make testing web applications easy from .NET, and it sounds like it could be handy for what you want to do:
Following is the Hello world example
of web test automation; searching
Google.
[Test] public void
SearchForWatiNOnGoogle() { using (IE
ie = new IE("http://www.google.com"))
{
ie.TextField(Find.ByName("q")).TypeText("WatiN");
ie.Button(Find.ByName("btnG")).Click();
Assert.IsTrue(ie.ContainsText("WatiN"));
} }
WatiN Feature List
Automates all major HTML elements
Find elements by multiple attributes
Supports AJAX website testing
Supports frames (cross domain) and iframes
Supports popup dialogs like alert, confirm, login etc..
Supports HTML dialogs (modal and modeless)
Works with Internet Explorer 6, 7, 8 and FireFox 2 and 3
It's billed as a testing application, but Selenium RC can be used to fill in forms and is fairly easy to setup. You could also check out WatiN. Don't know anything about what security issues you might see though.
You might also want to check out Selenium which is a web application testing framework that you can programmitically interact the web UI.
If you use fiddler you may be able to see what the browser sends back to the server, and so you could write C# code to generate the same kind of HTTP request.
If the interaction is very complex (it often is with modern webapps), you could instead automate the browser, as you suggested.
I've had some success automating IE by using the InternetExplorer.Application object. It basically launches a copy of IE and lets you control it from code. I wrote a script this way a few years ago to search for cheap train ticket reservations for me on the Virgin Trains website.
The problem was that with some IE installs, it would sometimes stop to give security warnings that I couldn't skip automatically. There didn't seem to be a pattern to this.
If your users are simply using the application via a WindForms application, then is there any particular reason why you have to manipulate the user interface of an existing web browser, such as Internet Explorer, rather than just making the necessary HTTP requests yourself in your WinForms application? You can use the WebRequest class by setting the Method property to "POST" and writing the field data to the Stream, which you can get using the httpRequest.GetRequestStream() method.