Jump to content

Recommended Posts

Posted (edited)

Hi there...

I have used a small app called StartupMonitor for around 15 years to monitor the registry and system folders for any app that tries to create entries here without users knowledge. I've found it invaluable for stopping many programs from doing so. The downside is that it is 32bit and really old, 2010ish? (Just checked the EXE properties, the Last Modified date is actually 20 May 2000!!! 😨)

So, to help learn a little AutoIt, starting with a small project, I'm trying to use DuckAI to help create a script to do the same. It has come up with this after adding many descriptions and such to the conversation:

#include <File.au3>
#include <MsgBoxConstants.au3>
#include <Registry.au3>

Global $sRegistryKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"
Global $sFolderPath = @StartupDir & "\*"
Global $aPreviousEntries = _GetRegistryEntries($sRegistryKey)
Global $aPreviousFiles = _FileListToArray($sFolderPath)
Global $sLogFile = @ScriptDir & "\startup_monitor_log.txt"

; Delete existing log file if it exists
If FileExists($sLogFile) Then
    FileDelete($sLogFile)
EndIf

While True
    Sleep(5000) ; Check every 5 seconds

    ; Check for registry changes
    Local $aCurrentEntries = _GetRegistryEntries($sRegistryKey)
    If Not _ArrayCompare($aPreviousEntries, $aCurrentEntries) Then
        $aPreviousEntries = $aCurrentEntries
        Local $sNewEntry = _GetNewEntry($aPreviousEntries, $aCurrentEntries)
        _LogChange("A new startup entry has been detected: " & $sNewEntry)
        
        If MsgBox($MB_YESNO, "Startup Entry Detected", "A new startup entry has been detected: " & $sNewEntry & ". Do you want to allow it?") = $IDNO Then
            ; Remove the unauthorized entry
            RegDelete($sRegistryKey, $sNewEntry)
            _LogChange("Denied startup entry: " & $sNewEntry)
        EndIf
    EndIf

    ; Check for new files in the startup folder
    Local $aCurrentFiles = _FileListToArray($sFolderPath)
    If Not _ArrayCompare($aPreviousFiles, $aCurrentFiles) Then
        $aPreviousFiles = $aCurrentFiles
        Local $sNewFile = _GetNewFile($aPreviousFiles, $aCurrentFiles)
        _LogChange("A new file has been detected in the startup folder: " & $sNewFile)
        
        If MsgBox($MB_YESNO, "File Detected", "A new file has been detected in the startup folder: " & $sNewFile & ". Do you want to allow it?") = $IDNO Then
            ; Remove the unauthorized file
            FileDelete($sFolderPath & "\" & $sNewFile)
            _LogChange("Denied file: " & $sNewFile)
        EndIf
    EndIf
WEnd

Func _GetRegistryEntries($sKey)
    Local $aEntries[1] = [""]
    Local $hKey = RegOpenKey($sKey)
    If Not @error Then
        Local $iIndex = 0
        While True
            Local $sValue = RegEnumVal($hKey, $iIndex)
            If @error Then ExitLoop
            $aEntries[$iIndex + 1] = $sValue
            $iIndex += 1
            ReDim $aEntries[$iIndex + 1]
        WEnd
        RegCloseKey($hKey)
    EndIf
    Return $aEntries
EndFunc

Func _GetNewEntry($aOldEntries, $aNewEntries)
    For $i = 1 To UBound($aNewEntries) - 1
        If Not _ArraySearch($aOldEntries, $aNewEntries[$i]) Then
            Return $aNewEntries[$i]
        EndIf
    Next
    Return ""
EndFunc

Func _GetNewFile($aOldFiles, $aNewFiles)
    For $i = 1 To UBound($aNewFiles) - 1
        If Not _ArraySearch($aOldFiles, $aNewFiles[$i]) Then
            Return $aNewFiles[$i]
        EndIf
    Next
    Return ""
EndFunc

Func _LogChange($sMessage)
    FileWriteLine($sLogFile, @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " - " & $sMessage)
EndFunc

I'm using ISN AutoIT Studio to check the script, and it's giving an error:
D:\pathtoapp\ISN_AutoIt_Studio\Projects\StartupMonitor64\StartupMonitor64.au3 (14) : ==> Error opening the file.: 
#include <Registry.au3> 

The file doesn't exist. Should it, or is this used in an older version of AutoIT? I am using v3.3.16.1

Also, looking at the posted code, it was appearing in red after the line: _LogChange("Denied file: " & $sNewFile) does that mean it's incorrect?

Thanks for your help.

PS: I know using AI is probably not very much liked here, but I have tried learning AutoIT in a few different ways, but my ADHD/autism makes it difficult.

Edited by sl23
Posted (edited)
2 hours ago, sl23 said:

PS: I know using AI is probably not very much liked here, but I have tried learning AutoIT in a few different ways, but my ADHD/autism makes it difficult.

Ok, from one with learning disabilities atypical brain to another :)
I love AI. Is the best thing since fire to warm up a room.
The problem at times with AI is that can't tell a rope from shoelaces, and shoes from sandals, or... count fingers in a hand.
In the case of fire to warm a room, AI burns the house down because you're chatting with some form of intelligence that for now, does not reason. Is just a chatter box.

The solution for AI coding is going agentic and let it learn from trial and error, and that, ..that's not there for AutoIt yet, unless you run your own in your own hardware and let it learn.

So to be clear, the problem is that in this case, there is no "_GetRegistryEntries() " to be found, anywhere. And these AI tend to mis-remember training. After all, assigning a value to a word, and match words that way, ...is a miracle that LLMs work at all.

So no, noting wrong with AI, just don't believe it until you see running code, and to do that you ( or someone ) have to teach it, guide it, baby it, until it is proficient.

PS: am yet to make a set up to have AI coding for me :( 

Edited by argumentum
English

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)
2 hours ago, sl23 said:

monitor the registry and system folders for any app that tries to create entries

Take a look at: _WinAPI_RegNotifyChangeKeyValue() ; Notifies the caller about changes to the attributes or contents of a specified registry key
for the registry changes, and for folder changes: _WinAPI_ReadDirectoryChanges() ; Retrieves information that describes the changes within the specified directory

Edited by argumentum
more

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

In my "About me" page, there are IPC ( Inter-process communication ) examples ( search the page for IPC ) and, you will need that if you use the examples because _WinAPI_ReadDirectoryChanges() is a blocking function as is written and that will wait forever until there is an event. With IPC you can send to another script, "your main script" the changes that it reports and your main script then decides what to do with that info.

Don't let the "sounds complicated" scare you. Everything is complicated when we are not familiar with it.

PS: When you're finally done with it, share it here. Something like that, just running in the background, sounds good to have :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Thank you for your replies.

My trouble is actually the basics of programming. But more than that, I struggle to read. I can read fine, but sticking to reading a whole PDF about programming is almost insurmountable. If I do it in one go, it wears me down and melts my brain. If I break it up into smaller chunks, I get fed up after a couple days! I can't win. I really like AutoIT and want to learn, but think it's just too much. I know that once I understand the basics, it'll slot together and I'll mostly be fine. But it's that "piecing it all together" part that I really struggle with. That's why I tried the AI route. I guessed it wouldn't work, but no harm trying eh? :)

I'll check those links out, see if I can make anything out of it. Thanks again, appreciate your help.

Posted

...I never, to this day, memorized the multiplication tables 😅
The links I posted I had to look for it because my memory is ... meh :D 

I too learned AutoIt by modifying examples because after reading too long I: (1) get lost and (2) go to sleep, drained. Taking a "siesta" every 45 minutes is not strange for me when I have to code for a living. Add dyslexia to it and, .... God must have a great sense of humor :lol:

If you're patient with yourself and reality in it's totality, ( promote yourself as a guru :P ) you'll be able to get this coding thing enough to do what you wished you had :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Thanks for your confidence! I always thought it was just me, being this way, now the reading thing makes sense, that's how I have always been too! Sucks when you wanna learn something!! Btw, I never could remember them either :D

Posted
4 hours ago, sl23 said:

I have used a small app called StartupMonitor for around 15 years to monitor the registry and system folders for any app that tries to create entries here without users knowledge. I've found it invaluable for stopping many programs from doing so. The downside is that it is 32bit and really old, 2010ish? (Just checked the EXE properties, the Last Modified date is actually 20 May 2000!!! 😨)

alternative solution ? :unsure:
https://learn.microsoft.com/en-us/sysinternals/downloads/autoruns

I know that I know nothing

Posted

Thank you, I have that, but it isn't the same. StartupMonitor actually runs in the background and if something is added to the registry, like Microsoft Edge for example, it instantly alerts you and asks if you want to allow it or not. AutoRuns can't do that. Also, StartupMonitor is only a tiny EXE of 84.00KB.

Posted (edited)

I may have a working script. But I'm not quite sure how to manually add start up entries?

This script has been running error free for over 5 minutes:

#include <File.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>

Global $sRegistryKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"
Global $sFolderPath = @StartupDir ; Use the startup directory directly
Global $sLogFile = @ScriptDir & "\startup_monitor_log.txt"

; Delete existing log file if it exists
If FileExists($sLogFile) Then
    FileDelete($sLogFile)
EndIf

; Initialize previous entries and files
Global $aPreviousEntries = _GetRegistryEntries()
Global $aPreviousFiles = _FileListToArray($sFolderPath)

While True
    Sleep(5000) ; Check every 5 seconds

    ; Check for registry changes
    Local $aCurrentEntries = _GetRegistryEntries()
    If Not _ArraysEqual($aPreviousEntries, $aCurrentEntries) Then
        $aPreviousEntries = $aCurrentEntries
        Local $sNewEntry = _GetNewEntry($aPreviousEntries, $aCurrentEntries)
        _LogChange("A new startup entry has been detected: " & $sNewEntry)
        
        If MsgBox($MB_YESNO, "Startup Entry Detected", "A new startup entry has been detected: " & $sNewEntry & ". Do you want to allow it?") = $IDNO Then
            ; Remove the unauthorized entry
            RegDelete($sRegistryKey, $sNewEntry)
            _LogChange("Denied startup entry: " & $sNewEntry)
        EndIf
    EndIf

    ; Check for new files in the startup folder
    Local $aCurrentFiles = _FileListToArray($sFolderPath)
    If Not _ArraysEqual($aPreviousFiles, $aCurrentFiles) Then
        $aPreviousFiles = $aCurrentFiles
        Local $sNewFile = _GetNewFile($aPreviousFiles, $aCurrentFiles)
        _LogChange("A new file has been detected in the startup folder: " & $sNewFile)
        
        If MsgBox($MB_YESNO, "File Detected", "A new file has been detected in the startup folder: " & $sNewFile & ". Do you want to allow it?") = $IDNO Then
            ; Remove the unauthorized file
            FileDelete($sFolderPath & "\" & $sNewFile)
            _LogChange("Denied file: " & $sNewFile)
        EndIf
    EndIf
WEnd

; Function to get registry entries
Func _GetRegistryEntries()
    Local $aEntries[0] ; Start with an empty array
    Local $iIndex = 0

    ; Read all values from the registry key
    While True
        Local $sValue = RegEnumVal($sRegistryKey, $iIndex)
        If @error Then ExitLoop ; Exit loop if no more values
        ReDim $aEntries[$iIndex + 1] ; Resize array to hold new entry
        $aEntries[$iIndex] = $sValue ; Store the entry
        $iIndex += 1
    WEnd
    Return $aEntries ; Return the array of entries
EndFunc

; Function to compare two arrays
Func _ArraysEqual($aArray1, $aArray2)
    If UBound($aArray1) <> UBound($aArray2) Then Return False
    For $i = 0 To UBound($aArray1) - 1
        If $aArray1[$i] <> $aArray2[$i] Then Return False
    Next
    Return True
EndFunc

; Function to get the new entry
Func _GetNewEntry($aOldEntries, $aNewEntries)
    For $i = 0 To UBound($aNewEntries) - 1
        If Not _ArraySearch($aOldEntries, $aNewEntries[$i]) Then
            Return $aNewEntries[$i]
        EndIf
    Next
    Return ""
EndFunc

; Function to get the new file
Func _GetNewFile($aOldFiles, $aNewFiles)
    For $i = 0 To UBound($aNewFiles) - 1
        If Not _ArraySearch($aOldFiles, $aNewFiles[$i]) Then
            Return $aNewFiles[$i]
        EndIf
    Next
    Return ""
EndFunc

; Function to log changes
Func _LogChange($sMessage)
    FileWriteLine($sLogFile, @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " - " & $sMessage)
EndFunc

Unlikely it is working as desired though?

 

EDIT: I have a question but unsure if it is ok to ask here, or should I get this info somewhere else, seeing as this is primarily a coding site, not a support site:
I need to know all the possible startup locations from the registry.
Actually a second more related question:
Can AutoIT be used to also monitor the Task Scheduler too? I assume that is just another registry entry too? An example is certain apps seem to like adding Tasks without my knowledge or consent.

Thanks for any help.

Edited by sl23
Posted

If memory serves AutoRuns will give you/show you, the paths it uses, either registry or folder. You can use that info and add it to your script. The way you do it is by typing:
- Thank you, that was great !, now can you add these ...
And it will likely add them to the script :)

Ok, there is push and pull.
By that I mean that you can ask every X minutes or seconds "are we there yet" or, tell the system to inform you once you're there.
The links I gave you are for getting the system to tell you and is lighter on the PC and far more responsive.
What you are doing ( the way is coded ) is searching very 5 seconds but !, you have a working script.

I didn't run it but looks functional. Is a great start. :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)
25 minutes ago, sl23 said:

Actually a second more related question:
Can AutoIT be used to also monitor the Task Scheduler too?

Yes and yes ? :P
I know that TaskSched saves files as XML on the drive, ..at least is how I import them. Look it up.

25 minutes ago, sl23 said:

..or should I get this info somewhere else, seeing as this is primarily a coding site, not a support site

..is a forum and we chat. Now coding solutions for people asking for one, no. ...not always. It depends. If someone feels like it then yes, that and more too.
On the other hand we are here to help each other learn, and giving anyone a running script does not teach anything.

So, ask along and I'll personally send you to ....  google :lol:

Have your fun, am having fun in this post  :gathering:

Edited by argumentum
English ?

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Ah thanks. I checked those links, but am not at that level of understanding yet I'm afraid!

So, yeah, it's running, but isn't detecting anything. I will definitely use your method if better, I checked the original StartupMonitor resources, using 0.5MB of RAM. My script is using nearly 16MB!!! So I think it's safe to say that's a no-no! lol

Posted
1 minute ago, sl23 said:

So, yeah, it's running, but isn't detecting anything. I will definitely use your method if better,

Either method, if nothing changed, ..nothing changed. Then you have running as user and running as admin. Some stuff only works if the process ( the exe ) is running with admin rights

#RequireAdmin
; .. the rest of your code

as otherwise the process will not receive or be able to read those paths and/or registry values.

Welcome to programming :tv_horror:  :lol:

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

:tv_happy: Glad you're enjoying the show! :)

I don't expect to be spoon fed. I learnt Rainmeter code myself, with help from the great people on the forum, though still no expert.  And still don't understand some of the programming basics. But I learnt what variables are and several other simple things. But much still to learn. I keep dabbling now and then as It's good fun and if there's functional things like this within my realm of possibility, I'll try and achieve it. Hopefully, I can learn enough to get this working and then try bringing X-Launcher fully up to date! :)

Posted
1 minute ago, sl23 said:

the script needs to be run as admin? Didn't even think of that.

..and at times even higher. But am busy with other things and can't jump into coding along with you to troubleshoot it 🤷‍♂️
But I have to admit that you're getting the hang of it quite good, and fast ( AI or not ) :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Haha, I haven't a clue what I'm doing, it's all guess work with AI helping me!

I've got quite a lot of suggestions from AI that aren't helping at all, like adding logging info and such, but no logs are being created. But, but, I got a window to show! :hyper:

Posted (edited)
4 hours ago, sl23 said:

I may have a working script. But I'm not quite sure how to manually add start up entries?

This script has been running error free for over 5 minutes:


put an _ArrayDisplay to see the results (Common debugging practice)

; Initialize previous entries and files
Global $aPreviousEntries = _GetRegistryEntries()
_ArrayDisplay($aPreviousEntries, "$aPreviousEntries")

 

Edit:
and a friendly tip
replace the real deletes with virtual ones e.g.

ConsoleWrite("RegDelete(" & $sRegistryKey & ", " & $sNewEntry & ")" & @CRLF)
; RegDelete($sRegistryKey, $sNewEntry)
...
ConsoleWrite("FileDelete(" & $sFolderPath & "\" & $sNewFile & ")" & @CRLF)
; FileDelete($sFolderPath & "\" & $sNewFile)

until you are sure it will delete the right files

Otherwise, you risk deleting everything except what you don't want.

 

 

 

Edited by ioa747
Edit

I know that I know nothing

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...