WebBrowser control, isolation and IE8 InPrivate mode - internet-explorer-8

I have a need to run some automation tasks in a web browser control but I seem to be facing a few limitations/unknowns that I'm not 100% sure how to resolve. The application I'm running is not for public release, so I can enforce a prerequisite that IE8 is installed.
GeckoFX (http://geckofx.org) would be great except it does not offer me an acceptable way to manipulate the DOM as I would using the WebBrowser's InvokeMember method on HtmlElement objects.
WebKit.net would be even better but it's too early in its development to offer the functionality I need to do this either.
This leaves me with the WebBrowser control. The problem with WebBrowser though is that it just runs IE, which is a big fat shared environment with all processes. In other words, all instances share cookies, sessions, proxy settings, etc.
Here's what I want:
At the end of an automation session, cookies/sessions/cache objects are not retained. Rather than clearing the global Temporary Internet Files folder, is there a way for me to access the InPrivate mode exposed by IE8?
If there is a way to access InPrivate browsing, is it possible for me to run two InPrivate-mode sessions side-by-side isolated from each other?
Ideally I'd like to be able to run multiple isolated automation tasks in separate threads, each with its own private browser control, each with its own isolated session/environment that is not retained when the task completes.
Any help or input into this would be appreciated!

No, you cannot run the WebBrowser control in InPrivate mode; it's simply not a supported scenario.
Yes, you can run two instances of IE in InPrivate mode and isolate them from each other.
Use the command line: iexplore.exe -private -nomerge

Here's some code that will give you access to an InPrivate IE
Friend Function Open(Optional ByVal Url As String = "about:blank", Optional ByVal WindowState As ProcessWindowStyle = ProcessWindowStyle.Hidden) As WebBrowser
On Error Resume Next
Dim Start As New ProcessStartInfo
Dim Windows = New ShellWindowsClass
Dim Count = Windows.Count
Start.FileName = "iexplore.exe"
Start.Arguments = "-private -nomerge " & Url
If WindowState = ProcessWindowStyle.Hidden Then
Start.WindowStyle = ProcessWindowStyle.Minimized
Else
Start.WindowStyle = WindowState
End If
Process.Start(Start)
Wait.Reset()
Do
If Windows.Count > Count Then Exit Do
Loop While Wait.Waiting
Browser = Windows(Count)
Browser.Visible = (WindowState <> ProcessWindowStyle.Hidden)
Return Browser
End Function

Related

Can't access new window in Capybara

I've been trying to access a new window (well tab) when using Capybara, but keep getting
Selenium::WebDriver::Error::NoSuchWindowError: no such window
My process and understanding so far is
#session_1 = Capybara::Session.new(:chrome)
#session_1.visit("www.google.com")
So at this stage i have google open. Now lets say i want to open google in a new tab/window
#session_1.open_new_window
This opens a new window, and to access those windows I can do
#session_1.windows
which returns an array of windows
[#<Window #handle="CDwindow-09B6E81E-7874-4686-86A9-8BFB917E0F4F">,
#<Window #handle="CDwindow-5DA14173-8D63-422A-BF98-39B7C2A5D2DB">]
So as a test I wanted to check that latest windows url matches about:blank
#new_tab = #session_1.windows.last
# #new_tab = #<Window #handle="CDwindow-5DA14173-8D63-422A-BF98-39B7C2A5D2DB">
page.within_window #new_tab do
expect(current_url).to eq('about:blank')
end
It's here I get the error.
What I would like to know is
1) How to select the new tab
2) how to open a new url within the new tab
So I found the answer, turns out it was a lot simpler than i was trying, credit goes to Keiran Betteley and this post
#session_1.open_new_window
#session_1.switch_to_window(#session_1.windows.last)
#session_1.visit("url")
Capybara has a number of methods for dealing with windows, and open_new_window returns the window it opened so there's no need to go looking through the list of all windows
#session1.within_window(#session_1.open_new_window) do
#sessuion1.visit("url")
... more actions performed in the new window
end

Best way to control firefox via webdriver

I need to control Firefox browser via webdriver. Note, I'm not trying to control page elements (i.e. find element, click, get text, etc); rather I need access to Firefox's profiler and force gc (i.e. I need firefox's Chrome Authority and sdk). For context, I'm creating a micro benchmark framework, not running a normal webdriver test.
Obviously raw webdriver won't work, so what I've been trying to do is
1) Create a firefox extension/add-on that does what I need: i.e.
var customActions = function() {
console.log('calling customActions.')
// I need to access chrome authority:
var {Cc,Ci,Cu} = require("chrome");
Cc["#mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
Cu.forceGC();
var file = require('sdk/io/file');
// And do some writes:
var textWriter = file.open('a/local/path.txt', 'w');
textWriter.write('sample data');
textWriter.close();
console.log('called customActions.')
};
2) Expose my customActions function to a page:
var mod = require("sdk/page-mod");
var data = require("sdk/self").data;
mod.PageMod({
include: ['*'],
contentScriptFile: data.url("myscript.js"),
onAttach: function(worker) {
worker.port.on('callCustomActions', function() {
customActions();
});
}
});
and in myscript.js:
exportFunction(function() {
self.port.emit('callCustomActions');
}, unsafeWindow, {defineAs: "callCustomActions"});
3) Load the xpi during my webdriver test, and call out to global function callCustomActions
So two questions about this process.
1) This entire process is very roundabout. Is there a better practice for talking to a firefox extension via webdriver?
2) My current solution isn't working well. If I run my extension via cfx run directly (without webdriver) it works as expected. However, neither the sdk nor chrome authority do anything when running via webdriver.
By the way, I know my function is being called because the log line "calling customActions." and "called customActions." both do print.
Maybe there are some firefox preferences that I need to set but haven't?
It may be that you do not need the add-on at all. Mozilla uses Marionette for test automation of Firefox OS amongst other things:
Marionette is an automation driver for Mozilla's Gecko engine. It can
remotely control either the UI or the internal JavaScript of a Gecko
platform, such as Firefox or Firefox OS. It can control both the
chrome (i.e. menus and functions) or the content (the webpage loaded
inside the browsing context), giving a high level of control and
ability to replicate user actions. In addition to performing actions
on the browser, Marionette can also read the properties and attributes
of the DOM.
If this sounds similar to Selenium/WebDriver then you're correct!
Marionette shares much of the same ethos and API as
Selenium/WebDriver, with additional commands to interact with Gecko's
chrome interface. Its goal is to replicate what Selenium does for web
content: to enable the tester to have the ability to send commands to
remotely control a user agent.

VB6: Automation error The remote procedure call failed

In my VB6 application sometimes in some customer PC we get error like
Automation error
The remote procedure call failed.
The error comes for the code shown below
Dim WithEvents Web_popup As SHDocVw.InternetExplorer
Set Web_popup = Nothing
Set Web_popup = New SHDocVw.InternetExplorer
Set ppDisp = Web_popup.Application
Also for the below code
Dim iE As New SHDocVw.InternetExplorer iE.Navigate "www.example.com", 4 + 8
iE.Visible = True
What may be the reason for these errors? How to solve it?
You should include more information when asking for help. More importantly, you should point exactly which lines are causing the error. That being said, it sounds to me that you are not checking the ready state of the download of html to Explorer. Interacting with a web page before the web page has been completely download will cause this symptom.
If you are checking the ready state, the only other way I was able to produce the error was turning on protected mode in Internet Explorer. Some websites cause the error when Protected mode is on.

Ruby:Watir cannot connect to IE running under non-Admin account on 'default' desktop

Some Background on architecture of the app is needed:
Windows 2003/Apache-v2.2/IE7/Watir-v1.6.2/Ruby-v1.8.5
Apache running under 'localsystem' account.
Request to run a Watir script comes in.
Apache CGI kicks off IE7 under a particular user, e.g. 'tester', and attaches the IE7 window to the "default" desktop environment. This allows us to VNC into the machine and see all IE7 windows from all the accounts running.
IE7 has ruby embedded into the process through plugin and executes the ruby script in a thread.
For clicking on links/buttons in IE, Watir supplies a synchronous 'click' method and async 'click_no_wait' method. 'click_no_wait' spawns a completely new ruby process to connect back to the IE7 window to click the link/button.
This is what is failing for me. Since click_no_wait is spawning a new process. It cannot seem to see the IE7 window to connect to it and click on the link/button.
I have to use 'click_no_wait' due to a dialog box that IE pops up on a certain page, so that another ruby thread can close it.
I've tried a few things:
- using fire_event('OnClick') instead of click_no_wait hangs script like 'click' would.
- Modifying 'click' by commenting out '#container.wait', but the 'click!' itself is the API that hangs waiting for the dialog box to close.
- Make 'click_no_wait' spawn a new thread instead of a process', but other threads appear to be suspended while the 'click!' call executes in that thread. Which is strange.
- Executing the 'click_no_wait' process using the exact same code that is used to spawn the IE7 process, but it still can't find any IE7 windows.
By 'default' desktop described above, the code that spawns IE basically does a series of C++ calls to attach the IE7 window to the 'winsta0' desktop:
- LogonUser() // log in as tester account
- OpenWindowStation("winsta0") // to get default desktop
- SetProcessWindowStation()
- // add the user to interactive window station using (GetUserObjectSecurity, GetSecurityDescriptorDacl, GetAclInformation, AddAce, SetSecurityDescriptorDacl, SetUserObjectSecurity)
- // add user to "default" desktop using APIs listed above.
- CreateEnvironmentBlock
- ImpersonateLoggedOnUser
- CreateProcessAsUser('iexplore.exe')
- // cleanup
Running the following Watir script under the particular user IE7 is running under yields:
$IE = Watir::IE.attach(:title, /Google/)
$IE.button(:name, 'btnG').click!
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in `method_missing': Windows (WIN32OLERuntimeError)
OLE error code:80040154 in
HRESULT error code:0x80020009
Exception occurred. from c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in "each"
Which contains:
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246
shell = WIN32OLE.new("Shell.Application")
windows = shell.Windows ## Fails here
Let me know if I can supply more details or disambiguation! :)
Thanks,
Shane.
Ok, I have solved my own issue.
It turns out that the method that Watir uses to enumerate IE windows (i.e. Shell.Application) does not work across user spaces. So I had to write an intermediate application to retrieve the IWebBrowser2 COM pointer for the IE window, and modify the 'eval_in_spawned_process' Watir function to use this handle for 'pc = Watir::IE.bind(iWebBrowserPtr)'.
It's possible that I didn't need the external app to retrieve the IWebBrowser2 object, but I didn't know how to do it in Ruby, and I already had an IE BHO app that I could leverage for the purposes.
This now works fine. :)
Watir/page-container.rb:56
# This evaluates a cmd (e.g. "button(:id, 1).click!") in a new ruby process
# This is to primarily avoid a script hanging while a modal dialog is displayed in IE.
# It gets an IE handle from our IE BHO based off of window handle. It needs to do this
# to get around the problem of finding the IE window itself using Shell.Application
# which does not work across User-contexts.
# Note: This change probably invalidates the Watir unit-test for this API.
def eval_in_spawned_process(command)
command.strip!
load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
ruby_code = "require 'watir/ie'; "
ruby_code << 'controller = WIN32OLE.new("HttpPlugin.Controller"); '
ruby_code << "window = controller.BrowserFromHWND(#{hwnd}); "
ruby_code << "pc = Watir::IE.bind(window); "
ruby_code << "pc.#{command}; "
exec_string = "start rubyw -e #{(load_path_code + '; ' + ruby_code).inspect}"
result = system(exec_string)
end

scripted files download under Windows

I'm about to be forced to write a script to download some number of files under Windows XP. The machines the script will be run at are all behind a proxy, and the proxy settings are entered into the IE configuration.
What came to my mind was either to somehow call IE from the command line, and using its configuration download files I'd need. Is it even possible using some shell-techniques?
Other option would be to use wget under Win, but I'd need to pass the proxy-settings to it. How to recover those settings from IE configuration?
In principle, I would go for the wget approach rather than using IE in some way.
The path to the configuration script is stored in the registry in HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\DefaultConnectionSettings. It is a binary value, the script address starts at position 0x18 and seems ASCII encoded.
What I don't know is if wget can evaluate the script by itself, or if you need to parse it explicitly in your script that would then pass the proxy address to wget.
I agree with Treb you should prefer using wget and the path to the proxy settings can be found in "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer"
Use JScript:
function ie_NavigateComplete2(pDisp, url)
{
// output for testing
WScript.Echo('navigation to', url, 'complete');
// clear timer
t = 0;
}
// create ActiveX object
var ie = WScript.CreateObject('InternetExplorer.Application', 'ie_');
ie.Height = 200;
ie.Width = 200;
ie.Visible = true;
ie.Navigate('http://www.example.com/worddoc.doc');
var t = (+new Date()) + 30000;
// sleep 1/2 second for 30 seconds, or until NavigateComplete2 fires
while ((+new Date()) < t)
{
WScript.Sleep(500);
}
// close the Internet Explorer window
ie.Quit();
Then you invoke it with start download.js or cscript download.js. You can do something similar with VBScript, but I'm more comfortable in JScript.
Note that this ONLY works if the target of the ie.Navigate() is a file that prompts for Open/Save/Cancel. If it is a file type such as PDF that opens inside the browser, then IE will simply open the resource, then close the window, probably not what you want. Obviously you could adjust the script to suit your needs, such as not closing the IE window when the download is complete, or making the window larger, etc.
See the InternetExplorer Object documentation for more information about the Events, Methods and Properties available.
Using this method, you don't have to worry about reading the proxy settings for Internet Explorer, they will be used because you are using Internet Explorer to do the download.

Resources