質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.52%

Edgeの特定のタブを閉じたいです。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,768

cancat

score 247

こんにちは。 
Windows10でC#のアプリケーションを開発しています。 
Visual Studio 2017 Communityを使っています。 

前提・実現したいこと

Edgeの特定のタブを閉じたいです。

該当のソースコード

private void CloseEdgeTab(string title)
{
    var process = System.Diagnostics.Process.GetProcesses().Where(p => p.MainWindowTitle.Contains(title)).FirstOrDefault();
    process.CloseMainWindow();
}


と書いて、Edgeのウィンドウを閉じようとしています。

発生している問題・エラーメッセージ

これで閉じることは閉じれるのですが、タブではなくEdgeのウィンドウをすべて閉じてしまいます。
特定のタブのみを閉じるには、どのようにしたらよいでしょうか?
タスクマネージャーでは、Edgeは複数のプロセスにわかれているように見えるのですが、タブごとに、べつべつに閉じることはできませんか?

補足情報(言語/FW/ツール等のバージョンなど)

Microsoft Visual Studio Community 2017
Version 15.0.26228.9 D15RTWSVC
Microsoft .NET Framework
Version 4.6.01586

です。 
よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

何が最終的な目的か知りませんがXAMLで作成されたアプリケーションはUIAutomationで操作します。
EdgeのHTML内の自動操作をしたいのであれば、WebDriverを検討してください。

UI Automationのドキュメントを見てください。
また、Windows SDKをインストールしてinspectというツールを使ってみてください。
これはUIAutomationによる情報の取得と操作を試すことが出来ます。
最新のSDKをインストールすれば
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64
にあります。
Inepectを起動して左側のツリーからエレメントを選び、メニューのActionから行いたい操作を選択します。
なお、左上のドロップボックスでUIAutomationとMSAAを切り替えられますが、UIAutomationを使ってください。

以下はInepectを使用してEdgeを調べ、タブの閉じるボタンを押すところまで実施したサンプルです。
(コピペのロジックが多いです)

COMの設定は以下と同じ
https://teratail.com/questions/88664

using System;
using UIAutomationClient;

namespace ConsoleApp1
{
    class Program
    {   
        [STAThread]
        static void Main(string[] args)
        {
            //タブの名前
            string target_title = "新しいタブ";

            target_title += " タブ";//後ろに必ず付いているようなので足す

            string CLSID_CUIAutomation = "ff48dba4-60ef-4201-aa87-54103eef594e";
            Type type = Type.GetTypeFromCLSID(Guid.Parse(CLSID_CUIAutomation));
            IUIAutomation automation = Activator.CreateInstance(type) as IUIAutomation;

            IUIAutomationElement root = automation.GetRootElement();
            IUIAutomationTreeWalker walker = automation.RawViewWalker;

            IUIAutomationElement edge = null;
            edge = walker.GetFirstChildElement(root);
            while (edge != null)
            {
                string name = edge.CurrentName;
                if(!string.IsNullOrEmpty(name) && name .EndsWith(" ‎- Microsoft Edge"))
                {
                    break;
                }
                IUIAutomationElement next= walker.GetNextSiblingElement(edge);
                edge = next;
            }
            if (edge == null)
            {
                return;
            }

            IUIAutomationElement core_window = null;
            {
                const int UIA_ClassNamePropertyId = 30012;
                var cond = automation.CreatePropertyCondition(
                    UIA_ClassNamePropertyId, "Windows.UI.Core.CoreWindow");
                core_window = edge.FindFirst(TreeScope.TreeScope_Children, cond);
            }
            if(core_window == null)
            {
                return;
            }

            Console.WriteLine(core_window.CurrentName);

            IUIAutomationElement TabsList = null;
            TabsList = walker.GetFirstChildElement(core_window);
            while (TabsList != null)
            {
                string id = TabsList.CurrentAutomationId;
                if (!string.IsNullOrEmpty(id) && id == "TabsList")
                {
                    break;
                }
                IUIAutomationElement next = walker.GetNextSiblingElement(TabsList);
                TabsList = next;
            }

            if(TabsList == null)
            {
                return;
            }
            Console.WriteLine(TabsList.CurrentClassName);

            IUIAutomationElement target_tab = null;
            target_tab = walker.GetFirstChildElement(TabsList);
            while (target_tab != null)
            {
                string name = target_tab.CurrentName;
                if (!string.IsNullOrEmpty(name) && name == target_title)
                {
                    break;
                }
                IUIAutomationElement next = walker.GetNextSiblingElement(target_tab);
                target_tab = next;
            }
            if(target_tab == null)
            {
                return;
            }

            //タブを選択する操作をする
            IUIAutomationSelectionItemPattern select_pattern = null;
            const int UIA_SelectionItemPatternId = 10010;
            select_pattern = target_tab.GetCurrentPattern(UIA_SelectionItemPatternId);
            if(select_pattern == null)
            {
                return;
            }
            select_pattern.Select();
            //適当に待つ
            System.Threading.Thread.Sleep(1000);
            IUIAutomationElement m_tabItemRoot = null;
            m_tabItemRoot = walker.GetFirstChildElement(target_tab);
            if(m_tabItemRoot == null)
            {
                return;
            }

            //閉じるボタンを探す
            IUIAutomationElement AllInputCloseButton = null;
            AllInputCloseButton = walker.GetFirstChildElement(m_tabItemRoot);
            while (AllInputCloseButton != null)
            {
                string id = AllInputCloseButton.CurrentAutomationId;
                if (!string.IsNullOrEmpty(id) && id == "AllInputCloseButton")
                {
                    break;
                }
                IUIAutomationElement next = walker.GetNextSiblingElement(AllInputCloseButton);
                AllInputCloseButton = next;
            }
            if(AllInputCloseButton == null)
            {
                return;
            }

            //ボタンを押す
            const int UIA_InvokePatternId = 10000;
            IUIAutomationInvokePattern invoke_pattern = null;
            invoke_pattern = AllInputCloseButton.GetCurrentPattern(UIA_InvokePatternId);
            if(invoke_pattern == null)
            {
                return;
            }
            invoke_pattern.Invoke();

            Console.ReadKey();
        }

    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/25 17:03 編集

    ありがとうございます。
    試したところ、タブを終了できました。感謝します。
    ツールのご案内もありがとうございます。
    早速Inspectを使ってみました。細かくウィンドウやボタンの情報をとれて、強力そうです。

    ときどき目的を尋ねられるのですが、最終的な目的はひとことで説明するのは、とてもむずかしいです。

    キャンセル

+1

私のほうでも試してみましたが、結論から言うと難しいだと思います。

まず参考URL

How to open “Microsoft Edge” from c# and wait for it to be closed?
プロセスを強制的に終了する
他のプログラムのメインウィンドウを閉じて終了する

でサンプルコード
    foreach (var process in Process.GetProcesses().Where(p => p.ProcessName == "MicrosoftEdgeCP"))
    {
        Console.WriteLine(process.HasExited);
        if (!process.CloseMainWindow())
        {
            process.Kill();
        }
        Console.WriteLine(process.HasExited);
        Console.WriteLine(process.CloseMainWindow());
        process.Dispose();
    }

これをローカルで動かすと、たまーにタブが閉じられますが、基本的にはプロセスが殺された後ですぐに復活し、開いていたページを再読み込みするようです。

プロセス名として指定したMicrosoftEdgeCPがタブのプロセスらしいですが、ほかにMicrosoftEdgeってやつもいて、こいつがメインプロセスとしてタブたちの管理や死活制御を行なっているように見えます。
当然このメインプロセスを殺すとEdgeごとサヨナラします。

また別の試行としてタスクマネージャの右クリックから閉じるのも、上記動作と同じように一瞬タブが死んだように見えた後再読み込みする動きでした。

ということでいかがでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/24 21:34

    検証ありがとうございます。なるほど。プロセスにEdgeCPというのがあるのは気づいたのですが、それがタブだったんですね。で、それは消せないと…。なるほど。ありそうな感じですね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる