Jump to content

Recommended Posts

Posted

I've been reading the PDF again that I think I downloaded from the AutoIT site somewhere? It's called: Program on Windows Using FREE Tools by Jayme Fishman, 2015. Is there a newer version?

Anyway, onto my questions. I'll start with Variables and what I've noticed after reading up to the start of Chapter 5. I understand how variables are used, from learning Rainmeter coding, although different and simpler, it works pretty much the same. But what I'm seeing in the PDF differs from scripts I see.

For example there are two things that stick out:
1. Variables in the PDF are shown like this: 
 

$firstmessage = "Hello "
$secondmessage = "World"

MsgBox.... $firstmessage&$secondmessage

But in every script I looked at, variables are shown with another letter, like this: 
 

$aPreviousEntries
$aPreviousFiles
$hDirectory
$pBuffer
$iFilter

Is there a reason for this? Is it just simply a way of naming and linking variables to a specific script?

2. Every variable has "Global" before it, why is that? for example:
 

Global $aPreviousEntries = _GetRegistryEntries()
Global $aPreviousFiles = _FileListToArray($sFolderPath)
Global $hDirectory = FileOpen($sFolderPath, 0)
Global $pBuffer = DllStructCreate("byte[" & 1024 & "]")
Global $iFilter = $FILE_NOTIFY_CHANGE_FILE_NAME + $FILE_NOTIFY_CHANGE_DIR_NAME

I haven't seen any mention of Global in the PDF section on variables, so I'm wondering why it's there and it's purpose.

Thanks for your help.

Posted (edited)

Take a look Best_coding_practices.

Edit:
in the previous thread you said:
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.

But these are the questions you should be asking the AI, instead of asking him for the script. e.g.
 

Spoiler

But in every script I looked at, variables are shown with another letter, like this: 
 

$aPreviousEntries
$aPreviousFiles
$hDirectory
$pBuffer
$iFilter

Is there a reason for this? Is it just simply a way of naming and linking variables to a specific script?

 

GPT-4o mini:

📝 Variable Naming Conventions in Scripting

The use of specific prefixes in variable names, such as $a, $h, $p, and $i, is a common practice in programming and scripting languages. These prefixes often indicate the type or purpose of the variable, making the code more readable and maintainable. Here's a breakdown of what these prefixes typically represent:

📊 Common Prefixes and Their Meanings

Prefix Meaning Example
$a Array $aPreviousEntries
$h Hash or Dictionary $hDirectory
$p Parameter or Pointer $pBuffer
$i Integer $iFilter

🔍 Reasons for Using Prefixes

  1. Readability: Prefixes help developers quickly understand the type of data a variable holds, which can be especially useful in larger scripts or when collaborating with others.

  2. Consistency: Following a naming convention throughout a script or project promotes consistency, making it easier to follow the logic and structure of the code.

  3. Type Hinting: In dynamically typed languages, prefixes can serve as a form of type hinting, indicating what kind of operations are expected to be performed on the variable.

  4. Avoiding Conflicts: Using specific prefixes can help avoid naming conflicts, especially in larger codebases where many variables may be defined.

💡 Conclusion

Using prefixes in variable names is a helpful convention that enhances code clarity and organization. While it's not mandatory, adopting such practices can significantly improve the maintainability of your scripts. If you're working on a specific project, it might be beneficial to follow the established conventions used in that codebase.

 

 

Spoiler

Every variable has "Global" before it, why is that? for example:
 

Global $aPreviousEntries = _GetRegistryEntries()
Global $aPreviousFiles = _FileListToArray($sFolderPath)
Global $hDirectory = FileOpen($sFolderPath, 0)
Global $pBuffer = DllStructCreate("byte[" & 1024 & "]")
Global $iFilter = $FILE_NOTIFY_CHANGE_FILE_NAME + $FILE_NOTIFY_CHANGE_DIR_NAME
 

GPT-4o mini:
In programming, particularly in languages like AutoIt, the keyword Global is used to declare variables that can be accessed from anywhere within the script, not just within the local scope of a function or block. Here’s a breakdown of why you might see Global used before variable declarations:

📝 Purpose of Global Variables

🌍 Accessibility

  • Global Scope: Variables declared with Global can be accessed and modified from any function or part of the script. This is useful when you need to share data across different functions without passing them as parameters.

🔄 Persistence

  • Lifetime: Global variables persist for the duration of the program's execution. They retain their values between function calls, which is beneficial for maintaining state or configuration settings.

📊 Example Breakdown

Here’s a brief explanation of the variables you provided:

Variable Name Description
$aPreviousEntries Stores the result of the function _GetRegistryEntries(), likely holding registry data.
$aPreviousFiles Contains an array of files from the specified folder path, generated by _FileListToArray().
$hDirectory Holds a handle to the opened directory, obtained from FileOpen().
$pBuffer Represents a buffer created for data manipulation, defined by DllStructCreate().
$iFilter Combines constants for file change notifications, allowing the program to monitor specific events.

⚖️ Pros and Cons of Using Global Variables

Pros Cons
Easy access from anywhere in the code Can lead to unintended side effects if modified unexpectedly
Useful for maintaining state Makes debugging harder due to potential conflicts
Reduces the need for passing parameters Can increase memory usage if not managed properly

Using Global variables can simplify certain tasks, but it's essential to use them judiciously to avoid complications in larger codebases. Would you like to know more about best practices for using global variables?

 

Edited by ioa747

I know that I know nothing

Posted
1 hour ago, sl23 said:

I've been reading the PDF again that I think I downloaded from the AutoIT site somewhere? It's called: Program on Windows Using FREE Tools by Jayme Fishman, 2015. Is there a newer version?

There is the help file. If you install the full version of SciTE 4 AutoIt, pressing F1 on a word, will bring an explanation and an example script for you to play with.
It takes time but it'll be faster than you took to learn to walk, heck, that you took to crawl ! :lol:

You'd type FileOpen( in SciTE, place the cursor in the middle of the word and press F1. Same with Global, Local, and whatnot.
Now Global means global, for the whole script. Local if for inside a function, Local to itself.

Put the AI toy aside for a day and try the help file. You may just write the script in a day.
Am team @sl23 !, you can do it :cheer:

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

Posted (edited)

As argumentum suggested, I was trying to put aside AI. The trouble with AI, as is shown in @ioa747 post above, is that it gives a short essay for a simple question. A question much more elegantly answered by argumentum! Believe me, I have tried using AI for such questions, but it gets tiresome trying to sift through the short story of an answer every time in order to find a tiny bit of information.

I didn't know SCiTe could do that! I'll give it a go, but I have my kids this weekend, so may not be able to test it thoroughly until monday. Thanks for the tip. :D
Unlikely I'll be able to do it in a day! barely know my way around a single script yet!

Is my current script a good basis, or should I scrap that and start again?

#RequireAdmin

; Generated by DuckAI:
#include <File.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
#include <WinAPI.au3> ; Include the necessary library for WinAPI functions

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()
_ArrayDisplay($aPreviousEntries, "$aPreviousEntries") ; *** <---

Global $aPreviousFiles = _FileListToArray($sFolderPath)
_ArrayDisplay($aPreviousFiles, "$aPreviousFiles") ; *** <---

_LogChange("Starting Check for changes") ; *** <---

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

; Open the directory handle
Global $hDirectory = FileOpen($sFolderPath, 0)
Global $pBuffer = DllStructCreate("byte[" & 1024 & "]") ; Create a buffer for change notifications
Global $iFilter = $FILE_NOTIFY_CHANGE_FILE_NAME + $FILE_NOTIFY_CHANGE_DIR_NAME ; Set the filter for file and directory name changes

While True
    ; 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)
            ConsoleWrite("RegDelete(" & $sRegistryKey & ", " & $sNewEntry & ")" & @CRLF) ; *** <---

            _LogChange("Denied startup entry: " & $sNewEntry)
        EndIf
    EndIf

    ; Monitor the startup folder for changes
    Local $iBytesReturned = _WinAPI_ReadDirectoryChanges($hDirectory, $iFilter, $pBuffer, DllStructGetSize($pBuffer), 0)
    If $iBytesReturned > 0 Then
        ; Process the changes
        Local $sNewFile = DllStructGetData($pBuffer, 1) ; Get the new file name from the buffer
        _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)
            ConsoleWrite("FileDelete(" & $sFolderPath & "\" & $sNewFile & ")" & @CRLF) ; *** <---
            _LogChange("Denied file: " & $sNewFile)
        EndIf
    EndIf

    Sleep(5000) ; Check every 5 seconds
WEnd

; Close the directory handle when done
FileClose($hDirectory)

; 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)
    FileWrite($sLogFile, @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " - " & $sMessage)  ; *** <---
EndFunc

Thanks... :)

Edited by sl23
Posted

The part that checks for registry changes seems alright (untested).  The part that monitors the startup folder for changes is wrong,  Please take some time to study the example provided in the help file under _WinAPI_ReadDirectoryChanges.  $hDirectory must be obtained via _WinAPI_CreateFileEx, not thru FileOpen.   Like I already told you, the way you are using _WinAPI_ReadDirectoryChanges, is a blocking function.  It will not return unless there is a change in the directory (so it will not continue to check the registry part).

Most beginner programmers "forget" to check for @error (or something alike) after executing a function.  They tend to believe that AutoIt will inform them if a function is badly use.  Not the case, you should always put some error handling (more importantly when you start a new project). 

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...