.net Microsoft Edge:获取窗口URL和标题

.net Microsoft Edge:获取窗口URL和标题,.net,microsoft-edge,.net,Microsoft Edge,以前,我使用ShellWindows()API for IE获取应用程序的窗口标题和URL 现在,随着新的发展,微软边缘是新的,有许多功能正在开发中 我想知道如何获得在MS Edge中打开的所有页面的URL和标题。 因为没有一个shell API使用MS Edge。 我也尝试过UI自动化,但它不会返回所有UI元素 我正在使用MS Visual Studio 2010进行开发。我需要新版本的Visual Studio吗? 有人能帮我了解如何访问标题和URL吗? 或者,MS Edge是否出于安全考虑

以前,我使用ShellWindows()API for IE获取应用程序的窗口标题和URL 现在,随着新的发展,微软边缘是新的,有许多功能正在开发中

我想知道如何获得在MS Edge中打开的所有页面的URL和标题。 因为没有一个shell API使用MS Edge。 我也尝试过UI自动化,但它不会返回所有UI元素

我正在使用MS Visual Studio 2010进行开发。我需要新版本的Visual Studio吗? 有人能帮我了解如何访问标题和URL吗? 或者,MS Edge是否出于安全考虑不允许此类访问?
谢谢

我刚刚将Inspect SDK工具指向Edge,Edge显示了3个选项卡。(Inspect使用UIA客户端API访问应用程序中显示的所有UI,如果安装了SDK,可以在“C:\Program Files(x86)\Windows Kits\10\bin\x64”等位置找到)。下图显示主边缘窗口的UIA元素有一个子元素,该子元素是一个列表。Inspect还向我显示了该子元素的AutomationId是“TabsList”(但下图中没有显示)。作为选项卡列表的直接子项的列表项集的名称是Edge中加载的页面的标题。因此,访问Edge中加载的页面的标题似乎相对简单

但是,访问与页面相关联的URL看起来不是很干净。当我查看Inspect向我显示的内容时,我只在UIA树中找到了当前显示的页面的URL。URL可以从控件类型为Pane的元素的名称中找到,该控件类型位于Pane元素链的下面。我不知道用URL访问元素的最健壮的方法是什么。例如,如果它是唯一一个UIA类名为“InternetExplorer_Server”的元素,或者它的父元素是唯一一个类名为“TabWindowClass”的元素,那么对FindFirstBuildCache()的一次调用可能会使您接近感兴趣的元素。(看起来两个元素都没有要搜索的AutomationId。)

谢谢

家伙


我不熟悉通过Shell API可以实现什么,但我只是尝试了使用UIA进行测试。我写了下面的代码来访问标题、url和窗口句柄,它似乎工作正常。我运行代码时Edge显示了几个选项卡,显示的页面是Bing.com。这是测试发现的数据

C代码使用我通过tlbimp工具生成的UIA互操作dll

测试代码做出了一些假设,这些假设可能需要加强,但总体而言,它看起来可以获得您需要的数据。如果您发现此代码不适用于您,如果您让我确切知道涉及哪些元素,我可以查看它

谢谢

家伙


针对以上Yves的评论

我现在只使用WindowsUIAAPI。尽管.NETUIAAPI在某些方面可以很好地使用,但我相信WindowsUIAAPI近年来投入了更多的资金。例如,Windows UIA已被更新,以便在遇到无响应的UIA提供程序(例如挂起的进程)时更具弹性。此外,一些Windows UIA接口现在有“2”版本,我怀疑所有这些接口都存在于.NET UIA API中。因此,对我来说,我使用tlbimp.exe生成一个围绕Windows UIA API的包装器,并始终使用它

关于获取addressEdit框的内容,应该可以通过UIA值模式访问。通常,编辑控件具有描述编辑控件用途的UIA Name属性,控件的内容通过值模式公开

下面的屏幕截图显示了Inspect SDK工具,该工具报告通过值模式公开的属性。(屏幕截图是在没有网络连接的机器上拍摄的,因此“You't not connected”选项卡名。)Inspect显示值模式的Value属性为“microsoft.com”,IsReadOnly属性为false

我不知道.NET UIA API在Edge UI中的表现如何,但我希望Windows UIA API的客户端能够很好地访问编辑控件文本

谢谢

家伙


我在Windows 10 Professional机器中试用过上面的代码,效果非常好

如果我在Windows 10 Home Edition(从Windows 8.1升级)计算机中尝试了相同的代码,则它不工作,“urlement”为我返回null。代码找不到I
internet Explorer\u服务器
类。但是在使用inspect.exe进行导航时,发现了
internetexplorer\u服务器

IUIAutomationElement urlElement =
        edgeElement.FindFirstBuildCache(
            TreeScope.TreeScope_Descendants,
            conditionUrl,
            cacheRequest);

if(urlElement == null)//true
我进一步探索了Windows10家庭版机器中的代码不捕获窗格(Spartan XAML到Trident输入路由窗口)节点。所以我无法访问“InternetExplorer\uServer”类来查找URL

家庭版和专业版操作系统有什么区别吗?如何解决

谢谢


Satheesh

我使用VB.Net版本,Windows10家庭操作系统。对我有用。我得到页面标题和页面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
'-----------------------------------------------------------------------------
'允许代码获取Microsoft Edge URL和标题
'为UIAutomationClient和UIAutomationTypes添加.Net引用
导入System.Windows.Automation
'-----------------------------------------------------------------------------
公共函数ActiveMicrosoftedGetLeanDurl(ByRef HadError为布尔值,
ByVal(MSGBox为布尔值)为字符串()
作为整数的Dim i1
Dim tmp1为字符串=”,tmp2()为字符串,METitle为字符串,MEURL为字符串
尺寸strME为String=“Microsoft Edge”
'ActiveMicrosoftedGetLeanDurl(索引)=页面标题或“无标题”+Chr(255)+页面URL
'如果没有页面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
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);
        }
    }
}
    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