Retrieve Current Url from C# Windows Forms Application

Retrieve current URL from C# windows forms application

Here's what I have so far (though Chrome I'm not finding any helpful articles on, other than using FindWindowEx (I don't particularly like that method, personally).

public class BrowserLocation
{
/// <summary>
/// Structure to hold the details regarding a browed location
/// </summary>
public struct URLDetails
{
/// <summary>
/// URL (location)
/// </summary>
public String URL;

/// <summary>
/// Document title
/// </summary>
public String Title;
}

#region Internet Explorer

// requires the following DLL added as a reference:
// C:\Windows\System32\shdocvw.dll

/// <summary>
/// Retrieve the current open URLs in Internet Explorer
/// </summary>
/// <returns></returns>
public static URLDetails[] InternetExplorer()
{
System.Collections.Generic.List<URLDetails> URLs = new System.Collections.Generic.List<URLDetails>();
var shellWindows = new SHDocVw.ShellWindows();
foreach (SHDocVw.InternetExplorer ie in shellWindows)
URLs.Add(new URLDetails() { URL = ie.LocationURL, Title = ie.LocationName });
return URLs.ToArray();
}

#endregion

#region Firefox

// This requires NDde
// http://ndde.codeplex.com/

public static URLDetails[] Firefox()
{
NDde.Client.DdeClient dde = new NDde.Client.DdeClient("Firefox", "WWW_GetWindowInfo");
try
{
dde.Connect();
String url = dde.Request("URL", Int32.MaxValue);
dde.Disconnect();

Int32 stop = url.IndexOf('"', 1);
return new URLDetails[]{
new URLDetails()
{
URL = url.Substring(1, stop - 1),
Title = url.Substring(stop + 3, url.Length - stop - 8)
}
};
}
catch (Exception)
{
return null;
}
}

#endregion
}

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Internet Explorer: ");
(new List<BrowserLocation.URLDetails>(BrowserLocation.InternetExplorer())).ForEach(u =>
{
Console.WriteLine("[{0}]\r\n{1}\r\n", u.Title, u.URL);
});
Console.WriteLine();

Console.WriteLine("Firefox:");
(new List<BrowserLocation.URLDetails>(BrowserLocation.Firefox())).ForEach(u =>
{
Console.WriteLine("[{0}]\r\n{1}\r\n", u.Title, u.URL);
});
Console.WriteLine();
}
}

Getting the active url of browser in C# windows form application

Finally i found the answer

public string GetBrowsedUrl(Process process)
{
if (process.ProcessName == "firefox")
{
if (process == null)
throw new ArgumentNullException("process");

if (process.MainWindowHandle == IntPtr.Zero)
return null;

AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element == null)
return null;

AutomationElement doc = element.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
if (doc == null)
return null;

return ((ValuePattern)doc.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
else
{
if (process == null)
throw new ArgumentNullException("process");

if (process.MainWindowHandle == IntPtr.Zero)
return null;

AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element == null)
return null;

AutomationElement edit = element.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));

string result = ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
return result;
}

}

Find the URL of the current web application


string app = HttpContext.Current.Request.ApplicationPath;

That should do the trick.

Get URL from browser to C# application


Part 2:

Basically I have too much code to separate out the minimum for this example, but I have provided my own algorithm below for you to pour over.

This one also keeps track of tabs in browsers, as and when they reappear (IE only), so you will need to strip out the bits you don't want. I seem to remember I fixed this for IE8, but not sure if that fix went in this code, so don't be surprised if it needs a little tweak :)

    // Iterate all browsers and record the details
IntPtr hWnd = IntPtr.Zero;
NativeWIN32.EnumChildWindows(hWnd, new NativeWIN32.Win32Callback(BrowserEnumCallback), hWnd);

/// <summary>
/// Called back for each IE browser.
/// </summary>
/// <param name="hWnd"></param>
/// <param name="lParam"></param>
/// <returns></returns>
static bool BrowserEnumCallback(IntPtr hWnd, IntPtr lParam)
{
// Is this app IE?
if (NativeWIN32.GetClassName(hWnd) == "IEFrame")
{
// If this is a new browser, add it
if (!BrowserWindows.ContainsKey(hWnd))
{
// Record the Browser
BrowserWindow browser = new BrowserWindow()
{
hWnd = hWnd
};
// Store the browser in the temp list and temp member
TempCurrentBrowser = browser;
BrowserWindows.Add(hWnd, browser);
}
else
{
// Store the browser in the temp list and temp member
TempCurrentBrowser = BrowserWindows[hWnd];
}
TempCurrentBrowser.WindowText = NativeWIN32.GetWindowText(hWnd);
TempCurrentBrowser.Found = true;

// Now that we know it is a browser, look for tabbed windows and address bar
NativeWIN32.EnumChildWindows(hWnd, new NativeWIN32.Win32Callback(BrowserEnumChildrenCallback), hWnd);
}
return true;
}

/// <summary>
/// Called back for each child window in the browser
/// </summary>
/// <param name="hWnd"></param>
/// <param name="lParam"></param>
/// <returns></returns>
static bool BrowserEnumChildrenCallback(IntPtr hWnd, IntPtr lParam)
{
string classname = NativeWIN32.GetClassName(hWnd);
switch (classname)
{
// This is the main address bar
case "Edit":
{
string url = NativeWIN32.GetWindowText(hWnd);
if (url.StartsWith(@"http://") || url.StartsWith(@"https://") || url.StartsWith("about:"))
{
TempCurrentBrowser.Url = url;
return true;
}
}
break;

case "ComboBoxEx32":
{
string url = NativeWIN32.GetWindowText(hWnd);
if (url.StartsWith(@"http://") || url.StartsWith(@"https://") || url.StartsWith("about:"))
{
TempCurrentBrowser.Url = url;
return true;
}
}
break;

// Record any sub pages still active, by title to avoid revisiting popup
// If this name matches the name of the browser, it is the current window
// If so, record the browser url for reference in that tab window
case "TabWindowClass":
{
string title = NativeWIN32.GetWindowText(hWnd);
BrowserTabWindow tabWindow;
if (!TempCurrentBrowser.TabWindows.ContainsKey(hWnd))
{
// Create a new tabbed window for the current browser
tabWindow = new BrowserTabWindow()
{
hWnd = hWnd
};
TempCurrentBrowser.TabWindows.Add(hWnd, tabWindow);
}
else
{
tabWindow = TempCurrentBrowser.TabWindows[hWnd];
}
tabWindow.WindowText = title;
tabWindow.Found = true;
}
break;
}
return true;
}

Part 1:

If Microsoft Spy++ can see the address control, then yes it is possible.

I don't have Opera installed, but the Chrome control hierarchy in Spy++ looks like this:

alt text

I have done similar things with Internet Explorer:

  • To record a diary the sites visited - then a popup asks the user what they were doing
  • To display a widget that pops up when certain known sites were visited

Firefox was the problem child as it renders the address bar internally and not via a windows control but I see you have already found the solution to that one.

In C# you need to make unmanaged calls to Windows API methods. As you can see from the C# API code alone (below) it can get a little involved:

const int WM_GETTEXT = 0xD;

// used for an output LPCTSTR parameter on a method call
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct STRINGBUFFER
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szText;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/,
IntPtr next /*HWND*/,
string sClassName,
IntPtr sWindowTitle);

/// <summary>
///
/// </summary>
/// <param name="hWnd">handle to destination window</param>
/// <param name="msg">message</param>
/// <param name="wParam">first message parameter</param>
/// <param name="lParam"second message parameter></param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd,
int msg, int wParam, out STRINGBUFFER ClassName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount);

//[DllImport("user32.dll")]
//[return: MarshalAs(UnmanagedType.Bool)]
//static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

/// <summary>
/// Helper to get window classname
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
static public string GetClassName(IntPtr hWnd)
{
NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
NativeWIN32.GetClassName(hWnd, out sLimitedLengthWindowTitle, 256);
return sLimitedLengthWindowTitle.szText;
}

/// <summary>
/// Helper to get window text
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
static public string GetWindowText(IntPtr hWnd)
{
NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
SendMessage(hWnd, WM_GETTEXT, 256, out sLimitedLengthWindowTitle);
//NativeWIN32.GetWindowText(hWnd, out sLimitedLengthWindowTitle, 256);
return sLimitedLengthWindowTitle.szText;
}

The algorithm involved basically searches all windows from the Desktop on down until it finds Browser windows (based on specific class or window attributes). It then searches for specific child elements based on the type of browser. When you finally get to the address control you can extract the address from the control. Hopefully my helper class code will speed your development.

"NativeWIN32" Followup - Dec 2013

The NativeWIN32 references are simply to a wrapper class containing useful constants and methods for other Win32 features. I have added it here in full:

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

namespace YourProject
{
/// <summary>
/// Wrapper for native win32 calls
/// </summary>
public class NativeWIN32
{
const int WM_GETTEXT = 0xD;

// used for an output LPCTSTR parameter on a method call
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct STRINGBUFFER
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szText;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/,
IntPtr next /*HWND*/,
string sClassName,
IntPtr sWindowTitle);

/// <summary>
///
/// </summary>
/// <param name="hWnd">handle to destination window</param>
/// <param name="msg">message</param>
/// <param name="wParam">first message parameter</param>
/// <param name="lParam"second message parameter></param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd,
int msg, int wParam, out STRINGBUFFER ClassName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount);

//[DllImport("user32.dll")]
//[return: MarshalAs(UnmanagedType.Bool)]
//static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

/// <summary>
/// Helper to get window classname
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
static public string GetClassName(IntPtr hWnd)
{
NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
NativeWIN32.GetClassName(hWnd, out sLimitedLengthWindowTitle, 256);
return sLimitedLengthWindowTitle.szText;
}

/// <summary>
/// Helper to get window text
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
static public string GetWindowText(IntPtr hWnd)
{
NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
SendMessage(hWnd, WM_GETTEXT, 256, out sLimitedLengthWindowTitle);
//NativeWIN32.GetWindowText(hWnd, out sLimitedLengthWindowTitle, 256);
return sLimitedLengthWindowTitle.szText;
}
}
}

Get url of current page from modal popup

you can use this method:

var url1 = HttpContext.Request.Host;
var url2 = HttpContext.Request.Path;
var url = url1 + url2;

Sample Image



Related Topics



Leave a reply



Submit