Jump to content
Sign in to follow this  
Luigi

WRMF - Windows Registry Monitor Call Function

Recommended Posts

Luigi

I need improve the use of _WinAPI_RegNotifyChangeKeyValue and build this UDF to tracking many windows's registry keys.

It allows you add a function to change's of windows registry.

You can add many windows registry key's with function's associate.

If the function is not exist, they block function 'function.status' and not execute it more.

It is possible define a time's delay to prevent a function's re-execution.

You can help-me, rating about:

-UDF is write in AutoIt UDF standards;

-suggest best practices to improve code;

-alert bugs or errors.

-more... if you want...

BR, Luigi.

Example

#include <RegistryMonitor.au3>

Opt("MustDeclareVars", 1)

HotKeySet('^+{END}', '_quit') ; Ctrl + Shift + {END}

Local $reg1 = reg_monitor_add($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', BitOR($KEY_NOTIFY, $KEY_WOW64_64KEY), Default, 'ExampleFunctionA')
ConsoleWrite('reg1[ ' & $reg1 & ' ]' & @LF)

Local $reg2 = reg_monitor_add($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', $KEY_NOTIFY, Default, 'ExampleFunctionB')
ConsoleWrite('reg2[ ' & $reg2 & ' ]' & @LF)

Func ExampleFunctionA()
    ConsoleWrite('ExampleFunction[ SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall ]' & @LF)
EndFunc   ;==>ExampleFunctionA

Func ExampleFunctionB()
    ConsoleWrite('ExampleFunction[ SOFTWARE\Microsoft\Windows\CurrentVersion\Run ]' & @LF)
EndFunc   ;==>ExampleFunctionB

AdlibRegister('teste_one', 1000)
AdlibRegister('teste_two', 5000)
AdlibRegister('_quit', 8000)

While Sleep(100)

WEnd

Func teste_one()
    Local $hWrite = RegWrite('HKEY_LOCAL_MACHINE64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'TEST_KEY', 'REG_SZ', 'Hello this is a test')
    ConsoleWrite('$hWrite[ ' & $hWrite & ' ]' & @LF)
    Sleep(1000)
    Local $hRemove = RegDelete('HKEY_LOCAL_MACHINE64\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'TEST_KEY')
    ConsoleWrite('$hRemove[ ' & $hRemove & ' ]' & @LF)
    AdlibUnRegister('teste_one')
EndFunc   ;==>teste_one

Func teste_two()
    Local $hWrite = RegWrite('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 'TEST_KEY', 'REG_SZ', 'Hello this is a test')
    ConsoleWrite('$hWrite[ ' & $hWrite & ' ]' & @LF)
    Sleep(1000)
    Local $hRemove = RegDelete('HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run', 'TEST_KEY')
    ConsoleWrite('$hRemove[ ' & $hRemove & ' ]' & @LF)
    AdlibUnRegister('teste_two')
EndFunc   ;==>teste_two

Func _quit()
    Beep(1400, 200)
    Exit
EndFunc   ;==>_quit

RegistryMonitor.au3

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_AU3Check_Parameters= -q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
#Tidy_Parameters=/sf
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include-once
#include <APIRegConstants.au3>
#include <WinAPIDiag.au3>
#include <WinAPIReg.au3>

Opt('MustDeclareVars', 1)
; #INDEX# =======================================================================================================================
; Title .........: registry_monitor
; AutoIt Version : 3.3.12.0
; Description ...: Monitoring key's windows registry and associates a function this event
; Author(s) .....: HelpFile http://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_RegNotifyChangeKeyValue.htm
; Modified ......: Detefon
; ===============================================================================================================================

; #VARIABLES# ===================================================================================================================
Global $oEvents_RegistryMonitor = ObjCreate('Scripting.Dictionary')
$oEvents_RegistryMonitor.Comparemode = 1
; ===============================================================================================================================

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __reg_monitor_eval_key
; Description ...: Check if $iKey is a valid windows key
; Syntax.........: __reg_monitor_eval_key($iKey)
; Parameters ....: $iKey            - Integer. The value must be/represent a registry windows key
; Return values .: Boolean
; Author ........: Detefon
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __reg_monitor_eval_key($iKey)
    If ($iKey == $HKEY_CLASSES_ROOT) Or ($iKey == $HKEY_CURRENT_CONFIG) Or ($iKey == $HKEY_CURRENT_USER) Or ($iKey == $HKEY_LOCAL_MACHINE) Or ($iKey == $HKEY_USERS) Then Return 1
    Return 0
EndFunc   ;==>__reg_monitor_eval_key

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __reg_monitor_eval_subkey
; Description ...: Check if $sSubkey contains less of 32 terms
; Syntax.........: __reg_monitor_eval_subkey($sSubkey)
; Parameters ....: $sSubkey         - String. The value is a path's registry windows
; Return values .: Boolean
; Author ........: Detefon
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __reg_monitor_eval_subkey($sSubkey)
    Local $aSubkey = StringSplit($sSubkey, '\')
    If $aSubkey[0] >= 32 Then Return 0
    Return 1
EndFunc   ;==>__reg_monitor_eval_subkey

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __reg_monitor_eval_stop
; Description ...: Used when script is terminated, to close the opened handles (_WinAPI_RegCloseKey, _WinAPI_CloseHandle)
; Syntax.........: __reg_monitor_eval_stop()
; Parameters ....: none
; Return values .: none
; Author ........: Detefon
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func __reg_monitor_eval_stop()
    AdlibUnRegister('registry_monitor')
    For $each In $oEvents_RegistryMonitor
        ConsoleWrite('close key[ ' & $each & ' ] value[ ' & $oEvents_RegistryMonitor.Item($each).Item('handle') & ' ]' & @LF)
        If Not _WinAPI_RegCloseKey($oEvents_RegistryMonitor.Item($each).Item('handle')) Then ConsoleWrite('@error._WinAPI_RegCloseKey..........[ ' & _WinAPI_GetErrorMessage(@extended) & ' ]' & @LF)
        If Not _WinAPI_CloseHandle($oEvents_RegistryMonitor.Item($each).Item('main')) Then ConsoleWrite('@error._WinAPI_CloseHandle..........[ ' & _WinAPI_GetErrorMessage(@extended) & ' ]' & @LF)
    Next
EndFunc   ;==>__reg_monitor_eval_stop

; #FUNCTION# ====================================================================================================================
; Name...........: reg_monitor_add
; Description ...: Add a key's registro to monitoring and associate this to the function
; Syntax.........: reg_monitor_add($iKey = 0, $sSubkey = '', $iOpt = 0, $iDelay = 5000, $sFunction = '')
; Parameters ....: $iKey            - Integer. The value must be/represent a registry windows key
;                  $sSubkey         - String. The value is a path's registry windows
;                  $iOpt            - Integer. Positive. The value define a time in mileseconds to prevent function's re-execution.
;                                     Default value is 5.000 msec or 5 seconds
;                  $sFunction       - String. The name of function is called when event is happend
; Return values .: Handle's _WinAPI_RegOpenKey
; Author ........: Detefon
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func reg_monitor_add($iKey = 0, $sSubkey = '', $iOpt = 0, $iDelay = 5000, $sFunction = '')
    If $oEvents_RegistryMonitor.Exists($iKey & $sSubkey) Then Return SetError(1, 0, 1) ; prevent add function for same key

    Local $oTemp = ObjCreate('Scripting.Dictionary')
    $oTemp.Comparemode = 1

    If Not __reg_monitor_eval_key($iKey) Then Return SetError(1, 0, 2) ; check if $iKey is valid
    If Not __reg_monitor_eval_subkey($sSubkey) Or ($sSubkey == '') Then Return SetError(1, 0, 3) ; check if $sSubkey is valid
    $iOpt = Number($iOpt)
    If $iOpt < 0 Then $iOpt = Abs($iOpt)
    Local $hKey = _WinAPI_RegOpenKey($iKey, $sSubkey, $iOpt)
    If @error Then Return SetError(1, 0, _WinAPI_GetErrorMessage(@extended))

    If Not _WinAPI_RegQueryReflectionKey($hKey) Then Return SetError(1, 0, _WinAPI_GetErrorMessage(@extended))

    $oTemp.Add('main', _WinAPI_CreateEvent())
    If Not $oTemp.Item('main') Then Return SetError(1, 0, _WinAPI_GetErrorMessage(@extended))

    If Not _WinAPI_RegNotifyChangeKeyValue($hKey, $REG_NOTIFY_CHANGE_LAST_SET, 1, 1, $oTemp.Item('main')) Then
        If @error Then Return SetError(1, 0, _WinAPI_GetErrorMessage(@extended))
    EndIf

    If Not $sFunction Then Return SetError(1, 0, 4)
    $oTemp.Add('handle', $hKey)
    $oTemp.Add('function', $sFunction)
    $oTemp.Add('function.status', 1)
    $oTemp.Add('lasthit', 0)
    $oTemp.Add('delay', $iDelay)

    $oEvents_RegistryMonitor.Add($iKey & $sSubkey, $oTemp)
    AdlibRegister('registry_monitor', 100)
    OnAutoItExitRegister('__reg_monitor_eval_stop')
    Return $hKey
EndFunc   ;==>reg_monitor_add

; #FUNCTION# ====================================================================================================================
; Name...........: registry_monitor
; Description ...: Verify if happened a notify's windows registry
; Syntax.........: Called by reg_monitor_add
; Parameters ....: none
; Return values .: none
; Author ........: Detefon
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func registry_monitor()
    For $each In $oEvents_RegistryMonitor
        If Not _WinAPI_WaitForSingleObject($oEvents_RegistryMonitor.Item($each).Item('main'), 0) Then
            If _
                    $oEvents_RegistryMonitor.Item($each).Item('function.status') And _ ; if 'function.status' is valid, continue or not execute invalid function
                    (($oEvents_RegistryMonitor.Item($each).Item('lasthit') == 0) Or _ ; if 'lasthit' is 0, continue ('function' is never hited)
                    (TimerDiff($oEvents_RegistryMonitor.Item($each).Item('lasthit')) > ($oEvents_RegistryMonitor.Item($each).Item('delay')))) _ ; prevent reuse function in time less than delay time
                    Then
                $oEvents_RegistryMonitor.Item($each).Item('lasthit') = TimerInit() ; mark the last use time's function
                Call($oEvents_RegistryMonitor.Item($each).Item('function')) ; call the function
                If @error == 0xDEAD And @extended == 0xBEEF Then $oEvents_RegistryMonitor.Item($each).Item('function.status') = 0 ; if error, set 'function.status' equal 0
            EndIf
            If Not _WinAPI_RegNotifyChangeKeyValue($oEvents_RegistryMonitor.Item($each).Item('handle'), $REG_NOTIFY_CHANGE_LAST_SET, 0, 1, $oEvents_RegistryMonitor.Item($each).Item('main')) Then ExitLoop
        EndIf
    Next
EndFunc   ;==>registry_monitor
Edited by Luigi
  • Like 1

Visit my repository

Share this post


Link to post
Share on other sites
falcontechnics

First of all thank you for your efforts. I ask for your help with something. "Registry_monitor" function did not understand. Very simple example "reg_monitor_add" and "reg_monitor" function is able to show you the use of?

Local $reg1 = reg_monitor_add($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', BitOR($KEY_NOTIFY, $KEY_WOW64_64KEY), Default)

Local $reg2 = reg_monitor_add($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', $KEY_NOTIFY, Default)

Local $reg3 = reg_monitor_add($HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', BitOR($KEY_NOTIFY, $KEY_WOW64_64KEY), Default)

Share this post


Link to post
Share on other sites
falcontechnics

:) 

You're right. But I also want to take action until the monitor registry changes. You do not see my job this UDF ?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×