Close IE specific window with C# using Kill is not working - c#

I am trying to close the most recent window/tab of IE but when I call the Kill method the window relaunches without the content of the page.
This is the code that I use to get the most recent IE process:
var a = System.Diagnostics.Process.GetProcessesByName("iexplore");
DateTime earliestStart = DateTime.Today.Subtract(new TimeSpan(1,0,0,0));
System.Diagnostics.Process youngestProccess = a.FirstOrDefault();
foreach(var b in a){
if (b.StartTime > earliestStart)
{
earliestStart = b.StartTime;
youngestProccess = b;
}
}
youngestProccess.Kill();
The code is working in the way that the most recent window "stop" working but the window is not beeing closed
Any idea?

Hi I just discover how to solve the problem.
The message is being thrown because my IE has the option "Enable automatic crash recovery" checked in the Internet Options Advanced tab.
So if you face this you have 2 options: un-check that option forever (which might work for your case) or like in my case you can change the selection via registry keys and when you finish your testing return the value to be on.
So to do this you need to add this to your code before opening IE.
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Recovery", "AutoRecover", 2);
To turn back on the option you must do the same but with a 0
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Recovery", "AutoRecover", 0);

Related

Windows process launch fails silently - can't launch Bluetooth settings in certain scenario

Even though there are command-line commands to start (most of?) the various Control Panel screens in Windows 10, a specific scenario seems to fail:
If the machine starts with Bluetooth turned off (not disabled), running the command which should open the Bluetooth settings screen, simply does nothing. The command could be either ms-settings:bluetooth, bthprops.cpl or ms-settings:Bluetooth.
I've also tried to directly launch the Bluetooth Devices screen (using the command %windir%\explorer.exe shell:::{28803F59-3A75-4058-995F-4EE5503B023C} as described here), but clicking on the "Bluetooth settings" in this window does nothing as well.
The only way to get directly to the Bluetooth settings screen without going through the main Control Panel window and without turning on Bluetooth first, is by right clicking on the relevant tile in Windows Action Center:
Although this seems like a bug on the operating system level, I was wondering if there's any way to know when the launch fails from within C# code. So I've tried using the following code:
try
{
var process = new Process();
process.StartInfo.FileName = "control";
process.StartInfo.Arguments = "bthprops.cpl";
process.Exited += (s, e) =>
{
if (process.ExitCode != 0)
{
TurnOnBt();
}
};
var res = process.Start();
if (!res)
{
TurnOnBt();
}
}
catch (System.Exception ex)
{
int test = 6; // just for breakpoint
}
Problem is, no exception was ever thrown, and most of the time the Process.Exit event was never called.
Further more, calling Windows.Devices.Radios.Radio.GetRadiosAsync() returns an empty list!
Currently the only solution I've found is to manually turn on Bluetooth - it wouldn't change the Process.Start/Exit behavior, but it does allow to successfully lunch the command to directly open Bluetooth Settings window, and to get the list of the machine's Bluetooth/Radio devices. Still, when turning off Bluetooth and restarting the machine, same problem would happen all over again.
Any ideas for a code-based workaround?
note - all this based only on my debugging research, nothing from this is documented
i look how BT-settings window is open via Action Center (win8.1, win 10):
the IApplicationActivationManager interface created and called ActivateApplication method with:
appUserModelId = L"windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel"
arguments = L"page=SettingsPagePCSystemBluetooth"
code on c++ can be look like:
if (0 <= CoInitialize(0))
{
IApplicationActivationManager* pAppAct;
if (0 <= CoCreateInstance(__uuidof(ApplicationActivationManager), 0, CLSCTX_ALL, IID_PPV_ARGS(&pAppAct)))
{
ULONG dwProcessId;
pAppAct->ActivateApplication(
L"windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel",
L"page=SettingsPagePCSystemBluetooth",
AO_NONE ,
&dwProcessId);
pAppAct->Release();
}
CoUninitialize();
}
the processId (if all ok) reference to "X:\Windows\ImmersiveControlPanel\SystemSettings.exe" -ServerName:microsoft.windows.immersivecontrolpanel
for c# - look IApplicationActivationManager::ActivateApplication in C#?
the "windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel" and "page=SettingsPagePCSystemBluetooth" strings not documented anywhere and I not sure are it is "persist" - but currently it used to open manage Bluetooth page in system settings. as is.
in case we run control.exe bthprops.cpl - the process ( control.exe ) launched without any error - as result you and not got any errors when you call this code.
then control.exe bthprops.cpl exec new process rundll32.exe Shell32.dll,Control_RunDLL bthprops.cpl, and exit
the rundll32.dll call Control_RunDLLW(HWND_DESKTOP, (HINSTANCE)&__ImageBase, L"bthprops.cpl", SW_SHOWDEFAULT);
we can and direct call void WINAPI Control_RunDLLW(HWND hwndParent, HINSTANCE hInst, PCWSTR cplName, int nCmdShow ); this api exported from shell32.dll
internally Control_RunDLLW load "bthprops.cpl" (3-rd argument - cplName), find CPlApplet entry point, and send CPL_INIT message. the bthprops.cpl on this message check are bthserv is running via OpenService(L"BTHSERV", ) + QueryServiceStatus (in function BthpIsbluetoothServiceRunning) and if "BTHSERV" not running - it return zero (fail code)

How to open broswer's tab on remote machine

Scenario: I have configured Grid 2 and multiple tests are now running in parallel. When test starts there is opened browser window (only one tab opened) and some controls filled inside it. After that I open another tab (in the same browser window), switch to it and fill some controls inside it.
Before filling data inside second tab there needs to be done following steps:
1. Open new tab by calling SendKeys(Keys.Ctrl + 't')
2. Before switching to second tab wait for that second tab's handle to be added to driver instance.
3. If handle added to driver instance then switch to it, else 4.
4. Repeat operation 2. and 3. until timeout reached.
Problem:
When debugging I noticed that when opening a new tab, it's handle was not added to driver.WindowHandles. That means, if not checking if handle added and trying to switch to it, the exception will be thrown. In my case it would switch to incorrect tab as I'm calling driver.SwitchTo().Window(handles[handles.Count() -1]);. So I created method that waits for handle to be added. The problem is that, when running in multiple workers, it always times out. I have changed the timeout but nothing changes. The newly opened tab's handle is not added to WindowHandles. If I'm not running in parallel, then it works as expected.
// previousTabCount- browser's tab count before opening new one
public void WaitForTabToOpenAndSwtich(int previousTabCount)
{
int currentTabCount = driver.WindowHandles.Count();
int count = 0;
while(currentTabCount == previousTabCount)
{
// after 20 seconds throw exception
if(count > 20)
throw new Exception("The newly opened tab's handle was not added.");
// update current tab count
currentTabCount = driver.WindowHandles.Count();
count++;
Thread.Sleep(1000);
}
var handles = driver.WindowHandles;
driver.SwitchTo().Window(handles[handles.Count() -1]);
}
I found the solution. The problem was that when using SendKeys(Keys.Ctrl + 't') to open new tab on remote machine it did not work I'm not sure why. Fortunately I found an alternative approach. Instead of using that send keys command I used:
// script that opens a new tab
driver.ExecuteScript("var w = window.open(); w.document.open();");
After running this script the new tab was opened but I could not change its url by using driver.Navigate().GoToUrl("..."); and exception was thrown:
The HTTP request to the remote WebDriver server for URL 'http:
//example.com' timed out after 60 seconds
So I modified that script a bit by adding a page load at the end like this:
// script that opens new tab and reloads it
driver.ExecuteScript("var w = window.open(); w.document.open(); w.location.reload();");
This worked for me. Maybe someone will find this useful.

How to open "Microsoft Edge" from c# and wait for it to be closed?

I'm building a Windows Form application and I want to open "Microsoft Edge" through my app with a specific URL and wait until the user closes the Edge Window.
I tried it with this code:
using (Process p = Process.Start("microsoft-edge:www.mysite.com"))
{
p.WaitForExit();
}
When I execute this code, Edge is launching with the correct URL ... but got a null object reference. The "p" object that I'm getting from Process.Start is null.
I think it's related to the reuse of Windows application.
Does anyone have a workaround/have an idea how I can wait for the user to close Edge?
Finally I did managed to do so:
When you launch Edge (at least) two process get created:
MicrosoftEdge and MicrosoftEdgeCP.
MicrosoftEdgeCP - foreach tab. So we can "wait" on this new tab process that was just created.
//Edge process is "recycled", therefore no new process is returned.
Process.Start("microsoft-edge:www.mysite.com");
//We need to find the most recent MicrosoftEdgeCP process that is active
Process[] edgeProcessList = Process.GetProcessesByName("MicrosoftEdgeCP");
Process newestEdgeProcess = null;
foreach (Process theprocess in edgeProcessList)
{
if (newestEdgeProcess == null || theprocess.StartTime > newestEdgeProcess.StartTime)
{
newestEdgeProcess = theprocess;
}
}
newestEdgeProcess.WaitForExit();
From an older solution - use a WebBrowser control to load the HTML. Once you get the data back, use an ObjectForScripting to call a c# method to notify when done.
See http://www.codeproject.com/Tips/130267/Call-a-C-Method-From-JavaScript-Hosted-in-a-WebBrowser

Order of WindowHandles

I'm encountering an issue where WebDriver seems to change the order of WindowHandles. This causes us to close the wrong one intermittently after getting them in some cases.
What seems to happen is the previously established first window handle is returned as a subsequent handle, which causes my logic to of course, close the wrong one.
Is WebDriver supposed to return the window handles in the same order every time (order of first opened window to last?). This is what I initially expected, but now I'm not so sure.
I should also mention the problem seems to only occur in IE right now, but I'm not certain if this is a more generic issue.
Here is how I'm closing the active window and switching back to the root window.
public void Close()
{
//switch to latest window
string windowName = string.Empty;
if (_driver.WindowHandles.Count > 1)
{
//get 'root' window in list
windowName = _driver.WindowHandles[0];
_driver.Close();
_driver.SwitchTo().Window(windowName);
}
else
{
_driver.Close();
}
}
We're on WebDriver 2.45 (C# bindings, 32-bit IEDriver). If there is a method to close the active window in the C# bindings that would most likely solve this issue as well.
This pop up window handler is entirely unordered as per my understanding. I remember having same conversation on SO and luckily JimEvans(one of the contributors of Selenium) chimed in and clarify few factors. I read about the PopupWindowFinder of Selenium .NET bindings and found that class can make your life lot easier. API is here. However, the whole order issue is entirely complex and painful to deal with. See this thread. Just don't want to reinvent the wheel.

How to close Internet Explorer when it has been ran with Process.Start?

I'm have a WPF application that is starting Internet explorer (Version 9, on Win7 X64) using Process.Start method.
I save the ProcessID in order to close it when the application is closed. However, when the application exits, the Internet Explorer is still visible in the task manager.
Here is the code I'm using :
public class MyClass : IDisposable
{
Process _process;
public void Go()
{
ProcessStartInfo psi = new ProcessStartInfo {
FileName = "iexplore.exe",
Arguments = "-noframemerging -private \"http://whathaveyoutried.com\""
};
_process = Process.Start(psi);
_process.WaitForInputIdle();
}
private void Close(object sender, RoutedEventArgs e)
{
if (_process != null)
{
_process.Refresh();
_process.Close();
}
}
public void Dispose()
{
if (_process != null)
{
_process.Refresh();
_process.Close();
}
}
}
}
I double checked, the call to _process.Close() is actually done.
What can cause this behavior?
PS: I'm suspecting this is due to Internet Explorer internal. Running the exe won't necessary create a new process, but can use some IPC to control other instances. I use the -noframemerging command line argument, but it does not look to solve the issue.
[Edit] This is the continuation of another question I asked few days ago. Actually, I'm Pinvoking SetParent function to embbed the spawned IE in my application. I can't use the WebBrowser control because it does not support the isolation I'm looking for. So it's OK to close IE when my app closes.
Every tab of Internet Explorer is a process. If you open IE with multiple tabs or user opens another tabs, it won't be enough to kill process.
But
_process.Close();
Frees all resources belongs to _process. You can use _process.Kill() method instead of it.
For better security and stability, IE8 uses the Loosely Coupled Internet Explorer (LCIE) architecture and runs the browser frame and tabs in separate processes. LCIE prevents glitches and hangs from bringing down the entire browser and leads to higher performance and scalability. I read this on Wikipedia.
You can disable LCIE, but I am not sure why you would want to do that. I would consider using the a solution that #Damien_The_Unbeliever mention above.
I have an IE application in my win32 Application and i'm using Win32Api - SendMessage with WM_CLOSE = 0x0010
SendMessage(handle,0x0010,IntPtr.Zero, IntPtr.Zero)}
This closes the IE, how ever you need to have the specific handle of the Browser (Class IEFrame).
There is one drawback, in case you have more then one tab, the IE opens confirm close dialog which prevent the close process.
One way to overcome the dialog opening is to set it check box to (always close), but for me itţs not an option.

Categories

Resources