Starting and stopping firefox from c# - c#

When I start
/Applications/Firefox.app/Contents/MacOS/firefox-bin
on MacOSX using Process.Start() using Mono, the id of the process that gets returned does not match the process that firefox ends up running under.
It looks like firefox quickly decides to start another process, and kill the current one.
This makes it difficult to stop firefox, and to detect if it is still running. I've tried starting firefox using the -no-remote flag, to no avail.
Is there a way to start firefox in such a way that it doesn't do this "I'll quickly make a new process for you" dance?
The situation can somewhat be detected by making sure Firefox keeps on running for at least 3 seconds after its start, and when it does not, scan for other firefox processes. However, this technique is shaky at best, as on slow days it might take a bit more than 3 seconds, and then all tests depending on this behaviour fail.
It turns out, that this behaviour only happens when asking firefox to start a specific profile using -P MyProfile. (Which I need to do, as I need to start firefox with specific proxyserver settings) If I start firefox "normally" it does stick to its process.

When using mozilla programmatically / embedding in other apps you should use the provided components:
"The right way" as recommended by mozilla ...
https://developer.mozilla.org/en/XPCOM
"The easy way", general consensus from Mozilla dev guys ...
http://www.iol.ie/~locka/mozilla/control.htm
Need to "execute processes", simply instantiate an instance of the component and talk to that, you should then have everything you need.
However ...
If you really do insist on looking after the actual process for a firefox instance, you may want to call
Process.Start("...\firefox.exe");
Then try this (i believe this works on MAC OS too) ...
C#/mono: get list of child processes on Windows and Linux
The basic idea / thought pattern being that if it is in fact executing another process right away you should be able to find that as would be a "child" process instead of being just one from a list in the "task list" / process manager for the machine.

In case you are ok with the detection of Firefox process itself but don't know when you should start the detection, you can use the Process.Exited event. Don't forget to set EnableRaisingEvents first.

I suggest taking a different approach: list all running processes, find Firefox, get it's process ID and (optional) see if it is the one you started.
I'm not sure if there's a platform-independent way to accomplish this. On Linux, you can call "ps -ef" to list them, on Windows it's called "tasklist".

I don't have a Mac, so I can't be sure, but if it's anything like Linux the firefox 'binary' is actually a shell script which sets up a bunch of required environment variables and checks if firefox is already running (if it is, it will try and add a new tab to the existing instance, as far as I know).
You may be able to capture the new PID within the script, although if you update it do beware of it being overwritten during upgrades.

Related

How to add extension to running remote multilogin webdriver? (Selenium C#)

First I tried to add extension directly from chrome webstore, but problem is alert popup which appears after you click "add to chrome" is not reachable by selenium. After I wanted to try using options.AddExtension, but multilogin profile starts before selenium takes control so this method is useless. I know that I can manually import .crx for every profile but there are thousands of profiles and I need to automate process of installing extensions. I don't know what to do, I heared there's option to reach popup alert in chrome webstore but can't find it. Or maybe there are other ways to install extension after browser started? I'm glad for any help or advice
I have 2 possible scenarios for you, hope that works out since I don't have direct access to this specific need you have because the extensions may differ.
Not using Selenium, you gonna start the chrome process using the class Process and add the flag --load-extension= to load the specific profile/extension that you need. You can see the entire comma here. To sum, you can use this snippet below to load:
chrome --user-data-dir=/tmp/someuniquedirname --load-extension=path/to/extension --no-first-run //Note: some flags may change between versions of chrome, see full documentation
After defining the extension and start chrome, you can now get hold of the process with Selenium by using another flag: --remote-debugging-port=http://localhost:[localporthere]. After that, start the process than tell to Selenium to get hold of that process with the port and do your job.
Another way is to start the process installing the extension manually and in another Thread use some Automation UI (Teststack.White or FlaUI) to click on the popup you have. I can't extend here in the entire code for this solution because it will go to a opinion-based answer, but you can check on FlaUI for that use, and follow that path:
Selenium starts the program, click on the install extension and wait for the popup to show-up;
New Thread;
FlaUI gets hold of the process that you already start;
Using UIElements, click on the "ok" button you need;
FlaUI drops;
Back to the main thread.
If you need any clarifications about the solutions above, just comment and I'll try to help you further.

Taking an IE screenshot returns a black image

I'm building a console app which will connect to different computers in the network and take browser screenshots of a webpage.
Using Selenium 2.47.1 to set up server & nodes. The console app runs in the PC which is set up as selenium hub.
The screenshot is fine in firefox,chrome,ie from the hub computer.
The screenshot is also fine in firefox in remote pc.
But with IE it returns a black image.
Both the hub and node computers run on windows 7 64-bit, have IE11. I am using the 64bit IEDriver in both PCs.
The node computer is not locked.
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
static void Main(string[] args)
{
IWebDriver NewDriver = null;
using (NewDriver = new RemoteWebDriver(new Uri("http://172.165.10.111/wd/hub"), DesiredCapabilities.InternetExplorer()))
{
if (NewDriver != null)
{
NewDriver.Navigate().GoToUrl("http://www.google.com");
NewDriver.Manage().Window.Size = new Size(1804, 1096);
Screenshot ss = ((ITakesScreenshot)NewDriver).GetScreenshot();
ICapabilities capabilities = ((RemoteWebDriver)NewDriver).Capabilities;
ss.SaveAsFile(#"C:\Path\123.png", ImageFormat.Png);
NewDriver.Quit();
}
}
}
It's because your screen is locked, or a screensaver is running.
You will need to turn off your screensaver and configure windows to never lock itself when not in use. To turn off your screensaver:
Click the Start button.
Click Control Panel.
In the search box, type screen saver.
Click Turn screen saver on or off.
Then modify your screensaver settings. Make sure you have unchecked "On resume, display logon screen".
While you're in the control panel it's probably worth checking the power options and making sure the machine isn't going to sleep or powering down after a set period of time as well.
You will also want to use VNC or remote assist to access the GUI. If you RDP in it will lock the screen for the local user who is currently logged in and again it will lock the screen when you disconnect.
Finally don't use the 64-bit IE driver, you should be using the 32Bit one. Nobody runs the 64Bit version of IE (even if they have a 64Bit capable machine).
****** Edit
Adding a bit more info from a credible and reputable source ******
Below is a link to a post on the Selenium users forum where Jim Evans (the developer who wrote the IEDriver binaries) explains this:
http://selenium.10932.n7.nabble.com/IE-Screenshots-are-black-when-not-connected-via-Remote-Desktop-to-the-VM-hosting-an-IE-Node-td37004.html
This quote in particular about taking screenshots when you have disconnected from a RDP instance:
It's a known limitation. There is no known workaround. Complain to
Microsoft. They're the ones that make the PrintWindow API (which is
the proper API to use when grabbing screen captures) behave that way.
Either that, or if you discover a way to make it work, you're welcome
to submit a patch.
He explains how the screenshot code works in more detail on his blog here:
http://jimevansmusic.blogspot.co.uk/2014/09/screenshots-sendkeys-and-sixty-four.html
Specifically:
The IE driver takes screenshots using the PrintWindow API function.
PrintWindow can only take a screenshot of the visible portion of any
given window, which means that in order to get a full-page screenshot
(as required by the WebDriver API), the window must be sized large
enough to display the entire page without scroll bars. However,
Windows does not allow the window to be resized larger than the
visible screen resolution. When we ask IE to resize itself, a
WM_GETMINMAXINFO message is sent on a resize event so the IE can
figure how large a window can be. By intercepting that message with a
hook, and modifying the max values, we can trick IE into thinking that
a window can be sized greater than the screen resolution would
otherwise allow.
It looks like this might be a known issue with configuration:
https://code.google.com/p/selenium/issues/detail?id=3536
From what #ShubhasmitGupta mentioned above, it does look like the IE driver hands out black-screen screenshots when the desktop is locked (I'm assuming this has something to do with DWM/Explorer not rendering windows).
There's a workaround involving not locking the targeted computer when connecting to it via RDP. Essentially, you create a disconnect.bat file with the following contents:
tscon rdp-tcp#0 /dest:console
I'm not sure exactly when that's supposed to be run, but the concept is to prevent the test computer from being locked when connecting via Remote Desktop. If that helps, great; I haven't been able to test the workaround myself and figure out how to set it up. Maybe someone else can write a more concise answer.
Open up the Service Control Manager -- You can do WindowsKey+R (run) and type services.msc and hit <ENTER> and it'll start up.
Find the service and right click it and choose properties from the context menu.
Allow Service to Interact With Desktop
Now, select the Log On tab.
You want to make sure the checkbox is selected for "Allow service to interact with the desktop".
You can see it in the image below.
Note: I don't have that service so I just picked another one in the sample picture.
you may want to try removing below line
//NewDriver.Manage().Window.Size = new Size(1804, 1096);
maximize your browser instead.
NewDriver.Manage().Window.Maximize();
I have had a sneaky suspicion that IE has been rendering with DirectX for some time and this article certainly seems to indicate that this is the case... which would explain why you'd have problems as GDI based screen grabs won't work with DirectX surfaces.
I'm saying this is an absolute... just a hunch
I had the same issue a while back, and though I don't completely understand the problem it was basically that the process executing selenium was running under a system account and thus the IE gui was visible only in session 0, whereas session 1 was showing only a black screen.
The solution which worked for me was to create a local user account on the remote host, keep that user permanently signed in and unlocked so that they have an interactive desktop available, then run your selenium app/tests as that user. I know that is not ideal, but as we had dozens of old boxes lying around, it didn't hurt to use one as a dedicated test server. Hope that helps somewhat!
Sorry, not enough rep to add this as a comment.
Perhaps an interesting hint...
...working with Selenium 2.47.x and 2.52.0 Jenkins, RDP and IE 11 in mode IE 7 (setting by website) on the server Win 2008. Additional to this, I have to screens connected to my PC.
If I am disconnected from the Win Server (not logged off) I have two situations:
The JAVA prog on the Server produces black boxes or real screenshoots. The difference is just one marker in RDP options in the display part on the local RDP configuration of my client (Win 7).
I have not an english spoken display so I hope the translation may ok.
The configuration detail is: "using all monitors by remote session"
If this marker is set, I get real screen shoots. If this one is not set I have black boxes. I can't explain why, but it works in this way...
Windows would sometimes cause black screens because the machine/desktop was not in use.

How to hide PhantomJS.exe when running GhostDriver on Selenium

I've been working on an app to crawl through a list of URLs and pull down the live source code (i.e. generated source instead of raw) - and I've used PhantomJS via Selenium.NET to do this as I wanted to have the operation done in a headless form.
The process itself works fine, but each time one of my threads loads an instance of the PhantomJS driver it runs PhantomJS.exe (as GhostDriver) in a newly opened console. I'd like to avoid this is possible as each time a thread starts the console windows are stealing focus on the machine. Does anyone know whether this is possible? I'm using a really basic snippet to launch the instance:
IWebDriver driver = new PhantomJSDriver();
driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 30));
driver.Navigate().GoToUrl(Entry);
///... Store HTML and do main work here ...
driver.Quit();
driver.Dispose();
Is there a way to hide the exe window via one of the additional capabilities that can be passed into the constructor, or a better way to load the instance via Process.Start etc..?
Any help would be appreciated as I can't seem to find any official documentation dealing with this issue for the .NET platform.
Thanks in advance!
The appearance of the console window is by design. The developer and maintainer of the .NET bindings believes strongly that launching processes that may output to the console while not displaying the console window is detrimental to debugging efforts. If this is really that huge an issue for you, you can launch PhantomJS.exe using your own System.Diagnostics.Process object, and use the RemoteWebDriver class to connect to and control it. Be aware, though, that you are then responsible for the lifetime of the PhantomJS.exe process, and will need to handle closing that process yourself (i.e., you can't rely on driver.Quit() to exit the process for you, like you can with the browser-specific PhantomJSDriver class).

How can I recover a reference to a process that has been relaunched?

Using Process.Start, I am starting various IE8 and Firefox (3.5) processes which I keep a Process instance for.
A little while later in the application, I'll use the Process instances' MainWindowHandle property to target the window for use with some platform API functions via P/Invoke.
However, both IE8 and Firefox will kill the second process I start, then restart it using the first. This means that my Process instance now refers to a closed process, and so HasExited is true and MainWindowHandle is equal to IntPtr.Zero.
Here's an example of what happens (I'm using IE8 for this example):
Process.Start is called with "iexplore.exe"
Process starts and continues running
Process.Start is called again with "iexplore.exe"
First process continues running, but the second is killed immediately
Another iexplore process is started (presumably by the first iexplore process).
During this time, the user sees the second IE window only after the second process is killed and restarted.
I understand why these browsers behave this way, but it does create a problem for me if I want to control the created process later on.
Has anyone come across this problem before? How would you recommend getting a reference to the process back? I thought about using GetProcessesByName and iterating through their window titles, but unfortunately the titles may be the same as the first process launched.
Note: IE8 was the first version of IE to use process separation and so only IE8 behaves this way, I don't have this problem with IE7, unfortuantely I need IE8 support as well.
I have used the Running Object Table (ROT) in the past to find a specific process and control it.
http://www.codeproject.com/KB/COM/ROTStuff.aspx

Prevent Process 'A' from spawning Process 'B' which then shows up on top of what should be the "TopMost" Process 'C'

I have a windows form application which needs to be the TopMost. I've set my form to be the TopMost and my application works as I'd like it to except for in one case.
There is a 3rd party application (referred to as player.exe) that displays SWF movie files on a portion of the screen that popup on top of my application.
Using Process Monitor I determined that player.exe application calls
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
in my case:
flash.exe 901 96 379 261 somemovie.swf
Since flash.exe is being spawned in a new process after my form has been set to the TopMost it is appearing on top of my application.
First thing I did was make my application minimize the player.exe main application window hoping that this would prevent the Flash from appearing also. But, unfortunately it doesn't... even with the window minimized whenever the flash movie starts it shows up at the pixel location (901,96). I then tried creating a timer to keep setting the form.TopMost property to true every 10ms. This sort of works but you still see a very quick blip of the swf file.
Is there some type of Windows API call which can be used to temporarily prevent player.exe from spawning child processes which are visible? I admit it sounds a little far fetched. But, curious if anyone else has had a similar problem.
Addendum:
This addendum is to provide a reply to some of the suggestions layed out in Mathew's post below.
For the emergency situation described in the comments, I would look at possible solutions along these lines:
1) How does the third party application normally get started and
stopped? Am I permitted to close it
the same way? If it is a service, the
Service Control Manager can stop it.
If it is a regular application,
sending an escape keystroke (with
SendInput() perhaps) or WM_CLOSE
message to its main window may work.
Easiest way to close the app is to CTRL-ALT-DEL, then kill process. -OR-
The proper way is to Hold ESC while clicking the left mouse button... then input your username and password, navigate some menu's to stop the player.
There is no PAUSE command... believe it or not.
I don't think using WM_CLOSE will help since minimizing the application doesn't. Would that kill the process also? If not, how do you reopen it.
2) If I can't close it nicely, am I permitted to kill it? If so,
TerminateProcess() should work.
I can't kill the process for two reasons. 1) Upon relaunch you need to supply username/password credentials... There may be a way to get around this since it doesn't prompt when the machine is rebooted but... 2) Whenever I kill the process in task manager it doesn't die gracefully and asks if you want to send an error report.
3) If I absolutely have to leave the other process running, I would try
to see if I can programmatically
invoke fast user switching to take me
to a different session (in which there
will be no competing topmost windows).
I don't know where in the API to start
with this one. (Peter Ruderman
suggests SwitchDesktop() for this
purpose in his answer.)
I got really excited by this idea... I found this article on CodeProject which provides a lot of the API Wrapper methods. I stopped implementing it because I think that in order for desktop's to work you must have explorer.exe running (which I do not).
EDIT2: On second thought... maybe explorer.exe isn't needed. I'll give it a try and report back.
Edit3: Was unable to get the code in that article working. Will have to put this on hold for a moment.
Answer Summary
As one might have expected, there is no simple answer to this problem. The best solution would be to problematically switch to a different desktop when you need to guarantee nothing will appear over it. I was unable to find a simple C# implementation of desktop switching that worked and I had a looming doubt that I would just be opening a whole new set of worms once it was implemented. Therefore, I decided not to implement the desktop switching. I did find a C++ Implementation that works well. Please post working C# virtual desktop implementations for others.
Setting the TopMost property (or adding the WS_EX_TOPMOST style to a window) does not make it unique in the system. Any number of topmost windows may be created by any number of applications; the only guarantee is that all topmost windows will be drawn 'above' all non-topmost windows. If there are two or more topmost windows, the Z-order still applies. From your description, I suspect that flash.exe is also creating a topmost window.
Aside from periodically forcing your window to the top of the Z-order, I think there is little you can do. Be warned, however, that this approach is dangerous: if two or more windows are simultaneously trying to force themselves to the top of the Z-order, the result will be a flickering mess that the user will likely have to use the task manager to escape.
I recommend that your program not attempt to meddle with other processes on the computer (unless that is its explicit purpose, e.g. a task manager clone). The computer belongs to the user, and he may not value your program more highly than all others.
Addendum:
For the emergency situation described in the comments, I would look at possible solutions along these lines:
How does the third party application normally get started and stopped? Am I permitted to close it the same way? If it is a service, the Service Control Manager can stop it. If it is a regular application, sending an escape keystroke (with SendInput() perhaps) or WM_CLOSE message to its main window may work.
If I can't close it nicely, am I permitted to kill it? If so, TerminateProcess() should work.
If I absolutely have to leave the other process running, I would try to see if I can programmatically invoke fast user switching to take me to a different session (in which there will be no competing topmost windows). I don't know where in the API to start with this one. (Peter Ruderman suggests SwitchDesktop() for this purpose in his answer.)
You can use the Process class to start flash.exe directly - and use an appropriate ProcessStartInfo settings to show the window in a hidden state - or with a WindowStyle of hidden or minimized.
You could also consider using the SetWindowsHookEx API to intercept the process start API calls, and when the process is flash.exe run some code to restore you window to top-most status.
Matthew's answer is excellent, but I suspect you may be asking the wrong question. Why does your application need to be topmost? If you're trying to create a kiosk or some such, then topmost is not the way to go.
Edit: After reading your response to Matthew's comment, I'd suggest creating a new desktop and switching to it before displaying your alert. (See CreateDesktop and SwitchDesktop in MSDN.)

Categories

Resources