WebBrowserのJavaScriptを無効化する

過去のブログのアーカイブ
この記事は前身のブログのアーカイブを引き継いだものです. 画像が正しく表示できないなど,コンテンツの表示に問題がある恐れがあります.

C#のFormsApplicationにはWebBrowserという便利なコントロールがあるのですがいまいち融通が利かず、昔のIEをそのままはめ込んだだけというお粗末な仕様になっています。
今回はJavaScriptの無効化の方法。普段仕様することはあまりない気がしますが備忘録としてまとめておきます。

はじめに

昔のプロジェクトを漁ったら出てきたものです。既にライブラリ化されていたものを逆コンパイルして取り出したもので、動作は確認しましたがソースコードは無茶苦茶です。とりあえず動作さえすればいいという方は下の方にダウンロードリンクを貼ってありますのでそこからダウンロードしてください。
記事書き終わってコードを見返したのですがとんでもないコードですね…コードの内容に参考にはならないかも

インターフェースから実装していく

WebBrowserから直接JavaScriptを無効化する手段はないため、IOleClientSiteというインターフェースからWebBrowserをコントロールして上げる必要があります。

using System;
using System.Runtime.InteropServices;
[Guid("00000118-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleClientSite
{
    void SaveObject();
    void GetMoniker(int dwAssign, int dwWhichMoniker, ref object ppmk);
    void GetContainer(ref object ppContainer);
    void ShowObject();
    void OnShowWindow(bool fShow);
    void RequestNewObjectLayout();
}

GUIDから直接インターフェースを実装。このインターフェースを使用して実装していきます。

using Microsoft.VisualBasic.CompilerServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
[ComVisible(true)]
    public class WebBrowserControler : Control, IOleClientSite
    {
        private static List<WeakReference> __ENCList = new List<WeakReference>();
        private const int DISPID_AMBIENT_DLCONTROL = -5512;
        private WebBrowser _WebBrowser;
        private DLCTL _DlControl;
        public DLCTL DlControl
        {
            get
            {
                return this._DlControl;
            }
            set
            {
                this._DlControl = value;
                this.OnAmbientPropertyChange();
                this._WebBrowser.Refresh();
            }
        }
        [DebuggerNonUserCode]
        private static void __ENCAddToList(object value) {
            List<WeakReference> _ENCList = WebBrowserControler.__ENCList;
            bool flag = false;
            checked {
                try {
                    Monitor.Enter(_ENCList, ref flag);
                    bool flag2 = WebBrowserControler.__ENCList.Count == WebBrowserControler.__ENCList.Capacity;
                    if (flag2) {
                        int num = 0;
                        int arg_44_0 = 0;
                        int num2 = WebBrowserControler.__ENCList.Count - 1;
                        int num3 = arg_44_0;
                        while (true) {
                            int arg_95_0 = num3;
                            int num4 = num2;
                            if (arg_95_0 > num4) {
                                break;
                            }
                            WeakReference weakReference = WebBrowserControler.__ENCList[num3];
                            flag2 = weakReference.IsAlive;
                            if (flag2) {
                                bool flag3 = num3 != num;
                                if (flag3) {
                                    WebBrowserControler.__ENCList[num] = WebBrowserControler.__ENCList[num3];
                                }
                                num++;
                            }
                            num3++;
                        }
                        WebBrowserControler.__ENCList.RemoveRange(num, WebBrowserControler.__ENCList.Count - num);
                        WebBrowserControler.__ENCList.Capacity = WebBrowserControler.__ENCList.Count;
                    }
                    WebBrowserControler.__ENCList.Add(new WeakReference(RuntimeHelpers.GetObjectValue(value)));
                }
                finally {
                    bool flag3 = flag;
                    if (flag3) {
                        Monitor.Exit(_ENCList);
                    }
                }
            }
        }
        public WebBrowserControler(WebBrowser WebBrowser) {
            WebBrowserControler.__ENCAddToList(this);
            this._DlControl = (DLCTL)112;
            this._WebBrowser = WebBrowser;
            ((IOleObject)this._WebBrowser.ActiveXInstance).SetClientSite(this);
        }
        [DispId(-5512)]
        public int Didpid_Ambient_DlControl() {
            return (int)this._DlControl;
        }
        private void OnAmbientPropertyChange() {
            ((IOleControl)NewLateBinding.LateGet(this._WebBrowser.ActiveXInstance, null, "Application", new object[0], null, null, null)).OnAmbientPropertyChange(-5512);
        }
        public void GetContainer(ref object ppContainer) {}
        public void GetMoniker(int dwAssign, int dwWhichMoniker, ref object ppmk) {}
        public void OnShowWindow(bool fShow) {}
        public void RequestNewObjectLayout() {}
        public void SaveObject() {}
        public void ShowObject() {}
    }

仕組み的にはWebBrowserのActiveXInstanceのClientSiteをこのクラスにくくりつけて操作している感じ。
JavaScriptの無効化に特化しているので最低限のコードのみ。

ダウンロード

ソースコードのダウンロードはこちらからどうぞ。列挙体とか他の必要なコードもこちらに入っています。
[wpdm_file id=31]

使い方

WebBrowserを貼っているフォームのクラスにWebBrowserContainerのクラスの変数/プロパティを宣言する

private WebBrowserControler ctrler;

操作するWebBrowserを入れ、JavaとかJavaScriptとか動作させたくないものを列挙体で指定すればOK

this.ctrler = new WebBrowserControler(this.webBrowser1);
this.ctrler.DlControl = (this.ctrler.DlControl | DLCTL.NO_JAVA | DLCTL.NO_SCRIPTS);

これでJavaScriptを動作させずにページを表示することができます。
スクリーンショット 2017-03-30 18.27.13

まとめ

IOleClientSiteインターフェースから操作することができる。それ以外の方法もあるみたいだけどこれが一番簡単かも。
一度コンパイルされたコードは人間が読むものではない