[C#][WPF]偵測HKey_Current_User機碼異動, 以國稅局報稅軟體為例

  • 2804
  • 0
  • C#
  • 2013-07-24

摘要:[C#][WPF]偵測HKey_Current_User機碼異動, 以國稅局報稅軟體為例

如果要偵測機碼的異動 可以使用 WMI 來達成

不過對於屬於HKey_Classes_Root 及 HKey_Current_User 底下  的機碼卻不適用

因此如果要偵測HKey_Current_User機碼的異動 , 其實也很簡單, 先取得 Current User 對應的 SID

再去偵測HKey_User\SID\ 下對應的機碼 就可以了

而 HKey_Classes_Root  就是 偵測HKey_User\SID_classes\ 或是 HKey_Local_Machine\Software\Classes\ 下對應的機碼

特別要說明的是 :不管我們使用 RegisryKeyEvent , RegistryTreeEvent, RegistryValue Event 哪一個 class 都只能知道有異動發生

異動前後的Data 必須自行讀取 Regisrty

此處以WPF 專案為例 , 偵測異動的目標是很多人都很熟悉的國稅局報稅軟體

方案名稱: DetectHKCU

專案名稱: DetectHKCU

加入的參考: System.Management 及 System.Security

MainWindow.xaml.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Security.Principal;
using System.Management;
using Microsoft.Win32;

namespace DetectHKCU
{
    /// 
    /// MainWindow.xaml 的互動邏輯
    /// 
    public partial class MainWindow : Window
    {

        const string RegistrySubKey = @"Software\eTax\Irc\101";
        Dictionary<string, string> Registries;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            string UserSID = WindowsIdentity.GetCurrent().User.Value;
            btnStart.IsEnabled = false;
            if (!IsRegistryExists(Registry.CurrentUser, "Software", "eTax"))
            {
                AddItemToListBox(this.lstLog, "Can't detect registry data, pleast install eTax software.");
                return;
            }
            try
            {
                GetPreviouseData();
                WqlEventQuery query = new WqlEventQuery("SELECT * FROM RegistryKeyChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath ='" + UserSID + string.Format(@"\{0}'", RegistrySubKey).Replace(@"\", @"\\"));
                ManagementEventWatcher watcher = new ManagementEventWatcher(query);
                watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
                watcher.Start();
            }
            catch (Exception ex)
            {
                AddItemToListBox(this.lstLog, ex.ToString());
            }
            btnStart.IsEnabled = true;
        }

        private void GetPreviouseData()
        {
            Registries = new Dictionary<string, string>();
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistrySubKey, false))
            {
                foreach (string name in key.GetValueNames().ToList())
                {
                    Registries.Add(name, key.GetValue(name).ToString());
                }
                key.Close();
            }
        }

        private void watcher_EventArrived(object sender, EventArrivedEventArgs e)
        {
            (sender as ManagementEventWatcher).Stop();
            ManagementBaseObject eventObject = e.NewEvent;
            CompareData();
        }

        private void CompareData()
        {
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistrySubKey, false))
            {
                foreach (string name in key.GetValueNames().ToList())
                {

                    if (!Registries.ContainsKey(name))
                    {
                        AddItemToListBox(this.lstLog, string.Format("New registry key created.\nKey Name:{0}Key Value:{1}", name, key.GetValue(name).ToString()));
                    }
                    else
                    {
                        string oldValue = Registries[name];
                        string newValue = key.GetValue(name).ToString();
                        if (oldValue != newValue)
                        {
                            AddItemToListBox(this.lstLog, string.Format("Registry key updated.\nKey Name:{0}\nOld Key Value:{1}\nNew Key Value:{2}", name, oldValue, newValue));
                        }
                    }
                }
                key.Close();
            }
        }
        private delegate void AddItemToListBoxDelegate(ListBox listBox, string data);

        private void AddItemToListBox(ListBox listBox, string data)
        {
            if (listBox.Dispatcher.CheckAccess())
            {
                listBox.Items.Add(data);
            }
            else
            {
                listBox.Dispatcher.Invoke(new AddItemToListBoxDelegate(AddItemToListBox), listBox, data);
            }
        }

        private bool IsRegistryExists(RegistryKey root, string subKey, string keyToCheck)
        {
            bool result;
            RegistryKey Reg = root.OpenSubKey(subKey, false);
            result = Reg.GetSubKeyNames().Contains(keyToCheck);
            return result;
        }
    }
}

MainWindow.xaml


<Window x:Class="DetectHKCU.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox Name="lstLog" Margin="5,40,12,12" />
        <Button Content="Start Detect" Height="23" HorizontalAlignment="Left" Margin="416,5,0,0" Name="btnStart" VerticalAlignment="Top" Width="75" Click="btnStart_Click" />
    </Grid>
</Window>

執行畫面:

 

 

Reference : 

Registry Event Classes

Asynchronous Registry Notification Using Strongly-typed WMI Classes in .NET

RegistryMonitor - a .NET wrapper class for RegNotifyChangeKeyValue