[C#.NET][VB.NET] 如何 列舉 Registry / 使用 treeView 實作
1.Registry 類別 提供我們 讀/寫,昏到死的機碼
Registry 公開的機碼為:
- CurrentUser:儲存有關使用者喜好設定的資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_CURRENT_USER。
 
 - CurrentConfig:儲存非使用者特定的硬體資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_CURRENT_CONFIG。
 
LocalMachine:儲存本機電腦 (Local Machine) 的組態資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_LOCAL_MACHINE。
ClassesRoot:儲存有關型別 (和類別) 和屬性 (Property) 的資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_CLASSES_ROOT。
Users:儲存有關預設使用者設定的資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_USERS。
PerformanceData:儲存軟體元件的效能資訊。這個欄位會讀取 Windows 登錄主要機碼 HKEY_PERFORMANCE_DATA。
DynData:儲存動態 (Dynamic) 資料。這個欄位會讀取 Windows 登錄主要機碼 HKEY_DYN_DATA。動態機碼原本是在 Microsoft Windows 95 中所引入用來處理動態的登錄資料。它們只在 Windows 98/Windows ME 中支援。
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);
}
 
         
 
基本上往下圖方向發展
    Step1.開一個新的WinForm專案,拖曳一個splitContainer1至專案,拖曳treeView1至splitContainer1的左邊,拖曳listView1至splitContainer1的右邊(開始沒耐心打下去了
)
  Step2.設定treeView1及listView1的Dock屬性為FIll
     
   
  Step3.拖曳一個imageList1至專案,並加入圖庫。
    Step4.設定listView1的Columns
    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);
      }
  
 
 
  
  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筆的資料
     
  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);                  }
              }
          }
      }
   
  點選資料夾後會將資料夾的內容秀出
    實作結果
   
    
  4.範例下載:
  
                    若有謬誤,煩請告知,新手發帖請多包涵

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

 
                
