トップ回答者
VisualStudio2013: C# IE11(複数タブ状態)において表示されているタブのタイトルやURL情報を取得する方法は?

質問
-
お世話になります。 C# にてアクティブなウィンドウのタイトルやプロセスIDなどの情報をタイマーイベントを利用して逐次ファイルに出力するツールを作成しています。
その中で InternetExplorer、IE11(複数タブ表示中)の場合、複数タブ中の表示されているウィンドウのタイトルや URL情報を取得したいのですが可能でしょうか?
複数タブの全てのタブの情報を取得するようなサンプルは見つかりましたが表示中のタブだけとなると、どのタブなのか(左から何番目など?)を認識する必要がありますが、
この部分のやり方がわかりません。 参考になるような情報/サンプルなどございましたら、ご教示の程よろしくお願い致します。
回答
-
こんな?
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Windows.Automation; //UIAutomationClient.dllとUIAutomationTypes.dllを参照 using SHDocVw; //Microsoft Internet Controlsを参照 using mshtml; //Microsoft HTML Object Libraryを参照 namespace ConsoleApplication1 { class Program { [STAThread()] static void Main(string[] args) { var allIE = GetAllIEWindows(); foreach (IntPtr hwnd in allIE.Keys) { Console.WriteLine("****************************"); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("HWND={0:X}", hwnd); foreach (Item item in allIE[hwnd]) { if (item.IsActive) { Console.ForegroundColor = ConsoleColor.Red; } else { Console.ForegroundColor = ConsoleColor.White; } Console.WriteLine("{0}\t{1}", item.Title, item.URL); } Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(); } Console.ReadKey(); } [ComImport] [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IServiceProvider { void QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object obj); } private enum SendMessageTimeoutFlags : uint { SMTO_NORMAL = 0x0000, SMTO_BLOCK = 0x0001, SMTO_ABORTIFHUNG = 0x0002, SMTO_NOTIMEOUTIFNOTHUNG = 0x0008, SMTO_ERRORONEXIT = 0x0020 } [DllImport("user32.dll")] public 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 IntPtr result); [DllImport("oleacc.dll", PreserveSig = false)] [return: MarshalAs(UnmanagedType.Interface)] private static extern object ObjectFromLresult(IntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam); class Item { public Item(SHDocVw.IWebBrowser2 browser) { this.Title = browser.LocationName; this.URL = browser.LocationURL; this.ComPtr = Marshal.GetIUnknownForObject(browser); } public string Title { get; private set; } public string URL { get; private set; } public bool IsActive { get; set; } public IntPtr ComPtr { get; private set; } public bool IsSameBrowser(SHDocVw.IWebBrowser2 browser) { return this.ComPtr == Marshal.GetIUnknownForObject(browser); } public override string ToString() { return Title + "\t" + URL; } } /// <summary>全てのIEで表示されているページ情報を取得<summary> /// <returns></returns> private static Dictionary<IntPtr, List<Item>> GetAllIEWindows() { Dictionary<IntPtr, List<Item>> dic = new Dictionary<IntPtr, List<Item>>(); SHDocVw.ShellWindows windows = new SHDocVw.ShellWindows(); try { foreach (dynamic w in windows) { try { SHDocVw.IWebBrowser2 webBrowser2 = w as SHDocVw.IWebBrowser2; if (string.Equals(System.IO.Path.GetFileName(webBrowser2.FullName), "iexplore.exe", StringComparison.InvariantCultureIgnoreCase)) { Item item = new Item(webBrowser2); IntPtr hwnd = new IntPtr(webBrowser2.HWND); List<Item> list; if (!dic.TryGetValue(hwnd, out list)) { list = new List<Item>(); dic.Add(hwnd, list); } list.Add(item); } } finally { Marshal.ReleaseComObject(w); } } foreach (IntPtr hwndWindow in dic.Keys) { var browser = GetBrowser(hwndWindow); if (browser != null) { foreach (Item item in dic[hwndWindow]) { item.IsActive = item.IsSameBrowser(browser);//現在アクティブタブで表示されているか } Marshal.ReleaseComObject(browser); } } } finally { Marshal.ReleaseComObject(windows); } return dic; } private static uint WM_HTML_GETOBJECT = RegisterWindowMessage("WM_HTML_GETOBJECT"); /// <summary>IEのウィンドウに現在表示されているページを表示しているWebBrowserを取得</summary> private static SHDocVw.IWebBrowser2 GetBrowser(IntPtr hwndWindow) { if (WM_HTML_GETOBJECT != 0) { //IEの表示しているWebBrowerのハンドルを調べる(EnumChildWindowで掘ってもいいです) var root = System.Windows.Automation.AutomationElement.FromHandle(hwndWindow); var conditionServer = new PropertyCondition(AutomationElement.ClassNameProperty, "Internet Explorer_Server"); var server = root.FindFirst(TreeScope.Subtree, conditionServer); var hwndServer = new IntPtr((int)server.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty, false)); //ハンドルからIHtmlDocumentを取得 IntPtr lRes; SendMessageTimeout(hwndServer, WM_HTML_GETOBJECT, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes); if (lRes != IntPtr.Zero) { var obj = ObjectFromLresult(lRes, typeof(mshtml.IHTMLDocument).GUID, IntPtr.Zero); var doc = obj as mshtml.IHTMLDocument2; try { //IHTMLDocumentからIWebBrowser2を取得 var ww = doc.parentWindow as mshtml.IHTMLWindow2; var isp = ww as IServiceProvider; if (isp != null) { object obj2; Guid guidApp = typeof(SHDocVw.IWebBrowserApp).GUID; Guid guidWB = typeof(SHDocVw.IWebBrowser2).GUID; isp.QueryService(ref guidApp, ref guidWB, out obj2); var wb2 = obj2 as SHDocVw.IWebBrowser2; return wb2; } } finally { Marshal.ReleaseComObject(doc); } } } return null; } } }
#UIAutomationで選択タブまで行けたと思ったらOSによっては取れなかった…個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 栗下 望Microsoft employee, Moderator 2016年12月14日 0:24
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月19日 9:51
すべての返信
-
こんな?
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Windows.Automation; //UIAutomationClient.dllとUIAutomationTypes.dllを参照 using SHDocVw; //Microsoft Internet Controlsを参照 using mshtml; //Microsoft HTML Object Libraryを参照 namespace ConsoleApplication1 { class Program { [STAThread()] static void Main(string[] args) { var allIE = GetAllIEWindows(); foreach (IntPtr hwnd in allIE.Keys) { Console.WriteLine("****************************"); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("HWND={0:X}", hwnd); foreach (Item item in allIE[hwnd]) { if (item.IsActive) { Console.ForegroundColor = ConsoleColor.Red; } else { Console.ForegroundColor = ConsoleColor.White; } Console.WriteLine("{0}\t{1}", item.Title, item.URL); } Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(); } Console.ReadKey(); } [ComImport] [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IServiceProvider { void QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object obj); } private enum SendMessageTimeoutFlags : uint { SMTO_NORMAL = 0x0000, SMTO_BLOCK = 0x0001, SMTO_ABORTIFHUNG = 0x0002, SMTO_NOTIMEOUTIFNOTHUNG = 0x0008, SMTO_ERRORONEXIT = 0x0020 } [DllImport("user32.dll")] public 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 IntPtr result); [DllImport("oleacc.dll", PreserveSig = false)] [return: MarshalAs(UnmanagedType.Interface)] private static extern object ObjectFromLresult(IntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam); class Item { public Item(SHDocVw.IWebBrowser2 browser) { this.Title = browser.LocationName; this.URL = browser.LocationURL; this.ComPtr = Marshal.GetIUnknownForObject(browser); } public string Title { get; private set; } public string URL { get; private set; } public bool IsActive { get; set; } public IntPtr ComPtr { get; private set; } public bool IsSameBrowser(SHDocVw.IWebBrowser2 browser) { return this.ComPtr == Marshal.GetIUnknownForObject(browser); } public override string ToString() { return Title + "\t" + URL; } } /// <summary>全てのIEで表示されているページ情報を取得<summary> /// <returns></returns> private static Dictionary<IntPtr, List<Item>> GetAllIEWindows() { Dictionary<IntPtr, List<Item>> dic = new Dictionary<IntPtr, List<Item>>(); SHDocVw.ShellWindows windows = new SHDocVw.ShellWindows(); try { foreach (dynamic w in windows) { try { SHDocVw.IWebBrowser2 webBrowser2 = w as SHDocVw.IWebBrowser2; if (string.Equals(System.IO.Path.GetFileName(webBrowser2.FullName), "iexplore.exe", StringComparison.InvariantCultureIgnoreCase)) { Item item = new Item(webBrowser2); IntPtr hwnd = new IntPtr(webBrowser2.HWND); List<Item> list; if (!dic.TryGetValue(hwnd, out list)) { list = new List<Item>(); dic.Add(hwnd, list); } list.Add(item); } } finally { Marshal.ReleaseComObject(w); } } foreach (IntPtr hwndWindow in dic.Keys) { var browser = GetBrowser(hwndWindow); if (browser != null) { foreach (Item item in dic[hwndWindow]) { item.IsActive = item.IsSameBrowser(browser);//現在アクティブタブで表示されているか } Marshal.ReleaseComObject(browser); } } } finally { Marshal.ReleaseComObject(windows); } return dic; } private static uint WM_HTML_GETOBJECT = RegisterWindowMessage("WM_HTML_GETOBJECT"); /// <summary>IEのウィンドウに現在表示されているページを表示しているWebBrowserを取得</summary> private static SHDocVw.IWebBrowser2 GetBrowser(IntPtr hwndWindow) { if (WM_HTML_GETOBJECT != 0) { //IEの表示しているWebBrowerのハンドルを調べる(EnumChildWindowで掘ってもいいです) var root = System.Windows.Automation.AutomationElement.FromHandle(hwndWindow); var conditionServer = new PropertyCondition(AutomationElement.ClassNameProperty, "Internet Explorer_Server"); var server = root.FindFirst(TreeScope.Subtree, conditionServer); var hwndServer = new IntPtr((int)server.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty, false)); //ハンドルからIHtmlDocumentを取得 IntPtr lRes; SendMessageTimeout(hwndServer, WM_HTML_GETOBJECT, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes); if (lRes != IntPtr.Zero) { var obj = ObjectFromLresult(lRes, typeof(mshtml.IHTMLDocument).GUID, IntPtr.Zero); var doc = obj as mshtml.IHTMLDocument2; try { //IHTMLDocumentからIWebBrowser2を取得 var ww = doc.parentWindow as mshtml.IHTMLWindow2; var isp = ww as IServiceProvider; if (isp != null) { object obj2; Guid guidApp = typeof(SHDocVw.IWebBrowserApp).GUID; Guid guidWB = typeof(SHDocVw.IWebBrowser2).GUID; isp.QueryService(ref guidApp, ref guidWB, out obj2); var wb2 = obj2 as SHDocVw.IWebBrowser2; return wb2; } } finally { Marshal.ReleaseComObject(doc); } } } return null; } } }
#UIAutomationで選択タブまで行けたと思ったらOSによっては取れなかった…個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 栗下 望Microsoft employee, Moderator 2016年12月14日 0:24
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月19日 9:51