C#のProcessでIEを複数起動して、すべてのプロセスを閉じる方法

以下記事は以前に書いたCOM経由でIEを操作する方法です。

COMの記事を書いたタイミングでは、-nomergeオプションを使ってなかったのでCOMに変更して対応した。
確か、-noframemergingオプションは試したけど、これはうまくいかなかった。
でも、以下のサンプルコードでやってみると上手くいく。
ということは、後ほど記述するけど、これは起動したIEのx64,x86バージョンの違いによるものかもしれない。

今回の内容は、IE起動の起動と終了をProcess経由でやる方法です。
ただし、いくつか満たすべき条件があります。

満たすべき条件

・64bitのIEを使う必要がある
・-nomergeか-noframemerging オプションの追加が必要
・Windowが立ち上がるまで待つ必要がある。

上記条件を満たして実際に動くソースは以下です。

実験用のソースコード

using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.Threading;

namespace ExperimentCsharpCode.ProcessDir.HandleIE
{
    class OpenIE
    {
        private string _iePath = @"C:\Program Files\Internet Explorer\iexplore.exe";
        //private string _iePath = @"C:\Program Files (x86)\Internet Explorer\iexplore.exe";
        private List<Process> _pList = new List<Process>();

        public OpenIE()
        {
            try
            {
                //SimpleOpen();
                //HandleMultiIE();
                HandleMultiIEWithNoMergeArg();
                ProcessCloseMainWindow();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
        /// <summary>
        /// 一つだけIEを起動して閉じる。
        /// </summary>
        public void SimpleOpen()
        {
            var arg = "https://www.yahoo.co.jp/";
            ProcessStartInfo pInfo = new ProcessStartInfo(_iePath, arg);
            var p = Process.Start(pInfo);
            Thread.Sleep(3000);
            p.CloseMainWindow();
        }
        /// <summary>
        /// 複数IEを起動
        /// </summary>
        public void HandleMultiIE()
        {
            var arg = "https://www.yahoo.co.jp/";
            for (int i = 0; i < 5; i++)
            {
                ProcessStartInfo pInfo = new ProcessStartInfo(_iePath, arg);
                _pList.Add(Process.Start(pInfo));
                Thread.Sleep(3000);
            }

        }
        /// <summary>
        /// -nomergeをつけて複数IEを起動
        /// </summary>
        public void HandleMultiIEWithNoMergeArg()
        {
            var arg = "-nomerge https://www.yahoo.co.jp/";
            for (int i = 0; i < 5; i++)
            {
                ProcessStartInfo pInfo = new ProcessStartInfo(_iePath, arg);
                _pList.Add(Process.Start(pInfo));
                Thread.Sleep(3000);
            }
        }
        /// <summary>
        /// 開いたすべてのプロセスを閉じる
        /// </summary>
        private void ProcessCloseMainWindow()
        {
            for (int i = _pList.Count - 1; i >= 0; i--)
            {
                _pList[i].CloseMainWindow();
                Thread.Sleep(3000);
            }
        }
    }
}

実験用ソースコードを呼び出す側

using System;
using System.Collections.Generic;
using System.Text;
using ExperimentCsharpCode.LinkedList;
using ExperimentCsharpCode.ProcessDir.HandleIE;

namespace ExperimentCsharpCode
{
    class Program
    {
        static void Main(string[] args)
        {
            var sample = new OpenIE();
        }
    }
    
}

考察

Processをひとつだけ起動する場合は32bit,64bitどちらのケースでも-nomergeがなくてもうまく閉じれる

なぜという部分がまだよくわからない。
連続で起動した場合だと-nomerge

そもそも-nomergeとは何なのか。
こちらのサイトで詳しい説明があった。
内容を見ていると、セッションを別にするとのことだけど、
なぜセッションと複数IE起動したプロセスが変化することが関係あるのかわからなかった。

32bit,64bit IE どちらが呼ばれているかわからないパターンがある

64bitのIEを使う理由は、なぜか32bitのIEだとCloseMainWindow()でウィンドウが閉じられない。実験用のソースでコメントアウトしている_iePathの(x86)のほうをコメント解除して実行すると再現できると思います。

仮に実務で使うことを想定すると、どこかにIEの実行パスを書く必要があるのか?直感的にIEの格納パスはどのPCでも同じと思われるけど、例えば今回の例でいうと、ProgramFIleをDドライブとかにしてるとアウトですよねぇ。

ふと気づいたけど、 COM経由でIEを操作する方法の記事でProcess経由の実験コードも載せていた。
そこでは、IEを以下のように呼び出していた。

var p = Process.Start("IExplore.exe", "https://www.yahoo.co.jp/");

これだと私の環境では32bitが呼び出されいるようだった。
恐らくこれも設定で変更可能みたいだけど、特にやってない。
この方法でやるとすると、IE側での設定が必要かもしれないなと、以下の記事を読んでいて思った。

以前書いたサンプル(WinFormで作成)だと例外が発生する

以前書いたサンプルでは、リストに格納されたプロセスに対してCloseMainWindow()すると例外が発生していた。
先ほども書いたけどもう一度。
恐らく32bitが呼び出されていたはず。

var p = Process.Start("IExplore.exe", "https://www.yahoo.co.jp/");

っで、今回のサンプルはコンソールだったのだけど、そこでは例外が発生しなかった。
例外発生しなかったけど、開いたIEが閉じたわけでもない。
ブレークポイントで止めると、ちゃんとプロセスは存在していた。

まとめ

IEをProcessで操作したいというこだわりがあったわけでなく、なぜProcessではなく、COMを使うのかということを聞かれたため調べた。
COMは実際に実装したからよかったけど、ProcessでIEの操作は、開始早々諦めた。(複数起動だけでなく、子→孫まで終了できるようにしたいということだったので)なので、少しばかりサンプルコード作ってみてみようと思った。
また、今回のケースではDOMを内容を見て何かするというものでなかったので、Processも選択肢になったようだ。

ProcessでIEを操作するという点で色んなサイトを見たけど、少し複雑なことがしたいならCOMを使えという内容がいくつかあったと思う。
それ以外にも、WebBrowser コントロールを使ったり等。
あと、違う記事で書いているけど、ChromiumベースのブラウザCefSharpを使うというのもありだと思う。
今回はIE限定の話だったので、上記のように色々調べたわけです。

C#C#

Posted by takumioda