C# 实现向浏览器的兼容性视图列表中添加、删除网站和检查网站是否在兼容性网站列表中

今天回答论坛上的一个问题,搜索了一下网上,并没有找到一个完整的例子,下面根据网上的一些资料,经过转换、完善成一个完整的例子。下面的例子可以实现添加、删除、检测网站是否在兼容性网站列表中的功能。

以下代码在IE8、Windows2003环境下测试通过。测试时要重新打开浏览器进行验证。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;

namespace WindowsFormsApplication4
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }
    
    /*
     * 
     * 添加、删除兼容性网站列表的代码。
     * 
     * 孟宪会@2014-04-20
     * 
     */


    //兼容性列表在注册表中的位置,注意:不同位的操作系统可能不同,请注意测试。
    private const string CLEARABLE_LIST_DATA = @"Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
    private const string USERFILTER = "UserFilter";
    private byte[] header = new byte[] { 0x41, 0x1F, 0x00, 0x00, 0x53, 0x08, 0xAD, 0xBA };
    private byte[] delim_a = new byte[] { 0x01, 0x00, 0x00, 0x00 };
    private byte[] delim_b = new byte[] { 0x0C, 0x00, 0x00, 0x00 };
    private byte[] checksum = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
    private byte[] filler = BitConverter.GetBytes(DateTime.Now.ToBinary());//new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
    private byte[] regbinary = new byte[] { };


    /// <summary>
    /// 得到已经存在的所有兼容网站列表,如果没有,则返回空数组。
    /// </summary>
    /// <returns></returns>
    private string[] GetDomains()
    {
      string[] domains = { };
      using (RegistryKey regkey = Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
      {
        //可能不存在此key.
        Object filterData = regkey.GetValue(USERFILTER);
        if (filterData != null)
        {
          byte[] filter = filterData as byte[];
          domains = GetDomains(filter);
        }
      }
      return domains;
    }

    /// <summary>
    /// 从byte数组中分析所有网站名称
    /// </summary>
    /// <param name="filter"></param>
    /// <returns></returns>
    private string[] GetDomains(byte[] filter)
    {
      List<string> domains = new List<string>();
      int length;
      int offset_filter = 24;
      int totalSize = filter.Length;
      while (offset_filter < totalSize)
      {
        length = BitConverter.ToUInt16(filter, offset_filter + 16);
        domains.Add(System.Text.Encoding.Unicode.GetString(filter, 16 + 2 + offset_filter, length * 2));
        offset_filter += 16 + 2 + length * 2;
      }
      return domains.ToArray();
    }

    /// <summary>
    /// 从兼容性列表中删除一个网站。
    /// </summary>
    /// <param name="domain">要删除网站</param>
    private void RemoveUserFilter(string domain)
    {
      String[] domains = GetDomains();
      if (!domains.Contains(domain)) {
        return;
      }
      using (RegistryKey regkey = Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA,true))
      {
        object oldData = regkey.GetValue(USERFILTER);
        if (oldData != null)
        {
          byte[] filter = oldData as byte[];
          byte[] newReg = GetRemovedValue(domain, filter);

          if (GetDomains(newReg).Length == 0)
            regkey.DeleteValue(USERFILTER);
          else
            regkey.SetValue(USERFILTER, newReg, RegistryValueKind.Binary);
        }
      }
    }

    /// <summary>
    /// 得到一个网站的存储的数据
    /// </summary>
    /// <param name="domain"></param>
    /// <param name="filter"></param>
    /// <returns></returns>
    private byte[] GetRemovedValue(string domain, byte[] filter)
    {
      byte[] newReg;
      int length;
      int offset_filter = 24;
      int offset_newReg = 0;
      int totalSize = filter.Length;

      newReg = new byte[totalSize];
      Array.Copy(filter, 0, newReg, 0, offset_filter);
      offset_newReg += offset_filter;

      while (offset_filter < totalSize)
      {
        length = BitConverter.ToUInt16(filter, offset_filter + 16);
        if (domain != System.Text.Encoding.Unicode.GetString(filter, offset_filter + 16 + 2, length * 2))
        {
          Array.Copy(filter, offset_filter, newReg, offset_newReg, 16 + 2 + length * 2);
          offset_newReg += 16 + 2 + length * 2;
        }
        offset_filter += 16 + 2 + length * 2;
      }
      Array.Resize(ref newReg, offset_newReg);
      byte[] newSize = BitConverter.GetBytes((UInt16)(offset_newReg - 12));
      newReg[12] = newSize[0];
      newReg[13] = newSize[1];

      return newReg;
    }

    /// <summary>
    /// 向兼容性列表中添加一个网站
    /// </summary>
    /// <param name="domain"></param>
    private void AddNewSiteToCompatibilityViewList(String domain)
    {
      String[] domains = GetDomains();
      if (domains.Length > 0)
      {
        if (domains.Contains(domain))
        {
          return;
        }
        else
        {
          domains = domains.Concat(new String[] { domain }).ToArray();
        }
      }
      else
      {
        domains = domains.Concat(new String[] { domain }).ToArray();
      }

      int count = domains.Length;
      byte[] entries = new byte[0];
      foreach (String d in domains)
      {
        entries = this.Combine(entries, this.GetDomainEntry(d));
      }
      regbinary = header;
      regbinary = this.Combine(regbinary, BitConverter.GetBytes(count));
      regbinary = this.Combine(regbinary, checksum);
      regbinary = this.Combine(regbinary, delim_a);
      regbinary = this.Combine(regbinary, BitConverter.GetBytes(count));
      regbinary = this.Combine(regbinary, entries);
      Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA,true).SetValue(USERFILTER, regbinary, RegistryValueKind.Binary);
    }

    /// <summary>
    /// 得到一个网站在兼容性列表中的数据,跟GetRemovedValue类似
    /// </summary>
    /// <param name="domain"></param>
    /// <returns></returns>
    private byte[] GetDomainEntry(String domain)
    {
      byte[] tmpbinary = new byte[0];
      byte[] length = BitConverter.GetBytes((UInt16)domain.Length);
      byte[] data = System.Text.Encoding.Unicode.GetBytes(domain);
      tmpbinary = Combine(tmpbinary, delim_b);
      tmpbinary = Combine(tmpbinary, filler);
      tmpbinary = Combine(tmpbinary, delim_a);
      tmpbinary = Combine(tmpbinary, length);
      tmpbinary = Combine(tmpbinary, data);
      return tmpbinary;
    }

    //把两个byte[]数组合并在一起
    private byte[] Combine(byte[] a, byte[] b)
    {
      byte[] c = new byte[a.Length + b.Length];
      System.Buffer.BlockCopy(a, 0, c, 0, a.Length);
      System.Buffer.BlockCopy(b, 0, c, a.Length, b.Length);
      return c;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      //添加10个
      for (int i = 0; i < 10; i++)
      {
        AddNewSiteToCompatibilityViewList("meng" + i + ".com");
      }

      //删除2个
      for (int i = 3; i < 5; i++)
      {
        this.RemoveUserFilter("meng" + i + ".com");
      }
    }
  }
}

网上的3篇资料与本文关系较大。

http://www3.xuebuyuan.com/1567759.html
http://jeffgraves.me/2014/02/19/modifying-ie-compatibility-view-settings-with-powershell/
http://stackoverflow.com/questions/16722454/editing-binary-registry-key


为了确保原文的丢失能找到内容,先把有用的PowerShell脚本粘贴过来。

$key = "HKCU:\Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData"
$item = "UserFilter"

. .\Get-IPrange.ps1
$cidr = "^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)/(3[0-2]|[1-2]?[0-9])$"

[byte[]] $regbinary = @()

#This seems constant
[byte[]] $header = 0x41,0x1F,0x00,0x00,0x53,0x08,0xAD,0xBA

#This appears to be some internal value delimeter
[byte[]] $delim_a = 0x01,0x00,0x00,0x00

#This appears to separate entries
[byte[]] $delim_b = 0x0C,0x00,0x00,0x00

#This is some sort of checksum, but this value seems to work
[byte[]] $checksum = 0xFF,0xFF,0xFF,0xFF

#This could be some sort of timestamp for each entry ending with 0x01, but setting to this value seems to work
[byte[]] $filler = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01

#Examples: mydomain.com, 192.168.1.0/24
$domains = @("google.com","192.168.1.0/24")

function Get-DomainEntry($domain) {
[byte[]] $tmpbinary = @()

[byte[]] $length = [BitConverter]::GetBytes([int16]$domain.Length)
[byte[]] $data = [System.Text.Encoding]::Unicode.GetBytes($domain)

$tmpbinary += $delim_b
$tmpbinary += $filler
$tmpbinary += $delim_a
$tmpbinary += $length
$tmpbinary += $data

return $tmpbinary
}

if($domains.Length -gt 0) {
[int32] $count = $domains.Length

[byte[]] $entries = @()

foreach($domain in $domains) {
if($domain -match $cidr) {
$network = $domain.Split("/")[0]
$subnet = $domain.Split("/")[1]
$ips = Get-IPrange -ip $network -cidr $subnet
$ips | %{$entries += Get-DomainEntry $_}
$count = $count - 1 + $ips.Length
}
else {
$entries += Get-DomainEntry $domain
}
}

$regbinary = $header
$regbinary += [byte[]] [BitConverter]::GetBytes($count)
$regbinary += $checksum
$regbinary += $delim_a
$regbinary += [byte[]] [BitConverter]::GetBytes($count)
$regbinary += $entries
}

Set-ItemProperty -Path $key -Name $item -Value $regbinary

IE11下的PowerShell

$key = "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft"

if(-Not (Test-Path "$key\Internet Explorer")) {
New-Item -Path $key -Name "Internet Explorer" | Out-Null
}

if(-Not (Test-Path "$key\Internet Explorer\BrowserEmulation")) {
New-Item -Path "$key\Internet Explorer" -Name "BrowserEmulation" | Out-Null
}

if(-Not (Test-Path "$key\Internet Explorer\BrowserEmulation\PolicyList")) {
New-Item -Path "$key\Internet Explorer\BrowserEmulation" -Name "PolicyList" | Out-Null
}

. .\Get-IPrange.ps1
$cidr = "^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)/(3[0-2]|[1-2]?[0-9])$"

#Examples: mydomain.com, 192.168.1.0/24
$domains = @("google.com","192.168.1.0/24")

$regkey = "$key\Internet Explorer\BrowserEmulation\PolicyList"

foreach($domain in $domains) {
if($domain -match $cidr) {
$network = $domain.Split("/")[0]
$subnet = $domain.Split("/")[1]
$ips = Get-IPrange -ip $network -cidr $subnet
$ips | %{$val = New-ItemProperty -Path $regkey -Name $_ -Value $_ -PropertyType String | Out-Null}
$count = $count - 1 + $ips.Length
}
else {
New-ItemProperty -Path $regkey -Name $domain -Value $domain -PropertyType String | Out-Null
}
}


  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值