簡介
本文講述了.NET Compact Framework下的註冊表開發的基本概念,介紹在Windows Mobile和Wince下操作註冊表的工具,同時使用C#實現了一個註冊表匯出工具。
背景
Wince和Windows案頭系統一樣都是把系統資訊,驅動資訊,應用程式資訊等重要存放在註冊表裡面。最近需要實現3G裝置的自動註冊,3G連結項的自動建立功能。在實現該功能的過程中發現裝置註冊資訊和連結項資訊均儲存在註冊表裡面,所以需要實現匯出註冊表功能,把註冊前後的註冊表資訊進行比較。
什麼是註冊表
註冊表(Registry)其實就是一個層次型的檔案資料庫,用於儲存作業系統資訊,驅動資訊,應用程式資訊,使用者資訊等等。在註冊表內有兩個關鍵項,Key和Value,這裡我保留英文,因為翻譯成中文是鍵(key)和值(Value)比較容易混淆。所謂Key就是可以包含SubKey和Value的項。可以理解為一個容器節點,SubKey和Key在本質上是一樣,SubKey可以繼續包含SubKey和Value。Value就是包含資料類型,資料值的項,也可以理解為葉子節點,Value不能包含其他SubKey和Value。
方案
查看和修改註冊表,推薦使用以下兩個工具:
Windows CE Remote Registry Editor
Windows CE Remote Registry Editor可以在VS 2005和VS 2008的菜單下找到。可以遠程查看和修改註冊表,非常方便。可是該工具不支援匯入匯出功能。
PHM Registry Editor
該工具可以安裝在裝置上,在裝置上直接查看和修改註冊表。PHM Registry Editor只是支援匯入功能,不支援匯出功能,同時匯出是使用私人格式,和MS的不相容。
現實
由於上述兩個工具的局限性,所以我實現了一個註冊表匯出功能,和案頭版的Registry Editor匯出功能的檔案格式相容。
操作註冊表類是在CF.net 2.0引入的,CF.net 1.0不支援。使用註冊表功能,需要引用Microsoft.Win32 namespace。
using Microsoft.Win32;
下面是匯出介面,把根下所有的key匯出到StringBuilder中。
public StringBuilder Export()
{
StringBuilder sb = new StringBuilder();
Export(sb, Registry.ClassesRoot);
Export(sb, Registry.CurrentUser);
Export(sb, Registry.LocalMachine);
Export(sb, Registry.Users);
return sb;
}
在Windows Mobile和Wince系統下註冊表的項比案頭系統少一些,如可見。
匯出具體的一個key的代碼
public void Export(StringBuilder sb, RegistryKey key)
{
//log down itself.
sb.AppendFormat(CultureInfo.CurrentCulture, "\r\n[{0}]\r\n", key.Name);
//log down values
string[] s = key.GetValueNames();
Array.Sort(s);
//log down "Default" first
try
{
key.GetValue(Default);
ExportValue(sb, key, Default);
}
catch
{
}
foreach(string name in s)
{
if (!name.Equals(Default))
{
ExportValue(sb, key, name);
}
}
//log down subkeys
s = key.GetSubKeyNames();
Array.Sort(s);
foreach(string subKeyName in s)
{
Export(sb, key.OpenSubKey(subKeyName));
}
}
匯出Key時先匯出其自身,然後匯出Key下的所有Values,匯出Value時如果有Default Value的話先匯出Default Value,然後匯出其他Value。匯出Value後再遞迴匯出所有的SubKeys。
匯出Value的代碼
private void ExportValue(StringBuilder sb, RegistryKey key, string name)
{
switch (key.GetValueKind(name))
{
case RegistryValueKind.DWord:
int dword = (int)key.GetValue(name);
if (name.Equals(Default))
{
sb.AppendFormat(CultureInfo.CurrentCulture, "@=dword:{0:X8}\r\n", dword);
}
else
{
sb.AppendFormat(CultureInfo.CurrentCulture, "\"{0}\"=dword:{1:X8}\r\n", name, dword);
}
break;
case RegistryValueKind.String:
if (name.Equals(Default))
{
sb.AppendFormat(CultureInfo.CurrentCulture, "@=\"{0}\"\r\n", key.GetValue(name));
}
else
{
sb.AppendFormat(CultureInfo.CurrentCulture, "\"{0}\"=\"{1}\"\r\n", name, key.GetValue(name));
}
break;
case RegistryValueKind.MultiString:
string[] values = (string[])key.GetValue(name);
if (name.Equals(Default))
{
sb.Append("@=multi_sz:");
}
else
{
sb.AppendFormat(CultureInfo.CurrentCulture, "\"{0}\"=multi_sz:", name);
}
for (int i = 0; i < values.Length; i++)
{
if (i != 0)
{
sb.Append(",");
}
sb.AppendFormat(CultureInfo.CurrentCulture, "\"{0}\"", values[i]);
}
sb.Append("\r\n");
break;
case RegistryValueKind.Binary:
byte[] bytes = (byte[])key.GetValue(name);
if (name.Equals(Default))
{
sb.Append("@=hex:");
}
else
{
sb.AppendFormat(CultureInfo.CurrentCulture, "\"{0}\"=hex:", name);
}
int j = 0;
for (int i = 0; i < bytes.Length; i++)
{
// Display each byte as two hexadecimal digits.
if (i == (bytes.Length - 1))
{
sb.AppendFormat(CultureInfo.CurrentCulture, "{0:X2}", bytes[i]);
}
else
{
sb.AppendFormat(CultureInfo.CurrentCulture, "{0:X2},", bytes[i]);
}
++j;
if (j == 25)
{
j = 0;
sb.Append("\\\r\n");
}
}
sb.Append("\r\n");
break;
}
}
由於Value有不同的資料類型,匯出的時候根據資料類型來匯出不同的格式。key.GetValueKind()函數可以取出Key資料類型RegistryValueKind。
程式運行效果
原始碼:RegistryExporter.rar
環境:Visual Studio 2008 + Windows Mobile 6 professional SDK + .NET Compact Framework 2.0