我一直在使用Visual C#设计一个程序,并且遇到了使我的程序与Web浏览器交互的问题。基本上我需要的是从Web浏览器(Internet Explorer,Firefox,Chrome等)中检索URL地址。
我认为这对任务来说不是太困难,但经过数天和数天的研究和测试,似乎几乎不可能!到目前为止,我遇到过这个......
其中包含以下代码:
using NDde.Client;
Class Test
{
public static string GetFirefoxURL()
{
DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url = dde.Request("URL", int.MaxValue);
dde.Disconnect();
return url;
}
}
这对Firefox来说是完美的,但出于某种原因,我无法让它与其他任何东西一起使用。我已经将代码“Firefox”的部分更改为“Iexplore”,就像我在互联网上找到的一样,并尝试其他形式的表达Internet Explorer,我收到以下错误:
“客户端无法连接到”IExplorer | WWW_GetWindowInfo“,请确保服务器应用程序正在运行,并且它支持指定的服务名称和主题名称对”
对此问题的任何帮助都将非常感激,因为它已经成为一项非常重要的任务。
答案 0 :(得分:20)
以下是基于Microsoft UI Automation的代码:
public static string GetChromeUrl(Process process)
{
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.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
return ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
public static string GetInternetExplorerUrl(Process process)
{
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 rebar = element.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ReBarWindow32"));
if (rebar == null)
return null;
AutomationElement edit = rebar.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
return ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
public static string GetFirefoxUrl(Process process)
{
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;
}
您可以使用UI Spy tool来了解所有3种浏览器的视觉层次结构。您可能需要调整一些事项以确保它在您的特定情况下真正起作用,但您应该对这些样本有所了解。
这是一个转储当前在系统中运行的所有3种进程(IE,FF,CH)的所有URL的示例:
static void Main(string[] args)
{
foreach (Process process in Process.GetProcessesByName("firefox"))
{
string url = GetFirefoxUrl(process);
if (url == null)
continue;
Console.WriteLine("FF Url for '" + process.MainWindowTitle + "' is " + url);
}
foreach (Process process in Process.GetProcessesByName("iexplore"))
{
string url = GetInternetExplorerUrl(process);
if (url == null)
continue;
Console.WriteLine("IE Url for '" + process.MainWindowTitle + "' is " + url);
}
foreach (Process process in Process.GetProcessesByName("chrome"))
{
string url = GetChromeUrl(process);
if (url == null)
continue;
Console.WriteLine("CH Url for '" + process.MainWindowTitle + "' is " + url);
}
}
答案 1 :(得分:6)
在IE的oDde.Request(“URL”,int.MaxValue)中使用参数“1”而不是“URL”。
public static void ProcessIEURLs()
{
string sURL;
try
{
DdeClient oDde = new DdeClient("IExplore", "WWW_GetWindowInfo");
try
{
oDde.Connect();
sURL = oDde.Request("1", int.MaxValue);
oDde.Disconnect();
bool bVisited = false;
if ( oVisitedURLList != null && oVisitedURLList.Count > 0 )
{
bVisited = FindURL(sURL, oVisitedURLList);
}
if ( !bVisited )
{
oVisitedURLList.Add(sURL);
}
}
catch ( Exception ex )
{
throw ex;
}
}
catch ( Exception ex )
{
throw ex;
}
}
答案 2 :(得分:4)
Mourier,感谢您的解决方案 Microsoft UI Automation 。 即便如此,它对Firefox 41.0也没有用, 我用小工具"Automation Spy"分析了Firefox窗口结构。 然后我稍微改变了搜索条件,它完美地运行了!
public static string GetFirefoxUrl(Process process)
{
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;
element = element.FindFirst(TreeScope.Subtree,
new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, "search or enter address", PropertyConditionFlags.IgnoreCase),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
if (element == null)
return null;
return ((ValuePattern)element.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
以下是Chromium 48的解决方案:
public static string GetChromeUrl(Process process)
{
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.Subtree,
new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, "address and search bar", PropertyConditionFlags.IgnoreCase),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
return ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
Automation Spy显示Firefox窗口控件结构。控制类型'编辑'使用名称'搜索或输入地址'持有网址:
注意:在.NET项目中,您需要2个引用:
答案 3 :(得分:3)
这是我到目前为止所做的事情(虽然Chrome我没有找到任何有用的文章,除了使用FindWindowEx(我个人并不特别喜欢这种方法)。
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();
}
}
答案 4 :(得分:0)
在IE中支持WWW_GetWindowInfo,在16位日内支持has been since version 3.02!适用于Firefox和Opera
我认为Chrome实际上是奇怪的。
我不知道事情是如何超越这四个人的。
答案 5 :(得分:0)
最好的选择是使用selenium webdriver。完全允许的最佳和强大的api