1

I'm doing this:

Process.Start("http://www.google.com");

After the default webbrowser is opened the website i want to check somehow that the website is opened by the webbrowser and close the specicif tab with this website.

To make a button click event that will check that if the website is already opened then close it.

Satpal
  • 132,252
  • 13
  • 159
  • 168
user2760148
  • 427
  • 2
  • 9
  • 19
  • 1
    That is not easily possible. – SLaks Sep 30 '13 at 15:53
  • Look into browser helper objects. http://code.msdn.microsoft.com/windowsdesktop/CSBrowserHelperObject-c5f3d2f6 – P.Brian.Mackey Sep 30 '13 at 15:54
  • @P.Brian.Mackey: That will not help for Chrome. – SLaks Sep 30 '13 at 15:56
  • @SLaks - He may need to write multiple browser extensions. If necessary, centralize results with some medium an XML file, client/server app or the like. Certainly not easy, but do-able. – P.Brian.Mackey Sep 30 '13 at 15:59
  • 1
    That's going to be different for every possible browser. – Marius Bancila Sep 30 '13 at 15:59
  • What are you trying to achieve? Opening a specific site and then closing it immediatelly hardly makes any sense… – Ondrej Tucny Sep 30 '13 at 15:59
  • Ondrei i don't want the user to click the button many times to open nonstop windows of the same website. In the other hand my program is doing something that need to click the button each sometime to update it. Could be after 5minutes or after 20minutes or after a day. The idea is that the user will be able to click any time and also won't click it nonstop and open too many windows . – user2760148 Sep 30 '13 at 16:05
  • Are you talking about stand-alone browser clients that would have an addon with this behavior installed? Or is it a specific browser control in a WinForms application? –  Sep 30 '13 at 16:05

1 Answers1

5

You would need to write an API for manipulating tabs in other browsers besides Internet Explorer, but you could start Internet Explorer processes and enumerate open windows/tabs like this:

using SHDocVw;
....
    public class IEClass
    {
        List<InternetExplorer> IEWindows;

        public IEClass()
        {
            IEWindows = new List<InternetExplorer>();
        }

        public List<InternetExplorer> GetIEInstances()
        {
            IEWindows.Clear();
            ShellWindows shellWindows = new ShellWindows();
            string filename;

            foreach (InternetExplorer ie in shellWindows)
            {
                filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
                if (filename.Equals("iexplore"))
                {
                    IEWindows.Add(ie);
                }
            }
            return IEWindows;
        }

        public bool QuitInstance(int key)
        {
            InternetExplorer ie = (InternetExplorer)IEWindows[key];

            try
            {
                ie.Quit();
                return true;
            }
            catch (Exception ex)
            {
                // handle any exception
            }
            return false;
        }

        public void StartInstance(string url)
        {
            InternetExplorer ie = new InternetExplorer();

            ieInstance.Visible = true;
            ieInstance.Navigate2(ref (object)url, ref Empty, ref Empty, ref Empty, ref Empty);
            IEWindows.Add(ie);
        }
    }

This may not be the most efficient code, but it does work for getting existing instances, creating new instances, and quitting instances of Internet Explorer windows/tabs. I tested it in Windows XP IE 6 up through Windows 7 IE 10.

I also wrote some C++ for getting the foreground window information which you could use to read the window title and process name to determine if a particular tab is open:

HWND foregroundWindow = GetForegroundWindow();
DWORD* processID = new DWORD;
GetWindowText(foregroundWindow, buf, 255);
GetWindowThreadProcessId(foregroundWindow, processID);
DWORD p = *processID;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
                              PROCESS_VM_READ,
                              FALSE, p);
TCHAR szProcessName[MAX_PATH];

if (NULL != hProcess )
{
    HMODULE hMod;
    DWORD cbNeeded;

    if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
                             &cbNeeded) )
    {
        GetModuleBaseName( hProcess, hMod, szProcessName,
                           sizeof(szProcessName)/sizeof(TCHAR) );
    }
}
CloseHandle(hProcess);

You could wrap this code in a C++ DLL or call the Windows API functions from pinvoke in C#.

This is the rough equivalent of the C++ code in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ForegroundWindowTest
{
    class Program
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        static extern int GetWindowTextLength(IntPtr hWnd);

        //  int GetWindowText(
        //      __in   HWND hWnd,
        //      __out  LPTSTR lpString,
        //      __in   int nMaxCount
        //  );
        [DllImport("user32.dll")]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        //  DWORD GetWindowThreadProcessId(
        //      __in   HWND hWnd,
        //      __out  LPDWORD lpdwProcessId
        //  );
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        //HANDLE WINAPI OpenProcess(
        //  __in  DWORD dwDesiredAccess,
        //  __in  BOOL bInheritHandle,
        //  __in  DWORD dwProcessId
        //);
        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr handle);

        //  DWORD WINAPI GetModuleBaseName(
        //      __in      HANDLE hProcess,
        //      __in_opt  HMODULE hModule,
        //      __out     LPTSTR lpBaseName,
        //      __in      DWORD nSize
        //  );
        [DllImport("psapi.dll")]
        private static extern uint GetModuleBaseName(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);

        //  DWORD WINAPI GetModuleFileNameEx(
        //      __in      HANDLE hProcess,
        //      __in_opt  HMODULE hModule,
        //      __out     LPTSTR lpFilename,
        //      __in      DWORD nSize
        //  );
        [DllImport("psapi.dll")]
        private static extern uint GetModuleFileNameEx(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);

        public static string GetTopWindowText()
        {
            IntPtr hWnd = GetForegroundWindow();
            int length = GetWindowTextLength(hWnd);
            StringBuilder text = new StringBuilder(length + 1);
            GetWindowText(hWnd, text, text.Capacity);
            return text.ToString();
        }

        public static string GetTopWindowName()
        {
            IntPtr hWnd = GetForegroundWindow();
            uint lpdwProcessId;
            GetWindowThreadProcessId(hWnd, out lpdwProcessId);

            IntPtr hProcess = OpenProcess(0x0410, false, lpdwProcessId);

            StringBuilder text = new StringBuilder(1000);
            //GetModuleBaseName(hProcess, IntPtr.Zero, text, text.Capacity);
            GetModuleFileNameEx(hProcess, IntPtr.Zero, text, text.Capacity);

            CloseHandle(hProcess);

            return text.ToString();
        }


        static void Main(string[] args)
        {
            while (!Console.KeyAvailable)
            {
                Console.WriteLine(GetTopWindowText());
                Console.WriteLine(GetTopWindowName());
            }
        }
    }
}

You might also check out this answer here: How can I get URLs of open pages from Chrome and Firefox?

Community
  • 1
  • 1
Cameron Tinker
  • 9,634
  • 10
  • 46
  • 85