[英]How to retrieve information in a second thread with a Windows Forms C# Application
[英]Retrieve current URL from C# windows forms application
我一直在使用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“,请确保服务器应用程序正在运行,并且它支持指定的服务名称和主题名称对”
任何关于这个问题的帮助都会受到高度赞赏,因为它已成为一项非常重要的任务。
这是基于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工具来了解所有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);
}
}
在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;
}
}
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个引用:
这是我到目前为止(虽然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();
}
}
选择是使用selenium webdriver。 最佳和功率完整的api与完整的首映
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.