2015-08-12 2 views
2

Раньше я использовал интерфейс ShellWindows() для IE, чтобы получить окно. Название и URL для моего приложения. Теперь с новой разработкой Microsoft Edge является новой и имеет множество функций в разработке.Microsoft Edge: получить URL-адрес окна и заголовок

Я хочу знать, как получить URL и название всех страниц, открытых в MS-Edge. Поскольку ни один из API-интерфейсов оболочки не работает с MS-Edge. Я пробовал также с UI Automation, но он не возвращает все элементы пользовательского интерфейса

Я использую MS Visual Studio 2010 для разработки. Нужна ли мне новая версия Visual Studio? Может ли кто-нибудь помочь мне узнать, как получить доступ к названию и URL-адресу? Или MS-Edge не разрешает такой доступ из-за безопасности? спасибо

ответ

1

Я только что указал инструмент Inspect SDK на Edge, когда Edge показал 3 вкладки. (Inspect использует API клиента UIA для доступа ко всему пользовательскому интерфейсу, показанному в приложениях, и если у вас установлен SDK, его можно найти в таких местах, как «C: \ Program Files (x86) \ Windows Kits \ 10 \ bin \ x64».) На следующем рисунке показано, что элемент UIA для главного окна Edge имеет дочерний элемент, который является списком. Inspect также показывает мне, что AutomationId этого дочернего элемента является «TabsList» (но это не показано на изображении ниже). Набор элементов списка, которые являются прямыми дочерними элементами TabsList, имеют имена, которые являются названиями страниц, загружаемых в Edge. Таким образом, похоже, что доступ к заголовкам страниц, загруженных в Edge, довольно просто.

Однако, похоже, что это не так чисто для доступа к URL-адресу, связанному со страницей. Когда я просмотрел то, что показывал мне Inspect, я нашел URL-адрес в дереве МАС для страницы, отображаемой в настоящее время. URL-адрес можно найти из имени элемента с типом управления Pane, который находится под цепочкой элементов панели. Я не знаю, какой самый надежный способ получить элемент с URL-адресом. Например, если это единственный элемент с именем класса UIA «InternetExplorer_Server» или его родительский элемент является единственным элементом с именем класса «TabWindowClass», тогда, возможно, один вызов FindFirstBuildCache() может приблизить вас к элементу, заинтересованы в. (похоже, ни один элемент имеет AutomationId для поиска.)

Спасибо,

Guy

enter image description here

+0

Спасибо Что касается Accessibility API: Я попытался с UI Automation, Вы правы, нет простого способа достичь URL-адреса. Еще более важно то, что когда я пытаюсь обходить дерево, API не возвращает те же элементы, которые отображаются в дереве Inspect. А также он имеет разные результаты. Один раз вы получаете элемент, а в следующий раз он пуст. Ни один из возвращаемых элементов не имеет типа управления. Возможно, что-то еще предстоит разработать командой разработчиков MS-Edge. .NET API: Я искал что-то вроде Shellwindows(), чтобы получить окно и URL-адрес с помощью .NET-класса. Есть ли какие-нибудь? – Waqas

+0

На самом деле мне нужно три вещи за раз. 1- Окно, 2- Название, 3- URL. Мне нужно закрыть окно, если заголовок/URL совпадает с каким-то запросом. – Waqas

4

Я не знаком с тем, что возможно через Shell API, здесь , но я просто попробовал тест с МАУ. Я написал код ниже, чтобы получить доступ к заголовку, URL-адресу и окну, и он, похоже, работает нормально. Я запустил код, в то время как у Edge появилось несколько вкладок, а страница была Bing.com. Это данные, найденный с помощью теста ...

MessageBox showing page title, url and Edge window handle

# кода C использует Interop DLL МАУ, что я сгенерированный с помощью инструмента TLBIMP.

В тестовом коде есть несколько предположений, которые могут потребоваться подтянуть, но в целом похоже, что они могут получить нужные вам данные. Если вы обнаружите, что этот код не работает для вас, если вы сообщите мне, какие именно элементы задействованы, я могу изучить его.

Спасибо,

Guy

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); 
} 
+0

Приведенный выше код отлично работает, это то, что я искал. Спасибо, Гай Баркер за эту отличную помощь – Waqas

+0

Я вижу, что это IUIAutomation - разве это невозможно с помощью API System.Windows.Automation? –

+0

Я могу сделать то же самое с AutomationElement и т. Д. - но я не могу найти URL-адрес из «addressEditBox» - только имя сайта из заголовка (который является родительским элементом «addressEditBox» «). –

0

В ответ на замечания Yves выше ...

В настоящее время я использую API UIA Windows. В то время как .NET UIA API отлично подходит для некоторых вещей, я считаю, что API UIA Windows имеет больше инвестиций в последние годы. Например, UIA для Windows обновлен, чтобы быть более устойчивым, когда он сталкивается с невосприимчивыми поставщиками МАУ (например, приостановленными процессами). Кроме того, некоторые интерфейсы UIA для Windows теперь имеют версии «2», и я сомневаюсь, что все эти интерфейсы существуют в API UIA .NET. Поэтому для меня я использую tlbimp.exe для создания обертки вокруг API UIA Windows и всегда использую это.

Что касается получения содержимого блока AddressEdit, это должно быть доступно через шаблон значений UIA. Обычно элементы управления имеют свойство UA Name, которое описывает назначение элемента управления редактирования, а содержимое элемента управления отображается через шаблон Value.

На скриншоте ниже показан инструмент Inspect SDK, сообщающий свойства, выставленные с помощью шаблона Value. (Снимок экрана был сделан на машине без подключения к сети, поэтому имена вкладки «Вы не связаны»). Inspect показывает мне, что свойство Value pattern Value - «microsoft.com», а свойство IsReadOnly - false.

Я не знаю, как хорошо работает интерфейс UIA .NET с Edge UI, но я ожидаю, что клиент API UIA Windows сможет получить доступ к тексту редактирования.

Спасибо,

Guy

enter image description here

+0

Привет, как я могу различать .NET UIA и Windows? Я пытаюсь извлечь текст в точке мыши в браузере, но используя System.Windows.Automation. Есть ли что-то еще, что я должен использовать? – tofutim

0

Я попытался Guy Barker выше код в Windows 10 Professional машины, его работы большой.

Если я пробовал тот же код в Windows 10 Home Edition (обновлен из окна 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 

меня исследовать дальше, код не захватить панель (Spartan XAML-To-Trident Input Routing Window) узла в окнах 10 Главная редакция машины. Поэтому я не смог найти класс «Internet Explorer_Server», чтобы найти URL-адрес.

Есть ли разница между домашней и профессиональной версией ОС? Как его решить?

Благодаря

Satheesh

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 
1

Этот пример проекта контролирует название и URL для активного окна Microsoft Active и активной вкладки. Проверено на 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); 
     } 
    } 
}