摘要:[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
執行畫面:
Reference :
Asynchronous Registry Notification Using Strongly-typed WMI Classes in .NET
RegistryMonitor - a .NET wrapper class for RegNotifyChangeKeyValue
<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>