Windows関連

【2017年8月版】起動中のMicrosoft EdgeからタイトルとURLを取得するC#コード

当ブログでは、EdgeからタイトルとURLを取得するコードについて、いくつか記事を書いてきました。

しかし、現時点(2018年8月)ではEdgeのアップデートに伴いこれらの記事にあるコードが動作しなくなっているため、今回コードを書き直すことにしました。

テスト環境

  1. Microsoft Windows 10 Pro Insider Preview バージョン:10.0.16257 ビルド 16257 64ビット版
  2. Microsoft.MicrosoftEdge 41.16257.1.0

C#コード

using System;
using System.Text;
using System.Runtime.InteropServices;
 
namespace GetUrlAndTitleFromEdge
{
  class Program
  {
    [Flags]
    private enum SendMessageTimeoutFlags : uint
    {
      SMTO_NORMAL = 0x0000,
      SMTO_BLOCK = 0x0001,
      SMTO_ABORTIFHUNG = 0x0002,
      SMTO_NOTIMEOUTIFNOTHUNG = 0x0008,
      SMTO_ERRORONEXIT = 0x0020
    }
    private delegate bool Win32Callback(IntPtr hWnd, ref IntPtr lParam);
     
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumWindows(Win32Callback lpEnumFunc, ref IntPtr lParam);
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    [DllImport("oleacc.dll", PreserveSig=false)]
    [return: MarshalAs(UnmanagedType.Interface)]
    private static extern object ObjectFromLresult(UIntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam);
    [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    private static extern uint RegisterWindowMessage(string lpString);
    [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    private static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out UIntPtr result);
    
    public static void Main(string[] args)
    {
      IntPtr hWin = IntPtr.Zero;
      Win32Callback proc = new Win32Callback(EnumWindowsProc);
      EnumWindows(proc, ref hWin);
      Console.Write("Press any key to continue . . . ");
      Console.ReadKey(true);
    }
    
    private static bool EnumWindowsProc(IntPtr hWnd, ref IntPtr lParam)
    {
      IntPtr hChild = IntPtr.Zero;
      StringBuilder buf = new StringBuilder(1024);
      GetClassName(hWnd, buf, buf.Capacity);
      if (buf.ToString() == "TabWindowClass") {
        //get 'Internet Explorer_Server' window
        hChild = FindWindowEx(hWnd, IntPtr.Zero, "Internet Explorer_Server", "");
        if (hChild != IntPtr.Zero) {
          dynamic doc = null;
          doc = GetHTMLDocumentFromWindow(hChild);
          if (doc != null) {
            Console.WriteLine(doc.Title + ", " + doc.url); //get document title & url
          }
        }
      }
      return true;
    }
     
    //get HTMLDocument object
    private static object GetHTMLDocumentFromWindow(IntPtr hWnd)
    {
      UIntPtr lRes;
      object doc = null;
      Guid IID_IHTMLDocument2 = new Guid("332C4425-26CB-11D0-B483-00C04FD90119");
      uint nMsg = RegisterWindowMessage("WM_HTML_GETOBJECT");
      if (nMsg != 0) {
        SendMessageTimeout(hWnd, nMsg, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes);
        if (lRes != UIntPtr.Zero) {
          doc = ObjectFromLresult(lRes, IID_IHTMLDocument2, IntPtr.Zero);
        }
      }
      return doc;
    }
  }
}

仕組みは下記記事のVBAマクロと同じで、TabWindowClassクラスのウィンドウを決め打ちして、その下にあるInternet Explorer_ServerクラスのウィンドウからHTMLDocumentを取得しているだけです。

上記記事でも書いていますが、今回の方法はMicrosoftが推奨している方法では無く、いつ使えなくなるかも分からないため、可能であれば正式にサポートされている「WebDriver」を使うことをお薦めします。

コメント

  • コメント (0)

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

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

Time limit is exhausted. Please reload CAPTCHA.

最近の記事

アーカイブ

RapidSSL_SEAL-90x50
PAGE TOP