Jump to content

Trong

Active Members
  • Posts

    1,118
  • Joined

  • Days Won

    2

Everything posted by Trong

  1. Version 1.0.0

    28 downloads

    ImageSearchDLL & UDF - The Complete Guide Author: Dao Van Trong - TRONG.PRO Last Updated: 2025-08-04 1. Introduction ImageSearchDLL is a high-performance image recognition solution for Windows, designed to be both powerful for modern systems and compatible with legacy environments. The project consists of three distinct C++ DLL versions and a smart AutoIt User-Defined Function (UDF) that automatically selects the best DLL for the job. This architecture ensures that your scripts get the best possible performance on modern systems (like Windows 10/11) while maintaining full functionality on older systems like Windows 7 and even Windows XP. New is the Special Feature is the function of searching for pictures in pictures! 2. How it Works: The Smart UDF Loader The core of this project is the AutoIt UDF (ImageSearch_UDF.au3). You don’t need to worry about which DLL to use; the _ImageSearch_Startup() function handles it all automatically. Here is the loading logic: On Modern OS (Windows 8, 10, 11+): It first looks for the Modern DLL (ImageSearch_x64.dll or ImageSearch_x86.dll). If not found, it falls back to the Windows 7 DLL. If neither is found, it deploys the Embedded XP DLL. On Windows 7: It prioritizes the Windows 7 DLL (ImageSearch_Win7_x64.dll or ImageSearch_Win7_x86.dll). If not found, it deploys the Embedded XP DLL. On Windows XP: It exclusively uses the Embedded XP DLL, which is extracted from a HEX string inside the UDF. This ensures maximum performance where possible and maximum compatibility where needed. 3. The DLL Versions Explained There are three distinct DLLs, each compiled for a specific purpose. Feature Modern (Win10+) Windows 7 Legacy (XP) Target OS Windows 8, 10, 11+ Windows 7 SP1+ Windows XP SP3+ Filename ImageSearch_x64.dll ImageSearch_x86.dll ImageSearch_Win7_x64.dll ImageSearch_Win7_x86.dll Embedded in UDF Compiler VS 2022 (C++23) VS 2017+ (C++14) VS 2010 (C++03) Performance Excellent Very Good Good AVX2 Support Yes (auto-detected) Yes (auto-detected) No Thread-Safety Yes (thread_local) Yes (thread_local) No (static buffer) Best Use Case High-performance automation on modern PCs. Scripts that need to run reliably on both modern systems and Windows 7 machines. Maximum compatibility for legacy systems or when no external DLLs are provided. 4. Getting Started (For AutoIt Users) Using the library is simple. Just make sure your files are organized correctly. File Structure For the best experience, place the DLL files in the same directory as your script and the UDF. /YourScriptFolder/ | |-- MyScript.au3 |-- ImageSearch_UDF.au3 |-- ImageSearch_x64.dll (Modern DLL for 64-bit) |-- ImageSearch_x86.dll (Modern DLL for 32-bit) |-- ImageSearch_Win7_x64.dll (Win7 DLL for 64-bit) |-- ImageSearch_Win7_x86.dll (Win7 DLL for 32-bit) | /-- images/ |-- button.png Quick Start Example Here is a basic AutoIt script to get you started. #include "ImageSearch_UDF.au3" ; 1. Initialize the library. The UDF will automatically load the best DLL. _ImageSearch_Startup() If @error Then MsgBox(16, "Error", "ImageSearch DLL could not be initialized. Exiting.") Exit EndIf ; You can check which version was loaded ConsoleWrite(">> Loaded DLL Version: " & _ImageSearch_GetVersion() & @CRLF) ConsoleWrite(">> System Info: " & _ImageSearch_GetSysInfo() & @CRLF) ; 2. Perform a search for an image on the entire screen. Local $sImagePath = @ScriptDir & "\images\button.png" Local $aResult = _ImageSearch($sImagePath) ; 3. Process the results. The result is ALWAYS a 2D array. If $aResult[0][0] > 0 Then ConsoleWrite("Found " & $aResult[0][0] & " match(es)!" & @CRLF) ; Loop through each match For $i = 1 To $aResult[0][0] Local $iX = $aResult[$i][1] ; X coordinate Local $iY = $aResult[$i][2] ; Y coordinate ConsoleWrite("Match #" & $i & " found at: " & $iX & ", " & $iY & @CRLF) MouseMove($iX, $iY, 20) Sleep(1000) Next Else ConsoleWrite("Image not found." & @CRLF) EndIf ; 4. Shutdown is handled automatically when the script exits. No need to call _ImageSearch_Shutdown(). 5. Full API Reference Main Functions _ImageSearch_Area(…): The main function with all available options. _ImageSearch(…): A simplified wrapper for searching the entire screen. _ImageInImageSearch_Area(…): Searches for an image within another image file. Common Parameters Parameter Description Default $sImageFile Path to the image(s). Use | to search for multiple images. $iLeft, $iTop, $iRight, $iBottom The coordinates of the search area. Entire Screen $iTolerance Color tolerance (0-255). Higher values allow for more variation. 10 $iTransparent A color in 0xRRGGBB format to be ignored during the search. -1 (disabled) $iMultiResults The maximum number of results to return. 1 $iCenterPos 1 returns the center coordinates; 0 returns the top-left. 1 $fMinScale, $fMaxScale Minimum and maximum scaling factor (e.g., 0.8 for 80%). 1.0 $fScaleStep The increment between scales (e.g., 0.1 for 10% steps). 0.1 $iFindAllOccurrences 1 finds all matches; 0 stops after the first. 0 $iUseCache 1 enables the file-based location cache; 0 disables it. 1 $iDisableAVX2 1 disables AVX2 optimization (for debugging). 0 Return Value All search functions return a 2D array. $aResult[0][0]: Contains the number of matches found. For each match $i (from 1 to $aResult[0][0]): aResult[aResult[i][1]: X coordinate aResult[aResult[i][2]: Y coordinate aResult[aResult[i][3]: Width of the found image aResult[aResult[i][4]: Height of the found image Utility Functions _ImageSearch_GetVersion(): Returns the version string of the currently loaded DLL. _ImageSearch_GetSysInfo(): Returns system info from the DLL (AVX2 support, screen resolution). _ImageSearch_ClearCache(): Deletes all cache files from the temp directory.
  2. Will the normal program check the time zone regularly? Anyway I will add and run this code in the time function! Thank you.
  3. I have a problem when getting the time to process (with @HOUR @MIN @SEC macros) when changing the time zone, the system time also changes but the macro time is not updated according to the system time. Is this a serious bug of autoit?
  4. I haven't tried it yet but you can try this suggestion from AI: You can disable Alt + F4 in an AutoIt GUI using two primary methods. The most recommended approach is using GUISetOnEvent because it handles all standard window-closing actions. ## Method 1: Using GUISetOnEvent (Recommended) This is the best practice because it disables not only Alt + F4 but also the "X" button on the title bar and other standard window-closing methods. This gives you complete control over when the window is allowed to close. How it works: You register a function to handle the window's close event ($GUI_EVENT_CLOSE). When the user tries to close the GUI, your function is called instead of the default action (closing the window). If your function does nothing or simply Returns, the window will not close. Example: #include <GUIConstantsEx.au3> ; Create a simple GUI window $hGUI = GUICreate("Window that can't be closed by Alt+F4", 400, 300) ; Set a function to handle the close event. ; When the user presses Alt+F4 or the X button, the "onClose" function will be called. GUISetOnEvent($GUI_EVENT_CLOSE, "onClose") GUISetState(@SW_SHOW, $hGUI) ; Main loop to keep the program running While 1 Sleep(100) WEnd ; This function will be called on a close event Func onClose() ; You can put a message here to inform the user MsgBox(48, "Notice", "Alt + F4 has been disabled!") ; Since we don't call Exit() or GUIDelete(), ; the window will not close. Just returning is enough. Return EndFunc ## Method 2: Using HotKeySet This method specifically blocks only the Alt + F4 key combination. The user can still close the window by clicking the "X" button. This is useful if you only want to disable that specific shortcut. How it works: You register a hotkey for the !{F4} combination (the ! represents the Alt key). When this key combination is pressed, AutoIt calls the function you specified instead of performing the default operating system action. Example: #include <GUIConstantsEx.au3> ; Set a hotkey for Alt+F4, which will call the "doNothing" function when pressed HotKeySet("!{F4}", "doNothing") ; Create a GUI window $hGUI = GUICreate("Only Alt+F4 is disabled", 400, 300) $hLabel = GUICtrlCreateLabel("You can still close this window with the X button.", 30, 130, 340, 20) GUISetState(@SW_SHOW, $hGUI) ; Main loop While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ; This event still works when the user presses the X button ExitLoop EndSwitch WEnd ; An empty function to "catch" the Alt+F4 keypress and do nothing Func doNothing() ; No code here, so nothing happens when Alt+F4 is pressed EndFunc ## Summary Method Pros Cons When to Use GUISetOnEvent Comprehensive: Blocks all standard ways to close a window (Alt+F4, X button, etc.). Cannot distinguish if the user used Alt+F4 or the X button. When you want to prevent the user from closing the window through any normal means. This is the recommended choice. HotKeySet Specific: Only blocks the Alt + F4 key combination. The user can still close the window in other ways. When you only want to disable the Alt+F4 shortcut but still allow closing via the X button.
  5. I want to share a framework that I am using in my "Taskbar Program" project. ; =============================================================================================================================== ; SCRIPT: Controller-Worker-Task Manager Framework ; AUTHOR: Dao Van Trong - TRONG.PRO ; VERSION: 4.0 (Optimized, INI-driven, Tray-Only) ; DESCRIPTION: This script implements a robust Controller-Worker-Task architecture for running background processes. ; It is designed to be a flexible framework for automation tasks. ; ; ARCHITECTURE: ; - Controller: The main process that runs persistently. It has no GUI and is controlled entirely via a system tray icon. ; Its responsibilities include: ; 1. Reading the configuration from 'Configs.ini'. ; 2. Creating and managing the tray menu. ; 3. Starting, stopping, and monitoring Worker processes. ; 4. Launching one-shot Task processes. ; 5. Automatically reloading the configuration when 'Configs.ini' is modified. ; ; - Workers: Long-running background processes that perform recurring tasks (e.g., monitoring, syncing). ; They are started and stopped by the Controller and run completely hidden. ; Each worker monitors the Controller and will self-terminate if the Controller exits. ; ; - Tasks: Short-lived background processes that perform a single, one-shot action (e.g., generate a report). ; They can be configured to run exclusively (locking all other tasks) or concurrently. ; They can also be configured to run as a separate sub-process or directly within the Controller's process. ; ; HOW IT WORKS: ; - IPC (Inter-Process Communication): Communication between the Controller and Workers is handled via the Windows Registry. ; The Controller writes a signal to a specific registry key to gracefully shut down a Worker. ; - Asynchronous Operations: All monitoring (process status, config file changes) and Worker functions are handled ; asynchronously using AdlibRegister, ensuring the Controller remains responsive. ; - Configuration: All Workers and Tasks are defined in the master arrays within this script, but they are enabled, ; disabled, and configured via an external 'Configs.ini' file. This allows for easy customization without ; modifying the source code. ; - Logging: The script generates a detailed log file ('manager.log') in the same directory, recording all major ; events like startup, shutdown, worker status changes, and errors. ; =============================================================================================================================== #include <TrayConstants.au3> #include <Array.au3> #include <File.au3> #include <FileConstants.au3> ; =============================================================================================================================== ; --- GLOBAL CONSTANTS AND VARIABLES ; =============================================================================================================================== ; --- Settings --- Global Const $g_sConfigFile = @ScriptDir & "\Configs.ini" Global Const $g_sLogFile = @ScriptDir & "\Manager.log" Global $g_sAppName = "Controller-Worker-Task Manager" Global $g_iCheckConfigInterval = 10000 Global $g_sLastConfigModDate = "" ; --- Registry & IPC --- Global Const $g_sRegBase = "HKCU\Software\ControllerWorkerApp" Global Const $g_iAdlibCheckInterval = 1000 Global Const $g_iGracefulShutdownTimeout = 3000 ; --- Status Constants for internal logic --- Global Const $STATUS_STOPPED = 0, $STATUS_RUNNING = 1, $STATUS_ERROR = 2 ; --- Task Execution Mode & Type Constants --- Global Const $TASK_MODE_EXCLUSIVE = 0, $TASK_MODE_CONCURRENT = 1 Global Const $TASK_RUN_TYPE_SUBAPP = 0, $TASK_RUN_TYPE_DIRECT = 1 ; --- Menu Type Constants --- Global Const $MENU_TYPE_MAIN = 0, $MENU_TYPE_SUB = 1 ; --- MASTER DATA STRUCTURES (Hard-coded definitions) --- ; [InternalName, DisplayName, FunctionName, MenuType] Global Const $g_aMasterWorkers[10][4] = [ _ ["CheckResources", "Check Resources", "Worker1Function", $MENU_TYPE_MAIN], _ ["SyncFiles", "Sync Files", "Worker2Function", $MENU_TYPE_MAIN], _ ["MonitorNetwork", "Monitor Network", "Worker3Function", $MENU_TYPE_MAIN], _ ["BackupDB", "Backup DB", "Worker4Function", $MENU_TYPE_SUB], _ ["CleanupLogs", "Cleanup Logs", "Worker5Function", $MENU_TYPE_SUB], _ ["ProcessEmails", "Process Emails", "Worker6Function", $MENU_TYPE_SUB], _ ["AutoScreenshot", "Auto Screenshot", "Worker7Function", $MENU_TYPE_SUB], _ ["MonitorTemp", "Monitor Temp", "Worker8Function", $MENU_TYPE_SUB], _ ["CheckUpdates", "Check Updates", "Worker9Function", $MENU_TYPE_SUB], _ ["SecurityScan", "Security Scan", "Worker10Function", $MENU_TYPE_SUB] _ ] ; [InternalName, DisplayName, FunctionName, MenuType, ExecutionMode, RunType] Global Const $g_aMasterTasks[10][6] = [ _ ["QuickCleanup", "Quick Cleanup", "TaskA_Function", $MENU_TYPE_MAIN, $TASK_MODE_EXCLUSIVE, $TASK_RUN_TYPE_SUBAPP], _ ["GenerateReport", "Generate Report", "TaskB_Function", $MENU_TYPE_MAIN, $TASK_MODE_EXCLUSIVE, $TASK_RUN_TYPE_SUBAPP], _ ["SendNotification", "Send Notification (Direct)", "TaskJ_Function", $MENU_TYPE_MAIN, $TASK_MODE_EXCLUSIVE, $TASK_RUN_TYPE_DIRECT], _ ["TaskC", "Run Task C (Direct)", "TaskC_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_DIRECT], _ ["TaskD", "Run Task D", "TaskD_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP], _ ["TaskE", "Run Task E", "TaskE_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP], _ ["TaskF", "Run Task F", "TaskF_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP], _ ["TaskG", "Run Task G", "TaskG_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP], _ ["TaskH", "Run Task H", "TaskH_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP], _ ["TaskI", "Run Task I", "TaskI_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP] _ ] ; --- Dynamic Data Structures (Populated from Master based on INI) --- Global $g_aWorkers, $g_iNumWorkers Global $g_aTasks, $g_iNumTasks ; --- Tray Menu Control Variables --- Global $g_aWorkerTrayItems[1], $g_aTaskTrayItems[1], $g_iTrayExit ; --- Shared Global Variables for Worker processes --- Global $g_sWorkerInternalName, $g_iControllerPID, $g_sWorkerRegKey ; =============================================================================================================================== ; --- MAIN SCRIPT LOGIC ; =============================================================================================================================== _Main() ;/** ; * @brief Main entry point of the script. ; * ; * Determines whether to run as the Controller or as a sub-process (Worker/Task) ; * based on the command-line arguments. ; */ Func _Main() If $CmdLine[0] > 0 Then Local $aCmd = StringSplit($CmdLine[1], ":") If $aCmd[0] < 2 Then Exit Local $sType = $aCmd[1], $sInternalName = $aCmd[2], $iControllerPID = ($CmdLine[0] > 1 ? $CmdLine[2] : 0) Switch $sType Case "worker" _RunAsWorker($sInternalName, $iControllerPID) Case "task" _RunAsTask($sInternalName) EndSwitch Else _RunAsController() EndIf EndFunc ;==>_Main ; =============================================================================================================================== ; --- CONTROLLER FUNCTIONS ; =============================================================================================================================== ;/** ; * @brief Initializes the Controller process. ; * ; * This function sets up the entire Controller environment: ; * 1. Cleans up any leftover registry keys from previous runs. ; * 2. Loads the configuration from Configs.ini. ; * 3. Creates the tray menu. ; * 4. Registers Adlib functions for background monitoring. ; * 5. Starts the main event loop. ; */ Func _RunAsController() _CleanupAllRegistryKeys() _LoadConfiguration() _CreateTrayMenu() AdlibRegister("_CheckStatus_Adlib", $g_iAdlibCheckInterval) AdlibRegister("_CheckForConfigChanges_Adlib", $g_iCheckConfigInterval) _WriteLog("INFO: Controller started successfully.") _ControllerMainLoop() EndFunc ;==>_RunAsController ;/** ; * @brief Loads and parses the configuration from Configs.ini. ; * ; * If Configs.ini exists, it reads the settings and the disable lists. ; * If not, it uses the default configuration (all master items enabled). ; * It then populates the dynamic $g_aWorkers and $g_aTasks arrays with only the enabled items. ; * This function is optimized to count items first, then Dim the arrays once to avoid ReDim in a loop. ; */ Func _LoadConfiguration() Local $sDisabledWorkers = "", $sDisabledTasks = "" If FileExists($g_sConfigFile) Then $g_sLastConfigModDate = FileGetTime($g_sConfigFile, $FT_MODIFIED, $FT_STRING) $g_sAppName = IniRead($g_sConfigFile, "Settings", "AppName", "Controller Framework") $g_iCheckConfigInterval = IniRead($g_sConfigFile, "Settings", "CheckConfigInterval", 10000) $sDisabledWorkers = "," & IniRead($g_sConfigFile, "Workers", "Disable", "") & "," $sDisabledTasks = "," & IniRead($g_sConfigFile, "Tasks", "Disable", "") & "," Else $g_sLastConfigModDate = "" $sDisabledWorkers = "," $sDisabledTasks = "," EndIf Local $iWorkerCount = 0, $iTaskCount = 0 For $i = 0 To UBound($g_aMasterWorkers) - 1 If Not StringInStr($sDisabledWorkers, "," & $g_aMasterWorkers[$i][0] & ",") Then $iWorkerCount += 1 Next For $i = 0 To UBound($g_aMasterTasks) - 1 If Not StringInStr($sDisabledTasks, "," & $g_aMasterTasks[$i][0] & ",") Then $iTaskCount += 1 Next $g_iNumWorkers = $iWorkerCount $g_iNumTasks = $iTaskCount Dim $g_aWorkers[$g_iNumWorkers][7] Dim $g_aTasks[$g_iNumTasks][7] Local $iWorkerIdx = 0, $iTaskIdx = 0 For $i = 0 To UBound($g_aMasterWorkers) - 1 Local $sInternalName = $g_aMasterWorkers[$i][0] If StringInStr($sDisabledWorkers, "," & $sInternalName & ",") Then ContinueLoop $g_aWorkers[$iWorkerIdx][0] = $sInternalName $g_aWorkers[$iWorkerIdx][1] = $g_aMasterWorkers[$i][1] $g_aWorkers[$iWorkerIdx][2] = $g_aMasterWorkers[$i][2] $g_aWorkers[$iWorkerIdx][3] = 0 $g_aWorkers[$iWorkerIdx][4] = False $g_aWorkers[$iWorkerIdx][5] = $STATUS_STOPPED $g_aWorkers[$iWorkerIdx][6] = $g_aMasterWorkers[$i][3] $iWorkerIdx += 1 Next For $i = 0 To UBound($g_aMasterTasks) - 1 Local $sInternalName = $g_aMasterTasks[$i][0] If StringInStr($sDisabledTasks, "," & $sInternalName & ",") Then ContinueLoop $g_aTasks[$iTaskIdx][0] = $sInternalName $g_aTasks[$iTaskIdx][1] = $g_aMasterTasks[$i][1] $g_aTasks[$iTaskIdx][2] = $g_aMasterTasks[$i][2] $g_aTasks[$iTaskIdx][3] = 0 $g_aTasks[$iTaskIdx][4] = $g_aMasterTasks[$i][4] $g_aTasks[$iTaskIdx][5] = $g_aMasterTasks[$i][5] $g_aTasks[$iTaskIdx][6] = $g_aMasterTasks[$i][3] $iTaskIdx += 1 Next EndFunc ;==>_LoadConfiguration ;/** ; * @brief Creates the entire tray menu structure based on the loaded configuration. ; * ; * It iterates through the dynamic $g_aWorkers and $g_aTasks arrays and creates ; * main menu items or sub-menu items based on their MenuType property. ; * This ensures that the menu item index directly corresponds to the data array index. ; */ Func _CreateTrayMenu() Opt("TrayMenuMode", 3) TraySetToolTip($g_sAppName) ReDim $g_aWorkerTrayItems[$g_iNumWorkers] ReDim $g_aTaskTrayItems[$g_iNumTasks] Local $hSubWorkersMenu = 0, $hSubTasksMenu = 0 For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][6] = $MENU_TYPE_MAIN Then $g_aWorkerTrayItems[$i] = TrayCreateItem("[OFF] " & $g_aWorkers[$i][1]) Else If $hSubWorkersMenu = 0 Then $hSubWorkersMenu = TrayCreateMenu("Sub Workers") $g_aWorkerTrayItems[$i] = TrayCreateItem("[OFF] " & $g_aWorkers[$i][1], $hSubWorkersMenu) EndIf Next TrayCreateItem("") For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][6] = $MENU_TYPE_MAIN Then $g_aTaskTrayItems[$i] = TrayCreateItem($g_aTasks[$i][1]) Else If $hSubTasksMenu = 0 Then $hSubTasksMenu = TrayCreateMenu("Sub Tasks") $g_aTaskTrayItems[$i] = TrayCreateItem($g_aTasks[$i][1], $hSubTasksMenu) EndIf Next TrayCreateItem("") $g_iTrayExit = TrayCreateItem("Exit") TraySetState(1) EndFunc ;==>_CreateTrayMenu ;/** ; * @brief The main event loop for the Controller. ; * ; * It waits for and dispatches tray menu click events to the appropriate handler functions. ; */ Func _ControllerMainLoop() While 1 Local $iTrayMsg = TrayGetMsg() Switch $iTrayMsg Case 0 Case $g_iTrayExit _ExitController() Case Else Local $iIndex = _GetIndexFromTrayID($iTrayMsg, $g_aWorkerTrayItems) If $iIndex <> -1 Then _HandleWorkerClick($iIndex) ContinueLoop EndIf $iIndex = _GetIndexFromTrayID($iTrayMsg, $g_aTaskTrayItems) If $iIndex <> -1 Then _HandleTaskClick($iIndex) ContinueLoop EndIf EndSwitch Sleep(100) WEnd EndFunc ;==>_ControllerMainLoop ;/** ; * @brief Handles a click on a Worker menu item. ; * @param $iIndex The index of the clicked worker in the $g_aWorkers array. ; */ Func _HandleWorkerClick($iIndex) _UpdateWorkerState($iIndex, Not $g_aWorkers[$iIndex][4]) EndFunc ;==>_HandleWorkerClick ;/** ; * @brief Handles a click on a Task menu item. ; * @param $iIndex The index of the clicked task in the $g_aTasks array. ; */ Func _HandleTaskClick($iIndex) _RunTask($iIndex) EndFunc ;==>_HandleTaskClick ;/** ; * @brief Central function to change a worker's state (on/off). ; * @param $iIndex The index of the worker. ; * @param $bNewState The new state to apply (True for ON, False for OFF). ; */ Func _UpdateWorkerState($iIndex, $bNewState) $g_aWorkers[$iIndex][4] = $bNewState If $bNewState Then _StartWorker($iIndex) Else _StopWorker($iIndex) EndIf _UpdateTrayItemForWorker($iIndex) EndFunc ;==>_UpdateWorkerState ;/** ; * @brief Updates a worker's tray menu item text and checked state. ; * @param $iIndex The index of the worker. ; */ Func _UpdateTrayItemForWorker($iIndex) Local $sPrefix, $iTrayState If $g_aWorkers[$iIndex][4] Then $sPrefix = "[ON] " $iTrayState = $TRAY_CHECKED Else $sPrefix = "[OFF] " $iTrayState = $TRAY_UNCHECKED EndIf TrayItemSetText($g_aWorkerTrayItems[$iIndex], $sPrefix & $g_aWorkers[$iIndex][1]) TrayItemSetState($g_aWorkerTrayItems[$iIndex], $iTrayState) EndFunc ;==>_UpdateTrayItemForWorker ;/** ; * @brief Starts a worker sub-process. ; * @param $iIndex The index of the worker. ; */ Func _StartWorker($iIndex) If ProcessExists($g_aWorkers[$iIndex][3]) Then Return Local $sCommand = 'worker:' & $g_aWorkers[$iIndex][0] _WriteLog("INFO: Starting Worker '" & $g_aWorkers[$iIndex][1] & "'...") Local $iPID = _RunScript($sCommand) If $iPID > 0 Then $g_aWorkers[$iIndex][3] = $iPID $g_aWorkers[$iIndex][5] = $STATUS_RUNNING Else _WriteLog("ERROR: Failed to start Worker '" & $g_aWorkers[$iIndex][1] & "'.") $g_aWorkers[$iIndex][4] = False $g_aWorkers[$iIndex][5] = $STATUS_ERROR EndIf EndFunc ;==>_StartWorker ;/** ; * @brief Stops a worker sub-process gracefully. ; * @param $iIndex The index of the worker. ; */ Func _StopWorker($iIndex) Local $iPID = $g_aWorkers[$iIndex][3] If $iPID = 0 Or Not ProcessExists($iPID) Then $g_aWorkers[$iIndex][3] = 0 $g_aWorkers[$iIndex][5] = $STATUS_STOPPED Return EndIf _WriteLog("INFO: Stopping Worker '" & $g_aWorkers[$iIndex][1] & "' (PID: " & $iPID & ")...") Local $sRegKey = $g_sRegBase & "\" & $g_aWorkers[$iIndex][0] RegWrite($sRegKey, "Signal", "REG_SZ", "exit") If @error Then _WriteLog("ERROR: Failed to write exit signal to registry for " & $g_aWorkers[$iIndex][0]) Local $iResult = ProcessWaitClose($iPID, $g_iGracefulShutdownTimeout / 1000) If $iResult = 0 Then _WriteLog("WARN: Worker PID " & $iPID & " did not respond. Forcing shutdown.") ProcessClose($iPID) EndIf RegDelete($sRegKey) $g_aWorkers[$iIndex][3] = 0 $g_aWorkers[$iIndex][5] = $STATUS_STOPPED EndFunc ;==>_StopWorker ;/** ; * @brief Runs a task either directly or as a sub-process. ; * @param $iIndex The index of the task. ; */ Func _RunTask($iIndex) Local $sTaskName = $g_aTasks[$iIndex][1] _WriteLog("INFO: Running Task '" & $sTaskName & "'...") If $g_aTasks[$iIndex][5] = $TASK_RUN_TYPE_DIRECT Then TrayItemSetState($g_aTaskTrayItems[$iIndex], $TRAY_DISABLE) Call($g_aTasks[$iIndex][2], $sTaskName) TrayItemSetState($g_aTaskTrayItems[$iIndex], $TRAY_ENABLE) _WriteLog("INFO: Direct Task '" & $sTaskName & "' has completed.") Else If $g_aTasks[$iIndex][3] <> 0 And ProcessExists($g_aTasks[$iIndex][3]) Then Return Local $sCommand = 'task:' & $g_aTasks[$iIndex][0] Local $iPID = _RunScript($sCommand, False) If $iPID > 0 Then $g_aTasks[$iIndex][3] = $iPID _UpdateAllTaskMenusState() Else _WriteLog("ERROR: Failed to run Task '" & $sTaskName & "'.") EndIf EndIf EndFunc ;==>_RunTask ;/** ; * @brief Adlib function to monitor the status of running workers and tasks. ; */ Func _CheckStatus_Adlib() For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][4] And Not ProcessExists($g_aWorkers[$i][3]) Then _WriteLog("WARN: Worker '" & $g_aWorkers[$i][1] & "' died. Restarting...") $g_aWorkers[$i][5] = $STATUS_ERROR _UpdateTrayItemForWorker($i) _StartWorker($i) EndIf Next Local $bTaskStateChanged = False For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][5] = $TASK_RUN_TYPE_SUBAPP And $g_aTasks[$i][3] > 0 And Not ProcessExists($g_aTasks[$i][3]) Then $g_aTasks[$i][3] = 0 $bTaskStateChanged = True EndIf Next If $bTaskStateChanged Then _UpdateAllTaskMenusState() EndFunc ;==>_CheckStatus_Adlib ;/** ; * @brief Checks if any exclusive task is currently running as a sub-process. ; * @return True if an exclusive task is running, otherwise False. ; */ Func _IsExclusiveTaskRunning() For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][4] = $TASK_MODE_EXCLUSIVE And $g_aTasks[$i][3] > 0 And ProcessExists($g_aTasks[$i][3]) Then Return True EndIf Next Return False EndFunc ;==>_IsExclusiveTaskRunning ;/** ; * @brief Updates the enabled/disabled state of all task menu items based on current activity. ; */ Func _UpdateAllTaskMenusState() Local $bExclusiveRunning = _IsExclusiveTaskRunning() For $i = 0 To $g_iNumTasks - 1 If $bExclusiveRunning Then TrayItemSetState($g_aTaskTrayItems[$i], $TRAY_DISABLE) Else If $g_aTasks[$i][3] > 0 And ProcessExists($g_aTasks[$i][3]) Then TrayItemSetState($g_aTaskTrayItems[$i], $TRAY_DISABLE) Else TrayItemSetState($g_aTaskTrayItems[$i], $TRAY_ENABLE) EndIf EndIf Next EndFunc ;==>_UpdateAllTaskMenusState ;/** ; * @brief Adlib function to check for modifications to the Configs.ini file. ; */ Func _CheckForConfigChanges_Adlib() Local $iCurrentModDate = FileGetTime($g_sConfigFile, $FT_MODIFIED, $FT_STRING) If $iCurrentModDate <> $g_sLastConfigModDate Then _WriteLog("INFO: Configuration file change detected. Reloading...") _UnregisterAllMasterAdlibs() _StopAllWorkers() TraySetState(2) _LoadConfiguration() _CreateTrayMenu() _WriteLog("INFO: Configuration reloaded and menu recreated.") EndIf EndFunc ;==>_CheckForConfigChanges_Adlib ;/** ; * @brief Stops all currently active workers. ; */ Func _StopAllWorkers() For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][4] Then _StopWorker($i) Next EndFunc ;==>_StopAllWorkers ;/** ; * @brief A generic function to run the script as a sub-process. ; * @param $sArgument The argument to pass to the new process (e.g., "worker:MyWorker"). ; * @param $bPassControllerPID If True, the current controller's PID is passed as the second argument. ; * @return The PID of the new process, or 0 on failure. ; */ Func _RunScript($sArgument, $bPassControllerPID = True) Local $sControllerPID = ($bPassControllerPID ? " " & @AutoItPID : "") Local $sCommand = '"' & @ScriptFullPath & '" "' & $sArgument & '"' & $sControllerPID Local $sExecutable = (@Compiled ? "" : '"' & @AutoItExe & '" ') Return Run($sExecutable & $sCommand, @ScriptDir, @SW_HIDE) EndFunc ;==>_RunScript ;/** ; * @brief Performs all necessary cleanup before the Controller exits. ; */ Func _ExitController() _WriteLog("INFO: Controller shutting down...") _UnregisterAllMasterAdlibs() _CleanupAllRegistryKeys() _StopAllWorkers() Exit EndFunc ;==>_ExitController ;/** ; * @brief Unregisters all possible Adlib callbacks defined in the master lists. ; * ; * This is a crucial cleanup step to prevent orphaned callbacks, especially when reloading the configuration. ; */ Func _UnregisterAllMasterAdlibs() AdlibUnRegister("_CheckStatus_Adlib") AdlibUnRegister("_CheckForConfigChanges_Adlib") For $i = 0 To UBound($g_aMasterWorkers) - 1 AdlibUnRegister($g_aMasterWorkers[$i][2]) Next EndFunc ;==>_UnregisterAllMasterAdlibs ;/** ; * @brief Deletes the entire registry key used by the application for IPC. ; */ Func _CleanupAllRegistryKeys() RegDelete($g_sRegBase) If @error Then _WriteLog("ERROR: Failed to delete base registry key: " & $g_sRegBase) EndFunc ;==>_CleanupAllRegistryKeys ;/** ; * @brief Finds the array index corresponding to a given tray item ID. ; * @param $nID The tray item ID to find. ; * @param $aTrayItems The array of tray item IDs to search in. ; * @return The array index if found, otherwise -1. ; */ Func _GetIndexFromTrayID($nID, ByRef $aTrayItems) For $i = 0 To UBound($aTrayItems) - 1 If $aTrayItems[$i] = $nID Then Return $i Next Return -1 EndFunc ;==>_GetIndexFromTrayID ;/** ; * @brief Writes a message to both the console and the log file. ; * ; * This function provides a synchronized way to log events. Opening and closing the file ; * for each write minimizes the chance of file corruption from multiple processes. ; * @param $sMessage The message to log. ; */ Func _WriteLog($sMessage) Local $sTimeStamp = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC Local $sFormattedMessage = $sTimeStamp & " - " & $sMessage & @CRLF ConsoleWrite($sFormattedMessage) Local $hFile = FileOpen($g_sLogFile, 2 + 8) ; Open in Write + Append mode to lock the file during write If $hFile = -1 Then Return FileWrite($hFile, $sFormattedMessage) FileClose($hFile) EndFunc ;==>_WriteLog ; =============================================================================================================================== ; --- WORKER / TASK SUB-PROCESS EXECUTION ; =============================================================================================================================== ;/** ; * @brief Initializes the script when run as a Worker sub-process. ; * @param $sInternalName The internal name of the worker to run. ; * @param $iControllerPID The PID of the parent Controller process to monitor. ; */ Func _RunAsWorker($sInternalName, $iControllerPID) $g_sWorkerInternalName = $sInternalName $g_iControllerPID = $iControllerPID $g_sWorkerRegKey = $g_sRegBase & "\" & $sInternalName RegDelete($g_sWorkerRegKey) Local $sFunction = "" For $i = 0 To UBound($g_aMasterWorkers) - 1 If $g_aMasterWorkers[$i][0] = $sInternalName Then $sFunction = $g_aMasterWorkers[$i][2] ExitLoop EndIf Next If $sFunction = "" Then Exit AdlibRegister($sFunction, 1000) AdlibRegister("_WorkerHeartbeat_Adlib", 2000) While 1 Sleep(100) WEnd EndFunc ;==>_RunAsWorker ;/** ; * @brief Adlib function for workers to monitor the Controller and exit signals. ; */ Func _WorkerHeartbeat_Adlib() If $g_iControllerPID > 0 And Not ProcessExists($g_iControllerPID) Then _WorkerExitGracefully() EndIf RegRead($g_sWorkerRegKey, "Signal") If @error Then _WorkerExitGracefully() Return EndIf If RegRead($g_sWorkerRegKey, "Signal") = "exit" Then _WorkerExitGracefully() EndIf EndFunc ;==>_WorkerHeartbeat_Adlib ;/** ; * @brief Performs all necessary cleanup for a Worker before it exits. ; */ Func _WorkerExitGracefully() AdlibUnRegister("_WorkerHeartbeat_Adlib") Local $sFunction = "" For $i = 0 To UBound($g_aMasterWorkers) - 1 If $g_aMasterWorkers[$i][0] = $g_sWorkerInternalName Then $sFunction = $g_aMasterWorkers[$i][2] ExitLoop EndIf Next If $sFunction <> "" Then AdlibUnRegister($sFunction) RegDelete($g_sWorkerRegKey) Exit EndFunc ;==>_WorkerExitGracefully ;/** ; * @brief Initializes the script when run as a Task sub-process. ; * @param $sInternalName The internal name of the task to run. ; */ Func _RunAsTask($sInternalName) Local $sFunction, $sDisplayName For $i = 0 To UBound($g_aMasterTasks) - 1 If $g_aMasterTasks[$i][0] = $sInternalName Then $sDisplayName = $g_aMasterTasks[$i][1] $sFunction = $g_aMasterTasks[$i][2] ExitLoop EndIf Next If $sFunction = "" Then Exit Call($sFunction, $sDisplayName) Exit EndFunc ;==>_RunAsTask ; =============================================================================================================================== ; --- SPECIFIC WORKER/TASK FUNCTIONS (IMPLEMENTATION) ; =============================================================================================================================== Func Worker1Function() _WriteLog("Worker 'Check Resources' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker1Function Func Worker2Function() _WriteLog("Worker 'Sync Files' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker2Function Func Worker3Function() _WriteLog("Worker 'Monitor Network' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker3Function Func Worker4Function() _WriteLog("Worker 'Backup DB' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker4Function Func Worker5Function() _WriteLog("Worker 'Cleanup Logs' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker5Function Func Worker6Function() _WriteLog("Worker 'Process Emails' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker6Function Func Worker7Function() _WriteLog("Worker 'Auto Screenshot' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker7Function Func Worker8Function() _WriteLog("Worker 'Monitor Temp' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker8Function Func Worker9Function() _WriteLog("Worker 'Check Updates' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker9Function Func Worker10Function() _WriteLog("Worker 'Security Scan' is running...") ; This is PlaceHoder - Your Code Repalce Here EndFunc ;==>Worker10Function Func TaskA_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(2000) EndFunc ;==>TaskA_Function Func TaskB_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(3000) EndFunc ;==>TaskB_Function Func TaskC_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskC_Function Func TaskD_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskD_Function Func TaskE_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskE_Function Func TaskF_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskF_Function Func TaskG_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskG_Function Func TaskH_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskH_Function Func TaskI_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1500) EndFunc ;==>TaskI_Function Func TaskJ_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Repalce Here Sleep(1000) EndFunc ;==>TaskJ_Function !
  6. Updated code, try it out!
  7. Version 2.0.0.0

    78 downloads

    An ultimate, professional GUI tool for complex, configurable image search tasks, built upon the high-performance ImageSearch UDF. Include ImageSearch UDF Embedded dll
  8. Source ImageSearch Automation Suite: #RequireAdmin #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #pragma compile(x64, true) #cs ---------------------------------------------------------------------------- ; ; Title .........: ImageSearch Automation Suite (Refactored) ; AutoIt Version : 3.3.16.1 ; Author ........: Dao Van Trong (TRONG.PRO) ; Date ..........: 2025-07-28 ; Note ..........: This script is a graphical user interface (GUI) front-end for the ; ImageSearch_UDF.au3 and its underlying ImageSearch.dll. ; ; ------------------------------------------------------------------------------------------------------------------------------- ; #SECTION# SCRIPT OVERVIEW ; ------------------------------------------------------------------------------------------------------------------------------- ; ; This script provides a powerful and user-friendly interface for performing complex image search and automation tasks. ; It acts as a control panel for the high-performance ImageSearch UDF, allowing you to visually configure, execute, ; and log search operations without writing complex code. It is designed for tasks ranging from simple automation ; to advanced botting and UI testing. ; ; ------------------------------------------------------------------------------------------------------------------------------- ; #SECTION# FIRST-TIME SETUP ; ------------------------------------------------------------------------------------------------------------------------------- ; ; Before you can start a search, you need to provide the images you want to find. ; ; 1. RUN THE SCRIPT: The main window will appear. On the right side, you will see 12 empty "Image Target" slots. ; ; 2. CREATE AN IMAGE: Click the "Create" button next to slot #1. ; ; 3. CAPTURE THE REGION: The script window will hide. Your mouse cursor will turn into a crosshair. ; Click and drag a rectangle around the object on the screen you want to find. When you release the mouse button, ; a bitmap image named "Search_1.bmp" will be saved in the same directory as the script. ; ; 4. PREVIEW UPDATES: The image you just captured will now appear in the preview panel for slot #1. ; ; 5. REPEAT: Repeat this process for any other images you need to find (up to 12). ; ; ------------------------------------------------------------------------------------------------------------------------------- ; #SECTION# GUI ELEMENT GUIDE ; ------------------------------------------------------------------------------------------------------------------------------- ; ; === Image Targets (Right Panel) === ; - Checkbox (1-12): Tick the box next to an image to include it in the next search operation. ; - Create Button: Click to capture a screen region and save it as the image for that slot. ; - Image Preview: Shows the image that will be searched for. It displays a placeholder if the .bmp file doesn't exist. ; ; === Configuration -> Search Mode (Top-Left) === ; - [ ] Multi Search (All at once): ; - If UNCHECKED (Single Mode - Default): The script searches for selected images one by one, in order. ; - If CHECKED (Multi Mode): The script searches for ALL selected images in a single, highly efficient operation. ; It will find the FIRST available match from the list of selected images. ; ; - [ ] Find All Occurrences: ; - If UNCHECKED (Default): The search stops as soon as the first match is found. ; - If CHECKED: The search will find EVERY instance of the selected image(s) on the screen. ; ; - [ ] Wait for Image Found: ; - If CHECKED: The script will repeatedly search for the image until it is found or the "Timeout" value is reached. ; ; - [ ] Use Tolerance: ; - If CHECKED: Allows for inexact matches. The "Tolerance" value (0-255) determines how much color variation is allowed. ; ; - [ ] Use Custom Area: ; - If CHECKED: The search will be restricted to the coordinates defined in the "Search Area" group box. ; - If UNCHECKED: The search will be performed on the entire screen. ; ; - [ ] Enable DLL Debug: ; - If CHECKED: The raw output from the DLL, including detailed debug info, will be printed in the Activity Log. ; Useful for advanced troubleshooting. ; ; === Configuration -> Parameters === ; - Timeout (ms): The maximum time (in milliseconds) to wait when "Wait for Image Found" is enabled. ; - Tolerance: A number from 0 (exact match) to 255 (very loose match). A good starting value is 10-20. ; - Delay (ms): The time (in milliseconds) to pause after performing an action (like a click) on a found image. ; ; === Configuration -> Search Area === ; - Left, Top, Right, Bottom: The pixel coordinates of the rectangular search area. ; - Select Area Button: A convenient tool to draw a rectangle on the screen with your mouse to automatically fill in these coordinates. ; ; === Configuration -> Actions on Found === ; - [ ] Move Mouse: If checked, the mouse cursor will move to the location of the found image. ; - Click (None / Single / Double): Choose the mouse action to perform after the image is found. The click will happen at the ; coordinates of the found image (center or top-left, depending on UDF settings). ; ; === Main Action Buttons === ; - Start Search: Begins the search operation using all the currently selected settings. ; - Select All: Checks all 12 image target boxes. ; - Deselect All: Unchecks all 12 image target boxes. ; ; === Bottom Panels === ; - Activity Log: Displays a timestamped log of all actions, search results, and errors. ; - System Information: Shows details about your OS, AutoIt version, and the specific ImageSearch DLL being used. ; - Status Bar: Provides real-time feedback on the script's current state (e.g., "Ready", "Searching...", "Search complete"). ; ; ------------------------------------------------------------------------------------------------------------------------------- ; #SECTION# WORKFLOW EXAMPLES ; ------------------------------------------------------------------------------------------------------------------------------- ; ; Scenario 1: Click a "Login" button that might be in one of two different styles. ; -------------------------------------------------------------------------------- ; 1. Create "Search_1.bmp" of the first login button style. ; 2. Create "Search_2.bmp" of the second login button style. ; 3. Check the boxes for images 1 and 2. ; 4. Check "Multi Search" (to find whichever appears first). ; 5. Set "Actions on Found" to "Single" click. ; 6. Click "Start Search". The script will find the first available login button and click it. ; ; Scenario 2: Count how many gold coin icons are visible inside a game window. ; -------------------------------------------------------------------------------- ; 1. Create "Search_1.bmp" of a single gold coin icon. ; 2. Check the box for image 1. ; 3. Uncheck "Multi Search". ; 4. Check "Find All Occurrences". ; 5. Check "Use Custom Area" and use the "Select Area" button to draw a box around the game window. ; 6. Set "Actions on Found" to "None" for the click action. ; 7. Click "Start Search". The Activity Log will show "Found X match(es)" where X is the number of coins. ; #ce ---------------------------------------------------------------------------- #include <Array.au3> #include <GDIPlus.au3> #include <ScreenCapture.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <EditConstants.au3> #include <StaticConstants.au3> #include <ButtonConstants.au3> #include <Date.au3> #include <Misc.au3> #include <Math.au3> #include <GuiEdit.au3> #include <GuiStatusBar.au3> #include "ImageSearch_UDF.au3" ;Opt("MustDeclareVars", 1) ; === GLOBAL CONSTANTS AND VARIABLES === Global Const $MAX_IMAGES = 12 Global Const $g_sPlaceholderPath = @WindowsDir & "\Web\Wallpaper\Windows\img0.jpg" Global $g_asImagePaths[$MAX_IMAGES], $g_nMsg, $g_hMainGUI, $g_hLog, $g_hStatusBar ; --- GUI Control IDs --- Global $g_idBtnStart, $g_idBtnSelectAll, $g_idBtnDeselectAll, $g_idBtnSelectArea Global $g_idInputDelay, $g_idChkMoveMouse Global $g_idRadNoClick, $g_idRadSingleClick, $g_idRadDoubleClick Global $g_idChkWait, $g_idInputWaitTime Global $g_idChkUseArea, $g_idInputLeft, $g_idInputTop, $g_idInputRight, $g_idInputBottom Global $g_idChkMultiSearch, $g_idChkFindAll, $g_idChkUseTolerance, $g_idInputTolerance, $g_idChkEnableDebug Global $g_aidPic[$MAX_IMAGES], $g_aidChkSearch[$MAX_IMAGES], $g_aidBtnCreate[$MAX_IMAGES] _Main() ; #FUNCTION# ==================================================================================================================== ; Name...........: _Main ; Description....: Main program entry point. Initializes components and enters the GUI message loop. ; =============================================================================================================================== Func _Main() ; Explicitly initialize the ImageSearch library If Not _ImageSearch_Startup() Then MsgBox(16, "Fatal Error", "Failed to initialize the ImageSearch DLL. @error: " & @error & @CRLF & "The script will now exit.") Exit EndIf _GDIPlus_Startup() _InitializeImagePaths() _CreateGUI() _UpdateAllImagePreviews() ; Main message loop to handle GUI events. While 1 $g_nMsg = GUIGetMsg() Switch $g_nMsg Case $GUI_EVENT_CLOSE ExitLoop Case $g_idBtnStart _StartSearch() Case $g_idBtnSelectAll _SelectAll(True) Case $g_idBtnDeselectAll _SelectAll(False) Case $g_idBtnSelectArea _SelectAreaOnScreen() Case $g_aidBtnCreate[0] To $g_aidBtnCreate[$MAX_IMAGES - 1] _HandleImageCreation($g_nMsg) EndSwitch WEnd _Exit() EndFunc ;==>_Main ; === GUI AND INITIALIZATION FUNCTIONS === ; #FUNCTION# ==================================================================================================================== ; Name...........: _InitializeImagePaths ; Description....: Populates the global array with default paths for the search images. ; =============================================================================================================================== Func _InitializeImagePaths() For $i = 0 To $MAX_IMAGES - 1 $g_asImagePaths[$i] = @ScriptDir & "\Search_" & $i + 1 & ".bmp" Next EndFunc ;==>_InitializeImagePaths ; #FUNCTION# ==================================================================================================================== ; Name...........: _CreateGUI ; Description....: Creates the entire graphical user interface, defining all controls and their positions. ; =============================================================================================================================== Func _CreateGUI() $g_hMainGUI = GUICreate("ImageSearch Automation Suite (Refactored) by Dao Van Trong - TRONG.PRO", 904, 650) ; --- TOP: CONFIGURATION --- GUICtrlCreateGroup("Configuration", 10, 10, 390, 300) ; --- Search Mode --- GUICtrlCreateGroup("Search Mode", 20, 30, 180, 175) $g_idChkMultiSearch = GUICtrlCreateCheckbox("Multi Search (All at once)", 30, 50, 160, 20) GUICtrlSetTip(-1, "Searches for all selected images in a single operation." & @CRLF & "Finds the FIRST occurrence of ANY of the selected images.") $g_idChkFindAll = GUICtrlCreateCheckbox("Find All Occurrences", 30, 75, 160, 20) GUICtrlSetTip(-1, "Finds EVERY instance of the selected image(s), not just the first one.") $g_idChkWait = GUICtrlCreateCheckbox("Wait for Image Found", 30, 100, 160, 20) $g_idChkUseTolerance = GUICtrlCreateCheckbox("Use Tolerance", 30, 125, 160, 20) GUICtrlSetState(-1, $GUI_CHECKED) $g_idChkUseArea = GUICtrlCreateCheckbox("Use Custom Area", 30, 150, 160, 20) $g_idChkEnableDebug = GUICtrlCreateCheckbox("Enable DLL Debug", 30, 175, 160, 20) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlSetTip(-1, "Log detailed information from the DLL.") ; --- Parameters --- GUICtrlCreateGroup("Parameters", 210, 30, 180, 94) GUICtrlCreateLabel("Timeout (ms)", 220, 50, 80, 20) $g_idInputWaitTime = GUICtrlCreateInput("5000", 300, 47, 80, 21) GUICtrlCreateLabel("Tolerance:", 220, 75, 80, 20) $g_idInputTolerance = GUICtrlCreateInput("10", 300, 72, 80, 21) GUICtrlCreateLabel("Delay (ms)", 220, 100, 80, 20) $g_idInputDelay = GUICtrlCreateInput("500", 300, 97, 80, 21) ; --- Search Area --- GUICtrlCreateGroup("Search Area", 16, 210, 188, 98) GUICtrlCreateLabel("Left:", 26, 230, 30, 20) $g_idInputLeft = GUICtrlCreateInput("0", 61, 227, 50, 21) GUICtrlCreateLabel("Top:", 121, 230, 30, 20) $g_idInputTop = GUICtrlCreateInput("0", 156, 227, 30, 21) GUICtrlCreateLabel("Right:", 26, 255, 35, 20) $g_idInputRight = GUICtrlCreateInput(@DesktopWidth, 61, 252, 50, 21) GUICtrlCreateLabel("Bottom:", 121, 255, 40, 20) $g_idInputBottom = GUICtrlCreateInput(@DesktopHeight, 156, 252, 30, 21) $g_idBtnSelectArea = GUICtrlCreateButton("Select Area", 24, 276, 163, 25) ; --- Actions on Found --- GUICtrlCreateGroup("Actions on Found", 214, 134, 174, 146) $g_idChkMoveMouse = GUICtrlCreateCheckbox("Move Mouse", 224, 154, 100, 20) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlCreateLabel("Click:", 224, 179, 40, 20) $g_idRadNoClick = GUICtrlCreateRadio("None", 264, 179, 55, 20) GUICtrlSetState(-1, $GUI_CHECKED) $g_idRadSingleClick = GUICtrlCreateRadio("Single", 224, 199, 60, 20) $g_idRadDoubleClick = GUICtrlCreateRadio("Double", 284, 199, 65, 20) ; --- RIGHT COLUMN: IMAGES & INFO --- GUICtrlCreateGroup("Image Targets", 410, 6, 486, 464) Local $iPicWidth = 100, $iPicHeight = 100 Local $iX_Start = 425, $iY_Start = 38 Local $iX = $iX_Start, $iY = $iY_Start Local $iColWidth = 118 For $i = 0 To $MAX_IMAGES - 1 If $i > 0 And Mod($i, 4) = 0 Then ; New row $iX = $iX_Start $iY += 144 EndIf $g_aidChkSearch[$i] = GUICtrlCreateCheckbox(String($i + 1), $iX, $iY, 34, 20) $g_aidBtnCreate[$i] = GUICtrlCreateButton("Create", $iX + 37, $iY, 59, 22) $g_aidPic[$i] = GUICtrlCreatePic("", $iX, $iY + 30, $iPicWidth, $iPicHeight, $SS_CENTERIMAGE) $iX += $iColWidth Next ; --- BOTTOM: LOGS & SYSTEM INFO --- GUICtrlCreateGroup("Activity Log", 13, 472, 880, 142) $g_hLog = GUICtrlCreateEdit("", 18, 487, 862, 114, BitOR($ES_MULTILINE, $ES_READONLY, $WS_VSCROLL, $ES_AUTOVSCROLL)) GUICtrlSetFont(-1, 9, 400, 0, "Consolas") GUICtrlCreateGroup("System Information", 12, 363, 392, 104) GUICtrlCreateLabel("OS: " & @OSVersion & " (" & @OSArch & ")" & " | AutoIt: " & @AutoItVersion & (@AutoItX64 ? " (x64)" : ""), 28, 385, 360, 20) GUICtrlCreateLabel("DLL In Use:" & " v" & $__IMAGESEARCH_UDF_VERSION, 28, 410, 360, 20) GUICtrlCreateInput($g_sImageSearchDLL_Path, 23, 437, 360, 21, $ES_READONLY) ; --- MAIN ACTION BUTTONS --- $g_idBtnStart = GUICtrlCreateButton("Start Search", 9, 318, 264, 40, $BS_DEFPUSHBUTTON) GUICtrlSetFont(-1, 14, 700) $g_idBtnSelectAll = GUICtrlCreateButton("Select All", 295, 318, 105, 22) $g_idBtnDeselectAll = GUICtrlCreateButton("Deselect All", 295, 345, 105, 22) ; --- STATUS BAR --- $g_hStatusBar = _GUICtrlStatusBar_Create($g_hMainGUI) _UpdateStatus("Ready") GUISetState(@SW_SHOW) EndFunc ;==>_CreateGUI ; === CORE LOGIC FUNCTIONS === ; #FUNCTION# ==================================================================================================================== ; Name...........: _StartSearch ; Description....: Gathers all settings from the GUI, validates them, and initiates the appropriate search function. ; =============================================================================================================================== Func _StartSearch() GUICtrlSetData($g_hLog, "") _UpdateStatus("Starting search...") ; --- Read and Validate GUI inputs --- Local $iDelay = Number(GUICtrlRead($g_idInputDelay)) Local $bMoveMouse = (GUICtrlRead($g_idChkMoveMouse) = $GUI_CHECKED) Local $iClickType = 0 ; 0 = None, 1 = Single, 2 = Double If GUICtrlRead($g_idRadSingleClick) = $GUI_CHECKED Then $iClickType = 1 If GUICtrlRead($g_idRadDoubleClick) = $GUI_CHECKED Then $iClickType = 2 Local $bWaitSearch = (GUICtrlRead($g_idChkWait) = $GUI_CHECKED) Local $iWaitTime = Number(GUICtrlRead($g_idInputWaitTime)) Local $bMultiSearch = (GUICtrlRead($g_idChkMultiSearch) = $GUI_CHECKED) Local $iFindAll = (GUICtrlRead($g_idChkFindAll) = $GUI_CHECKED ? 1 : 0) Local $iTolerance = Number(GUICtrlRead($g_idInputTolerance)) Local $iDebugMode = (GUICtrlRead($g_idChkEnableDebug) = $GUI_CHECKED ? 1 : 0) ; --- Determine Search Area --- Local $iLeft, $iTop, $iRight, $iBottom If GUICtrlRead($g_idChkUseArea) = $GUI_CHECKED Then $iLeft = GUICtrlRead($g_idInputLeft) $iTop = GUICtrlRead($g_idInputTop) $iRight = GUICtrlRead($g_idInputRight) $iBottom = GUICtrlRead($g_idInputBottom) Else $iLeft = 0 $iTop = 0 $iRight = @DesktopWidth $iBottom = @DesktopHeight EndIf ; --- Get list of images to search for, validating existence --- Local $aSearchList[1] = [0] For $i = 0 To $MAX_IMAGES - 1 If GUICtrlRead($g_aidChkSearch[$i]) = $GUI_CHECKED Then If Not FileExists($g_asImagePaths[$i]) Then _LogWrite("WARN: Image " & $i + 1 & " not found. Unchecking and skipping.") GUICtrlSetState($g_aidChkSearch[$i], $GUI_UNCHECKED) _UpdateSingleImagePreview($i) ContinueLoop EndIf _ArrayAdd($aSearchList, $g_asImagePaths[$i]) $aSearchList[0] += 1 EndIf Next If $aSearchList[0] = 0 Then _LogWrite("ERROR: No valid images selected for search.") _UpdateStatus("Error: No valid images selected. Ready.") Return EndIf _LogWrite("====================================") _LogWrite("Starting search for " & $aSearchList[0] & " image(s)...") If $bMultiSearch Then _SearchMultipleImages($aSearchList, $bWaitSearch, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebugMode, $iFindAll, $bMoveMouse, $iClickType, $iDelay) Else _SearchSingleImages($aSearchList, $bWaitSearch, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebugMode, $iFindAll, $bMoveMouse, $iClickType, $iDelay) EndIf _LogWrite("====================================" & @CRLF) _UpdateStatus("Search complete. Ready.") EndFunc ;==>_StartSearch ; #FUNCTION# ==================================================================================================================== ; Name...........: __ExecuteSearch ; Description....: A centralized wrapper function to call the appropriate UDF search function. ; Parameters.....: $sImagePath - The path(s) to the image(s) to search for. ; ... All other search parameters. ; Return values..: The 2D array result from the UDF. ; =============================================================================================================================== Func __ExecuteSearch($sImagePath, $bWait, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebug, $iFindAll) Local $iMaxResults = ($iFindAll = 1 ? 99 : 1) If $bWait Then Return _ImageSearch_WaitArea($iWaitTime, $sImagePath, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, -1, $iMaxResults, 1, $iDebug, 1.0, 1.0, 0.1, $iFindAll) Else Return _ImageSearch_Area($sImagePath, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, -1, $iMaxResults, 1, $iDebug, 1.0, 1.0, 0.1, $iFindAll) EndIf EndFunc ;==>__ExecuteSearch ; #FUNCTION# ==================================================================================================================== ; Name...........: _SearchMultipleImages ; Description....: Performs a search for all selected images at once. ; Parameters.....: $aImageList - Array of image paths to search for. ; ... and other search and action parameters. ; =============================================================================================================================== Func _SearchMultipleImages($aImageList, $bWait, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebug, $iFindAll, $bMove, $iClickType, $iDelay) _UpdateStatus("Mode: Multi Search (All at once)...") _LogWrite("Mode: Multi Search (All at once)") _LogWrite("Find All Occurrences: " & ($iFindAll = 1 ? "Enabled" : "Disabled")) Local $sImageListStr = _ArrayToString($aImageList, "|", 1) Local $aResult = __ExecuteSearch($sImageListStr, $bWait, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebug, $iFindAll) If $iDebug = 1 Then _LogWrite("DLL Return: " & $g_sLastDllReturn) If $g_bImageSearch_Debug Then _LogWrite("DEBUG: UDF returned an array. Checking aResult[0][0] = " & $aResult[0][0]) If $aResult[0][0] > 0 Then _ProcessMultiResults($aResult, $bMove, $iClickType, $iDelay) Else _LogSearchError($aResult[0][0]) EndIf EndFunc ;==>_SearchMultipleImages ; #FUNCTION# ==================================================================================================================== ; Name...........: _SearchSingleImages ; Description....: Performs a search for each selected image individually, one by one. ; Parameters.....: $aImageList - Array of image paths to search for. ; ... and other search and action parameters. ; =============================================================================================================================== Func _SearchSingleImages($aImageList, $bWait, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebug, $iFindAll, $bMove, $iClickType, $iDelay) _LogWrite("Mode: Single Search (One by one)") _LogWrite("Find All Occurrences: " & ($iFindAll = 1 ? "Enabled" : "Disabled")) Local $iTotalFound = 0 For $i = 1 To $aImageList[0] Local $sCurrentImage = $aImageList[$i] Local $sImageName = StringRegExpReplace($sCurrentImage, ".+\\(.+)", "$1") _UpdateStatus("Searching for: " & $sImageName & "...") _LogWrite(" -> Searching for: " & $sImageName) Local $aResult = __ExecuteSearch($sCurrentImage, $bWait, $iWaitTime, $iLeft, $iTop, $iRight, $iBottom, $iTolerance, $iDebug, $iFindAll) If $iDebug = 1 Then _LogWrite("DLL Return: " & $g_sLastDllReturn) If $g_bImageSearch_Debug Then _LogWrite("DEBUG: UDF returned an array. Checking aResult[0][0] = " & $aResult[0][0]) If $aResult[0][0] > 0 Then $iTotalFound += $aResult[0][0] _ProcessMultiResults($aResult, $bMove, $iClickType, $iDelay) Else _LogSearchError($aResult[0][0]) EndIf Next _LogWrite("Single search finished. Total matches found: " & $iTotalFound) EndFunc ;==>_SearchSingleImages ; #FUNCTION# ==================================================================================================================== ; Name...........: _ProcessMultiResults ; Description....: Processes the 2D array result from a search and performs actions for each found item. ; Parameters.....: $aResult - The 2D result array from the UDF. ; $bMove - Boolean, whether to move the mouse. ; $iClickType - 0 for none, 1 for single, 2 for double click. ; $iDelay - Delay in ms after actions. ; =============================================================================================================================== Func _ProcessMultiResults($aResult, $bMove, $iClickType, $iDelay) Local $iFoundCount = $aResult[0][0] _LogWrite("Success: Found " & $iFoundCount & " match(es). Performing actions...") For $i = 1 To $iFoundCount Local $iX = $aResult[$i][1], $iY = $aResult[$i][2], $iW = $aResult[$i][3], $iH = $aResult[$i][4] _UpdateStatus("Performing action on match #" & $i & " at " & $iX & "," & $iY & "...") _LogWrite(" -> Found match #" & $i & " at X=" & $iX & ", Y=" & $iY) _HighlightFoundArea($iX, $iY, $iW, $iH, 0xFF00FF00) _PerformActions($iX, $iY, $bMove, $iClickType, $iDelay) Next _LogWrite("All actions complete for this search cycle.") EndFunc ;==>_ProcessMultiResults ; #FUNCTION# ==================================================================================================================== ; Name...........: _PerformActions ; Description....: Executes the user-defined actions (move, click, delay) at a given coordinate. ; Parameters.....: $iX, $iY - The coordinates to perform actions at. ; ... and other action parameters. ; =============================================================================================================================== Func _PerformActions($iX, $iY, $bMove, $iClickType, $iDelay) If $bMove Then _LogWrite(" - Moving mouse...") MouseMove($iX, $iY, 10) EndIf If $iClickType > 0 Then _LogWrite(" - Performing " & ($iClickType = 1 ? "single" : "double") & " click...") MouseClick("left", $iX, $iY, $iClickType, 0) EndIf _LogWrite(" - Delaying for " & $iDelay & "ms...") Sleep($iDelay) EndFunc ;==>_PerformActions ; === HELPER AND UTILITY FUNCTIONS === ; #FUNCTION# ==================================================================================================================== ; Name...........: _HandleImageCreation ; Description....: Event handler that determines which "Create" button was pressed and calls the creation function. ; Parameters.....: $nMsg - The control ID of the pressed button. ; =============================================================================================================================== Func _HandleImageCreation($nMsg) For $i = 0 To $MAX_IMAGES - 1 If $nMsg = $g_aidBtnCreate[$i] Then _CreateImageFile($g_asImagePaths[$i], "Create/Update Image " & $i + 1, $i) Return EndIf Next EndFunc ;==>_HandleImageCreation ; #FUNCTION# ==================================================================================================================== ; Name...........: _CreateImageFile ; Description....: Manages the process of calling the screen capture function and updating the log/GUI. ; Parameters.....: $sFilePath - The path to save the image file. ; $sTitle - The title for the capture window. ; $iIndex - The index of the image slot being updated. ; =============================================================================================================================== Func _CreateImageFile($sFilePath, $sTitle, $iIndex) _UpdateStatus("Preparing to create image " & $iIndex + 1 & "...") Local $iResult = _CaptureRegion($sTitle, $sFilePath) If $iResult = -1 Then _LogWrite("ERROR: Could not capture screen.") ElseIf $iResult = -2 Then _LogWrite("CANCELLED: User cancelled image creation for " & $sFilePath) Else _LogWrite("Image saved successfully: " & $sFilePath) _UpdateSingleImagePreview($iIndex) EndIf _UpdateStatus("Ready") EndFunc ;==>_CreateImageFile ; #FUNCTION# ==================================================================================================================== ; Name...........: _SelectAreaOnScreen ; Description....: Manages the process of selecting a screen area and updating the GUI input fields. ; =============================================================================================================================== Func _SelectAreaOnScreen() _UpdateStatus("Preparing to select search area...") Local $aCoords = _CaptureRegion("Select an area and release the mouse", "") If Not IsArray($aCoords) Then _LogWrite("INFO: Area selection cancelled.") Else GUICtrlSetData($g_idInputLeft, $aCoords[0]) GUICtrlSetData($g_idInputTop, $aCoords[1]) GUICtrlSetData($g_idInputRight, $aCoords[2]) GUICtrlSetData($g_idInputBottom, $aCoords[3]) _LogWrite("INFO: Search area updated to L:" & $aCoords[0] & " T:" & $aCoords[1] & " R:" & $aCoords[2] & " B:" & $aCoords[3]) EndIf _UpdateStatus("Ready") EndFunc ;==>_SelectAreaOnScreen ; #FUNCTION# ==================================================================================================================== ; Name...........: _CaptureRegion ; Description....: Creates a transparent GUI to allow the user to select a screen region by dragging the mouse. ; MODIFIED: Selection area is now always a square. ; Parameters.....: $sTitle - The title for the capture window. ; $sFilePath - If provided, captures and saves an image. If empty, returns coordinates. ; Return values..: If $sFilePath is provided: 0 on success, -1 on capture error, -2 on user cancel. ; If $sFilePath is empty: A 4-element array [Left, Top, Right, Bottom] on success, -2 on user cancel. ; =============================================================================================================================== Func _CaptureRegion($sTitle, $sFilePath) Local $hUserDLL = DllOpen("user32.dll") If $hUserDLL = -1 Then Return -1 Local $hCrossGUI = GUICreate($sTitle, @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) GUISetBkColor(0x000001) WinSetTrans($hCrossGUI, "", 1) GUISetState(@SW_SHOW, $hCrossGUI) GUISetCursor(3, 1, $hCrossGUI) _UpdateStatus("Drag the mouse to select a square area. Press ESC to cancel.") ToolTip("Drag the mouse to select a square area. Press ESC to cancel.", 0, 0) While Not _IsPressed("01", $hUserDLL) If _IsPressed("1B", $hUserDLL) Then ToolTip("") GUIDelete($hCrossGUI) DllClose($hUserDLL) Return -2 EndIf Sleep(20) WEnd ToolTip("") Local $aStartPos = MouseGetPos() Local $iX1 = $aStartPos[0], $iY1 = $aStartPos[1] Local $hRectGUI While _IsPressed("01", $hUserDLL) Local $aCurrentPos = MouseGetPos() Local $iX2 = $aCurrentPos[0], $iY2 = $aCurrentPos[1] If IsHWnd($hRectGUI) Then GUIDelete($hRectGUI) ; Calculate the absolute width and height of the drag area Local $iAbsWidth = Abs($iX1 - $iX2) Local $iAbsHeight = Abs($iY1 - $iY2) ; Determine the side length of the square (the larger of width or height) Local $iSide = _Max($iAbsWidth, $iAbsHeight) ; Determine the top-left corner of the square based on drag direction Local $iLeft_Temp = $iX1 If $iX2 < $iX1 Then $iLeft_Temp = $iX1 - $iSide Local $iTop_Temp = $iY1 If $iY2 < $iY1 Then $iTop_Temp = $iY1 - $iSide ; Create the square feedback GUI $hRectGUI = GUICreate("", $iSide, $iSide, $iLeft_Temp, $iTop_Temp, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) GUISetBkColor(0xFF0000) _WinAPI_SetLayeredWindowAttributes($hRectGUI, 0, 100) GUISetState(@SW_SHOWNOACTIVATE, $hRectGUI) Sleep(10) WEnd Local $aEndPos = MouseGetPos() Local $iX2 = $aEndPos[0], $iY2 = $aEndPos[1] GUIDelete($hCrossGUI) If IsHWnd($hRectGUI) Then GUIDelete($hRectGUI) DllClose($hUserDLL) ; Final coordinate calculation for the square Local $iAbsWidth = Abs($iX1 - $iX2) Local $iAbsHeight = Abs($iY1 - $iY2) Local $iSide = _Max($iAbsWidth, $iAbsHeight) If $iSide = 0 Then Return -2 ; If there was no drag, treat as cancel Local $iLeft = $iX1 If $iX2 < $iX1 Then $iLeft = $iX1 - $iSide Local $iTop = $iY1 If $iY2 < $iY1 Then $iTop = $iY1 - $iSide Local $iRight = $iLeft + $iSide Local $iBottom = $iTop + $iSide ; If $sFilePath is empty, it's an area selection, not an image capture If $sFilePath = "" Then Local $aReturn[4] = [$iLeft, $iTop, $iRight, $iBottom] Return $aReturn EndIf Local $aMousePos = MouseGetPos() MouseMove(0, 0, 0) Sleep(250) Local $hBitmap = _ScreenCapture_Capture("", $iLeft, $iTop, $iRight, $iBottom, False) If @error Then MouseMove($aMousePos[0], $aMousePos[1], 0) Return -1 EndIf Local $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) _GDIPlus_ImageSaveToFile($hImage, $sFilePath) _GDIPlus_BitmapDispose($hImage) _WinAPI_DeleteObject($hBitmap) MouseMove($aMousePos[0], $aMousePos[1], 0) Return 0 EndFunc ;==>_CaptureRegion ; #FUNCTION# ==================================================================================================================== ; Name...........: _CaptureRegion ; Description....: Creates a transparent GUI to allow the user to select a screen region by dragging the mouse. ; Parameters.....: $sTitle - The title for the capture window. ; $sFilePath - If provided, captures and saves an image. If empty, returns coordinates. ; Return values..: If $sFilePath is provided: 0 on success, -1 on capture error, -2 on user cancel. ; If $sFilePath is empty: A 4-element array [Left, Top, Right, Bottom] on success, -2 on user cancel. ; =============================================================================================================================== Func _CaptureRegion_free($sTitle, $sFilePath) Local $hUserDLL = DllOpen("user32.dll") If $hUserDLL = -1 Then Return -1 Local $hCrossGUI = GUICreate($sTitle, @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) GUISetBkColor(0x000001) WinSetTrans($hCrossGUI, "", 1) GUISetState(@SW_SHOW, $hCrossGUI) GUISetCursor(3, 1, $hCrossGUI) _UpdateStatus("Drag the mouse to select an area. Press ESC to cancel.") ToolTip("Drag the mouse to select an area. Press ESC to cancel.", 0, 0) While Not _IsPressed("01", $hUserDLL) If _IsPressed("1B", $hUserDLL) Then ToolTip("") GUIDelete($hCrossGUI) DllClose($hUserDLL) Return -2 EndIf Sleep(20) WEnd ToolTip("") Local $aStartPos = MouseGetPos() Local $iX1 = $aStartPos[0], $iY1 = $aStartPos[1] Local $hRectGUI While _IsPressed("01", $hUserDLL) Local $aCurrentPos = MouseGetPos() Local $iX2 = $aCurrentPos[0], $iY2 = $aCurrentPos[1] If IsHWnd($hRectGUI) Then GUIDelete($hRectGUI) Local $iLeft = ($iX1 < $iX2 ? $iX1 : $iX2) Local $iTop = ($iY1 < $iY2 ? $iY1 : $iY2) Local $iWidth = Abs($iX1 - $iX2) Local $iHeight = Abs($iY1 - $iY2) $hRectGUI = GUICreate("", $iWidth, $iHeight, $iLeft, $iTop, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) GUISetBkColor(0xFF0000) _WinAPI_SetLayeredWindowAttributes($hRectGUI, 0, 100) GUISetState(@SW_SHOWNOACTIVATE, $hRectGUI) Sleep(10) WEnd Local $aEndPos = MouseGetPos() Local $iX2 = $aEndPos[0], $iY2 = $aEndPos[1] GUIDelete($hCrossGUI) If IsHWnd($hRectGUI) Then GUIDelete($hRectGUI) DllClose($hUserDLL) Local $iLeft = ($iX1 < $iX2 ? $iX1 : $iX2) Local $iTop = ($iY1 < $iY2 ? $iY1 : $iY2) Local $iRight = ($iX1 > $iX2 ? $iX1 : $iX2) Local $iBottom = ($iY1 > $iY2 ? $iY1 : $iY2) ; If $sFilePath is empty, it's an area selection, not an image capture If $sFilePath = "" Then Local $aReturn[4] = [$iLeft, $iTop, $iRight, $iBottom] Return $aReturn EndIf Local $aMousePos = MouseGetPos() MouseMove(0, 0, 0) Sleep(250) Local $hBitmap = _ScreenCapture_Capture("", $iLeft, $iTop, $iRight, $iBottom, False) If @error Then MouseMove($aMousePos[0], $aMousePos[1], 0) Return -1 EndIf Local $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) _GDIPlus_ImageSaveToFile($hImage, $sFilePath) _GDIPlus_BitmapDispose($hImage) _WinAPI_DeleteObject($hBitmap) MouseMove($aMousePos[0], $aMousePos[1], 0) Return 0 EndFunc ;==>_CaptureRegion ; #FUNCTION# ==================================================================================================================== ; Name...........: _HighlightFoundArea ; Description....: Creates a temporary, semi-transparent GUI to highlight a found image location. ; Parameters.....: $iX, $iY - The center coordinates of the area to highlight. ; $iWidth - The width of the highlight rectangle. ; $iHeight - The height of the highlight rectangle. ; $iColor - [optional] The color of the highlight rectangle. ; =============================================================================================================================== Func _HighlightFoundArea($iX, $iY, $iWidth, $iHeight, $iColor = 0xFFFF0000) Local $hGUI = GUICreate("", $iWidth, $iHeight, $iX - $iWidth / 2, $iY - $iHeight / 2, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST, $WS_EX_TOOLWINDOW)) GUISetBkColor($iColor) _WinAPI_SetLayeredWindowAttributes($hGUI, 0, 128) GUISetState(@SW_SHOWNOACTIVATE) Sleep(500) GUIDelete($hGUI) EndFunc ;==>_HighlightFoundArea ; #FUNCTION# ==================================================================================================================== ; Name...........: _LogWrite ; Description....: Writes a timestamped message to the activity log and ensures it scrolls to the bottom. ; Parameters.....: $sMessage - The string message to log. ; =============================================================================================================================== Func _LogWrite($sMessage) GUICtrlSetData($g_hLog, _NowTime() & " " & $sMessage & @CRLF, 1) _GUICtrlEdit_SetSel(GUICtrlGetHandle($g_hLog), 0x7FFFFFFF, 0x7FFFFFFF) EndFunc ;==>_LogWrite ; #FUNCTION# ==================================================================================================================== ; Name...........: _LogSearchError ; Description....: Translates an error code from the UDF into a human-readable message and logs it. ; Parameters.....: $iErrorCode - The status code returned by the _ImageSearch* function. ; =============================================================================================================================== Func _LogSearchError($iErrorCode) Switch $iErrorCode Case 0 _LogWrite(" - Not found.") Case -1 _LogWrite("ERROR: DllCall failed. Check if the DLL is corrupted or blocked by antivirus.") Case -2 _LogWrite("ERROR: Invalid format returned from DLL. The UDF could not parse the result.") Case -3 _LogWrite("ERROR: Invalid content returned from DLL. The result string was malformed.") Case -11 _LogWrite("ERROR: The source image file was not found on disk (checked by UDF).") Case -12 _LogWrite("ERROR: Failed to deploy or load the ImageSearch DLL. Call _ImageSearch_Startup().") Case Else _LogWrite("ERROR: An internal DLL error occurred. Code: " & $iErrorCode) EndSwitch EndFunc ;==>_LogSearchError ; #FUNCTION# ==================================================================================================================== ; Name...........: _UpdateAllImagePreviews ; Description....: Iterates through all image slots and updates their preview images. ; =============================================================================================================================== Func _UpdateAllImagePreviews() For $i = 0 To $MAX_IMAGES - 1 _UpdateSingleImagePreview($i) Next EndFunc ;==>_UpdateAllImagePreviews ; #FUNCTION# ==================================================================================================================== ; Name...........: _UpdateSingleImagePreview ; Description....: Updates a single image preview slot. Shows the placeholder if the image doesn't exist. ; Parameters.....: $iIndex - The index of the image slot to update. ; =============================================================================================================================== Func _UpdateSingleImagePreview($iIndex) If FileExists($g_asImagePaths[$iIndex]) Then GUICtrlSetImage($g_aidPic[$iIndex], $g_asImagePaths[$iIndex]) Else If FileExists($g_sPlaceholderPath) Then GUICtrlSetImage($g_aidPic[$iIndex], $g_sPlaceholderPath) Else GUICtrlSetImage($g_aidPic[$iIndex], "shell32.dll", 22) EndIf EndIf EndFunc ;==>_UpdateSingleImagePreview ; #FUNCTION# ==================================================================================================================== ; Name...........: _SelectAll ; Description....: Checks or unchecks all image target checkboxes. ; Parameters.....: $bState - True to check all, False to uncheck all. ; =============================================================================================================================== Func _SelectAll($bState) Local $iCheckState = $GUI_UNCHECKED If $bState Then $iCheckState = $GUI_CHECKED For $i = 0 To $MAX_IMAGES - 1 GUICtrlSetState($g_aidChkSearch[$i], $iCheckState) Next EndFunc ;==>_SelectAll ; #FUNCTION# ==================================================================================================================== ; Name...........: _UpdateStatus ; Description....: Sets the text of the status bar. ; Parameters.....: $sMessage - The message to display. ; =============================================================================================================================== Func _UpdateStatus($sMessage) _GUICtrlStatusBar_SetText($g_hStatusBar, $sMessage) EndFunc ;==>_UpdateStatus ; #FUNCTION# ==================================================================================================================== ; Name...........: _Exit ; Description....: Exits the script cleanly. This will trigger the OnAutoItExitRegister function. ; =============================================================================================================================== Func _Exit() _GDIPlus_Shutdown() Exit EndFunc ;==>_Exit ; Dao Van Trong - TRONG.PRO This program is an example of using ImageSearchUDF. Download ImageSearchUDF here: Download ImageSearch Automation Suite HERE:
  9. Yes, thanks. I forgot to fix it when fixing the "If Not IsNumber()" bug!
  10. Version 2.5.0.0

    38 downloads

    A professional tool to convert binary files into self-contained AutoIt hex functions. Features architecture detection, GUI and CLI modes, and robust code generation.
  11. Helper App: ; ================================================================================================= ; Title .........: AutoIt Embedded File Generator ; Author(s) .....: Dao Van Trong - TRONG.PRO ; Version .......: 2.5 (Fixed syntax and delimiter logic in generated code) ; Description ...: A professional tool to convert binary files into self-contained AutoIt hex functions. ; Features architecture detection, GUI and CLI modes, and robust code generation. ; ================================================================================================= #Region ; *** INCLUDES *** #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <Clipboard.au3> #include <File.au3> #include <Array.au3> #include <ListViewConstants.au3> #EndRegion ; *** INCLUDES *** #Region ; *** GLOBAL VARIABLES *** ; Global variables for GUI controls Global $g_hGUI, $g_hListView, $g_hEditOutput, $g_hInputChunkSize Global $g_hBtnAddFiles, $g_hBtnRemoveSelected, $g_hBtnClearAll, $g_hCheckAddHelpers, $g_hBtnGenerate, $g_hBtnPreview, $g_hBtnCopy, $g_hBtnSaveAll, $g_hBtnSaveSeparate, $g_hBtnExit ; Global 2D array to store file information. ; Index [x][0]: Full Path ; Index [x][1]: File Name ; Index [x][2]: Formatted File Size ; Index [x][3]: Architecture ; Index [x][4]: Generated Function Name Global $g_aSelectedFiles[0][5] #EndRegion ; *** GLOBAL VARIABLES *** #Region ; *** SCRIPT ENTRY POINT *** ; Check if command-line arguments were provided to determine execution mode. If $CmdLine[0] > 0 Then _RunCommandLineMode() Else _RunGuiMode() EndIf #EndRegion ; *** SCRIPT ENTRY POINT *** #Region ; *** GUI MODE FUNCTIONS *** ; ------------------------------------------------------------------------------------------------- ; Function: _RunGuiMode() ; Purpose: Creates and manages the main Graphical User Interface (GUI). ; ------------------------------------------------------------------------------------------------- Func _RunGuiMode() $g_hGUI = GUICreate("AutoIt Embedded File Generator by Dao Van Trong - TRONG.PRO", 800, 650) GUISetBkColor(0xF0F0F0) _CreateGUI_Controls() GUISetState(@SW_SHOW, $g_hGUI) Local $nMsg While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE, $g_hBtnExit ExitLoop Case $g_hBtnAddFiles _GUI_HandleAddFiles() Case $g_hBtnRemoveSelected _GUI_HandleRemoveSelected() Case $g_hBtnClearAll _GUI_HandleClearAll() Case $g_hBtnGenerate _GUI_HandleGenerateAll() Case $g_hBtnPreview _GUI_HandlePreviewSingle() Case $g_hBtnCopy _GUI_HandleCopyToClipboard() Case $g_hBtnSaveAll _GUI_HandleSaveAll() Case $g_hBtnSaveSeparate _GUI_HandleSaveSeparate() EndSwitch WEnd GUIDelete($g_hGUI) EndFunc ;==>_RunGuiMode ; ------------------------------------------------------------------------------------------------- ; Function: _CreateGUI_Controls() ; Purpose: Creates all controls for the main GUI window. ; ------------------------------------------------------------------------------------------------- Func _CreateGUI_Controls() GUICtrlCreateLabel("1. File Selection:", 10, 15, 150, 20) GUICtrlSetFont(-1, 9, 600) $g_hBtnAddFiles = GUICtrlCreateButton("Add Files...", 10, 35, 100, 25) $g_hBtnRemoveSelected = GUICtrlCreateButton("Remove Selected", 120, 35, 120, 25) $g_hBtnClearAll = GUICtrlCreateButton("Clear All", 250, 35, 80, 25) $g_hListView = GUICtrlCreateListView("File Name|Size|Architecture|Function Name", 10, 70, 780, 150) GUICtrlSendMsg($g_hListView, $LVM_SETCOLUMNWIDTH, 0, 250) GUICtrlSendMsg($g_hListView, $LVM_SETCOLUMNWIDTH, 1, 100) GUICtrlSendMsg($g_hListView, $LVM_SETCOLUMNWIDTH, 2, 100) GUICtrlSendMsg($g_hListView, $LVM_SETCOLUMNWIDTH, 3, 320) GUICtrlCreateLabel("2. Generation Options:", 10, 235, 150, 20) GUICtrlSetFont(-1, 9, 600) GUICtrlCreateLabel("Line Length (chars):", 20, 260, 120, 20) $g_hInputChunkSize = GUICtrlCreateInput("4000", 150, 257, 100, 22) $g_hCheckAddHelpers = GUICtrlCreateCheckbox("Include helper functions", 270, 257, 150, 22) GUICtrlSetState($g_hCheckAddHelpers, $GUI_CHECKED) $g_hBtnGenerate = GUICtrlCreateButton("3. Generate All Functions", 10, 290, 200, 35) GUICtrlSetFont(-1, 10, 700) GUICtrlSetBkColor($g_hBtnGenerate, 0x90EE90) $g_hBtnPreview = GUICtrlCreateButton("Preview Single", 220, 290, 100, 35) GUICtrlCreateLabel("Generated Code:", 10, 340, 150, 20) GUICtrlSetFont(-1, 9, 600) $g_hEditOutput = GUICtrlCreateEdit("", 10, 360, 780, 220, $WS_VSCROLL + $WS_HSCROLL) GUICtrlSetFont(-1, 9, 400, 0, "Consolas") $g_hBtnCopy = GUICtrlCreateButton("Copy to Clipboard", 10, 590, 130, 30) $g_hBtnSaveAll = GUICtrlCreateButton("Save All to File", 150, 590, 130, 30) $g_hBtnSaveSeparate = GUICtrlCreateButton("Save Separate Files", 290, 590, 130, 30) $g_hBtnExit = GUICtrlCreateButton("Exit", 660, 590, 130, 30) GUICtrlSetBkColor($g_hBtnExit, 0xFFB6C1) EndFunc ;==>_CreateGUI_Controls ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleAddFiles() ; Purpose: Opens a file dialog and adds selected files to the list. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleAddFiles() Local $sFiles = FileOpenDialog("Select Files", @ScriptDir, "All Files (*.*)", 4) If @error Then Return Local $aNewFiles = StringSplit($sFiles, "|") If $aNewFiles[0] = 1 Then _AddFileToList($aNewFiles[1]) Else Local $sBasePath = $aNewFiles[1] For $i = 2 To $aNewFiles[0] _AddFileToList($sBasePath & "\" & $aNewFiles[$i]) Next EndIf EndFunc ;==>_GUI_HandleAddFiles ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleRemoveSelected() ; Purpose: Removes the selected file from the list. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleRemoveSelected() Local $iIndex = GUICtrlSendMsg($g_hListView, $LVM_GETNEXTITEM, -1, $LVNI_SELECTED) If $iIndex = -1 Then Return _ArrayDelete($g_aSelectedFiles, $iIndex) GUICtrlSendMsg($g_hListView, $LVM_DELETEITEM, $iIndex, 0) EndFunc ;==>_GUI_HandleRemoveSelected ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleClearAll() ; Purpose: Clears all files from the list and resets the UI. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleClearAll() ReDim $g_aSelectedFiles[0][5] GUICtrlSendMsg($g_hListView, $LVM_DELETEALLITEMS, 0, 0) GUICtrlSetData($g_hEditOutput, "") EndFunc ;==>_GUI_HandleClearAll ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleGenerateAll() ; Purpose: Generates the complete code for all files in the list. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleGenerateAll() If UBound($g_aSelectedFiles) = 0 Then Return MsgBox(48, "Warning", "Please add at least one file first.") GUICtrlSetData($g_hEditOutput, "Generating code, please wait...") Sleep(10) Local $bAddHelpers = (GUICtrlRead($g_hCheckAddHelpers) = $GUI_CHECKED) Local $iChunkSize = _ValidateChunkSize(GUICtrlRead($g_hInputChunkSize)) Local $sCode = _GenerateCodeBundle($g_aSelectedFiles, $bAddHelpers, $iChunkSize) GUICtrlSetData($g_hEditOutput, $sCode) EndFunc ;==>_GUI_HandleGenerateAll ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandlePreviewSingle() ; Purpose: Generates code for only the selected file. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandlePreviewSingle() Local $iIndex = GUICtrlSendMsg($g_hListView, $LVM_GETNEXTITEM, -1, $LVNI_SELECTED) If $iIndex = -1 Then Return MsgBox(48, "Warning", "Please select a file from the list first.") GUICtrlSetData($g_hEditOutput, "Generating preview...") Sleep(10) Local $iChunkSize = _ValidateChunkSize(GUICtrlRead($g_hInputChunkSize)) Local $sOutput = "; Preview for: " & $g_aSelectedFiles[$iIndex][1] & @CRLF $sOutput &= "; Architecture: " & $g_aSelectedFiles[$iIndex][3] & @CRLF & @CRLF $sOutput &= _GenerateHexFunction($g_aSelectedFiles[$iIndex][0], $g_aSelectedFiles[$iIndex][4], $g_aSelectedFiles[$iIndex][1], $g_aSelectedFiles[$iIndex][3], "$sHexData", $iChunkSize) GUICtrlSetData($g_hEditOutput, $sOutput) EndFunc ;==>_GUI_HandlePreviewSingle ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleCopyToClipboard() ; Purpose: Copies the output text to the clipboard. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleCopyToClipboard() Local $sCode = GUICtrlRead($g_hEditOutput) If StringStripWS($sCode, 8) = "" Then Return MsgBox(48, "Warning", "No code to copy. Please generate code first.") _ClipBoard_SetData($sCode) ToolTip("Code copied to clipboard!", @DesktopWidth / 2, @DesktopHeight / 2, "Success", 1, 1) Sleep(1500) ToolTip("") EndFunc ;==>_GUI_HandleCopyToClipboard ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleSaveAll() ; Purpose: Saves the generated code for all files into a single .au3 file. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleSaveAll() Local $sCode = GUICtrlRead($g_hEditOutput) If StringStripWS($sCode, 8) = "" Then Return MsgBox(48, "Warning", "No code to save. Please generate code first.") Local $sSaveFile = FileSaveDialog("Save Combined Code", @ScriptDir, "AutoIt Scripts (*.au3)", 16, "All_Embedded.au3") If @error Then Return If Not _SaveStringToFile($sSaveFile, $sCode) Then MsgBox(16, "Error", "Could not create file: " & $sSaveFile) Else MsgBox(64, "Success", "All functions saved to: " & @CRLF & $sSaveFile) EndIf EndFunc ;==>_GUI_HandleSaveAll ; ------------------------------------------------------------------------------------------------- ; Function: _GUI_HandleSaveSeparate() ; Purpose: Saves the generated code for each file into its own separate .au3 file. ; ------------------------------------------------------------------------------------------------- Func _GUI_HandleSaveSeparate() If UBound($g_aSelectedFiles) = 0 Then Return MsgBox(48, "Warning", "No files to process.") Local $sSaveDir = FileSelectFolder("Select folder to save separate files", @ScriptDir) If @error Then Return Local $iChunkSize = _ValidateChunkSize(GUICtrlRead($g_hInputChunkSize)) Local $bAddHelpers = (GUICtrlRead($g_hCheckAddHelpers) = $GUI_CHECKED) Local $iSaved = 0 For $i = 0 To UBound($g_aSelectedFiles) - 1 Local $sFilePath = $g_aSelectedFiles[$i][0] Local $sFileName = $g_aSelectedFiles[$i][1] Local $sArch = $g_aSelectedFiles[$i][3] Local $sFuncName = $g_aSelectedFiles[$i][4] Local $sDrive, $sDir, $sNameOnly, $sExt _PathSplit($sFilePath, $sDrive, $sDir, $sNameOnly, $sExt) Local $sSaveFile = $sSaveDir & "\" & $sNameOnly & "_Embedded.au3" Local $sCode = "; Generated from: " & $sFileName & @CRLF $sCode &= "; Architecture: " & $sArch & @CRLF & @CRLF $sCode &= _GenerateHexFunction($sFilePath, $sFuncName, $sFileName, $sArch, "$sHexData", $iChunkSize) If $bAddHelpers Then $sCode &= _GenerateHelperFunction($sFuncName, $sFileName) EndIf If _SaveStringToFile($sSaveFile, $sCode) Then $iSaved += 1 Next MsgBox(64, "Success", "Saved " & $iSaved & " of " & UBound($g_aSelectedFiles) & " files to:" & @CRLF & $sSaveDir) EndFunc ;==>_GUI_HandleSaveSeparate #EndRegion ; *** GUI MODE FUNCTIONS *** #Region ; *** COMMAND-LINE MODE FUNCTIONS *** ; ------------------------------------------------------------------------------------------------- ; Function: _RunCommandLineMode() ; Purpose: Handles the script's execution when run from the command line. ; ------------------------------------------------------------------------------------------------- Func _RunCommandLineMode() Local $aFilePaths[0] For $i = 1 To $CmdLine[0] If FileExists($CmdLine[$i]) Then _ArrayAdd($aFilePaths, $CmdLine[$i]) Else ConsoleWrite("! Warning: File not found - " & $CmdLine[$i] & @CRLF) EndIf Next If UBound($aFilePaths) = 0 Then ConsoleWrite("! Error: No valid files provided." & @CRLF & " Usage: " & @ScriptName & " <file1> [file2] ..." & @CRLF) Exit 1 EndIf Local $aFilesData[UBound($aFilePaths)][5] For $i = 0 To UBound($aFilePaths) - 1 _PopulateFileInfo($aFilesData, $i, $aFilePaths[$i]) Next ConsoleWrite("+ Generating code for " & UBound($aFilesData) & " file(s)..." & @CRLF) Local $sCode = _GenerateCodeBundle($aFilesData, True, 4000) Local $sOutputFile If UBound($aFilesData) = 1 Then Local $sDrive, $sDir, $sFileName, $sExtension _PathSplit($aFilePaths[0], $sDrive, $sDir, $sFileName, $sExtension) $sOutputFile = $sDrive & $sDir & $sFileName & "_Embedded.au3" Else $sOutputFile = @ScriptDir & "\All_Embedded.au3" EndIf If _SaveStringToFile($sOutputFile, $sCode) Then ConsoleWrite("+ Success: Output saved to - " & $sOutputFile & @CRLF) Else ConsoleWrite("! Error: Could not create output file - " & $sOutputFile & @CRLF) Exit 1 EndIf EndFunc ;==>_RunCommandLineMode #EndRegion ; *** COMMAND-LINE MODE FUNCTIONS *** #Region ; *** FILE AND DATA HANDLING *** ; ------------------------------------------------------------------------------------------------- ; Function: _AddFileToList($sFilePath) ; Purpose: Adds a file's information to the global array and updates the GUI list. ; ------------------------------------------------------------------------------------------------- Func _AddFileToList($sFilePath) If Not FileExists($sFilePath) Then Return For $i = 0 To UBound($g_aSelectedFiles) - 1 If $g_aSelectedFiles[$i][0] = $sFilePath Then Return Next Local $iUBound = UBound($g_aSelectedFiles) ReDim $g_aSelectedFiles[$iUBound + 1][5] _PopulateFileInfo($g_aSelectedFiles, $iUBound, $sFilePath) Local $sListViewItem = $g_aSelectedFiles[$iUBound][1] & "|" & $g_aSelectedFiles[$iUBound][2] & "|" & $g_aSelectedFiles[$iUBound][3] & "|" & $g_aSelectedFiles[$iUBound][4] GUICtrlCreateListViewItem($sListViewItem, $g_hListView) EndFunc ;==>_AddFileToList ; ------------------------------------------------------------------------------------------------- ; Function: _PopulateFileInfo(ByRef $aArray, $iIndex, $sFilePath) ; Purpose: Gathers file info and populates a row in the provided 2D array. ; ------------------------------------------------------------------------------------------------- Func _PopulateFileInfo(ByRef $aArray, $iIndex, $sFilePath) Local $sFileName = _GetFileName($sFilePath) Local $sArch = _DetectArchitecture($sFilePath) $aArray[$iIndex][0] = $sFilePath $aArray[$iIndex][1] = $sFileName $aArray[$iIndex][2] = _FormatFileSize(FileGetSize($sFilePath)) $aArray[$iIndex][3] = $sArch $aArray[$iIndex][4] = "_GetBinData_" & _SanitizeName($sFileName) & "_" & $sArch EndFunc ;==>_PopulateFileInfo #EndRegion ; *** FILE AND DATA HANDLING *** #Region ; *** CORE CODE GENERATION *** ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateCodeBundle(ByRef $aFiles, $bAddHelpers, $iChunkSize) ; Purpose: The main code generation engine. Creates the full script content. ; ------------------------------------------------------------------------------------------------- Func _GenerateCodeBundle(ByRef $aFiles, $bAddHelpers, $iChunkSize) Local $sOutput = "; Generated by AutoIt Embedded File Generator - TRONG.PRO" & @CRLF $sOutput &= "; Total files: " & UBound($aFiles) & @CRLF $sOutput &= "; Generated on: " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF For $i = 0 To UBound($aFiles) - 1 $sOutput &= _GenerateHexFunction($aFiles[$i][0], $aFiles[$i][4], $aFiles[$i][1], $aFiles[$i][3], "$sHexData", $iChunkSize) & @CRLF & @CRLF Next If $bAddHelpers Then If UBound($aFiles) = 1 Then $sOutput &= _GenerateHelperFunction($aFiles[0][4], $aFiles[0][1]) Else $sOutput &= _GenerateMasterHelperFunctionFromArray($aFiles) EndIf EndIf Return $sOutput EndFunc ;==>_GenerateCodeBundle ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateHexFunction($sFilePath, $sFuncName, $sFileName, $sArch, $sVarName, $iChunkSize) ; Purpose: Reads a binary file and wraps its hex content in an AutoIt function. ; ------------------------------------------------------------------------------------------------- Func _GenerateHexFunction($sFilePath, $sFuncName, $sFileName, $sArch, $sVarName = "$sHexData", $iChunkSize = 4000) Local $hFile = FileOpen($sFilePath, 16) If $hFile = -1 Then ConsoleWrite("! Error: Unable to open file in binary mode: " & $sFilePath & @CRLF) Return "" EndIf Local $bData = FileRead($hFile) FileClose($hFile) If @error Or $bData = "" Then ConsoleWrite("! Error reading binary data from file: " & $sFilePath & @CRLF) Return "" EndIf Local $sHexWithPrefix = StringToBinary($bData) If StringLeft($sVarName, 1) <> "$" Then $sVarName = "$" & $sVarName Local $sOutput = "Func " & $sFuncName & "()" & @CRLF $sOutput &= @TAB & '; This function holds the hex data for ' & $sFileName & @CRLF $sOutput &= @TAB & '; File size: ' & _FormatFileSize(FileGetSize($sFilePath)) & @CRLF $sOutput &= @TAB & '; Architecture: ' & $sArch & @CRLF $sOutput &= @TAB & '; Generated by AutoIt Embedded File Generator' & @CRLF Local $iHexLen = StringLen($sHexWithPrefix) $sOutput &= @TAB & "Local " & $sVarName & " = '" & StringMid($sHexWithPrefix, 1, $iChunkSize) & "'" & @CRLF For $i = $iChunkSize + 1 To $iHexLen Step $iChunkSize $sOutput &= @TAB & $sVarName & " &= '" & StringMid($sHexWithPrefix, $i, $iChunkSize) & "'" & @CRLF Next $sOutput &= @CRLF & @TAB & "Return " & $sVarName & @CRLF $sOutput &= "EndFunc ;==>" & $sFuncName Return $sOutput EndFunc ;==>_GenerateHexFunction ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateHelperFunction($sFuncName, $sOriginalFileName) ; Purpose: Generates a helper function to deploy a single embedded file. ; ------------------------------------------------------------------------------------------------- Func _GenerateHelperFunction($sFuncName, $sOriginalFileName) Local $sHelperFunc = @CRLF & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= '; Helper function to deploy the file from hex data.' & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= 'Func _DeployFileFromHex()' & @CRLF $sHelperFunc &= @TAB & 'Local $sHexData = ' & $sFuncName & '()' & @CRLF $sHelperFunc &= @TAB & 'Local $Deploy_Dir = @TempDir' & @CRLF $sHelperFunc &= @TAB & 'If $sHexData = "" Then Return SetError(1, 0, MsgBox(16, "Error", "Hex data is empty."))' & @CRLF $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & 'Local $sOutputFilename = "' & $sOriginalFileName & '"' & @CRLF $sHelperFunc &= @TAB & 'Local $sTempFilePath = $Deploy_Dir & "\" & $sOutputFilename' & @CRLF $sHelperFunc &= @TAB & 'Local $hFile = FileOpen($sTempFilePath, 18)' & @CRLF $sHelperFunc &= @TAB & 'If $hFile = -1 Then Return SetError(2, 0, MsgBox(16, "Error", "Failed to open file for writing at: " & $sTempFilePath))' & @CRLF $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & 'FileWrite($hFile, BinaryToString($sHexData))' & @CRLF $sHelperFunc &= @TAB & 'FileClose($hFile)' & @CRLF $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & 'If Not FileExists($sTempFilePath) Then Return SetError(3, 0, MsgBox(16, "Error", "Failed to write file to: " & $sTempFilePath))' & @CRLF $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & 'MsgBox(64, "Success", "File deployed successfully to:" & @CRLF & $sTempFilePath)' & @CRLF $sHelperFunc &= @TAB & 'Return $sTempFilePath' & @CRLF $sHelperFunc &= 'EndFunc ;==>_DeployFileFromHex' & @CRLF & @CRLF $sHelperFunc &= '; Example usage: _DeployFileFromHex()' & @CRLF Return $sHelperFunc EndFunc ;==>_GenerateHelperFunction ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateMasterHelperFunctionFromArray(ByRef $aFiles) ; Purpose: Generates a master helper function to deploy all embedded files. ; ------------------------------------------------------------------------------------------------- Func _GenerateMasterHelperFunctionFromArray(ByRef $aFiles) Local $sDelimiter = '"/"' Local $sHelperFunc = "#include <Array.au3>" & @CRLF & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= '; Master helper function to deploy all embedded files.' & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= 'Func _DeployAllFiles()' & @CRLF $sHelperFunc &= @TAB & 'Local $aResults[0]' & @CRLF $sHelperFunc &= @TAB & 'Local $Deploy_Dir = @TempDir' & @CRLF $sHelperFunc &= @CRLF For $i = 0 To UBound($aFiles) - 1 Local $sFileName = $aFiles[$i][1] Local $sFuncName = $aFiles[$i][4] Local $sArch = $aFiles[$i][3] $sHelperFunc &= @TAB & '; Deploy ' & $sFileName & ' (' & $sArch & ')' & @CRLF $sHelperFunc &= @TAB & 'Local $sHexData' & $i & ' = ' & $sFuncName & '()' & @CRLF $sHelperFunc &= @TAB & 'If $sHexData' & $i & ' <> "" Then' & @CRLF $sHelperFunc &= @TAB & @TAB & 'Local $sOutputPath' & $i & ' = $Deploy_Dir & "\' & $sFileName & '"' & @CRLF $sHelperFunc &= @TAB & @TAB & 'Local $hFile' & $i & ' = FileOpen($sOutputPath' & $i & ', 18)' & @CRLF $sHelperFunc &= @TAB & @TAB & 'If $hFile' & $i & ' <> -1 Then' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'FileWrite($hFile' & $i & ', BinaryToString($sHexData' & $i & '))' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'FileClose($hFile' & $i & ')' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'If FileExists($sOutputPath' & $i & ') Then' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & @TAB & '_ArrayAdd($aResults, "' & $sFileName & '" & ' & $sDelimiter & ' & $sOutputPath' & $i & ' & ' & $sDelimiter & ' & "Success")' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'Else' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & @TAB & '_ArrayAdd($aResults, "' & $sFileName & '" & ' & $sDelimiter & ' & "' & $sArch & '" & ' & $sDelimiter & ' & "Write failed")' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & @TAB & 'Else' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & '_ArrayAdd($aResults, "' & $sFileName & '" & ' & $sDelimiter & ' & "' & $sArch & '" & ' & $sDelimiter & ' & "Cannot create file")' & @CRLF $sHelperFunc &= @TAB & @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & 'Else' & @CRLF $sHelperFunc &= @TAB & @TAB & '_ArrayAdd($aResults, "' & $sFileName & '" & ' & $sDelimiter & ' & "' & $sArch & '" & ' & $sDelimiter & ' & "No hex data")' & @CRLF $sHelperFunc &= @TAB & 'EndIf' & @CRLF $sHelperFunc &= @CRLF Next $sHelperFunc &= @TAB & '; Display results' & @CRLF $sHelperFunc &= @TAB & 'Local $sReport = "Deployment Results (" & UBound($aResults) & " files):" & @CRLF & @CRLF' & @CRLF $sHelperFunc &= @TAB & 'For $i = 0 To UBound($aResults) - 1' & @CRLF $sHelperFunc &= @TAB & @TAB & 'Local $aParts = StringSplit($aResults[$i], ' & $sDelimiter & ')' & @CRLF $sHelperFunc &= @TAB & @TAB & 'If $aParts[0] = 3 Then' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & '$sReport &= "• " & $aParts[1] & ": " & $aParts[3]' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'If $aParts[3] = "Success" Then' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & @TAB & '$sReport &= " → " & $aParts[2]' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'Else' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & @TAB & '$sReport &= " (" & $aParts[2] & ")"' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & '$sReport &= @CRLF' & @CRLF $sHelperFunc &= @TAB & @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & 'Next' & @CRLF $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & 'MsgBox(64, "Deployment Complete", $sReport)' & @CRLF $sHelperFunc &= @TAB & 'Return $aResults' & @CRLF $sHelperFunc &= 'EndFunc ;==>_DeployAllFiles' & @CRLF & @CRLF $sHelperFunc &= '; Example usage: _DeployAllFiles()' & @CRLF Return $sHelperFunc EndFunc ;==>_GenerateMasterHelperFunctionFromArray #EndRegion ; *** CORE CODE GENERATION *** #Region ; *** PE HEADER AND ARCHITECTURE DETECTION *** ; ------------------------------------------------------------------------------------------------- ; Function: _DetectArchitecture($sFilePath) ; Purpose: A wrapper that returns the architecture string for a file. ; ------------------------------------------------------------------------------------------------- Func _DetectArchitecture($sFilePath) Local $sArch = _DetectArchitecture_File($sFilePath) If @error Then Return "N/A" Return $sArch EndFunc ;==>_DetectArchitecture ; ------------------------------------------------------------------------------------------------- ; Function: _DetectArchitecture_File($sFilePath) ; Purpose: Reads a file's PE headers to identify the target CPU architecture. ; ------------------------------------------------------------------------------------------------- Func _DetectArchitecture_File($sFilePath) If Not FileExists($sFilePath) Then Return SetError(1, 0, "FILE_NOT_FOUND") Local $hFile = FileOpen($sFilePath, 16) If $hFile = -1 Then Return SetError(2, 0, "CANNOT_OPEN_FILE") Local $bDOSHeader = FileRead($hFile, 64) If @error Then FileClose($hFile) Return SetError(3, 0, "CANNOT_READ_DOS_HEADER") EndIf If BinaryMid($bDOSHeader, 1, 2) <> "0x4D5A" Then FileClose($hFile) Return "Not PE" EndIf Local $iPEOffset = _BinaryToInt(BinaryMid($bDOSHeader, 61, 4)) FileSetPos($hFile, $iPEOffset, $FILE_BEGIN) Local $bPESig = FileRead($hFile, 4) If @error Or $bPESig <> "0x50450000" Then FileClose($hFile) Return SetError(5, 0, "INVALID_PE_SIGNATURE") EndIf Local $bCOFF = FileRead($hFile, 2) FileClose($hFile) If @error Then Return SetError(6, 0, "CANNOT_READ_COFF_HEADER") Local $iMachine = _BinaryToInt($bCOFF) Switch $iMachine Case 0x014c Return "x86" Case 0x8664 Return "x64" Case 0x01c0, 0x01c4 Return "ARM" Case 0xAA64 Return "ARM64" Case 0x0200 Return "IA64" Case Else Return "UNKNOWN_0x" & Hex($iMachine, 4) EndSwitch EndFunc ;==>_DetectArchitecture_File ; ------------------------------------------------------------------------------------------------- ; Function: _BinaryToInt($bData) ; Purpose: Converts a little-endian binary string to an integer value. ; ------------------------------------------------------------------------------------------------- Func _BinaryToInt($bData) Local $iResult = 0 For $i = 1 To BinaryLen($bData) $iResult += Number(BinaryMid($bData, $i, 1)) * (256 ^ ($i - 1)) Next Return $iResult EndFunc ;==>_BinaryToInt #EndRegion ; *** PE HEADER AND ARCHITECTURE DETECTION *** #Region ; *** UTILITY FUNCTIONS *** ; ------------------------------------------------------------------------------------------------- ; Function: _SanitizeName($sInput) ; Purpose: Removes illegal characters from a string to make it a valid function name. ; ------------------------------------------------------------------------------------------------- Func _SanitizeName($sInput) Local $sCleaned = StringRegExpReplace($sInput, "[^a-zA-Z0-9_]", "") If StringLeft($sCleaned, 1) = "$" Then $sCleaned = StringTrimLeft($sCleaned, 1) Return $sCleaned EndFunc ;==>_SanitizeName ; ------------------------------------------------------------------------------------------------- ; Function: _GetFileName($sFilePath) ; Purpose: Extracts the filename and extension from a full path. ; ------------------------------------------------------------------------------------------------- Func _GetFileName($sFilePath) Return StringRegExpReplace($sFilePath, "^.*\\", "") EndFunc ;==>_GetFileName ; ------------------------------------------------------------------------------------------------- ; Function: _FormatFileSize($iBytes) ; Purpose: Converts a file size in bytes into a human-readable string (KB, MB, GB). ; ------------------------------------------------------------------------------------------------- Func _FormatFileSize($iBytes) If $iBytes < 1024 Then Return $iBytes & " B" ElseIf $iBytes < 1048576 Then Return Round($iBytes / 1024, 1) & " KB" ElseIf $iBytes < 1073741824 Then Return Round($iBytes / 1048576, 2) & " MB" Else Return Round($iBytes / 1073741824, 2) & " GB" EndIf EndFunc ;==>_FormatFileSize ; ------------------------------------------------------------------------------------------------- ; Function: _ValidateChunkSize($iChunkSize) ; Purpose: Ensures the chunk size is within a valid range. ; ------------------------------------------------------------------------------------------------- Func _ValidateChunkSize($iChunkSize) ; First, check if the input from the GUI is a string containing only digits. If Not StringIsDigit($iChunkSize) Then Return 4000 ; If not, it's invalid, return the default value. EndIf ; If it is a digit string, convert it to a real number. Local $nChunkSize = Number($iChunkSize) If ($iChunkSize < 100) Or ($iChunkSize > 4000) Then Return 4000 EndIf Return Int($iChunkSize) EndFunc ;==>_ValidateChunkSize ; ------------------------------------------------------------------------------------------------- ; Function: _SaveStringToFile($sFilePath, $sContent) ; Purpose: A robust function to save a string to a file. ; Returns: True on success, False on failure. ; ------------------------------------------------------------------------------------------------- Func _SaveStringToFile($sFilePath, $sContent) Local $hFile = FileOpen($sFilePath, 2) If $hFile = -1 Then Return False Local $bSuccess = FileWrite($hFile, $sContent) FileClose($hFile) Return $bSuccess EndFunc ;==>_SaveStringToFile #EndRegion ; *** UTILITY FUNCTIONS *** !
  12. Actually, there have been many topics discussing IsNumber and its problems, and every time we code, we sometimes make the same old mistake of using IsNumber in a way that is not designed 🤣
  13. Yes, I accept that it is not a bug! I mean the way it is designed to work. Does it make sense to check if "a number" is a number but "its data type is a number"? Shouldn't it accept strings of numbers?
  14. Normally when dealing with data it is often extracted using strings, I think it should be designed to work with strings! It seems so limited!
  15. I was debugging my script and felt it was not working properly and found out it was due to the IsNumber() function. Is this a bug? Let's see the example code and the output: #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ; This script demonstrates the behavior of the IsNumber() function. ConsoleWrite("--\\ AutoIt v" & @AutoItVersion & (@AutoItX64 = 1 ? " _x64" : " x86") & " OSArch: " & @OSArch & " //-- " & @CRLF) ; Open the console to view the output ConsoleWrite("--- Testing the IsNumber() Function ---" & @CRLF & @CRLF) ; Test Case 1: A string containing a valid integer Local $sVar1 = "123" ConsoleWrite("1. Testing string: '" & $sVar1 & "'" & @CRLF) ConsoleWrite("! > IsNumber() returns: " & IsNumber($sVar1) & " (Note: 1 means True)" & @CRLF & @CRLF) ; Test Case 2: A string containing a negative number Local $sVar2 = "-45" ConsoleWrite("2. Testing string: '" & $sVar2 & "'" & @CRLF) ConsoleWrite("! > IsNumber() returns: " & IsNumber($sVar2) & " (1 = True)" & @CRLF & @CRLF) ; Test Case 3: A string containing a floating-point number Local $sVar3 = "98.6" ConsoleWrite("3. Testing string: '" & $sVar3 & "'" & @CRLF) ConsoleWrite("! > IsNumber() returns: " & IsNumber($sVar3) & " (1 = True)" & @CRLF & @CRLF) ; Test Case 4: An actual number (integer) variable Local $nVar4 = 500 ConsoleWrite("4. Testing a numeric variable: " & $nVar4 & @CRLF) ConsoleWrite("+ > IsNumber() returns: " & IsNumber($nVar4) & " (1 = True)" & @CRLF & @CRLF) ; Test Case 5: A string containing numbers AND text Local $sVar5 = "76 trombones" ConsoleWrite("5. Testing a mixed string: '" & $sVar5 & "'" & @CRLF) ConsoleWrite("- > IsNumber() returns: " & IsNumber($sVar5) & " (Note: 0 means False)" & @CRLF & @CRLF) ; Test Case 6: A string containing only text Local $sVar6 = "Hello World" ConsoleWrite("6. Testing a text-only string: '" & $sVar6 & "'" & @CRLF) ConsoleWrite("- > IsNumber() returns: " & IsNumber($sVar6) & " (0 = False)" & @CRLF & @CRLF) ; --- Practical Usage Example --- ConsoleWrite("--- Practical Usage Example ---" & @CRLF) Local $sUserInput = "99" ; Simulate user input that is always a string If IsNumber($sUserInput) Then ConsoleWrite("'" & $sUserInput & "' is a valid number. Proceeding with calculation." & @CRLF) Local $iResult = Number($sUserInput) + 1 ConsoleWrite(" Calculation result ($sUserInput + 1) = " & $iResult & @CRLF) Else ConsoleWrite("! '" & $sUserInput & "' is NOT a valid number." & @CRLF & @CRLF) EndIf Output: --\\ AutoIt v3.3.16.1 _x64 OSArch: X64 //-- --- Testing the IsNumber() Function --- 1. Testing string: '123' ! > IsNumber() returns: 0 (Note: 1 means True) 2. Testing string: '-45' ! > IsNumber() returns: 0 (1 = True) 3. Testing string: '98.6' ! > IsNumber() returns: 0 (1 = True) 4. Testing a numeric variable: 500 + > IsNumber() returns: 1 (1 = True) 5. Testing a mixed string: '76 trombones' - > IsNumber() returns: 0 (Note: 0 means False) 6. Testing a text-only string: 'Hello World' - > IsNumber() returns: 0 (0 = False) --- Practical Usage Example --- ! '99' is NOT a valid number. I had to create a replacement function: Func _IsNumber($vValue, $iMode = -1) $vValue = StringStripWS($vValue, 8) Switch $iMode Case 0 ; Mode 0: The string must start with a number. Local $sPattern = "^\s*[+-]?[0-9]" Return StringRegExp($vValue, $sPattern) = 1 Case 1 ; Mode 1: The string contains at least one digit anywhere. Local $sPattern = "\d" Return StringRegExp($vValue, $sPattern) = 1 Case Else ; Default to strict mode if an invalid mode is provided. ; Mode -1: The entire string must be a valid number (decimal, hex, or scientific). Local $sPattern = "(^[+-]?[0-9]+\.?[0-9]*$|^0x[0-9A-Fa-f]{1,8}$|^[0-9]+\.?[0-9]*[Ee][+-][0-9]+$)" Return StringRegExp($vValue, $sPattern) = 1 EndSwitch EndFunc ;==>_IsNumber Give your opinion!
  16. High-Performance ImageSearch UDF & DLL for AutoIt This project provides a highly optimized UDF (User Defined Function) and two versions of a DLL (Dynamic-Link Library) for fast and flexible image searching on the screen using AutoIt. It serves as a powerful replacement for standard image search functions, delivering superior speed, especially on modern CPUs, by leveraging advanced SIMD instructions. ✨ Key Features Superior Speed: The modern version utilizes the AVX2 instruction set to accelerate the search speed by several factors compared to traditional methods. Two DLL Versions: Provides both a modern version (optimized for speed) and a legacy version (for Windows XP support). Multi-Image Search: Search for multiple image files in a single function call by separating paths with a pipe (|). Multi-Scale Searching: Automatically search for an image across a range of sizes (e.g., from 80% to 120% of its original size). Color Tolerance: Find images even with slight color variations by setting a tolerance value (0-255). Transparent Color Support: Specify a color in the source image to be ignored during the search. Flexible Result Handling: Find and return the first match. Find and return all matches on the screen. Limit the maximum number of results. Smart (Hybrid) DLL Loading: The UDF prioritizes an external DLL for maximum performance and automatically falls back to an embedded DLL to ensure the script always runs. Unicode Support: Works flawlessly with file paths containing Unicode characters. Thread-Safe: The DLL is designed to operate stably in multi-threaded scenarios. Debug Information: Provides an option to return a detailed debug string for easy troubleshooting. 🚀 The Two DLL Versions The project offers two DLL versions to meet different needs: 1. ImageSearch_x86.dll ImageSearch_x64.dll (Modern Version) (Attached in the same UDF folder - Because the DLL file with AVX2 support is large in size) This is the recommended version for most users. Strengths: AVX2 Support: Leverages Advanced Vector Extensions 2 on modern CPUs to process multiple pixels in parallel, resulting in extremely fast search speeds. Built with modern C++, ensuring stability and efficiency. Limitations: Not compatible with Windows XP. When to use: When you need maximum performance on Windows 7, 8, 10, 11, and newer. 2. ImageSearch_XP.dll (Legacy Version) (Embedded in UDF code) This version is created for backward compatibility. Strengths: Windows XP Compatibility: Works well on the Windows XP (SP3) operating system. Limitations: No AVX2 Support: Search speed will be significantly slower than the modern version on AVX2-supported CPUs. When to use: When your script must run in a Windows XP environment. ⚙️ How the UDF Works The ImageSearch_UDF.au3 file uses a very smart "hybrid" DLL loading mechanism: Prioritize External DLL: When the _ImageSearch function is called, the UDF first looks for ImageSearch_x86.dll and ImageSearch_x64.dll in the same directory as the script (@ScriptDir). If found, it uses this file to achieve the best performance (with AVX2 if available). Fallback to Embedded DLL: If the external DLL is not found, the UDF will automatically extract and use a legacy (non-AVX2) compatible DLL version that is embedded within it as a hex string. ➡️ This ensures that your script can always run, even if you forget to copy the DLL file. However, for the highest speed, always place the modern ImageSearch_x86.dll and ImageSearch_x64.dll next to your script. 📦 Setup Place the DLL file: Copy ImageSearch_x86.dll and ImageSearch_x64.dll (the modern version) into the same directory as your AutoIt script file. Include the UDF in your script: Use the line #include <ImageSearch_UDF.au3> in your script. 📖 API Reference The main function for performing an image search. _ImageSearch($sImageFile, [$iLeft = 0], [$iTop = 0], [$iRight = 0], [$iBottom = 0], [$iTolerance = 10], [$iTransparent = 0xFFFFFFFF], [$iMultiResults = 0], [$iCenterPOS = 1], [$iReturnDebug = 0], [$fMinScale = 1.0], [$fMaxScale = 1.0], [$fScaleStep = 0.1], [$iFindAllOccurrences = 0]) Parameters Parameter Type Default Description $sImageFile String - Path to the image file. To search for multiple images, separate paths with a pipe (` $iLeft Int 0 The left coordinate of the search area. 0 defaults to the entire screen. $iTop Int 0 The top coordinate of the search area. 0 defaults to the entire screen. $iRight Int 0 The right coordinate of the search area. 0 defaults to the entire screen. $iBottom Int 0 The bottom coordinate of the search area. 0 defaults to the entire screen. $iTolerance Int 10 Color tolerance (0-255). A higher value allows for greater color variation. $iTransparent Int 0xFFFFFFFF The color (in 0xRRGGBB format) to be ignored in the source image. 0xFFFFFFFF means no transparency. $iMultiResults Int 0 The maximum number of results to return. 0 means no limit. $iCenterPOS Bool 1 (True) If True, the returned X/Y coordinates will be the center of the found image. If False, they will be the top-left corner. $iReturnDebug Bool 0 (False) If True, the function returns a debug string instead of the results array. $fMinScale Float 1.0 The minimum scaling factor for the search (e.g., 0.8 for 80%). Must be >= 0.1. $fMaxScale Float 1.0 The maximum scaling factor for the search (e.g., 1.2 for 120%). $fScaleStep Float 0.1 The increment to use when searching between min and max scales. Must be >= 0.01. $iFindAllOccurrences Bool 0 (False) If False, the search stops after the first match. If True, it finds all possible matches. Return Value On Success: Returns a 2D array containing the coordinates of the found images. $aResult[0][0] = The number of matches found. $aResult[1] to $aResult[$aResult[0][0]] = An array for each match. $aResult[$i][0] = X coordinate $aResult[$i][1] = Y coordinate $aResult[$i][2] = Width of the found image $aResult[$i][3] = Height of the found image On Failure / No Match: Sets @error to 1 and returns 0. In Debug Mode: If $iReturnDebug is True, returns a string containing detailed information about the last search operation. 💻 Examples Example 1: Basic Search Find the first occurrence of button.png on the screen. #include <ImageSearch_UDF.au3> Local $aResult = _ImageSearch("C:\images\button.png") If @error Then MsgBox(48, "Error", "Image not found on screen.") Else Local $iCount = $aResult[0][0] Local $iX = $aResult[1][0] Local $iY = $aResult[1][1] MsgBox(64, "Success", "Found " & $iCount & " image(s). First match is at: " & $iX & ", " & $iY) MouseMove($iX, $iY, 20) ; Move mouse to the center of the found image EndIf Example 2: Advanced Search (Multiple Images, Tolerance, Scaling) Search for icon1.png or icon2.png within a specific region, with a tolerance of 20 and scaling from 90% to 110%. Find all occurrences. #include <ImageSearch_UDF.au3> Local $sImages = "icon1.png|icon2.png" Local $iTolerance = 20 Local $fMinScale = 0.9 Local $fMaxScale = 1.1 Local $fStep = 0.05 Local $aResult = _ImageSearch($sImages, 500, 300, 1200, 800, $iTolerance, 0xFFFFFFFF, 0, True, False, $fMinScale, $fMaxScale, $fStep, True) If @error Then MsgBox(48, "Error", "No matching images found in the specified region.") Else Local $iCount = $aResult[0][0] ConsoleWrite("Found " & $iCount & " total matches." & @CRLF) For $i = 1 To $iCount ConsoleWrite("Match #" & $i & ": X=" & $aResult[$i][0] & ", Y=" & $aResult[$i][1] & ", W=" & $aResult[$i][2] & ", H=" & $aResult[$i][3] & @CRLF) Next EndIf Example 3: Using Debug Mode To diagnose issues, use the $iReturnDebug parameter. #include <ImageSearch_UDF.au3> Local $2dDLLResult = _ImageSearch("image_not_exist.png", 0, 0, 0, 0, 10, 0xFFFFFFFF, 0, True, True) ConsoleWrite(">> DLL Return: " & $g_sLastDllReturn & @CRLF) ; Example output: {0}[No Match Found] | DEBUG: File=image_not_exist.png, Rect=(0,0,1920,1080), Tol=10, Trans=0xffffffff, Multi=0, Center=1, FindAll=0, AVX2=true, Scale=(1.00,1.00,0.10) SPECIAL NOTE: The function always returns a 2D array for both results and errors. Credits Author: Dao Van Trong - TRONG.PRO Source Dll on GitHub: daovantrong/ImageSearchDLL: A DLL for finding an image on the screen Download UDF:
  17. The article is a bit long, I will add more example code below when finished!
  18. Using BarCodeGenerator.dll in AutoIt: A Comprehensive Guide This guide introduces you to the BarCodeGenerator.dll—a dynamic link library designed for generating various types of barcodes and QR codes. You will learn about the structure of its exported functions, the necessary parameters, and how you can integrate and call these functions from an AutoIt script. The article also includes example code to illustrate both the in-memory image handling (using GDIPlus) as well as file-based output. 1. Exported Functions Overview The DLL exports two primary functions: a) CreateBarcode Purpose: Generates a barcode or QR code based on the provided text and other configuration parameters. Depending on the parameters, the function either returns an HBITMAP (when no file path is provided and when the output format is an image such as PNG, BMP, JPG, or TGA) or returns a text result with configuration details (for console output, SVG, or when output is generated to a file). Exported Signature (C/C++ Prototype): DLL_API void* __stdcall CreateBarcode( const wchar_t* textContent, const wchar_t* outputType, const wchar_t* eccStr, const wchar_t* qrColorHex, const wchar_t* bgColorHex, const wchar_t* outputFormat, const wchar_t* filePath, int sizeParam, int scale, int borderModules ); Parameters: textContent: The string content that you want to encode. For example, "Hello World". outputType: A string that defines the type of barcode/QR code. Accepted values include "qr", "code128", "code39", and "ean128". eccStr: Specifies the error correction level (primarily used for QR codes). Example values are "low", "medium", "quartile", and "high". qrColorHex and bgColorHex: These parameters represent the barcode (foreground) and background colors in hexadecimal notation. For example, passing "000000" for black and an empty string for the default background. outputFormat: Sets the desired output format. Valid options include "bmp", "png", "jpg", "jpeg", "tga", "svg", and "console". filePath: When provided with a valid path, the DLL saves the generated file to disk. If this parameter is an empty string, the function instead returns an HBITMAP (if the output is an image) that can be handled via GDIPlus in AutoIt. sizeParam: Indicates the desired overall size for the generated image. scale: The scale factor. If set to 0 (or less), the scale is determined automatically based on size and border parameters. borderModules: Determines the number of border modules (padding) around the generated symbol. Return Value: The function returns a pointer to a structure—BarcodeResult. This structure contains: A fixed-length wide-character array (wchar_t info[4096]) that includes the configuration details along with the generation result. A pointer (hBitmap) that will hold a valid HBITMAP if the output is generated in memory (i.e., when no file path is provided). b) GetBarcodeInfo Purpose: This function returns static information about the DLL, including version and author details. Exported Signature (C/C++ Prototype): DLL_API wchar_t* __stdcall GetBarcodeInfo(); Return Value: A pointer to a wide-character string containing DLL information (for example, version, author, etc.). 2. Structure Definition in the Header File For smooth integration with AutoIt, the DLL uses a predefined structure for the return value of CreateBarcode. Below is an example of the header file content (named BarCodeGenerator.h😞 #ifndef BARCODEGENERATOR_H #define BARCODEGENERATOR_H #ifdef _WIN32 #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif #else #define DLL_API #endif // Define the size of the buffer to store info details. #define INFO_BUFFER_SIZE 4096 #ifdef __cplusplus extern "C" { #endif // Structure returned from CreateBarcode typedef struct _BarcodeResult { wchar_t info[INFO_BUFFER_SIZE]; #ifdef _WIN32 void* hBitmap; // HBITMAP handle on Windows platforms #else void* hBitmap; #endif } BarcodeResult; // Exported function to create a barcode/QR code. DLL_API void* __stdcall CreateBarcode( const wchar_t* textContent, const wchar_t* outputType, const wchar_t* eccStr, const wchar_t* qrColorHex, const wchar_t* bgColorHex, const wchar_t* outputFormat, const wchar_t* filePath, int sizeParam, int scale, int borderModules ); // Exported function to get general renderer information. DLL_API wchar_t* __stdcall GetBarcodeInfo(); #ifdef __cplusplus } #endif #endif // BARCODEGENERATOR_H This header file clearly defines the exported functions and makes it easier to write AutoIt scripts to call these functions via the DllCall mechanism. 3. Using the DLL in AutoIt When integrating this DLL in AutoIt, you must create a structure that matches BarcodeResult. Typically, you'll use DllStructCreate() with a format string such as "wchar[4096];ptr hBitmap". Example AutoIt Workflow: Call CreateBarcode to generate a QR code in memory. Pass an empty string as the filePath parameter so that the DLL returns an HBITMAP for in-memory processing. Use GDIPlus (via the GDIPlus UDF) to convert the HBITMAP to a PNG image and save it to disk. Call CreateBarcode to output directly to a file. Provide a valid filePath (e.g., "C:\Temp\qr_output.png") so that the DLL writes the file to the disk and also returns a text report with the configuration and operation details. Call GetBarcodeInfo to retrieve additional information about the DLL. Below is a sample AutoIt code snippet that demonstrates how to call these functions: #RequireAdmin ;~ #Region ;**** Directives created by AutoIt3Wrapper_GUI **** ;~ #AutoIt3Wrapper_UseX64=y ;~ #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ;~ #pragma compile(x64, true) ; For test FileDelete(@ScriptDir & "\output_qr.png") FileDelete(@ScriptDir & "\output_code128.png") ; Path to the DLL (adjust according to the actual location of the DLL on your system) Global Const $g_sDllPath = @AutoItX64 ? @ScriptDir & "\BarCodeGenerator_x64.dll" : @ScriptDir & "\BarCodeGenerator_x86.dll" ; Path to the DLL (update to the correct path) #include <GDIPlus.au3> ; Define the BarcodeResult structure as follows: ; - wchar[4096]: a text string containing configuration and result information (fixed at 4096 characters) ; - ptr hBitmap: the hBitmap pointer returned when using in-memory image output Local $tBarcodeResultDef = "wchar[4096];ptr hBitmap" ConsoleWrite("; EG 1 -----------------------------" & @CRLF) ; ----------------------------- ; PART 1: Call CreateBarcode to generate a QR code in-memory ; (Since FilePath is "" the function returns an HBITMAP, and the PNG image will be saved using _GDIPlus) Local $aRet = DllCall($g_sDllPath, "ptr", "CreateBarcode", _ "wstr", "Hello World", _ ; textContent "wstr", "qr", _ ; outputType "wstr", "medium", _ ; eccStr "wstr", "000000", _ ; qrColorHex "wstr", "", _ ; bgColorHex (empty means default) "wstr", "png", _ ; outputFormat "wstr", "", _ ; filePath = empty => create image in memory "int", 128, _ ; sizeParam "int", 0, _ ; scale "int", 1) ; borderModules If Not IsArray($aRet) Then ConsoleWrite("CreateBarcode call failed." & @CRLF) Else ; $aRet[0] is the pointer to the BarcodeResult structure. Local $pResult = $aRet[0] ; Map the returned pointer to the BarcodeResult structure. Local $sBarcodeResult = DllStructCreate($tBarcodeResultDef, $pResult) ; Retrieve the configuration and status message string. Local $sInfo = DllStructGetData($sBarcodeResult, 1) ConsoleWrite("In-memory QR generation result info:" & @CRLF & $sInfo & @CRLF) ; Get the HBITMAP Local $hBmp = DllStructGetData($sBarcodeResult, 2) If @error Then ConsoleWrite("! Error in DllStructGetData, Code: " & @error & @CRLF) EndIf ; Use _GDIPlus to save this HBITMAP to a PNG file. _GDIPlus_Startup() ; Convert HBITMAP to a GDI+ Bitmap object Local $hBmpGp = _GDIPlus_BitmapCreateFromHBITMAP($hBmp) If $hBmpGp = 0 Then ConsoleWrite("Failed to convert HBITMAP to GDI+ Bitmap." & @CRLF) Else ; Save the image to a file If _GDIPlus_ImageSaveToFile($hBmpGp, @ScriptDir & "\output_qr.png") Then ConsoleWrite("Saved in-memory QR code to file " & @ScriptDir & "\output_qr.png" & @CRLF) If FileExists(@ScriptDir & "\output_qr.png") Then ShellExecute(@ScriptDir & "\output_qr.png"); show qr Else ConsoleWrite("! Failed to save the image to file." & @CRLF) EndIf _GDIPlus_ImageDispose($hBmpGp) EndIf _GDIPlus_Shutdown() EndIf ConsoleWrite("; EG 2 -----------------------------" & @CRLF) ; ----------------------------- ; PART 2: Call CreateBarcode to output the result directly to a file. ; Here, since filePath is provided, the DLL will write the file to disk. Local $aRet2 = DllCall($g_sDllPath, "ptr", "CreateBarcode", _ "wstr", "Hello World", _ "wstr", "code128", _ "wstr", "medium", _ "wstr", "000000", _ "wstr", "", _ "wstr", "png", _ "wstr", @ScriptDir & "\output_code128.png", _ ; Direct output to file "int", 128, _ "int", 0, _ "int", 4) If Not IsArray($aRet2) Then ConsoleWrite("! File output CreateBarcode call failed." & @CRLF) Else Local $pResult2 = $aRet2[0] Local $sBarcodeResult2 = DllStructCreate($tBarcodeResultDef, $pResult2) Local $sInfo2 = DllStructGetData($sBarcodeResult2, 1) If FileExists(@ScriptDir & "\output_code128.png") Then ShellExecute(@ScriptDir & "\output_code128.png") ; show bar code 128 ConsoleWrite("File output QR generation result info:" & @CRLF & $sInfo2 & @CRLF) EndIf ConsoleWrite("; Test 3 -----------------------------" & @CRLF) ; ----------------------------- ; PART 3: Call GetBarcodeInfo to retrieve additional information about the author, version, etc. Local $aRet3 = DllCall($g_sDllPath, "wstr", "GetBarcodeInfo") If Not IsArray($aRet3) Then ConsoleWrite("! GetBarcodeInfo call failed." & @CRLF) Else MsgBox(64 + 262144, "About ", $aRet3[0] & @CRLF) ;MsgBox(64 + 262144, "GetBarcodeInfo: ", CorrectFromCP1252ToUTF8($aRet3[0]) & @CRLF) EndIf ; Function to convert strings misinterpreted as CP1252 to proper UTF-8 Func CorrectFromCP1252ToUTF8($sMisinterpreted) ; Convert the string (encoded as CP1252) to binary. Local $aBinary = StringToBinary($sMisinterpreted, 0) ; Create an ADODB.Stream object to perform encoding conversion. Local $oStream = ObjCreate("ADODB.Stream") If Not IsObj($oStream) Then MsgBox(16, "Error", "Unable to create ADODB.Stream object.") Return $sMisinterpreted EndIf ; Write the binary data to the stream. $oStream.Type = 1 ; 1: Binary $oStream.Open $oStream.Write($aBinary) ; Reset stream position and switch to text mode. $oStream.Position = 0 $oStream.Type = 2 ; 2: Text $oStream.Charset = "utf-8" ; Read data as UTF-8. Local $sCorrect = $oStream.ReadText() $oStream.Close() Return $sCorrect EndFunc ;==>CorrectFromCP1252ToUTF8 Explanation of the AutoIt Code: Structure Initialization: The structure for the result (BarcodeResult) is defined in AutoIt using DllStructCreate with "wchar[4096];ptr hBitmap". This matches the DLL’s definition. Function Calls: For the first call to CreateBarcode, an empty filePath tells the DLL to generate the image in memory. The returned HBITMAP is then processed via _GDIPlus for conversion and saving. For the second call, a valid file path is provided so the DLL writes the image file directly to disk while also returning a text-based log of the configuration and status. Finally, the static information is retrieved using GetBarcodeInfo. Output Display: Instead of using message boxes, all feedback and information are displayed using ConsoleWrite(). 4. Conclusion In this guide, we have covered the following: The structure and purpose of the exported functions from BarCodeGenerator.dll. Detailed descriptions of all necessary parameters—including text content, barcode/QR type, error correction level, colors, output format, and file handling. How to set up and call these functions from an AutoIt script using the DLL call mechanism. An example AutoIt code that demonstrates both in-memory image retrieval (with _GDIPlus) and direct file output, and how to retrieve additional DLL information. By following this guide, you should be able to effectively integrate the barcode generation capabilities of the DLL into your AutoIt projects and further customize the functionality to suit your requirements. Happy coding! _________________________________________ For Vietnamese: >> Link Download Dll/Exe (Because it contains exe cli file so to avoid warning when downloading I set password as number 1) Limitation: due to using c++17, it will not support running on windows XP ________________________________________________________ QR Code generator library (c) Nayuki
  19. It works fine on my computer, make sure that window and tab are active, if you open multiple tabs on the browser it will only report for the current active tab
  20. I have written a function to run the ps command and get the result back, but the semicolon problem has been driving me crazy, as the command sent to ps quotes seems to have problems and cannot run the command correctly! no matter I try to add 2 double quotes or use single quotes, it still does not work properly. ; *** Add a program to Windows Defender Exclusions using PowerShell *** #RequireAdmin #include <AutoItConstants.au3> ; *** Example Usage *** ; Get the list of running processes and filter for processes named "notepad" Local $commandToRun = "Get-Process | Where-Object {$_.ProcessName -eq 'notepad'} | Format-List Name, Id, MainWindowTitle" Local $powerShellResult = RunPowerShellCommand($commandToRun) If @error Then MsgBox(16, "Error", "Could not get results from PowerShell.") Else If $powerShellResult Then MsgBox(64, "PowerShell Result", "Result returned from PowerShell: " & $powerShellResult) Else MsgBox(64, "Information", "No processes match the criteria.") EndIf EndIf ; Another example: Get the PowerShell version Local $versionCommand = "$PSVersionTable.PSVersion" Local $powerShellVersion = RunPowerShellCommand($versionCommand) If Not @error Then MsgBox(64, "PowerShell Version", "PowerShell Version: " & $powerShellVersion) EndIf ;~ ; *** Example Usage *** ; **Change the program path and rule name according to your needs** Local $programToExclude = @Compiled ? @ScriptFullPath : @AutoItExe Local $firewallRuleName = "AutoIt3" ; Add to Windows Defender Exclusions using PowerShell If AddToDefenderExclusions_PS($programToExclude) Then MsgBox(64, "Success", "Successfully added '" & $programToExclude & "' to Windows Defender Exclusions (PowerShell).") Else MsgBox(16, "Failure", "Failed to add '" & $programToExclude & "' to Windows Defender Exclusions (PowerShell). Please check the path or run the script with administrator privileges.") EndIf ; Add to Windows Firewall Exclusions using PowerShell If AddToFirewallExclusions_PS($programToExclude, $firewallRuleName) Then MsgBox(64, "Success", "Successfully added Firewall rule for '" & $programToExclude & "' (PowerShell).") Else MsgBox(16, "Failure", "Failed to add Firewall rule for '" & $programToExclude & "' (PowerShell). Please check the path or run the script with administrator privileges.") EndIf Func RunPowerShellCommand($powerShellCommand) Local $output = "" Local $error = "" Local $command_r = "PowerShell -Command '" & '"' & $powerShellCommand & '"' & "'" ConsoleWrite('-> ' & $command_r & @CRLF) Local $pid = Run(@ComSpec & ' /c ' & $command_r, "", @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD) If Not $pid Then MsgBox(16, "Error", "Could not run PowerShell.") Return SetError(-1, 0, False) EndIf While 1 $line = StdoutRead($pid) If @error Then ExitLoop $output &= $line & @CRLF WEnd While 1 $line = StderrRead($pid) If @error Then ExitLoop $error &= $line & @CRLF WEnd ProcessClose($pid) $error = StringStripWS($error, 7) $output = StringStripWS($output, 7) If StringLen(StringStripWS($error, 8)) > 0 Then ConsoleWrite($output & @CRLF & $error & @CRLF) MsgBox(16, "PowerShell Error", "Error returned from PowerShell: " & $error) Return SetError(1, 0, $error) Else ConsoleWrite($output & @CRLF) Return SetError(0, 0, $output) EndIf EndFunc ;==>RunPowerShellCommand Func AddToDefenderExclusions_PS($programPath) Local $command = 'Add-MpPreference -ExclusionPath "' & $programPath & '"' Local $result = RunPowerShellCommand($command) If @error Then MsgBox(16, "Defender Error", "Error running PowerShell command to add to Defender Exclusion." & @CRLF & "" & $result & "") Return False Else If StringLen($result) > 0 Then MsgBox(16, "Defender return", "" & $result & "") Return True Else Return False EndIf EndIf EndFunc ;==>AddToDefenderExclusions_PS ; *** Add a program to Windows Firewall Exclusions using PowerShell *** Func AddToFirewallExclusions_PS($programPath, $ruleName) Return AddToFirewall_InboundExclusions_PS($programPath, $ruleName) And AddToFirewall_OutboundExclusions_PS($programPath, $ruleName) EndFunc ;==>AddToFirewallExclusions_PS Func AddToFirewall_InboundExclusions_PS($programPath, $ruleName) ; Create Inbound rule Local $inboundCommand = 'New-NetFirewallRule -DisplayName "' & $ruleName & ' (Inbound)" -Direction Inbound -Action Allow -Program "' & $programPath & '" -Enabled True' Local $inboundResult = RunPowerShellCommand($inboundCommand) If @error Then MsgBox(16, "Firewall Error", "Error running PowerShell command to add Inbound Firewall rule." & @CRLF & "" & $inboundResult & "") Return False Else If StringLen($inboundResult) > 0 Then MsgBox(16, "Defender return", "" & $inboundResult & "") Return True Else Return False EndIf EndIf EndFunc ;==>AddToFirewall_InboundExclusions_PS Func AddToFirewall_OutboundExclusions_PS($programPath, $ruleName) ; Create Outbound rule Local $outboundCommand = 'New-NetFirewallRule -DisplayName "' & $ruleName & ' (Outbound)" -Direction Outbound -Action Allow -Program "' & $programPath & '" -Enabled True' Local $outboundResult = RunPowerShellCommand($outboundCommand) If @error Then MsgBox(16, "Firewall Error", "Error running PowerShell command to add OutboundFirewall rule." & @CRLF & "" & $outboundResult & "") Return False Else If StringLen($outboundResult) > 0 Then MsgBox(16, "Defender return", "" & $outboundResult & "") Return True Else Return False EndIf EndIf Return True EndFunc ;==>AddToFirewall_OutboundExclusions_PS
  21. How to show tray menu without clicking on tray icon? Or Click on tray icon automatically! #NoTrayIcon #include <MsgBoxConstants.au3> #include <StringConstants.au3> #include <TrayConstants.au3> ; Required for the $TRAY_ICONSTATE_SHOW constant. Opt("TrayMenuMode", 3) ; The default tray menu items will not be shown and items are not checked when selected. These are options 1 and 2 for TrayMenuMode. HotKeySet("{F12}", "_ShowTrayMenu") ; Đặt Hotkey là phím F12 Example() Func Example() Local $idAbout = TrayCreateItem("About") TrayCreateItem("") ; Create a separator line. Local $idExit = TrayCreateItem("Exit") TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu. While 1 Switch TrayGetMsg() Case $idAbout ; Display a message box about the AutoIt version and installation path of the AutoIt executable. MsgBox($MB_SYSTEMMODAL, "", "AutoIt tray menu example." & @CRLF & @CRLF & _ "Version: " & @AutoItVersion & @CRLF & _ "Install Path: " & StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", $STR_NOCASESENSEBASIC, -1) - 1)) ; Find the folder of a full path. Case $idExit ; Exit the loop. ExitLoop EndSwitch WEnd EndFunc ;==>Example Func _ShowTrayMenu() ;??????????????????????????????????????? EndFunc
  22. Your file is locked by "windows defender" you need to wait for the scan to complete, it's best to add the working path to the whitelist to improve, but it's best to disable it.
  23. DirMove and DirCopy are different in usage, try to understand it. Here is an example script for backing up and restoring folders: #RequireAdmin ; ----------------------------------------------- #include <AutoItConstants.au3> #include <FileConstants.au3> ; ----------------------------------------------- Opt("MustDeclareVars", 1) ; ----------------------------------------------- ; ------------------------------------------------------------- INPUT : Global Const $sUserName = @UserName Global $sNAME_Path[6] $sNAME_Path[0] = 4 $sNAME_Path[1] = 'SAC64' ; App Folder Name $sNAME_Path[2] = 'Software Audio Console64' ; Start Menu Folder Name $sNAME_Path[3] = 'SAWStudio' ; App Folder Name $sNAME_Path[4] = 'SAWStudio' ; Start Menu Folder Name $sNAME_Path[5] = 'RML' ; App Data Folder Name Global Const $aDirNAME_Path = $sNAME_Path Global Const $sORGAPP_Path = @HomeDrive Global Const $sBACKUP_Path = "D:\Backup" Global Const $sPathDir_BACKUP_Data = $sBACKUP_Path & "\Data" Global Const $sPathDir_BACKUP_App = $sBACKUP_Path & "\Apps" Global Const $sPathDir_BACKUP_Start_Menu = $sBACKUP_Path & "\Start_Menu" Global Const $iSleep_Time = 2500 ; ms Stop Show Result ; ---------------------------------------------------------------------- Global Const $sPathDir_ORG_StartMenuPrograms = @HomeDrive & "\Users\" & $sUserName & "\AppData\Roaming\Microsoft\Windows\Start Menu\Programs" ; @AppDataDir & "\Microsoft\Windows\Start Menu\Programs" Global $sPathDir_ORG[6] $sPathDir_ORG[0] = 5 $sPathDir_ORG[1] = $sORGAPP_Path & "\" & $aDirNAME_Path[1] $sPathDir_ORG[2] = $sPathDir_ORG_StartMenuPrograms & '\' & $aDirNAME_Path[2] $sPathDir_ORG[3] = $sORGAPP_Path & "\" & $aDirNAME_Path[3] $sPathDir_ORG[4] = $sPathDir_ORG_StartMenuPrograms & '\' & $aDirNAME_Path[4] $sPathDir_ORG[5] = $sPathDir_ORG_StartMenuPrograms & '\' & $aDirNAME_Path[5] Global Const $aPathDir_ORG = $sPathDir_ORG ; ---------------------------------------------------------------------- Global $sPathDir_BACKUP[6] $sPathDir_BACKUP[0] = 5 $sPathDir_BACKUP[1] = $sPathDir_BACKUP_App & "\" & $aDirNAME_Path[1] $sPathDir_BACKUP[2] = $sPathDir_BACKUP_Start_Menu & "\" & $aDirNAME_Path[2] $sPathDir_BACKUP[3] = $sPathDir_BACKUP_App & "\" & $aDirNAME_Path[3] $sPathDir_BACKUP[4] = $sPathDir_BACKUP_Start_Menu & "\" & $aDirNAME_Path[4] $sPathDir_BACKUP[5] = $sPathDir_BACKUP_Data & "\" & $aDirNAME_Path[5] Global Const $aPathDir_BACKUP = $sPathDir_BACKUP ; ---------------------------------------------------------------------- _Remove_RMLData_Backup() _Backup_RMLData() ;_Remove_RMLData_AppDir() ;_Restore_RMLData() ; ----------------------------------------------- Func _Backup_RMLData() ; ----------------------------------------------- Local $sResult, $iResult = 0, $sMessage = "Backup data..." & @CRLF & @CRLF ; ----------------------------------------------- For $i = 1 To $aPathDir_ORG[0] ToolTip('> COPY: ' & $aPathDir_ORG[$i] & ' -> TO: ' & $aPathDir_BACKUP[$i], (@DesktopWidth / 2) - 50, 5, 'Backing up data [' & $i & '/' & $aPathDir_ORG[0] & '] please wait...') ConsoleWrite('> COPY: ' & $aPathDir_ORG[$i] & ' (FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) ConsoleWrite('- TO: ' & $aPathDir_BACKUP[$i] & ' (FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) ConsoleWrite('! Please wait: Copying ....' & @CRLF) If Not FileExists($aPathDir_BACKUP[$i]) Then DirCreate($aPathDir_BACKUP[$i]) If FileExists($aPathDir_ORG[$i]) Then $sResult = DirCopy($aPathDir_ORG[$i], $aPathDir_BACKUP[$i], $FC_OVERWRITE) Else $sResult = 0 EndIf Switch $sResult Case 0 ConsoleWrite('!> Result (0): ERROR: Data was not backed-up! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] ERROR: Data was not backed up" Case 1 $iResult += 1 ConsoleWrite('-> Result (1): The data WAS backed-up successfully! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] The data WAS backed-up successfully!" EndSwitch ; ----------------- $sMessage &= $sResult & @CRLF $sResult = '' ToolTip('') Next ToolTip('') ; ----------------------------------------------- $sMessage &= @CRLF & "The Backup of data completed..." & @CRLF ; ----------------------------------------------- ToolTip($sMessage, (@DesktopWidth / 2) - 50, 5, "NOTICE!!", 1) Sleep($iSleep_Time) ToolTip('') $sResult = $aPathDir_ORG[0] - $iResult If ($sResult < 1) Then ConsoleWrite('+> The data WAS backed-up successfully!' & @CRLF) Return True Else ConsoleWrite('!> ERROR: Data was not backed-up!' & @CRLF) Return False EndIf ; ----------------------------------------------- EndFunc ;==>_Backup_RMLData ; ----------------------------------------------- Func _Restore_RMLData() ; ----------------------------------------------- Local $sResult, $iResult = 0, $sMessage = "Restore data..." & @CRLF & @CRLF ; ----------------------------------------------- For $i = 1 To $aPathDir_BACKUP[0] ToolTip('> COPY: ' & $aPathDir_BACKUP[$i] & ' -> TO: ' & $aPathDir_ORG[$i], (@DesktopWidth / 2) - 50, 5, 'Restoring data [' & $i & '/' & $aPathDir_BACKUP[0] & '] please wait...') ConsoleWrite('- COPY: ' & $aPathDir_BACKUP[$i] & ' (FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) ConsoleWrite('> TO: ' & $aPathDir_ORG[$i] & ' (FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) ConsoleWrite('! Please wait: Copying ....' & @CRLF) If Not FileExists($aPathDir_ORG[$i]) Then DirCreate($aPathDir_ORG[$i]) If FileExists($aPathDir_BACKUP[$i]) Then $sResult = DirCopy($aPathDir_BACKUP[$i], $aPathDir_ORG[$i], $FC_OVERWRITE) Else $sResult = 0 EndIf Switch $sResult Case 0 ConsoleWrite('+> Result (0): ERROR: Data not restored! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] ERROR: Data not restored!" Case 1 $iResult += 1 ConsoleWrite('+> Result (1): Data restored successfully! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] Data restored successfully!" EndSwitch ; ----------------- $sMessage &= $sResult & @CRLF $sResult = '' ToolTip('') Next ToolTip('') ; ----------------------------------------------- $sMessage &= @CRLF & "Data recovery completed." & @CRLF ; ----------------------------------------------- ToolTip($sMessage, (@DesktopWidth / 2) - 50, 5, "NOTICE!!", 1) Sleep($iSleep_Time) ToolTip('') $sResult = $aPathDir_ORG[0] - $iResult If ($sResult < 1) Then ConsoleWrite('+> Data restored successfully!' & @CRLF) Return True Else ConsoleWrite('!> ERROR: Data not restored!' & @CRLF) Return False EndIf EndFunc ;==>_Restore_RMLData ; ----------------------------------------------- Func _Remove_RMLData_Backup() ; ----------------------------------------------- Local $sResult, $iResult = 0, $sMessage = "Remove data..." & @CRLF & @CRLF ; ----------------------------------------------- For $i = 1 To $aPathDir_BACKUP[0] ToolTip('> Remove: ' & $aPathDir_BACKUP[$i], (@DesktopWidth / 2) - 50, 5, 'Removing data [' & $i & '/' & $aPathDir_BACKUP[0] & '] please wait...') ConsoleWrite('! Remove: ' & $aPathDir_BACKUP[$i] & ' (FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) ConsoleWrite('- Please wait: removing...' & @CRLF) If FileExists($aPathDir_BACKUP[$i]) Then $sResult = DirRemove($aPathDir_BACKUP[$i], $DIR_REMOVE) Else $sResult = 1 EndIf Switch $sResult Case 0 ConsoleWrite('+> Result (0): ERROR: Data not Removed! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] ERROR: Data not Removed!" Case 1 $iResult += 1 ConsoleWrite('+> Result (1): Data Removed successfully! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_BACKUP[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] Data Removed successfully!" EndSwitch ; ----------------- $sMessage &= $sResult & @CRLF $sResult = '' ToolTip('') Next ToolTip('') ; ----------------------------------------------- $sMessage &= @CRLF & "Data Removal Completed." & @CRLF ; ----------------------------------------------- ToolTip($sMessage, (@DesktopWidth / 2) - 50, 5, "NOTICE!!", 1) Sleep($iSleep_Time) ToolTip('') $sResult = $aPathDir_ORG[0] - $iResult If ($sResult < 1) Then ConsoleWrite('+> Data Removed successfully!' & @CRLF) Return True Else ConsoleWrite('!> ERROR: Data not Removed!' & @CRLF) Return False EndIf EndFunc ;==>_Remove_RMLData_Backup ; ----------------------------------------------- Func _Remove_RMLData_AppDir() ; ----------------------------------------------- Local $sResult, $iResult = 0, $sMessage = "Remove data..." & @CRLF & @CRLF ; ----------------------------------------------- For $i = 1 To $aPathDir_ORG[0] ToolTip('> Remove: ' & $aPathDir_ORG[$i], (@DesktopWidth / 2) - 50, 5, 'Removing data [' & $i & '/' & $aPathDir_ORG[0] & '] please wait...') ConsoleWrite('!> Remove: ' & $aPathDir_ORG[$i] & ' (FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) ConsoleWrite('- Please wait: removing ....' & @CRLF) If FileExists($aPathDir_ORG[$i]) Then $sResult = DirRemove($aPathDir_ORG[$i], $DIR_REMOVE) Else $sResult = 1 EndIf Switch $sResult Case 0 ConsoleWrite('+> Result (0): ERROR: Data not Removed! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] ERROR: Data not Removed!" Case 1 $iResult += 1 ConsoleWrite('+> Result (1): Data Removed successfully! (' & $aDirNAME_Path[$i] & ' - FileExists: ' & FileExists($aPathDir_ORG[$i]) & ') ' & @CRLF) $sResult = "[" & $aDirNAME_Path[$i] & "] Data Removed successfully!" EndSwitch ; ----------------- $sMessage &= $sResult & @CRLF $sResult = '' ToolTip('') Next ToolTip('') ; ----------------------------------------------- $sMessage &= @CRLF & "Data Removal Completed." & @CRLF ; ----------------------------------------------- ToolTip($sMessage, (@DesktopWidth / 2) - 50, 5, "NOTICE!!", 1) Sleep($iSleep_Time) ToolTip('') $sResult = $aPathDir_ORG[0] - $iResult If ($sResult < 1) Then ConsoleWrite('+> Data Removed successfully!' & @CRLF) Return True Else ConsoleWrite('!> ERROR: Data not Removed!' & @CRLF) Return False EndIf EndFunc ;==>_Remove_RMLData_AppDir ; -----------------------------------------------
  24. Thank you AspirinJunkie and pixelsearch for helping make my work easier.
×
×
  • Create New...