Windows 10

続・起動中のMicrosoft EdgeからタイトルとURLを取得するC#コード(UI Automation編)

2017/8/18 追記:
当記事のコードは現在動作しなくなっているため、新しくコードを書き直しました。


前回の記事で、UI Automationを使って起動中のMicrosoft EdgeからタイトルとURLを取得するC#コードを紹介しましたが、動作としてはEdgeのアドレス欄をフォーカスしてからURLを取得するという面倒なことをやっています。

それに対して「Microsoft Edge: Get Window URL and Title」では、ClassNameプロパティが「Internet Explorer_Server」のPaneコントロールからCachedNameプロパティを取得する形がとられています。

コードを見る限り、たしかにコチラの方が手間が無くて良いですね。
(実は私も「起動中のMicrosoft EdgeからタイトルとURLを取得するVBAマクロ(UI Automation編)」を書いたときに同じような方法を試したのですが、そのときは何故かURLが途中で切れてしまうページがあったので、結局アドレス欄から取得する方法にしました。)

ただ、一つ気になるのが下記の一文。

“The C# code uses a UIA interop dll that I generated through the tlbimp tool.”

えー!?Tlbimp.exeでわざわざDLL吐き出さないといけないの??
Visual Studio入れてない人はどうすれば良いの??

・・・というわけで、何とか別の方向から行けないか、調べてみることにしました。

まず、Inspectで先のPaneコントロールを調べたところ、NativeWindowHandleが0x1005CAになっていました。

AutomateMicrosoftEdge_UIA_Csharp_2_01

このウィンドウが何なのかをSpy++で調べたところ、「Windows.UI.Core.CoreComponentInputSource」クラスのウィンドウであることが分かりました。

AutomateMicrosoftEdge_UIA_Csharp_2_02

ということは、Edgeの子ウィンドウからWindows.UI.Core.CoreComponentInputSourceクラスのウィンドウを列挙して、そこからAutomationElementを捕まえれば良いのでは?

・・・ということで、さっそくやってみました。

※ UIAutomationClient, UIAutomationTypes 要参照

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Automation;

namespace UIAutomationEdge
{
  class Program
  {
    public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
    [DllImport("user32.Dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
    
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static public extern IntPtr GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    
    [DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
    public static extern IntPtr GetParent(IntPtr hWnd);
    
    public static void Main(string[] args)
    {
      AutomationElement root = AutomationElement.RootElement;
      AutomationElement edge = root.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "TitleBar"));
      if (edge != null) {
        edge = edge.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "Windows.UI.Core.CoreWindow"));
        if (edge != null) {
          Win32Callback childProc = new Win32Callback(EnumWindow);
          EnumChildWindows((IntPtr)edge.Current.NativeWindowHandle, childProc, (IntPtr)0);
          Console.ReadKey(true);
        }
      }
    }
    
    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
      StringBuilder buf = new StringBuilder(255);
      IntPtr ret = GetClassName(handle, buf, buf.Capacity);
      if (ret != IntPtr.Zero) {
        string className = buf.ToString();
        if (className == "Windows.UI.Core.CoreComponentInputSource") {
          IntPtr hTitle = GetParent(handle);
          AutomationElement title = AutomationElement.FromHandle(hTitle);
          AutomationElement url = AutomationElement.FromHandle(handle);
          Console.WriteLine(title.Current.Name + ", " + url.Current.Name);
        }
      }
      return true;
    }
  }
}

EnumChildWindowsでウィンドウを列挙してGetClassNameでクラス名を調べていくという、これはこれで面倒くさいものですが、一応下図の通り目的達成できました。

AutomateMicrosoftEdge_UIA_Csharp_2_03

関連記事

  1. Windows関連

    [Windows 8.1]VB5CCEをインストールしてみました。

    ※ 下記はWindows 8.1 RTM(日本語版・32ビット)に基づ…

  2. Windows関連

    [Windows 8]ストアでアプリを検索する。

    今回はWindows 8のストアでアプリを検索する方法を紹介します。…

  3. Windows 10

    【2017年1月版】Microsoft Edgeを操作するVBAマクロ(DOM編)(2)

    昨日の記事で、Microsoft Edgeを操作するVBAコードを改め…

コメント

  • コメント (0)

  • トラックバックは利用できません。

  1. この記事へのコメントはありません。

Time limit is exhausted. Please reload CAPTCHA.

最近の記事

アーカイブ

RapidSSL_SEAL-90x50
PAGE TOP