sl23 Posted Thursday at 09:34 PM Posted Thursday at 09:34 PM 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.
ioa747 Posted Thursday at 10:01 PM Posted Thursday at 10:01 PM (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 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. Consistency: Following a naming convention throughout a script or project promotes consistency, making it easier to follow the logic and structure of the code. 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. 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 Thursday at 11:31 PM by ioa747 I know that I know nothing
argumentum Posted Thursday at 11:00 PM Posted Thursday at 11:00 PM 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 ! 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 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
sl23 Posted yesterday at 08:31 AM Author Posted yesterday at 08:31 AM (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. 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? expandcollapse popup#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 22 hours ago by sl23
Nine Posted 20 hours ago Posted 20 hours ago 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). “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now