以前我在IE上使用ShellWindows()API来获取我的应用程序的标题和URL 现在有了新的开发,Microsoft Edge是新的,并且正在开发许多功能。
我想知道如何获取MS-Edge中打开的所有页面的URL和标题。 由于没有任何shell API与MS-Edge一起使用。 我也试过UI自动化,但它没有返回所有的UI元素
我正在使用MS Visual Studio 2010进行开发。我需要新版本的Visual Studio吗? 任何人都可以帮我看看如何访问标题和URL? 或者,由于安全性,MS-Edge是否不允许此类访问? 感谢
答案 0 :(得分:4)
我不熟悉Shell API的可能性,但我刚刚尝试了UIA测试。我编写了下面的代码来访问标题,网址和窗口句柄,它似乎工作正常。我运行代码,而Edge显示了几个标签,显示的页面是Bing.com。这是测试发现的数据......
C#代码使用我通过tlbimp工具生成的UIA互操作dll。
测试代码做了一些可能需要收紧的假设,但总的来说它看起来可以获得你需要的数据。如果您发现此代码不适合您,如果您确切地知道涉及哪些元素,我可以查看它。
谢谢,
盖
IUIAutomationElement rootElement = uiAutomation.GetRootElement();
int propertyName = 30005; // UIA_NamePropertyId
int propertyAutomationId = 30011; // UIA_AutomationIdPropertyId
int propertyClassName = 30012; // UIA_ClassNamePropertyId
int propertyNativeWindowHandle = 30020; // UIA_NativeWindowHandlePropertyId
// Get the main Edge element, which is a direct child of the UIA root element.
// For this test, assume that the Edge element is the only element with an
// AutomationId of "TitleBar".
string edgeAutomationId = "TitleBar";
IUIAutomationCondition condition =
uiAutomation.CreatePropertyCondition(
propertyAutomationId, edgeAutomationId);
// Have the window handle cached when we find the main Edge element.
IUIAutomationCacheRequest cacheRequestNativeWindowHandle = uiAutomation.CreateCacheRequest();
cacheRequestNativeWindowHandle.AddProperty(propertyNativeWindowHandle);
IUIAutomationElement edgeElement =
rootElement.FindFirstBuildCache(
TreeScope.TreeScope_Children,
condition,
cacheRequestNativeWindowHandle);
if (edgeElement != null)
{
IntPtr edgeWindowHandle = edgeElement.CachedNativeWindowHandle;
// Next find the element whose name is the url of the loaded page. And have
// the name of the element related to the url cached when we find the element.
IUIAutomationCacheRequest cacheRequest =
uiAutomation.CreateCacheRequest();
cacheRequest.AddProperty(propertyName);
// For this test, assume that the element with the url is the first descendant element
// with a ClassName of "Internet Explorer_Server".
string urlElementClassName = "Internet Explorer_Server";
IUIAutomationCondition conditionUrl =
uiAutomation.CreatePropertyCondition(
propertyClassName,
urlElementClassName);
IUIAutomationElement urlElement =
edgeElement.FindFirstBuildCache(
TreeScope.TreeScope_Descendants,
conditionUrl,
cacheRequest);
string url = urlElement.CachedName;
// Next find the title of the loaded page. First find the list of
// tabs shown at the top of Edge.
string tabsListAutomationId = "TabsList";
IUIAutomationCondition conditionTabsList =
uiAutomation.CreatePropertyCondition(
propertyAutomationId, tabsListAutomationId);
IUIAutomationElement tabsListElement =
edgeElement.FindFirst(
TreeScope.TreeScope_Descendants,
conditionTabsList);
// Find which of those tabs is selected. (It should be possible to
// cache the Selection pattern with the above call, and that would
// avoid one cross-process call here.)
int selectionPatternId = 10001; // UIA_SelectionPatternId
IUIAutomationSelectionPattern selectionPattern =
tabsListElement.GetCurrentPattern(selectionPatternId);
// For this test, assume there's always one selected item in the list.
IUIAutomationElementArray elementArray = selectionPattern.GetCurrentSelection();
string title = elementArray.GetElement(0).CurrentName;
// Now show the title, url and window handle.
MessageBox.Show(
"Page title: " + title +
"\r\nURL: " + url +
"\r\nhwnd: " + edgeWindowHandle);
}
答案 1 :(得分:1)
当Edge显示3个标签时,我刚刚将Inspect SDK工具指向Edge。 (Inspect使用UIA Client API访问应用程序中显示的所有UI,如果安装了SDK,则可以在" C:\ Program Files(x86)\ Windows Kits \ 10 \ bin \等位置找到x64"。)下图显示主Edge窗口的UIA元素有一个子元素,它是一个列表。 Inspect还向我显示该子元素的AutomationId是" TabsList",(但下图中未显示)。作为TabsList的直接子项的列表项集合具有名称,这些名称是Edge中加载的页面的标题。因此,访问Edge中加载的页面标题看起来相对简单。
但是,看起来访问与页面关联的URL并不是那么干净。当我查看Inspect向我展示的内容时,我只在UIA树中找到了当前显示的页面的URL。可以从控件类型为Pane的元素的名称中找到URL,该元素位于Pane元素链的下方。我不知道使用URL到达元素的最强大方法是什么。例如,如果它是UIA ClassName为" InternetExplorer_Server"的唯一元素,或者它的父元素是ClassName为" TabWindowClass"的唯一元素,则可能是单个元素调用FindFirstBuildCache()可以让你接近你感兴趣的元素。(看起来这两个元素都没有要搜索的AutomationId。)
谢谢,
盖
答案 2 :(得分:1)
此示例项目监视Microsoft Edge活动窗口和活动选项卡的标题和URL。 在Windows 10上测试:
C#
class Program
{
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
static bool TryGetMSEdgeUrlAndTitle(IntPtr edgeWindow, out string url, out string title)
{
const int UIA_NamePropertyId = 30005;
const int UIA_ClassNamePropertyId = 30012;
const int UIA_NativeWindowHandlePropertyId = 30020;
url = "";
title = "";
IUIAutomation uiA = new CUIAutomation();
IUIAutomationElement rootElement = uiA.GetRootElement();
IUIAutomationCacheRequest cacheRequest = uiA.CreateCacheRequest();
cacheRequest.AddProperty(UIA_NamePropertyId);
IUIAutomationCondition windowCondition = uiA.CreatePropertyCondition(UIA_NativeWindowHandlePropertyId, GetForegroundWindow());
IUIAutomationElement windowElement = rootElement.FindFirstBuildCache(TreeScope.TreeScope_Descendants, windowCondition, cacheRequest);
if (windowElement == null)
return false;
IUIAutomationCondition edgeCondition = uiA.CreatePropertyCondition(UIA_NamePropertyId, "Microsoft Edge");
IUIAutomationElement edgeElement = windowElement.FindFirstBuildCache(TreeScope.TreeScope_Subtree, edgeCondition, cacheRequest);
if (edgeElement == null)
return false;
IUIAutomationCondition tabCondition = uiA.CreatePropertyCondition(UIA_ClassNamePropertyId, "TabWindowClass");
IUIAutomationElement tabElement = edgeElement.FindFirstBuildCache(TreeScope.TreeScope_Descendants, tabCondition, cacheRequest);
if (tabElement == null)
return false;
IUIAutomationCondition ieCondition = uiA.CreatePropertyCondition(UIA_ClassNamePropertyId, "Internet Explorer_Server");
IUIAutomationElement ieElement = tabElement.FindFirstBuildCache(TreeScope.TreeScope_Descendants, ieCondition, cacheRequest);
if (ieElement == null)
return false;
url = ieElement.CachedName;
title = tabElement.CachedName;
return true;
}
static void Main(string[] args)
{
string oldUrl = "";
string oldTitle = "";
while (true)
{
string url = "";
string title = "";
if (TryGetMSEdgeUrlAndTitle(GetForegroundWindow(), out url, out title))
{
if ((url != oldUrl) || (title != oldTitle))
{
Console.WriteLine(String.Format("Page title: {0} \r\nURL: {1}", title, url));
oldUrl = url;
oldTitle = title;
}
}
Thread.Sleep(250);
}
}
}
答案 3 :(得分:0)
我在 Windows 10专业版机器上尝试了Guy Barker上面的代码,它运行良好。
如果我在 Windows 10 Home Edition(从Windows 8.1升级)计算机上尝试了相同的代码,则它无效,“urlElement”会为我返回null。代码找不到I nternet Explorer_Server
类。但是Internet Explorer_Server
类在使用inspect.exe导航时找到了。
IUIAutomationElement urlElement =
edgeElement.FindFirstBuildCache(
TreeScope.TreeScope_Descendants,
conditionUrl,
cacheRequest);
if(urlElement == null)//true
我进一步探讨了Windows 10家庭版机器中的代码不捕获窗格(Spartan XAML-To-Trident输入路由窗口)节点。所以我无法访问“Internet Explorer_Server”类来查找URL。
家用和专业版操作系统有什么区别吗?怎么解决?
由于
Satheesh
答案 4 :(得分:0)
我使用VB.Net版本,Windows 10 Home OS。适合我。我得到页面标题和页面URL。代码是我的一个模块的一部分。请根据需要进行复制和编辑。
'-----------------------------------------------------------------------------
'Allow code to get Microsoft Edge URL & Title
' Add .Net references for UIAutomationClient & UIAutomationTypes
Imports System.Windows.Automation
'-----------------------------------------------------------------------------
Public Function ActiveMicrosoftEdgeTitleAndURL(ByRef HadError As Boolean,
ByVal InhibitMsgBox As Boolean) As String()
Dim i1 As Integer
Dim tmp1 As String = "", tmp2() As String, METitle As String, MEURL As String
Dim strME As String = "Microsoft Edge"
'ActiveMicrosoftEdgeTitleAndURL(Index) = Page Title or "No Title" + Chr(255) + Page URL
'If no Page URL then any Page Title is ignored.
' If the form is minimized to the taskbar the url is typically not available.
HadError = False : ReDim tmp2(-1) : i1 = -1
Try
Dim conditions As Condition = Condition.TrueCondition
Dim BaseElement As AutomationElement = AutomationElement.RootElement
Dim elementCollection As AutomationElementCollection = BaseElement.FindAll(TreeScope.Children, conditions)
Dim AE As AutomationElement
For Each AE In elementCollection
If AE IsNot Nothing Then
tmp1 = AE.GetCurrentPropertyValue(AutomationElement.NameProperty).ToString
If StrComp(Strings.Right(tmp1, strME.Length), strME, vbTextCompare) = 0 Then
MEURL = "" : METitle = ""
'-----------------------------------------------------------------------------------------------------------
Dim AE1 As AutomationElement = _
AE.FindFirst(TreeScope.Subtree, New PropertyCondition(AutomationElement.AutomationIdProperty, "TitleBar"))
METitle = AutomationElementText(AE1)
METitle = Trim(METitle)
'-----------------------------------------------------------------------------------------------------------
AE1 = AE.FindFirst(TreeScope.Subtree, New PropertyCondition(AutomationElement.AutomationIdProperty, "addressEditBox"))
MEURL = AutomationElementText(AE1)
MEURL = Trim(MEURL)
'-----------------------------------------------------------------------------------------------------------
If MEURL <> "" Then
If METitle = "" Then METitle = "No Title"
i1 = i1 + 1 : Array.Resize(tmp2, i1 + 1)
tmp2(i1) = METitle + Chr(255) + MEURL
End If
End If
End If
Next
Catch ex As Exception
HadError = True
MsgBox("Function AutomationElementData system error." + vbCr + vbCr + ex.ToString, vbExclamation)
End Try
Return tmp2
End Function
Private Function AutomationElementText(ByRef AE As AutomationElement) As String
Dim MyPattern As AutomationPattern = ValuePattern.Pattern
Dim MyPattern1 As AutomationPattern = TextPattern.Pattern
Dim objPattern As Object = Nothing
Dim txt As String = ""
'Any error just return a null string. !r
If AE.TryGetCurrentPattern(MyPattern, objPattern) Then
Dim AEValuePattern As ValuePattern = AE.GetCurrentPattern(MyPattern)
txt = AEValuePattern.Current.Value
Else
If AE.TryGetCurrentPattern(MyPattern1, objPattern) Then
Dim AETextPattern As TextPattern = AE.GetCurrentPattern(MyPattern1)
txt = AETextPattern.DocumentRange.GetText(-1)
End If
End If
Return txt
End Function
答案 5 :(得分:0)
将tmp1昏暗为String =“” Dim strME As String =“ Microsoft Edge”
Try
Dim conditions As Condition = Condition.TrueCondition
Dim BaseElement As AutomationElement = AutomationElement.RootElement
Dim elementCollection As AutomationElementCollection = BaseElement.FindAll(TreeScope.Children, conditions)
Dim AE As AutomationElement
For Each AE In elementCollection
If AE IsNot Nothing Then
tmp1 = AE.GetCurrentPropertyValue(AutomationElement.NameProperty).ToString
If StrComp(Strings.Right(tmp1, strME.Length), strME, vbTextCompare) = 0 Then
Dim elmUrlBar0 As AutomationElement
elmUrlBar0 = AE.FindFirst(TreeScope.Subtree, New PropertyCondition(AutomationElement.AutomationIdProperty, "addressEditBox"))
If elmUrlBar0 IsNot Nothing Then
Dim patterns0 As AutomationPattern() = elmUrlBar0.GetSupportedPatterns()
If patterns0.Length > 0 Then
Dim val As ValuePattern = DirectCast(elmUrlBar0.GetCurrentPattern(patterns0(0)), ValuePattern)
If Not elmUrlBar0.GetCurrentPropertyValue(AutomationElement.HasKeyboardFocusProperty) Then
Dim pvgc As String = LCase(val.Current.Value).Trim
If pvgc.ToString <> "" Then
urls = pvgc.ToString
MsgBox(urls)
End If
End If
End If
End If
End If
End If
Next
Catch ex As Exception
MsgBox("Function AutomationElementData system error." + vbCr + vbCr + ex.ToString, vbExclamation)
End Try