Получить уведомление, когда значение RegistryKey было изменено

Мне нужно уведомление, когда конкретный RegistryKey в HKEY_CURRENT_USER изменяется. До сих пор я пробовал это через WMI безуспешно:

var query = new WqlEventQuery(string.Format(
"SELECT * FROM RegistryKeyChangeEvent WHERE Hive='{0}' AND KeyPath='{1}' AND ValueName='{2}'",
                hive, keyPath.Replace("\\","\\\\"), valueName));
_watcher = new ManagementEventWatcher(query);
_watcher.Scope.Path.NamespacePath = @"root\default";
_watcher.EventArrived += (sender, args) => KeyValueChanged();
_watcher.Start();

(Ошибка "Не найдено")

Мой второй подход заключался в использовании WBEM Scripting COM component с намерением перенести пример из http://msdn.microsoft.com/en-us/library/aa393042(VS.85).aspx на С#, но я не нашел примеров использования для WBEM COM в С#

Я нашел это http://www.codeproject.com/KB/system/registrymonitor.aspx, но он не соответствовал моим потребностям, так как этот класс отслеживает только весь ключ, и мне нужно только уведомление, когда конкретное значение (указанное с помощью ValueName в приведенных выше примерах) изменяется.

РЕДАКТИРОВАТЬ: Если вы измените Hive на HKEY_CURRENT_USER в примере msdn vbscript, он перестанет работать. Мне ничего не удалось найти об этом поведении, но ссылка 2003 года

EDIT2: изменения в ульях HKEY_CLASSES_ROOT и HKEY_CURRENT_USER не поддерживаются RegistryEvent или производными от него классами, такими как RegistryValueChangeEvent. (MSDN )


person RoXX    schedule 20.11.2010    source источник
comment
Я считаю, что вы можете изменить код проекта кода, чтобы использовать несколько дескрипторов/мониторов ожидания, чтобы все меньше сообщали, какой ключ был изменен. Однако я не уверен, каковы последствия использования n мониторов — вроде не так уж и плохо: blogs.technet.com/b/markrussinovich/archive/2009/09/29/ :-)   -  person    schedule 20.11.2010


Ответы (2)


Наконец-то я решил проблему и заставил работать версию запроса WMI:

var currentUser = WindowsIdentity.GetCurrent();
var query = new WqlEventQuery(string.Format(
"SELECT * FROM RegistryValueChangeEvent WHERE Hive='HKEY_USERS' AND KeyPath='{0}\\\\{1}' AND ValueName='{2}'",
currentUser.User.Value, keyPath.Replace("\\","\\\\"), valueName));
_watcher = new ManagementEventWatcher(query);
_watcher.EventArrived += (sender, args) => KeyValueChanged();
_watcher.Start();

Я нашел этот «взлом» по адресу http://www.codeproject.com/Messages/2844468/Monitoring-HKEY_CURRENT_USER.aspx

person RoXX    schedule 20.11.2010

Загрузил в pastbin хороший класс, который это делает. Надеюсь, это соответствует вашим потребностям.

http://www.csharp.pastebin.com/0reFh6v2

person byte_slave    schedule 20.11.2010
comment
Это похоже на класс RegistryMonitor из codeproject, который, как я уже упоминал в своем вопросе, не соответствует моим потребностям, потому что он уведомляет об изменении какого-либо значения в ключе, а не только об изменении конкретного... - person RoXX; 20.11.2010
comment
@RoXX, разве вы не можете просто перебрать значения, которые изменились, и посмотреть, изменилось ли то, что вы хотели? - person Moo-Juice; 20.11.2010
comment
Я мог бы, но есть много других значений, которые меняются, и было бы неплохо, если бы я мог отфильтровать их на более низком уровне, например, с запросом wmi, я ищу более приятное решение. - person RoXX; 20.11.2010
comment
Я снова просмотрел класс codeproject, и он не предоставляет никакой информации о том, какое значение ValueName изменилось в его событии, поэтому мне пришлось бы вручную проверять, изменился ли мой ключ, и это имело бы огромное влияние на производительность, что делает этот подход бесполезным. для меня - person RoXX; 20.11.2010