I am currently developing a tool that will run automation test cases.
So at the moment, I wanted to make the test cases run concurrently by creating a new thread for each of the test case.
Thread playThread = new Thread(this.PlayMainConcurrent);
playThread.Start(main);
When the playThread is started, an IE browser will launch and perform the automation, and there will be a few IE browser launched together. I want to know is there any way to close a specific IE browser among the browser launched by process id?
What I have tried is using
playThread.Abort();
but this only exited the thread, not closing the browser.
Also, I have tried using Process.Kill()
foreach (var proc in Process.GetProcessesByName("iexplore"))
{
proc.Kill();
}
this did closes the ie browser, however i don't want it to close all my ie browser because i just one to kill only one specific browser.
Additionally, my project can only support .NET Framework 2.0 and are not able to update to newer one.
Thanks in advance.
The trick is to keep the reference of each process
// Start a procecss that opens a Notepad
Process myProcess = Process.Start("Notepad.exe")
// Close process by sending a close message to its main window.
myProcess.CloseMainWindow();
// Free resources associated with process.
myProcess.Close();
Microsoft Documentation
Related
I am hoping to check at the beginning of an automated test if an application is open. I can check if the process is running by doing the following
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName.Contains(name))
{
return true;
}
}
However, the process I want to find starts up about a minute before the application actually opens and is ready to be used by the test methods (its a very slow starting application). The above code sample looks at all windows processes running, but I am wondering, is there a way to do a similar method but to look at windows applications running?
There is a method already in class Process that you can use to check if an app with a UI has fully started:
Process.WaitForInputIdle(int milliseconds)
This will wait up to milliseconds ms for the message loop to become idle (and returns a bool to indicate success status). Depending on the application you're waiting for, you might want to allow 30 seconds or longer.
This might work for you, but be aware that in my experience for some applications it is not totally reliable!
The Windows API documentation has more details about the Windows API function that WaitForInputIdle() calls behind the scenes.
When a process is started, you can say application has started.
What you want is to wait until application startup progress has completed or not.
This means, when process is started, application startup begins. When application startup is completed, is becomes ready for user input. So I think you should have a look at following question and its answers.
Programmatically, how does this application detect that a program is ready for input
Apllication is proces.
If you can modify app, at app start you can create file and at end delete it. So you can chceck file existance. If file exist app starting/started.
If you need info when main form is created use:
WINFORMS
Form.Shown event.
WPF Loaded Event
uITestControl.Exists did the trick for me.
This method will return a boolean value corresponding to the existence of the application window being open. This allows an if statement to be created that can open the application if not already open, or do nothing if its already open.
I'm running Selenium Webdriver through a Visual Studio Unit Test and using the InternetExplorerDriver. This fires up IEDriverServer.exe in a console window.
This works great and the test executes. Once test execution finishes i'd like that cmd.exe window killed so that it's not hanging around for me to have to do manual cleanup. I have thousands of tests so you can imagine the headache of managing this.
Is there an elegant way to handle this without having to do post test execution and killing cmd.exe processes with kill.exe, etc? I've tried InternetExplorerDriverService.HideCommandPromptWindow = true, but that just runs cmd.exe in hidden mode and leaves the process running until it's manually killed. I've also tried InternetExplorerDriverService.SuppressInitialDiagnosticInformation and all that does is suppress some of the information written to the cmd.exe window.
To complement the awser, some informations about the subject. There are 3 main methods that that you can use as you need:
.Close(): - This method is used to close the current open window. It closes the current open window on which driver has focus on.
.Quit(): - This method is used to destroy the instance of WebDriver. It closes all Browser Windows associated with that driver and safely ends the session. Quit() calls Dispose method to achieve this.
.Dispose(): - This method closes all Browser windows and safely ends the session
emphasized text
In your case, as you need to kill the process, the best choice is use .Quit().
Sometimes you're unable to end the process when your selenium instance broke up, and the current and all next tests starts to fail, or even when you cancel a current debugging test suit. In this cases, you really need to kill the process.
As #Prateek saw, one of they is using Runtime.getRuntime(). In C#, the better way to do it is:
foreach (var proc in Process.GetProcessesByName("IEDriverServer"))
{
proc.Kill();
}
You can use it in the constructor where you start your WebDriver (but before to start it!) or, if you're using some lib as NUnit, you can create a global OneTimeSetUp. A kind of method that runs only one time before all test.
Also, if you don't like to put code or create new methods to do this job, you can configure in yout main .csproj the pre-build and post-build to execute your cmd command. Whenever you will run your tests or build your project, it will kill the opened webdriver instance.
To configure it you will need:
Right button in your .csproj and click in "Properties";
Navigate to "Build Events";
Paste the command taskkill /f /fi "pid gt 0" /im IEDriverServer.exe in pre-build textarea, post-build or in both.
There are two ways:
As suggested in comments driver.quit() will do the job.
But sometimes our test fails and the Driver keeps running. To avoid having multiple instances of drivers you can use: Runtime.getRuntime().exec("taskkill /T /F /IM IEDriverServer.exe");.
The benefit of using this command is that even if your script doesn't run completely it would still kill the driver.
You can use it in a number of places. For example:
If you are using frameworks such as TestNG you can override onTestFailure().
You can add it in the beginning of your test so that if there are any instances already open they'll be killed.
Or you can add in other places such as catch block.
I think you should try this:
InternetExplorerDriverService service = InternetExplorerDriverService.CreateDefaultService();
service.Start();
IWebDriver driver = new ThreadLocal<IWebDriver>(() => { return new InternetExplorerDriver(service); }).Value;
int pid = service.ProcessId;
// Do any automation you want with your driver...
driver.Quit(); // it calls Dispose
service.Dispose();
// And if you want to ensure... :-)
try { Process.GetProcessById(pid).Kill(); }
catch { }
Please, notice that it is suitable for Chrome, Firefox and other drives!
I'm using following code to iterate over a list of browsers executable paths and start each of them:
foreach (var browser in browsers)
{
var proc = new Process();
proc.StartInfo.FileName = browser.ExecutablePath;
proc.StartInfo.Arguments = "http://google.com";
proc.Start();
proc.WaitForExit();
Console.WriteLine(proc.ExitCode.ToString());
proc.Close();
}
What is should do is: it should open browser window with google.com loaded and stop the application until the window is closed. And it works fine for both IE and Firefox, but fails with Chrome.
For Chrome proc is in Exit state just after launching the browser, when the window is still active and visible.
I tried using some of chromium command line switches, including --new-window and --single-process but with no success.
Question is, how can I force Google Chrome to run in the process it is started in, so it would be possible to wait until window is closed?
Update
Just to clarify the question:
I know why it does not work - it's because Chrome uses multiple processes for different things, like different tabs, plug-ins, etc.
I tried to find the correct process looking on process tree, but found nothing.
I can't just take the latest process created by chrome, because it may be the process created for a pluging the page requires, not the page itself.
If you want to open/close entire Chrome window:
Chrome by default is constantly running in background because of its default settings. Change this option to unchecked:
Settings > Show advanced > System > 'Continue running background apps when Google Chrome is closed'
So you have to make sure Chrome is closed before you run it again by your code. That works for me.
If you want to open/close related tabs only:
Chrome have one 'mother process' and some child processes.
The problem is that if you run chrome using your code you are trying to create new instance of 'mother process' but the existing one won't let you do it. She'll instantly kill your new process and create her own child instead. That's how it works...
So, all you need is figure out how to run another 'chrome mother process' and prevent the previous hug from killing her ;P
I figure out this solution:
Run new chrome process with this parameter --user-data-dir="%temp%/random_name". This means that you are opening chrome with new user profile.
Advantages:
It works
Chrome is opening in new window
Chrome is closing when all related tabs are closed
Disadvantages:
Default settings (no bookmarks, etc) but you can copy them from default user profile directory
So, maybe you should look for sth in this direction...
Another command line parameter that (sort of) works is --chrome-frame. It appears Chrome uses WinInet API when in this mode, because the IE history is available. I do like more the idea about using --user-data-dir with a unique temp folder, as proposed by #DamianDrygiel.
You could find all the child processes of the Chrome process you run and then wait for them to finish.
There is a StackOverflow question that has some useful code: Find all child processes of my own .NET process / find out if a given process is a child of my own?. Also you might find this useful: Monitor child processes of a process.
I'm developing a vbnet/c#.NET based application that opens files with different applications(excel, word, etc).
The application is launched using Dim app As Process = Process.Start(ProcessProperties)
Now, when I have to terminate the process I use app.Kill() but I need to check if the document has been modified before killing it.
How can I handle that? And if it's possible, how can I launch the application native prompt for save?
Thanks
For office applications use Office Interop Assemblies, not Process.Start to start and control them. Here is an example code for Excel (in VB.NET). You should add Microsoft.Office.Interop.Excel.dll to the project references in order for this to work.
oExcel = New Microsof.Office.Interop.Excel.Application
oBook = oExcel.Workbooks.Open(filepath)
'Do your stuff
oBook.Close 'This will trigger the application native prompt if the document was modified
oExcel.Quit()
For other programs it depends much on a program
You can achieve behaviour close to what you require by calling Process.CloseMainWindow rather than Process.Kill.
The behavior of CloseMainWindow is identical to that of a user closing an application's main window using the system menu. Therefore, the request to exit the process by closing the main window does not force the application to quit immediately.
Data edited by the process or resources allocated to the process can be lost if you call Kill. Kill causes an abnormal process termination, and should be used only when necessary. CloseMainWindow enables an orderly termination of the process and closes all windows, so it is preferable for applications with an interface.
In the case of Office applications with unsaved changes, CloseMainWindow would launch the Save dialog. You would need to handle scenarios where the users presses “Cancel”, since that may result in the WaitForExit call blocking indefinitely.
For example:
// Launch Word application.
Process wordProcess =
Process.Start(#"C:\Program Files (x86)\Microsoft Office\Office12\winword.exe");
// Give user some time to type in text.
Thread.Sleep(TimeSpan.FromSeconds(20));
// Request Word to close.
wordProcess.CloseMainWindow();
// Wait until user saves or discards changes.
// May block indefinitely if user cancels.
wordProcess.WaitForExit();
There are different approaches for this problem. You can calculate some sort of initial check-sum and see whether your document has any changes by redoing the check-sum and comparing against the original one.
This part is not very clear from your question, If the document gets saved, probably you can look at the date_modified value of the file to see whether there has been any modifications.
I'm starting a external application with System.Diagnostics.Process, this external process at one moment opens up a dialog where user has type something and then click OK. What i need is to wait with my application(the one where i started the external process) until the user has inserted something and clicked OK. After that OK i have to do some more task on that external process and then close it.
Yes, it's possible. There are a number of ways to get window information starting with a process handle and/or ID. See this question and responses for getting started. You will most likely end up using P/Invoke to the Win32 API to get this accomplished but there are dozens of good examples for getting this done.
Once you have the window handle you can use a timer polling scheme to test for the presence, or in your case, presence and then the disappearance of a window.
This is possible but there are some work behind it. First you need to run your code as unmanaged code as you will need to hook on Windows OS events with the Win32 API.
So an option would be to have a loop looking for the dialog to open, pause what ever your code are doing and continue when the dialog are gone.
If the application you are starting exists after the user interacts with the dialog, then you can just call Process.WaitFroExit() and your code will not continue until the process you started has quit.
There are quite a few helpful functions for interacting with processes in the System.Diagnostics.Process class (that I assume you are using to start this external application)