I'm trying to use C# to open two separate browser windows side by side. I've tried using Process.Start(url) but that causes Chrome to open new tabs instead of new windows. This seems to work on IE, however I'd like to have code that can work with different types of browsers, namely: IE, Chrome, Firefox, and Safari. How do I detect the default browser and then open two separate windows side-by-side? Additionally, I want to be able to position the two windows next to each other, is that possible?
If you want to open new window in chrome instead of new tab, this code worked for me
Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = "chrome";
process.StartInfo.Arguments = <yoururl> + " --new-window";
process.Start();
This is more about the way that the browser is configured than how the process is called from C#. In both cases, the system simply calls the default program assigned to handle the URL. There may or may not be arguments to that command, but typically it will simply invoke chrome.exe <url> and from there, the chrome.exe process decides how to handle the parameter.
The only method I am aware of would be to examine the registry (under HKEY_CLASSES_ROOT\http\shell\open\command) and parse the string value. Once you know the specific browser, you may be able to control the presentation using command-line arguments. Of course, this is specific to Windows and may be a pain to manage.
If the browser does not support setting a geometry from the command line, you will need to use FindWindow and SetWindowPos (using P/Invoke) to manipulate the window locations.
I am not sure about your application, but would embedding a WebBrowser Control meet your needs? Then you would have total control of the presentation.
Related
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.
On Windows, is there any way to modify the default browser in current application domain, but not system wide?
I'm developing an IDE using C# and I need that all child processes that try to launch the default web browser, see my IDE as the default web browser. But I need to do so in a way that it does not affect the rest of the system configuration.
Not sure if I'm explaining the issue clearly...
Anyone has any ideas how this could be done?
Actually there is no way to make it for a certain process. This value is stored in registry, and can be changed for a different user.
But in general are several options.
Run debuggee using a special user account, which has a different registry value for default browser.
Register your IDE as default browser in a reg key HKEY_CLASSES_ROOT\http\shell\open\command. If IDE could determine if the caller is not a debuggee, invoke original browser (don't forget to backup initial value).
If you use something like host process - intercept calls to RegQueryValue or other registry functions, and hijack the result for a debuggee. (if there is no host process, try to inject an interceptor). Alternatively you may intercept CreateProcess or ShellExecute.
I'm afraid that's not an option, but - you're able to register a dummy protocol (like myhttp://) and pretend it's http :) Your IDE will be a handler for it.
On which Windows are you? In windows 7 and 8 you can find the default program settings in the control panel. Just start the control panel and type 'default programs' in search box in the upper right hand corner.
I am using
System.Diagnostics.Process.Start(ProcessInfo);
to open a TEXT file in notepad from within my windows form application.
Detailed code snippet is
ProcessStartInfo PSI = new ProcessStartInfo("notepad.exe", LogFile);
PSI.WindowStyle = ProcessWindowStyle.Normal;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
However, it opens notepad on the default desktop but not on the extended desktop on which the main application is running.
Now, the question is, how to open notepad on the active desktop i.e. Window on which the current application is running?
Other that specifying the initial window state (normal, hidden, etc), you have basically no control over how the newly launched application starts up and where it shows itself.
The best bet here is to launch the application, then use its window handle to tell it to move. This all requires using P/Invoke, to call MoveWindow. The C# signatures for all of those functions are on pinvoke.net.
Here's a very simple (VB.NET) example that shows the basic idea. In this case, as #Lloyd points out, the window handle you need is the Process.MainWindowHandle you get back from Process.Start. Note that Process.MainWindowHandle isn't filled in immediately; you typically need to call WaitForInputIdle to make sure the window actually gets created. If MainWindowHandle is 0 then you'll know it's too soon.
I run Firefox (default browser) from C# with the code:
System.Diagnostics.Process.Start(browser.Document.Url.ToString());
I want Firefox to run in the background, because every time is open a new tab, the Windows is focusing on the Firefox, and is annoying.
How can I control Firefox tabs, close them after a time ?
You can use a ProcessStartInfo to tell it to run hidden or minimized or whatever. Not sure how to programmatically manipulate FireFox but I'm sure there's an API.
var psi = new System.Diagnostics.ProcessStartInfo();
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.FileName = browser.Document.Url.ToString();
var proc = System.Diagnostics.Process.Start(psi);
//after a while...
proc.Kill();
Technically, you are not starting Firefox, you are executing a url.
I'm not sure exactly what Windows does, but in effect, that url is opened in the system's default browser, be it IE, FF or some other thing that might not even support tabs, so finding and killing Firefox is not really a solution if the url is opened in Opera.
Moreover, the Process.Start method returns null if no process is actually started by the call, so if Firefox is already running and just displays an additional tab, you will get a null as the result of the call.
So, I'm pretty sure this is impossible to do in a broad sence (any browser), and, unless Firefox has some sort of API for client-side management, not possible for that scenario either.
BTW, on my system (IE is the default browser), the WindowStyle property is not working as expected, as IE pops up to the front.
Rather than trimming the tabs, why not just kill the entire Firefox process and restart it periodically?
You won't be able to do this. First of all, I'm pretty sure running Firefox in the background won't stop it gaining focus when a new tab is opened. Second, it is difficult to control firefox programmatically. The only way to do what you want is to use a plugin like MozRepl. You could also try using selenium or your own JavaScript to control the browser behaviour. I needed to be able to open and close tabs in a shell script without using selenium or MozRepl, check out my question From a shell script open a new tab in a specific instance of Firefox
is it possible ? any samples/patterns or ideas on how to go about it ?
Update -
this essentially becomes a text browser which displays various tables of information based on various commands on the prompt like typing the url in a browser
now instead of typing various commands like
prompt>command arg1 arg2
if only you could say "click" on the text in a certain "column"/"row" which would execute the command say
prompt>commandX arg1
it'd be somewhat faster/easier
Now, before someone mentions doing a typical browser/asp.net mvc/whatever app, i already have that running but have encountered some limitations esp. with accesing network files. etc. Now that's taken care of using a service-broker service which reads the file etc. but having added numerous extensions to it, it'd be somewhat easier if you could just run the app as a console prompt with a mvc pattern and add extensions to it etc. etc.
if only the text is clickable, it'd make it more friendly for use !!
Assuming no mouse, I would just launch the URL as a new process based on some keyboard trigger.
// this will launch the default browser
ProcessStartInfo psi = new ProcessStartInfo("https://stackoverflow.com");
Process p = new Process(psi);
p.Start();
VB syntax:
// this will launch the default browser
Dim psi = New ProcessStartInfo("https://stackoverflow.com")
Dim p As Process = Process.Start(psi)
The window's shell doesn't support clickable hyperlinks, so no, this isn't possible.
What are you trying to do that warrants the need for hyperlinks in the command shell? Perhaps this application would be better built as a WinForms/WPF or ASP.NET application.
I don't know what a "hyperlink" is for you, but in the context of a Console Application, you can have numbers or letters that you are expecting the user to press
(imagine a simple menu with 3 options)
Press one option
1 - Open ServerFault
2 - Open StackOverflow
3 - Open SuperUser
and in the readline you have a switch that start the IExplorer process for example and opens the webpage.
Is that what you call regarding "hyperlinks in a console application"?
For an idea of what it can look like, get your hands on a copy of links. It's a text-mode web browser that works just fine in several operating systems.
you can access the mouse from the console, if you wish to have clickable elements in your console application. you'll have to build the logic yourself of course for the clickable areas.
http://cboard.cprogramming.com/windows-programming/38680-win32-console-app-mouse-input.html