我正在尝试以编程方式在Internet Explorer中配置一些选项,如:
它们都存储在注册表中,因此我可以使用。
轻松编辑它们public void EditKey(String keyPath, String keyName, Int32 newValue)
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true))
{
if (key != null)
key.SetValue(keyName, newValue, RegistryValueKind.DWord);
}
}
这是我的问题:
我需要在工具中添加一个网站 - > Internet Explorer中的兼容性视图设置。
经过一番研究,我看到这个网站列表存储在:
HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ BrowserEmulation \ ClearableListData \ UserFilter.
问题是这个密钥是二进制密钥所以它有点困难,首先解码其中的内容并进行编辑
我发现每个存储的网站之间都有一个分隔符:
您清楚地看到网站:123.com和456.com在列表中。我需要在该列表中添加一个网站,但这里可以说这个分隔符似乎随机改变了。
我在我想要的网站上构建了一个预定义的分隔符,所以它看起来像这样:
private void ReadBinaryKey()
{
byte[] newWebsite = new byte []
{
0x0C,0x00,0x00,0x00,0xA8,0x82,0x8F,0x0D,
0xC1,0x57,0xCE,0x01,0x01,0x00,0x00,0x00,
0x08,0x00,0x32,0x00,0x30,0x00,0x32,0x00,
0x30,0x00,0x2E,0x00,0x6E,0x00,0x65,0x00,
0x74,0x00
};
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(PATH_CVS, true))
{
if (key != null)
{
var value = (byte[])key.GetValue("UserFilter");
// need to set my value here key.SetValue("UserFilter", newWebSite)
}
}
}
我没有尝试过,因为我已经知道它根本不起作用。问题是随机分隔符。还有其他方法可以满足我的需求吗?任何帮助将不胜感激。
感谢。
答案 0 :(得分:1)
这是有效的代码。我在Ryoichi Fukushima创建的代码中添加了一些代码。 我做的主要区别是我在字节数组中添加了域数。我在IE11,IE10中进行了测试。
private const string CLEARABLE_LIST_DATA = @"Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
private const string USERFILTER = "UserFilter";
private static string[] GetDomains()
{
string[] domains;
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
{
byte[] filter = regkey.GetValue(USERFILTER) as byte[];
domains = GetDomains(filter);
}
return domains;
}
/* IT'S DANGER!! */
// You shouldn't call until it becomes completely obvious that UNKNOWN parameter is meaning.
private static void AddUserFilter(string domain)
{
string[] domains = GetDomains();
foreach (string item in domains)
{
if (item==domain)
{
return;
}
}
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(CLEARABLE_LIST_DATA))
{
byte[] filter = regkey.GetValue(USERFILTER) as byte[];
if(filter==null) filter=new byte[0];
byte[] newReg = GetAddedValue(domain, filter);
regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
}
}
private static void RemoveUserFilter(string domain)
{
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
{
byte[] filter = regkey.GetValue(USERFILTER) as byte[];
byte[] newReg = GetRemovedValue(domain, filter);
if (GetDomains(newReg).Length == 0)
regkey.DeleteValue(USERFILTER);
else
regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
}
}
private static byte[] GetFilter()
{
byte[] filter;
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
{
filter = regkey.GetValue(USERFILTER) as byte[];
}
return filter;
}
private static 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();
}
private static byte[] GetAddedValue(string domain, byte[] filter)
{
byte[] SEPARATOR = new byte[] { 0x0C, 0x00, 0x00, 0x00 };
byte[] CONSTANT = new byte[] { 0x01, 0x00, 0x00, 0x00 };
byte[] UNKNOWN = BitConverter.GetBytes(DateTime.Now.ToBinary());
List<byte> newReg = new List<byte>();
byte[] binDomain = System.Text.Encoding.Unicode.GetBytes(domain);
newReg.AddRange(filter);
newReg.AddRange(SEPARATOR);
/************************************************************************************************/
newReg.AddRange(UNKNOWN); // IT'S IRRESPONSIBLE!! Setting 0x00 is preferable to adding DateTime
/************************************************************************************************/
newReg.AddRange(CONSTANT);
newReg.AddRange(BitConverter.GetBytes((UInt16)domain.Length));
newReg.AddRange(binDomain);
byte[] newSize = BitConverter.GetBytes((UInt16)(newReg.Count - 12));
newReg[12] = newSize[0];
newReg[13] = newSize[1];
string[] domains = GetDomains();
byte[] newCount = BitConverter.GetBytes((UInt16)(domains.Length + 1));
newReg[8] = newCount[0];
newReg[9] = newCount[1];
newReg[20] = newCount[0];
newReg[21] = newCount[1];
return newReg.ToArray();
}
private static 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;
}
答案 1 :(得分:0)
也许...
0x00-0x0B : header
0x0C-0x0D : "TOTAL BYTES-12" (UInt16)
0x0E-0x17 : constant A
0x18-0x1B : separator
0x1C-0x23 : UNKNOWN(id? NOT registered datetime...)
0x24-0x27 : constant B
0x28-0x29 : length of target domain(UInt16, ex. example.com is 0x0B,0x00)
0x2A- : target domain (UNICODE)
[repeat separator...target domain]
样本...
private const string CLEARABLE_LIST_DATA = @"Software\Microsoft\Internet Explorer\BrowserEmulation\ClearableListData";
private const string USERFILTER = "UserFilter";
private static string[] GetDomains()
{
string[] domains;
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
{
byte[] filter = regkey.GetValue(USERFILTER) as byte[];
domains = GetDomains(filter);
}
return domains;
}
/* IT'S DANGER!! */
// You shouldn't call until it becomes completely obvious that UNKNOWN parameter is meaning.
private static void AddUserFilter(string domain)
{
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(CLEARABLE_LIST_DATA))
{
byte[] filter = regkey.GetValue(USERFILTER) as byte[];
byte[] newReg = GetAddedValue(domain, filter);
regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
}
}
private static void RemoveUserFilter(string domain)
{
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
{
byte[] filter = regkey.GetValue(USERFILTER) as byte[];
byte[] newReg = GetRemovedValue(domain, filter);
if (GetDomains(newReg).Length == 0)
regkey.DeleteValue(USERFILTER);
else
regkey.SetValue(USERFILTER, newReg, Microsoft.Win32.RegistryValueKind.Binary);
}
}
private static byte[] GetFilter()
{
byte[] filter;
using (Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(CLEARABLE_LIST_DATA))
{
filter = regkey.GetValue(USERFILTER) as byte[];
}
return filter;
}
private static 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();
}
private static byte[] GetAddedValue(string domain, byte[] filter)
{
byte[] SEPARATOR = new byte[] { 0x0C, 0x00, 0x00, 0x00 };
byte[] CONSTANT = new byte[] { 0x01, 0x00, 0x00, 0x00 };
byte[] UNKNOWN = BitConverter.GetBytes(DateTime.Now.ToBinary());
List<byte> newReg = new List<byte>();
byte[] binDomain = System.Text.Encoding.Unicode.GetBytes(domain);
newReg.AddRange(filter);
newReg.AddRange(SEPARATOR);
/************************************************************************************************/
newReg.AddRange(UNKNOWN); // IT'S IRRESPONSIBLE!! Setting 0x00 is preferable to adding DateTime
/************************************************************************************************/
newReg.AddRange(CONSTANT);
newReg.AddRange(BitConverter.GetBytes((UInt16)domain.Length));
newReg.AddRange(binDomain);
byte[] newSize = BitConverter.GetBytes((UInt16)(newReg.Count - 12));
newReg[12] = newSize[0];
newReg[13] = newSize[1];
return newReg.ToArray();
}
private static 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;
}
答案 2 :(得分:0)
以下是我阅读此数据的方法:
Bytes Description
00-07 Header (Appears to be constant "41,1f,00,00,53,08,ad,ba")
08-11 Int64 Total # of entries in the list
12-15 Int64 Total # of bytes to follow including this number. (DataLen + 4)
16-19 Int64 Version (seems to always be 1)
20-?? Repeating entries.
Entry Format
Bytes Description
00-03 Int64 Entry Number (Increments for each entry)
04-07 Int64 Entry Header (Seems to be constant at 12 (0xC))
08-11 Int64 Unknown - Checksum?
12-15 Int64 Unknown - Timestamp?
16-19 Int64 Unknown - Always 1
20-21 Int32 Length of data to follow (an entry of abc.com would be 7)
22-?? Unicode Chars for the website/address