Microsoft Edge:获取窗口URL和标题

时间:2015-08-12 14:00:40

标签: .net microsoft-edge

以前我在IE上使用ShellWindows()API来获取我的应用程序的标题和URL 现在有了新的开发,Microsoft Edge是新的,并且正在开发许多功能。

我想知道如何获取MS-Edge中打开的所有页面的URL和标题。 由于没有任何shell API与MS-Edge一起使用。 我也试过UI自动化,但它没有返回所有的UI元素

我正在使用MS Visual Studio 2010进行开发。我需要新版本的Visual Studio吗? 任何人都可以帮我看看如何访问标题和URL? 或者,由于安全性,MS-Edge是否不允许此类访问? 感谢

6 个答案:

答案 0 :(得分:4)

我不熟悉Shell API的可能性,但我刚刚尝试了UIA测试。我编写了下面的代码来访问标题,网址和窗口句柄,它似乎工作正常。我运行代码,而Edge显示了几个标签,显示的页面是Bing.com。这是测试发现的数据......

MessageBox showing page title, url and Edge window handle

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。)

谢谢,

enter image description here

答案 2 :(得分:1)

此示例项目监视Microsoft Edge活动窗口和活动选项卡的标题和URL。 在Windows 10上测试:

  • 10240 Pro
  • 10586主页
  • 14939 Pro

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