Process.Kill() issue - c#

I have the following lines of code:
Process aProcess = Process.Start("ieexplorer", aDummyHTMLFilePath);
//I do nothing in between
aProcess.Kill();
This runs smooth if there are NO other IE windows open.
But if there is a window open, I get a System.InvalidOperationException on aProcess.Kill(); saying :
Cannot process request because the process has exited.
Also, I notice that in this case, aProcess.HasExited is true right after line 1 in the code above.
How can I smoothly close IE, even if there are other IE windows open?

When you start a new instance of Internet Explorer like you do it will try to see if Internet Explorer is already running. If that is true the URL is opened in the already running instance and the new instance exits immediately. This means that when you try to kill the process you started it has already exited voluntarily. However, you will see a new browser window or tab on your screen but that is being hosted by the existing Internet Explorer process.

I didnt get the same issues as you
I found that the following worked if the process was still running or not
Process p = Process.Start("notepad.exe", "");
Thread.Sleep(5000);
if (!p.HasExited) p.Kill();
It only complained IF the window had been closed. Hence the check

Related

Process.Exited raising immediately after Process.Start [duplicate]

i have a strange problem with IE8 installed in xp. i was trying to launch IE using an System.Diagnostics.Process.Start method in c#. And i have a requirement to trap the exited event of the IE and do some operation. But i ended up in a rather strange problem where the IE immediately fires the exited event after launch.
this is the sample code
Process objProcess = Process.Start("IEXPLORE.EXE", "http://google.com");
if (objProcess != null)
{
objProcess.EnableRaisingEvents = true;
objProcess.Exited += new EventHandler(myProcess_Exited);
}
public static void myProcess_Exited(object sender, System.EventArgs e)
{
MessageBox.Show("You exited");
}
But the above code perfectly works when laucnching different process (ex:notepad) and it fires the exit event when i close the exe.
this only gives problem launching IE 8. Can someone clarify me what is the problem??
UPDATE
Most friends replied my post and saying why you can't just use an URL? why stick with IE?
here the reason
the ultimate aim of the app is to launch an URL from the windows application and will hide an exe when working on the IE. And show the exe after closing the IE.
Thanks
Most probably is that you have IE already running as a process, so when you try to launch it again as a new process it looks that there are IE running already, tells it that user initiated a new window (so the initial IE will create a "new" window rather than a new one) and exit.
Possible solution:
try starting the process with "-nomerge" command line option:
Process objProcess = Process.Start("IEXPLORE.EXE", "-nomerge http://google.com/");
Interesting observation: objProcess.ExitCode (for IE8 at least) will be equal to 0 if exited passing control to another instance, and 1 if it was actually closed by user.
If another instance of iexplore.exe is already running on the machine, new instances will connect to that and immediately exit. Also, it's possible that even in the case where iexplore is not running, the multiprocess architecture of Internet Explorer 8 has the parent launch child broker process and exit immediately.
But these answers are besides the point. You should not be launching Internet Explorer directly. If the user has configured another default browser, they will be unhappy that you are ignoring their preferences. Instead, why don't you try
System.Diagnostics.Process.Start("http://google.com");
directly and that will do the right thing. You won't be able to tell when the browser closed, but if the command has opened a new tab in an existing browser session for example, the browser close event will be meaningless to your application.
Maybe IEXPLORE itself launches a different process for the URL and ends the process you created? Like a fork on Unix?

Kill all child processes before closing main Application (Selenium & WebDriver Processes)

I'm working with Selenium in my .NET Application, when using quit() on either a Firefox or Chrome driver the browser processes do not close correctly however the WebDriver process gets closed. So when my Application terminates the remaining Firefox and Chrome processes remain opened in the background (as child processes to my Application).
Screenshot when running normally with Firefox Driver Running
After trying to using quit() and closing my application
I'm looking for a way to close the WebDriver and the browser processes with it (without using a lazy "kill all processes named 'chrome' or 'firefox'"), if this is not possible then a a way to terminate all child processes associated with my Application when it exits would work for me too.
The current solutions that are available makes use of ManagementObjectSearcher but this would not be ideal because it would not work with Linux (Mono) but only on Windows.
I've tried to close all Windows using close() before using quit() but the browser process still remains opened
I've tried to debug the statements to see if it's actually sending a quit command to the Web Driver and it is.
Since i am using a RemoteDriver that is connected to a DriverService, i am using quit() on the RemoteDriver before disposing of the DriverService.
I expect all browser processes including WebDrivers to be closed when i use quit() or at least have a solution to terminate all child processes associated with my application to be killed before exiting the Application. But only the web drivers get closed and the browser processes remain opened in the background.
Chrome when not in headless mode, does actually close the Window but the process remains opened.
Firefox when not in headless mode, does not close the Window at all. even when using close()
Example Code
// Creating the RemoteDriver with Options
var DriverService = ChromeDriverService.CreateDefaultService();
var DriverOptions = new ChromeOptions();
DriverOptions.AddArgument("headless");
DriverOptions.AddArgument("mute-audio");
DriverService.Start();
var RemoteDriver = new RemoteWebDriver(DriverService.ServiceUrl, DriverOptions);
// Quitting
RemoteDriver.Quit();
DriverService.Dispose();
Update
After testing the same code on Linux, the browser processes has closed as expected unlike the problem that i faced when using Windows 10. After some more searching i discovered that other people has faced the same issue, see this issue and it seems to either be a problem related to a Windows update or the WebDrivers (I'm using the latest drivers that are available and stable) However this issue has not been opened or mentioned in a while.
In conclusion, this problem is only on Windows and more specifically Windows 10. There is still no solution to this problem and it's out of the reach of Selenium and more towards a WebDriver issue. Still.
Update
This is an issue on Opera as well, a desirable workaround as i mentioned above would be to kill all child processes associated with your process. To those who keep saying "USE CLOSE BEFORE QUIT" is not a solution as i explained more than once what i have already tried and what the unexpected results were
The solution i mentioned above can be accomplished with "ManagementObjectSearcher" but since i made this post i have learnt that this issue is only reproducible on Windows and is out of reach from your code, Selenium and more to do with the WebDriver or Browsers themselves. So the solution is to only use ManagementObjectSearcher to kill child processes associated with your process if you are running on Windows, because this will not work on Mono. But you don't need to worry since i already explained that this issue is not reproducible on Linux, only Windows.
Thanks for the help.
This is what I use. It won't help in cases where the driver has crashed (it's Java):
boolean closecaught = false;
try
{
if (driver!=null) { driver.close(); }
}
catch (Exception e)
{
closecaught = true;
System.out.println(e.toString());
try {
driver.quit();
}
catch (Exception exce)
{
System.out.println("Exception quitting" + exce.toString());
}
}
if (closecaught)
{
}
else
{
try
{
driver.quit();
}
catch (Exception ex)
{
// don't worry it should close
}

start and close instance of explorer.exe

I have a strange behaviour when I try to start explorer.exe from c# like this:
ProcessStartInfo info = new ProcessStartInfo("explorer.exe", "E:");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();
process.WaitForExit(5000);
The problem is:
the exception seems correct, because at this point HasExited returns already true. Nevertheless in the taskmanager the created instance of explorer is still present.
So I dont understand what my call does. I had thought it would directly start an instance of explorer, but it seems not or the explorer works in some different way.
And my second question: how can I start and shortly after that stop a new specific instance of explorer programmatically?
Edit
to answer some questions:
explorer option Launch Folder Windows in a separate process is set to true
the created process.Id is not present in taskmanager. For example: the new explorer instance shown in taskmanager has PID 4968 while the debugger shows 10752 as ID of the created (and exited) process.
Edit: here a screenshot from taskmanager after ~12 debug runs
This may be down to the fact that the explorer.exe process in question HAS exited. Windows does some strange things with multiple explorer windows and it depends on the options you have set. By default, all windows end up running in a single process if I remember correctly.
What I would do is output the processid for the process you just generated:
Console.WriteLine($"{process.Id} has exited {process.HasExited}");
Then look at task manager to see if you can find the corresponding process. I would imagine that the HasExited is true so you won't find the process, but the window will have opened.
You may have to set process.EnableRaisingEvents to true to get a valid answer from process.HasExited, I can't recall of the top of my head.
Also check the setting in Explorer via Folder Options to see if you have Launch Folder Windows in a separate process enabled or not on the view tab.
IF you do find your process, you can always kill off that process and see if your windows closes. If it does, then it may be that the explorer.exe is not creating a main window handle which you can check using Spy++
Edited with more info
Further more, #Hans Passant mentioned above that shell windows work different. So what actually happens is this, explorer.exe (1234) contacts the root explorer.exe (321), which in turn then creates a new window (if Launch separate is false) or spawns a subprocess explorer.exe (3445). Your process explorer.exe (1234) having done its job, then exits. No window is ever created by your process so CloseMainWindow() will not find a window to close and errors.
How to close a specific explorer window
To do so you need to utilise ShellWindows, see Is there a way to close a particular instance of explorer with C#?
For reference the code used there was:
ShellWindows _shellWindows = new SHDocVw.ShellWindows();
string processType;
foreach (InternetExplorer ie in _shellWindows)
{
//this parses the name of the process
processType = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
//this could also be used for IE windows with processType of "iexplore"
if (processType.Equals("explorer") && ie.LocationURL.Contains(#"C:/Users/Bob"))
{
ie.Quit();
}
}
Note, you need to be careful that you aren't closing a window the user wanted open in the first place. Is there a reason to close the window?
The problem is in the notion of has UI Interface, As per definition:
Closes a process that has a user interface by sending a close message
to its main window.
However explorer.exe is far more complicated than a simple process with UI.
If for example you use another, application, more simple (e.g Notepad), no exception will be raised:
ProcessStartInfo info = new ProcessStartInfo("notepad.exe");
info.WindowStyle = ProcessWindowStyle.Maximized;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();

Process.WaitForExit() not waiting for multiple Chrome instances

I'm trying to start Chrome from WPF application using .NET framework 4.0 with code similar to the following:
var arg = string.Format("--app=\"{0}\" --window-size=1024,1000", "http://bing.com");
this._process = Process.Start("chrome.exe", arg);
this._process.WaitForExit();
// Perform relevant operations once the process completes/ exit
I'm opening chrome in app mode.
Case 1: When I have a no additional Chrome instance/window opened, WaitForExit blocks the control till the Chrome window created through code is closed - This is what I'm looking for.
Case 2: If I have a Chrome instance running already. Then it does not wait for the chrome instance created through code to exit and moves on to the next line. I want to have similar experience as in case 1, that is the control should be blocked until the user closes the chrome instance.
Is there anything extra I need to do get this working when I have multiple instances of Chrome already opened?
You can use Process.GetProcessesByName to get all opened chrome process,and invoke WaitForExit for each process
Process.Start(#"%AppData%\..\Local\Google\Chrome\Application\chrome.exe",
"http:\\www.YourUrl.com");
You can also try with dis
Process.Start("chrome", #"http://www.stackoverflow.net/");

Process.Start("IEXPLORE.EXE") immediately fires the Exited event after launch.. why?

i have a strange problem with IE8 installed in xp. i was trying to launch IE using an System.Diagnostics.Process.Start method in c#. And i have a requirement to trap the exited event of the IE and do some operation. But i ended up in a rather strange problem where the IE immediately fires the exited event after launch.
this is the sample code
Process objProcess = Process.Start("IEXPLORE.EXE", "http://google.com");
if (objProcess != null)
{
objProcess.EnableRaisingEvents = true;
objProcess.Exited += new EventHandler(myProcess_Exited);
}
public static void myProcess_Exited(object sender, System.EventArgs e)
{
MessageBox.Show("You exited");
}
But the above code perfectly works when laucnching different process (ex:notepad) and it fires the exit event when i close the exe.
this only gives problem launching IE 8. Can someone clarify me what is the problem??
UPDATE
Most friends replied my post and saying why you can't just use an URL? why stick with IE?
here the reason
the ultimate aim of the app is to launch an URL from the windows application and will hide an exe when working on the IE. And show the exe after closing the IE.
Thanks
Most probably is that you have IE already running as a process, so when you try to launch it again as a new process it looks that there are IE running already, tells it that user initiated a new window (so the initial IE will create a "new" window rather than a new one) and exit.
Possible solution:
try starting the process with "-nomerge" command line option:
Process objProcess = Process.Start("IEXPLORE.EXE", "-nomerge http://google.com/");
Interesting observation: objProcess.ExitCode (for IE8 at least) will be equal to 0 if exited passing control to another instance, and 1 if it was actually closed by user.
If another instance of iexplore.exe is already running on the machine, new instances will connect to that and immediately exit. Also, it's possible that even in the case where iexplore is not running, the multiprocess architecture of Internet Explorer 8 has the parent launch child broker process and exit immediately.
But these answers are besides the point. You should not be launching Internet Explorer directly. If the user has configured another default browser, they will be unhappy that you are ignoring their preferences. Instead, why don't you try
System.Diagnostics.Process.Start("http://google.com");
directly and that will do the right thing. You won't be able to tell when the browser closed, but if the command has opened a new tab in an existing browser session for example, the browser close event will be meaningless to your application.
Maybe IEXPLORE itself launches a different process for the URL and ends the process you created? Like a fork on Unix?

Categories

Resources