[C#.NET][VB.NET] 如何 列舉 Registry / 使用 treeView 實作

[C#.NET][VB.NET] 如何 列舉 Registry / 使用 treeView 實作

1.Registry 類別 提供我們 讀/寫,昏到死的機碼

Registry 公開的機碼為:

CurrentUser:儲存有關使用者喜好設定的資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_CURRENT_USER。

 LocalMachine:儲存本機電腦 (Local Machine) 的組態資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_LOCAL_MACHINE。

 ClassesRoot:儲存有關型別 (和類別) 和屬性 (Property) 的資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_CLASSES_ROOT。

 Users:儲存有關預設使用者設定的資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_USERS。

 PerformanceData:儲存軟體元件的效能資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_PERFORMANCE_DATA。


2009-7-28 上午 10-07-42

CurrentConfig:儲存非使用者特定的硬體資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_CURRENT_CONFIG。

 DynData:儲存動態 (Dynamic) 資料。這個欄位會讀取 Windows 登錄主要機碼 HKEY_DYN_DATA。動態機碼原本是在 Microsoft Windows 95 中所引入用來處理動態的登錄資料。它們只在 Windows 98/Windows ME 中支援。

2009-7-28 上午 09-38-14

2.Registry 類別 需要與RegistryKey 類別搭配使用,如下:

 

 

 

3.除了使用上述類別之外,VB的My類別系列也有My.Computer.Registry

ClassesRoot:對應至 HKEY_CLASSES_ROOT。

CurrentConfig:對應至 HKEY_CURRENT_CONFIG。

CurrentUser:對應至 HKEY_CURRENT_USER。

DynData:對應至 HKEY_DYNAMIC_DATA。

LocalMachine:對應至 HKEY_LOCAL_MACHINE。

PerformanceData:對應至。HKEY_PERFORMANCE_DATA。

Users:對應至 HKEY_USERS。

 

以下程式碼需要匯入

Microsoft.Win32 命名空間 

 

如何列舉 Registry

1.引用類別
RegistryKey myReg = Registry.Users;
  


2.取得類別中的機碼名稱
String[] names = myReg.GetSubKeyNames();
  

 


3.列舉根目錄中的子目錄

string[] mySubKey = myReg.GetSubKeyNames();
foreach (string item in mySubKey)
{
listBox1.Items.Add(item);
}
2009-7-28 上午 10-30-56
  
  
 

  

 

基本上往下圖方向發展

2009-7-28 上午 09-38-14

Step1.開一個新的WinForm專案,拖曳一個splitContainer1至專案,拖曳treeView1至splitContainer1的左邊,拖曳listView1至splitContainer1的右邊(開始沒耐心打下去了)

Step2.設定treeView1及listView1的Dock屬性為FIll

2009-7-28 上午 10-42-10 

 

 

Step3.拖曳一個imageList1至專案,並加入圖庫。

2009-7-28 上午 10-46-51

Step4.設定listView1的Columns

2009-7-28 上午 10-57-45

Step5.在HandleCreated事件設定控制項的初始值

public Form1()
{
    InitializeComponent();
    this.HandleCreated += new EventHandler(Form1_HandleCreated);
}
void Form1_HandleCreated(object sender, EventArgs e)
{
    //treeView1屬性設定
    this.treeView1.ImageList = this.imageList1;//圖庫
    //listView1屬性設定
    this.listView1.View = View.Details;
    this.listView1.GridLines = true;
    this.listView1.SmallImageList = this.imageList1;//圖庫
    this.listView1.FullRowSelect = true;
    //加入根目錄
    TreeNode RootNode = new TreeNode("我的電腦", 2, 2);
    this.treeView1.Nodes.Add(RootNode); 
 
    //加入主要目錄
    TreeNode SubNode1 = new TreeNode("HKEY_CLASSES_ROOT", 0, 1);
    RootNode.Nodes.Add(SubNode1); 
 
    TreeNode SubNode2 = new TreeNode("HKEY_CURRENT_USER", 0, 1);
    RootNode.Nodes.Add(SubNode2); 
 
    TreeNode SubNode3 = new TreeNode("HKEY_LOCAL_MACHINE", 0, 1);
    RootNode.Nodes.Add(SubNode3); 
 
    TreeNode SubNode4 = new TreeNode("HKEY_USERS", 0, 1);
    RootNode.Nodes.Add(SubNode4); 
 
    TreeNode SubNode5 = new TreeNode("HKEY_CURRENT_CONFIG", 0, 1);
    RootNode.Nodes.Add(SubNode5);
}

 

 

 

 

 

2009-7-28 上午 11-01-00

Step6.在treeView1的BeforeExpand事件加入以下程式碼,並觀察其變化。

//展開樹狀節點
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
    foreach (TreeNode item in e.Node.Nodes)
    {
        AddSubRegKey(item);
    }
}
//列舉子目錄
private void AddSubRegKey(TreeNode node)
{
    //取得子目錄名稱
    if (node.Nodes.Count == 0)
    {
        try
        {
            RegistryKey myReg = GetRegKey(node);
            //Console.WriteLine("根目錄: " + node.Text);
            if (myReg != null)
            {
                //列舉根目錄中的子目錄
                string[] mySubKey = myReg.GetSubKeyNames();
                foreach (string item in mySubKey)
                {
                    //Console.WriteLine("子目錄: "+item);
                    node.Nodes.Add(item);
                }
            }
        }
        catch (Exception ee)
        {
            Console.WriteLine(ee.Message);
        }
    }
}
//取得節點的 "RegistryKey"
private RegistryKey GetRegKey(TreeNode node)
{
    //取得節點的完整名稱
    string myRegName = node.Text;
    string myPath = node.FullPath;
    RegistryKey myReg = null;
    //給根目錄使用
    //===========================================
    switch (myRegName)
    {
        case "我的電腦":
            myReg = Registry.LocalMachine;
            myReg = null;
            break; 
 
        default:
            switch (myRegName)
            {
                case "HKEY_CLASSES_ROOT":
                    myReg = Registry.ClassesRoot;
                    break;
                case "HKEY_CURRENT_USER":
                    myReg = Registry.CurrentUser;
                    break;
                case "HKEY_LOCAL_MACHINE":
                    myReg = Registry.LocalMachine;
                    break;
                case "HKEY_USERS":
                    myReg = Registry.Users;
                    break;
                case "HKEY_CURRENT_CONFIG":
                    myReg = Registry.CurrentConfig;
                    break;
            }
            break;
    }
    //給根目錄使用
    //=========================================== 
 
    //若有包含\\字串表示有子目錄
    if (myPath.IndexOf("\\") >= 1)
    {
        string[] KeyName = myPath.Split(new Char[] { '\\' });
        string myParent = node.Parent.Text;
        //取的目錄名稱2層
        if (KeyName.Length == 2)//例如:我的電腦\\HKEY_USERS
        {
            return myReg;
        }
        //取的目錄名稱3層以上
        if (KeyName.Length >= 3)//例如:我的電腦\\HKEY_USERS\\.DEFAULT
        {
            string OldQuery = null;
            //過濾"我的電腦"字串
            foreach (string item in KeyName)
            {
                if (item != "我的電腦")
                {
                    if (OldQuery == null)
                    {
                        OldQuery += item;
                    }
                    else
                    {
                        OldQuery += "\\" + item;
                    }
                }
            }
            string[] NewQuery = OldQuery.Split(new Char[] { '\\' });//字串分割
            //取得主機碼例如:HKEY_USERS
            switch (NewQuery[0])
            {
                case "HKEY_CLASSES_ROOT":
                    myReg = Registry.ClassesRoot;
                    break;
                case "HKEY_CURRENT_USER":
                    myReg = Registry.CurrentUser;
                    break;
                case "HKEY_LOCAL_MACHINE":
                    myReg = Registry.LocalMachine;
                    break;
                case "HKEY_USERS":
                    myReg = Registry.Users;
                    break;
                case "HKEY_CURRENT_CONFIG":
                    myReg = Registry.CurrentConfig;
                    break;
            }
            string query = null;
            //重新排列根目錄
            foreach (string item in NewQuery)
            {
                if (item != NewQuery[0])
                {
                    if (query == null)
                    {
                        query += item;
                    }
                    else
                    {
                        query += "\\" + item;
                    }
                }
            }
            myReg = myReg.OpenSubKey(query, true);
        }
    }
    //回傳
    return myReg;
}

 

 

 

1.設定中斷點

2.觀察列舉的結果

3.比對OS的登錄檔程式

我的HKEY_CLASSES_ROOT裡有9745筆的資料

2009-7-28 上午 11-10-39

 

Step7.在treeView1的AfterSele事件加入以下程式碼。  

//選取樹狀節點之後。(開啟資料夾)
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
    //清空
    this.listView1.Items.Clear();
    //依節點名稱取得 RegistryKey
    RegistryKey myReg = GetRegKey(this.treeView1.SelectedNode);
    //取得包含所有與這個機碼相關值名稱的字串陣列。
    if (myReg != null)
    {
        string[] AllValueName = myReg.GetValueNames();
        string RegName;
        RegistryValueKind GetType;
        object RegData;
        string RegType;
        //若陣列有資料
        if (AllValueName.Length != 0)
        {
            foreach (var item in AllValueName)
            {
                //取得名稱
                RegName = item.ToString();
                //取得資料
                RegData = myReg.GetValue(RegName);
                //取得類型
                GetType = myReg.GetValueKind(item);
                //Console.WriteLine( myReg.GetValueKind(item.ToString())); 
 
                ListViewItem mySubItem = null;
                Console.WriteLine("Name: " + RegName + "\t" + "Type: " + GetType.ToString() + "\t" + "Data: " + RegData.ToString()); 
 
                //判斷資料型態
                switch (GetType)
                {
                    case RegistryValueKind.String:
                        RegType = "REG_SZ";
                        //建立ListView子項目"名稱、類型、資料"
                        mySubItem = new ListViewItem(new String[] { RegName, RegType.ToString(), RegData.ToString() }, 3);
                        break;
                    case RegistryValueKind.Binary:
                        RegType = "REG_BINARY";
                        //建立ListView子項目"名稱、類型、資料"
                        mySubItem = new ListViewItem(new String[] { RegName, RegType.ToString(), RegData.ToString() }, 4);
                        break;
                    case RegistryValueKind.DWord:
                        RegType = "REG_DWORD";
                        //建立ListView子項目"名稱、類型、資料"
                        mySubItem = new ListViewItem(new String[] { RegName, RegType.ToString(), RegData.ToString() }, 4);
                        break;
                    case RegistryValueKind.MultiString:
                        RegType = "REG_MULTI_SZ";
                        //建立ListView子項目"名稱、類型、資料"
                        mySubItem = new ListViewItem(new String[] { RegName, RegType.ToString(), RegData.ToString() }, 3);
                        break;
                    case RegistryValueKind.ExpandString:
                        RegType = "REG_EXPAND_SZ";
                        //建立ListView子項目"名稱、類型、資料"
                        mySubItem = new ListViewItem(new String[] { RegName, RegType.ToString(), RegData.ToString() }, 3);
                        break;
                }
                this.listView1.Items.Add(mySubItem);
            }
        }
    }
}

 

點選資料夾後會將資料夾的內容秀出

2009-7-28 上午 11-20-18

實作結果

 

 

4.範例下載:

CS_TreeView.rar

VB_TreeView.rar

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo