2

I have a keyboard hook implementation that changes the output of certain text under given conditions. To determine how to format the output, I need to be able to see which window is in focus, and if Internet Explorer is in focus, I need to be able to determine which URL is open on that specific tab.

I've been working with the code posted by Simon in the following post: Retrieve current URL from C# windows forms application

Process[] localByName = Process.GetProcessesByName("iexplore");


if((Keys)vkCode == Keys.LShiftKey)
{
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}


foreach (Process process in Process.GetProcessesByName("iexplore"))
{
    string url = GetInternetExplorerUrl(process);
    if (url == null)
        continue;

    Console.WriteLine("IE Url for '" + process.MainWindowTitle + "' is " + url);
}

As I have Internet Explorer running (and have webpages open for that matter), I was hoping/expecting to see an output of some sort with URLs, showing the URL(s) open. Instead of getting URLs written to the console, I get nothing. In the case where I tried to use GetProcessesByName, I just get the following output, System.Diagnostics.Process[]

Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
Josh41
  • 29
  • 3
  • don't quote me on this, but i seem to remember reading the url from an external program was blocked on purpose. It's hard enough even doing it when you're embedding the active-x control in a form. – John Lord Jun 18 '19 at 19:18
  • With wich IE version ? If I check IE hierarchy with **Inspect** on my IE version (11), I see that this code is wrong... – Castorix Jun 18 '19 at 19:37
  • All of the URLs that need to be detected should be in IE11 for the time being. – Josh41 Jun 19 '19 at 03:24

2 Answers2

1

To get the all URL's from Internet Explorer tabs you can do the following:

1. Add a reference to "Microsoft Internet Controls" enter image description here

2. Add the following code to get the URL's:

SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();

List<string> urls = shellWindows
    .Cast<SHDocVw.InternetExplorer>()
    .Where(ie => System.IO.Path.GetFileNameWithoutExtension(ie.FullName).ToLower() == "iexplore")
    .Select(ie => ie.LocationURL)
    .ToList();

foreach (string url in urls)
{
    Console.WriteLine(url);
}
Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
  • Thanks! This works perfectly for pulling all of the URLs open in IE (at least in IE11), but what I'm really needing to do is to identify if one of these URLs is in the focused window. My initial thought was to try to tie these URLs to a process ID, but I'm not really sure how to go about that yet. – Josh41 Jun 19 '19 at 03:28
0

This solution is a hacky way of doing the job.

The main idea

  1. Send ALT+D to the browser to select the URL text
  2. Send CTRL+C to copy the URL

A few things to consider

  1. In order to send keys to a window, it needs to be the active window (foreground window).
  2. If the browser window state was changed, it would be good to return it to its original state.
  3. If the clipboard is used, it would be good to return it to its original state.

The steps to get the active tab URL

  1. Find processes named "iexplor" with a main window title.
  2. Remember the original active window and the original browser window state.
  3. Make the browser window the active window.
  4. Remember the original data on the clipboard.
  5. Send ALT+D, CTRL+C
  6. Copy the clipboard.
  7. Restore the original clipboard data.
  8. If the browser window was minimized, minimize it.
  9. Restore the original active window.

Disadvantages

  1. Changing the browser window state is visibly noticeable.
  2. If the browser window was not minimized, making it the active window will bring it to the front. Even if the original active window is restored, it will still be the window behind it.

Code requirements

  1. This code uses Vanara NuGet package for Win32 API
  2. A reference to System.Windows.Forms is required for Clipboard and SendKeys
  3. The Main needs to have [STAThread] attribute in order to use Clipboard

Code

using System.Windows.Forms;
using System.Diagnostics;
using Vanara.PInvoke;

…

// Get all Internet Explorer processes with a window title 
Process[] ieProcs = Process.GetProcessesByName("iexplore")
    .Where(p => !string.IsNullOrEmpty(p.MainWindowTitle))
    .ToArray();

// Initialize a URL array to hold the active tab URL
string[] ieUrls = new string[ieProcs.Length];

for (int i = 0; i < ieProcs.Length; i++)
{
    Process proc = ieProcs[i];

    // Remember the initial window style of the process window
    User32_Gdi.WindowStyles initialWndStyles = (User32_Gdi.WindowStyles)User32_Gdi.GetWindowLongPtr(proc.MainWindowHandle, User32_Gdi.WindowLongFlags.GWL_STYLE);

    // Remember the initial foreground window
    IntPtr initialFgdWnd = (IntPtr)User32_Gdi.GetForegroundWindow();

    // Show the process window.
    // If it is minimized, it needs to be restored, if not, just show
    if (initialWndStyles.HasFlag(User32_Gdi.WindowStyles.WS_MINIMIZE))
    {
        User32_Gdi.ShowWindow(proc.MainWindowHandle, ShowWindowCommand.SW_RESTORE);
    }
    else
    {
        User32_Gdi.ShowWindow(proc.MainWindowHandle, ShowWindowCommand.SW_SHOW);
    }

    // Set the process window as the foreground window
    User32_Gdi.SetForegroundWindow(proc.MainWindowHandle);

    ieUrls[i] = null;

    // Remember the initial data on the clipboard and clear the clipboard
    IDataObject dataObject = Clipboard.GetDataObject();
    Clipboard.Clear();

    // Start a Stopwatch to timeout if no URL found
    Stopwatch sw = Stopwatch.StartNew();

    // Try to copy the active tab URL
    while (string.IsNullOrEmpty(ieUrls[i]) && sw.ElapsedMilliseconds < 1000)
    {
        // Send ALT+D
        SendKeys.SendWait("%(d)");
        SendKeys.Flush();

        // Send CRTL+C
        SendKeys.SendWait("^(c)");
        SendKeys.Flush();

        ieUrls[i] = Clipboard.GetText();
    }
    // Return the initial clipboard data to the clipboard
    Clipboard.SetDataObject(dataObject);

    // If the process window was initially minimized, minimize it
    if(initialWndStyles.HasFlag(User32_Gdi.WindowStyles.WS_MINIMIZE))
    {
        User32_Gdi.ShowWindow(proc.MainWindowHandle, ShowWindowCommand.SW_MINIMIZE);
    }

    // Return the initial foreground window to the foreground
    User32_Gdi.SetForegroundWindow(initialFgdWnd);
}

// Print the active tab URL's
for (int i = 0; i < ieUrls.Length; i++)
{
    Console.WriteLine(ieUrls[i]);
}
Community
  • 1
  • 1
Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37