views:

1061

answers:

1

From a C# application I want to activate (brint to front) a site that is already open in the users default browser. I want to do this in a browser agnostic way.

The difficult part (for me at least) is that I do not want the browser to open a new tab and the browser must not reload the page if it is already open.

I can open the URI in the default browser with

System.Diagnostics.Process.Start("http://foo.example");

But the exact behaviour depends on the users default browser (IE6 seems to reuse the current topmost browser window, Google Chrome will always open a new tab and so on)

Another approach I tried was to enumerate all open Windows and find the one I want based on the window title (making the assumption that most browsers set the window title to the title of the currently open page)

public delegate bool EnumThreadWindowsCallback(int hWnd, int lParam);

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);

[DllImport("user32.dll")]
static extern int GetWindowText(int hWnd, StringBuilder text, int count);

private bool FindWindowByRx(int hWnd, int lParam)
{
    Regex pattern = new Regex("Example Title of Page", RegexOptions.IgnoreCase);
    StringBuilder windowTitle = new StringBuilder(256);
    GetWindowText(hWnd, windowTitle, 255);

    if (pattern.IsMatch(windowTitle.ToString()))
    {
        SetForegroundWindow(new IntPtr(hWnd));
        return false; // abort search
    }
    else
    {
        return true; // keep on searching
    }
}

using it with:

EnumWindows(new EnumThreadWindowsCallback(FindWindowByRx), new IntPtr());

This does what I need it to do, but feels very brittle and hackish, and is probably slow.

Is there a better, more elegant way?

+1  A: 

This will work, IF the user has that site active in their browser. If they're using a tabbed browser, and the site is open, but not in the selected tab, I don't believe you will ever find the browser window. (EnumWindows only enumerates top-level windows).

If the user's started a new tab, you'll end up not finding it, and (likely) starting a second copy of the site in a new tab.

Personally, if you really need to restrict to a single browser instance, I would consider whether its possible to embed the browser in your application instead of using the default browser. If this can be made a GUI element in your application using a browser control, you'd have much more control and be able to avoid this type of workaround.

Reed Copsey
I can live with the restriction that this will not work with background tabs. Embedding a browser ontrol in my app is not an option, unfortunately. (because it would change the exsting workflow too much)What I'm ideally hoping for is something like OpenUriInDefaultBrowser("http://foo.example", OpenUriOptions.ActivateOnly)I should probably mention that I also have control over the browser side of things so maybe if there was a way to activate a browser window 'from the inside', that'd work for me too (maybe it's possible to do something clever with custom URI-Schemes?)
levinalex
Unfortunately, there is no browser-agnostic way to do this. You could potentially do this via browser add-ins in IE and Firefox, but I don't think that would work for Chrome or Opera.
Reed Copsey