Leaderboard
Popular Content
Showing content with the highest reputation since 11/13/2025 in Posts
-
Added this UDF to the Wiki3 points
-
Walking a .json ( and failing )
Musashi and one other reacted to AspirinJunkie for a topic
Wow, that looks wild. To be honest, I haven't delved deep enough into your script to really understand how the path strings for _JSON_Get() are constructed there. As I understand it, you want to map this highly hierarchical structure to a 2D array—is that correct? From my point of view, neither manual fixed loops nor the use of _JSON_Get() are the ideal way to do this. Instead of manual nested loops, the format here literally cries out for recursion. And since _JSON_Get starts from the beginning again with each call and you can quickly get confused with the path string, you don't really need it here. You have the structure available as AutoIt data structures. So you can also process it directly to access it – you don't need _JSON_Get() for that. That is more for conveniently accessing certain values whose path you know in advance. On the other hand, first putting together a path and then using _JSON_Get to retrieve the element is artificially cumbersome, since you basically already have the element when you put the path together. So I simply implemented the whole thing recursively, and from my point of view, it seems to make sense: #include <JSON.au3> #include <Array.au3> ; extract array of devices from the json structure Global $aDevices = _extractDevices(_JSON_Parse(FileRead('Argumentum.json'))) ; display the result _ArrayDisplay($aDevices, "Devices", "", 64, "|", "Index|JSON-Path|ID|Text|Min|Value|Max|SensorID|Type|ImageURL") Func _extractDevices($mDevice, $bMaster = True, $sIndex = 0) Local Static $aDevices[0][0], $iElements Local Enum $eIdx, $ePath, $eID, $eText, $eMin, $eValue, $eMax, $eSensorID, $eType, $eImg ; check Input validity If Not IsMap($mDevice) Then Return SetError(1, 0, Null) ; first recursion level has to initialize things If $bMaster Then Redim $aDevices[8][$eImg + 1] $iElements = 0 EndIf ; add current device to result array If UBound($aDevices) <= $iElements Then Redim $aDevices[UBound($aDevices) * 2][$eImg + 1] ; resize array if necessary $aDevices[$iElements][$eIdx] = $sIndex $aDevices[$iElements][$ePath] = StringReplace(StringRegExpReplace(StringTrimLeft($sIndex, 2), "(\d+)", 'Children[$1]'), ',', '.') $aDevices[$iElements][$eID] = $mDevice["id"] $aDevices[$iElements][$eText] = $mDevice["Text"] $aDevices[$iElements][$eMin] = $mDevice["Min"] $aDevices[$iElements][$eValue] = $mDevice["Value"] $aDevices[$iElements][$eMax] = $mDevice["Max"] $aDevices[$iElements][$eSensorID] = $mDevice["SensorId"] $aDevices[$iElements][$eType] = $mDevice["Type"] $aDevices[$iElements][$eImg] = $mDevice["ImageURL"] $iElements += 1 ; process the childrens Local $aChildren = $mDevice["Children"] If IsArray($aChildren) And UBound($aChildren, 1) > 0 And UBound($aChildren, 0) = 1 Then For $i = 0 To UBound($aChildren) - 1 _extractDevices($aChildren[$i], False, $sIndex & "," & $i) Next EndIf If $bMaster Then Redim $aDevices[$iElements][$eImg + 1] Return $aDevices EndIf EndFunc I am therefore unable to assess where the problem lies in your script or whether there may even be a bug in the JSON UDF. In my script, I have therefore generated the query string for _JSON_Get() for each element in parallel, and when I use these with _JSON_Get(), it works as desired. Yes, that was highly unprofessional of me - I agree with you there. To me, it seemed logical to adjust the function to return a null instead of an empty string in the event of an error, so I simply changed it without further ado. Of course, I completely ignored the fact that this was a script-breaking change and didn't even mention it in the commit message. That's really not acceptable - sorry! I have therefore rolled it back in the GitHub repo.2 points -
WinSockUDF - TCP/UDP Networking Library for AutoIt
argumentum and one other reacted to Trong for a topic
It was all my fault, I fixed it! I didn't know that the dark theme of the forum didn't invert the text colors (it seems unintelligent) Thank you all for your feedback2 points -
Avoid "AutoIt Error" message box in unknown errors
argumentum and one other reacted to Jos for a topic
I am just supporting the au3stripper questions in this thread. So without looking at the details it is pretty simple to me: Does the original script work?: if Yes: Does au3stripper run cleanly without any warnings? if Yes: The stripped script should work as the original if No: You are responsible and "don't come crying to me" when you override the default to continue with force! 😉2 points -
WinCred UDF - Windows Credential Management API
argumentum and one other reacted to DonChunior for a topic
Description WinCred is a User Defined Function (UDF) library for AutoIt that provides a complete interface to the Windows Credential Management API. This UDF allows you to create, read, update, and delete credentials stored in the Windows Credential Manager, which is the same secure storage system used by Windows itself for storing passwords and other sensitive information. Features Create and modify credentials using _WinCred_CredWrite Read credentials from the user's credential set with _WinCred_CredRead Delete credentials using _WinCred_CredDelete Support for all credential types (Generic, Domain Password, Certificates, etc.) Configurable persistence options (Session, Local Machine, Enterprise) Full Unicode support Comprehensive error handling with detailed error codes Complete example scripts for all functions Fully documented following AutoIt UDF standards Functions The UDF provides three main functions: _WinCred_CredWrite - Creates a new credential or modifies an existing credential in the user's credential set _WinCred_CredRead - Reads a credential from the user's credential set and returns an array with all credential information _WinCred_CredDelete - Deletes a credential from the user's credential set All functions follow AutoIt's standard error handling mechanism. For detailed syntax, parameters, and return values, please refer to the function documentation in the UDF file. Constants All constants are defined in WinCredConstants.au3, including credential types ($CRED_TYPE_*), persistence options ($CRED_PERSIST_*), and flags ($CRED_PRESERVE_CREDENTIAL_BLOB). See the constants file for a complete list. Quick Start Example #include "WinCred.au3" ; Create a credential Local $sTargetName = "MyApp-Credential" Local $sUserName = "MyUsername" Local $vPassword = Binary("MySecretPassword") If _WinCred_CredWrite($sTargetName, $CRED_TYPE_GENERIC, $sUserName, $vPassword) Then ConsoleWrite("Credential created successfully!" & @CRLF) Else ConsoleWrite("Error creating credential: " & @error & @CRLF) EndIf ; Read the credential Local $aCredential = _WinCred_CredRead($sTargetName, $CRED_TYPE_GENERIC) If Not @error Then ConsoleWrite("TargetName: " & $aCredential[0] & @CRLF) ConsoleWrite("UserName: " & $aCredential[2] & @CRLF) ConsoleWrite("Blob Size: " & BinaryLen($aCredential[3]) & " bytes" & @CRLF) EndIf ; Delete the credential _WinCred_CredDelete($sTargetName, $CRED_TYPE_GENERIC) Example Scripts The UDF includes complete example scripts in the Examples directory: _WinCred_CredWrite.au3 - Demonstrates creating credentials with different persistence settings _WinCred_CredRead.au3 - Shows how to read credentials and display all available information _WinCred_CredDelete.au3 - Demonstrates deleting credentials and verifying deletion All examples are fully commented and follow AutoIt best practices. Security Notes Credentials are stored securely in the Windows Credential Manager The CredentialBlob should contain binary data (use Binary() function) For sensitive data, consider encrypting the blob before storing Documentation Full function documentation is included in the UDF file following AutoIt UDF standards. The UDF is compatible with AutoIt's built-in help file system. License This UDF is released under the MIT License. See the LICENSE file for details. Changelog See CHANGELOG.md for a complete list of changes. Links GitHub Repository: https://github.com/DonChunior/WinCred-UDF Microsoft Documentation: https://learn.microsoft.com/en-us/windows/win32/api/wincred/2 points -
Bug in map ( and how to avoid it )
Musashi and one other reacted to AspirinJunkie for a topic
It seems that this is less about index collisions. The real problem is obviously that memory areas are being used across multiple map instances. Whether this occurs exclusively when using string indices in conjunction with integer indices or in other cases as well, we cannot know here and now. Without having the source code for the implementation, we can only speculate about what is happening in the background based on the behavior. And so far, it seems to me that the memory areas for the buckets of the hash table are not completely cleaned up when dereferencing the map variable, and on the other hand, these areas are used when initializing a map variable without being fully prepared for use (e.g., memory area zeros or something like that). There may well be a clever idea behind this, for example, to increase performance or something like that—we don't know. However, the current implementation is undoubtedly a bug, and worse still, a bug whose consequences cannot really be assessed at present. Therefore, we cannot simply dismiss the issue with blanket statements such as “don't use integer keys” or something similar. This naturally raises the question of how to deal with it. It has been clearly stated that bug reports should not be created for maps. Nevertheless, the bug tracker is full of tickets for maps, and they are being processed as normal. That's why I would have liked to discuss the whole thing in advance in the forum, preferably with the developers involved (actually, I wanted to do just that in the German forum first, but you had already posted the thread here...). In my opinion, the “AutoIt General Help and Support” forum is not the right place for this, but rather “AutoIt Technical Discussion.” However, it may well be that the bug has already been fixed and has been resolved in the course of the following ticket: https://www.autoitscript.com/trac/autoit/ticket/3948 The phenomenon described there is quite similar.2 points -
WinRT - UI Gallery (Xaml Islands)
argumentum and one other reacted to MattyD for a topic
In order not to pollute other threads, here's one dedicated to Windows.UI controls and examples. These are for use with Xaml Islands, NOT WinUI3 - although porting them across shouldn't be too demanding. Both methods have their pros and cons - but I'd say the XAML Island approach is bit more robust at this point in time. Don't forget to update your manifests to make this work! (background/details in this thread) Download PS. More than happy for this to be a community thing if anyone else wishes to contribute2 points -
It was mentioned here how AI bots are intensively hitting the site. I suppose they also grab all the codes they can take...2 points
-
WinRT - WinUI3
WildByDesign and one other reacted to MattyD for a topic
Hi all, Updated libraries based on the new Version 1.8 of WindowsAppSDK are here. Until now we've been on 1.7.x The v1.8 runtime can be installed from here: (Remembering that we require the x64 version.) A copy of the latest bootstrapper dll is included in the zip - but if you need to manually update it later for whatever reason, it has moved. So you'll now find it here: https://www.nuget.org/packages/Microsoft.WindowsAppSdk.Foundation/ download package (on the right) > extract contents > then you'll find it under .\runtimes\win-x64\native2 points -
AutoIt v3.3.18.0 has been released - mainly a UDF release. Thanks to @jpm and the MVPs who were responsible for the majority of code in this version. Download it here. Complete list of changes: History2 points
-
1 point
-
Spawning a process with reduced privileges
Nine reacted to WildByDesign for a topic
This is pure gold! The IsProcessElevated() function is also fantastic. Thank you so much. As you said, it works perfectly on x86 and x64. By the way, related to this, I was able to integrate your WCD_IPC UDF into my engine script which is actually a multi-process engine. Your UDF was the only one light enough and fast enough to do the job. I actually ended up creating a "broker" process for my multi-process engine and that is where I put your IPC server function. And now with the help of your RunLow() function, I can drop the privileges of the GUI and the GUI can still control the elevated "broker" process and therefore also control the various processes. Your willingness to help combined with your abilities to educate others on this forum are absolutely top-notch!1 point -
Here (tested both x86 and x64) ; From Nine #RequireAdmin #AutoIt3Wrapper_UseX64=y #include <WinAPI.au3> Example() Func Example() Local $iPID = RunLow(@ComSpec, " /k Title Low") ConsoleWrite($iPID & " : " & IsProcessElevated($iPID) & @CRLF) EndFunc ;==>Example Func IsProcessElevated($iPID) Local $aRet, $iError = 0 Local $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, False, $iPID, True) If Not $hProcess Then Return SetError(1, 0, False) Local $hToken = _WinAPI_OpenProcessToken($TOKEN_QUERY, $hProcess) If Not $hToken Then $iError = 2 Else $aRet = DllCall('advapi32.dll', 'bool', 'GetTokenInformation', 'handle', $hToken, 'uint', 20, 'uint*', 0, 'dword', 4, 'dword*', 0) ; TOKEN_ELEVATION If @error Or Not $aRet[0] Then $iError = 3 EndIf _WinAPI_CloseHandle($hToken) _WinAPI_CloseHandle($hProcess) If $iError Then Return SetError($iError, 0, False) Return $aRet[3] = 1 EndFunc ;==>IsProcessElevated Func RunLow($sPath, $sCmd = "") Local $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_INFORMATION, False, ProcessExists("explorer.exe")) Local $hToken = _WinAPI_OpenProcessToken($TOKEN_DUPLICATE, $hProcess) Local $hDupToken = _WinAPI_DuplicateTokenEx($hToken, $TOKEN_ALL_ACCESS, $SECURITYIMPERSONATION) Local $tSTARTUPINFO = DllStructCreate($tagSTARTUPINFO) $tSTARTUPINFO.Size = DllStructGetSize($tSTARTUPINFO) Local $tPROCESS = DllStructCreate($tagPROCESS_INFORMATION) _WinAPI_CreateProcessWithToken($sPath, $sCmd, 0, $tSTARTUPINFO, $tPROCESS, $hDupToken) _WinAPI_CloseHandle($hDupToken) _WinAPI_CloseHandle($hToken) _WinAPI_CloseHandle($hProcess) Return $tPROCESS.ProcessID EndFunc ;==>RunLow1 point
-
I have removed the redundant - or, non-essential lines...which are implemented in "other" scripts...but of which are NOT required here. Thanks for the clarification....1 point
-
It could be something like this. #include <AutoItConstants.au3> Opt("MustDeclareVars", 1) Global $iTimeOut = 100 ; **** Preset Configuration Array **** ; This is a 2D array holding all the data that changes between presets. ; Column 0: Preset Name - e.g. "Preset 002" ; Column 1: AmpSimView MouseClick Y-coordinate - e.g. 544 or 564 ; Column 2: Mouse positioning X-coordinate - e.g. 885 ; Column 3: Mouse positioning Y-coordinate - e.g. 222 Global $aPresets[2][4] = [ _ ["Preset 002", 544, 885, 222], _ ["Preset 003", 564, 885, 222] _ ] CallPresetScene($aPresets[0][0], $aPresets[0][1], $aPresets[0][2], $aPresets[0][3]) ; 🔔 Preset 002 ;~ CallPresetScene($aPresets[1][0], $aPresets[1][1], $aPresets[1][2], $aPresets[1][3]) ; 🔔 Preset 003 ; ... ; ------------------------------------------------------------------------------ Func CallPresetScene($sPresetName, $iAmpSimY, $iMPosX, $iMPosY) ConfigureAmpSimView($sPresetName, $iAmpSimY) ConfigureFMixerView() UpdateScenesView($sPresetName, $iMPosX, $iMPosY) UpdateSceneProperties($iMPosX, $iMPosY) EndFunc ;==>CallPresetScene ; ------------------------------------------------------------------------------ Func ConfigureAmpSimView($sPresetName, $iMPosY) Sleep($iTimeOut) MouseClick($MOUSE_CLICK_LEFT, 534, $iMPosY, 2, 0) EndFunc ;==>ConfigureAmpSimView ; ------------------------------------------------------------------------------ Func ConfigureFMixerView() Sleep($iTimeOut) MouseClick($MOUSE_CLICK_LEFT, 50, 120, 1, 0) ; Select: Channel Label [ZMixer] EndFunc ;==>ConfigureFMixerView ; ------------------------------------------------------------------------------ Func UpdateScenesView($sPresetName, $iMPosX, $iMPosY) Local $hSAC_SCENES = "[CLASS:SAC_SCENES]" WinActivate($hSAC_SCENES) Send("{End}") ; Select: [End Of List] Sleep($iTimeOut) MouseClick($MOUSE_CLICK_LEFT, 188, 118, 1, 0) ; Select: [New] Sleep($iTimeOut) ClipPut($sPresetName) ; Copy the variable Preset Name ; Paste text Send("{CTRLDOWN}") Send("v") Send("{CTRLUP}") Send("{ENTER}") ; Select: [Ok] EndFunc ;==>UpdateScenesView ; ------------------------------------------------------------------------------ Func UpdateSceneProperties($iMPosX, $iMPosY) Local $hSAC_SCENEPROPERTIES = "[CLASS:SAC_SCENEPROPERTIES]" Sleep(1500) Send("{ENTER}") ; Select: [OK] EndFunc ;==>UpdateSceneProperties ; ------------------------------------------------------------------------------ Edit: It reflects the idea more. Because it has some problems, which stem from your examples. Like Func UpdatePreset002SceneProperties($iX, $iY) Func UpdatePreset003SceneProperties($iX, $iY) there are parameters $iX, $iY, but you don't use them anywhere in the function Func UpdatePreset002ScenesView($iX, $iY) Func UpdatePreset003ScenesView($iX, $iY) there are parameters $iX, $iY, but you don't use them anywhere in the function1 point
-
WinSockUDF - TCP/UDP Networking Library for AutoIt Version: 1.1 | Author: Dao Van Trong - TRONG.PRO | AutoIt: 3.3.14.2+ 📖 Overview WinSockUDF is a powerful, production-ready TCP/UDP networking library for AutoIt that brings enterprise-level networking capabilities to your scripts. Built on top of the Windows Sockets API (Winsock2), it provides asynchronous, event-driven communication with advanced features that go far beyond AutoIt's built-in networking functions. This library is designed for developers who need reliable, high-performance network communication in their AutoIt applications - whether you're building chat systems, file transfer utilities, remote administration tools, or IoT device controllers. ⚡ Key Features Core Networking ✅ Asynchronous Event-Driven Architecture - True non-blocking I/O with elegant callback system ✅ Full Winsock2 API Access - Direct Windows Sockets implementation for maximum performance ✅ TCP Server & Client - Production-ready server with multi-client support ✅ UDP Support - Connectionless datagram communication (SendTo/RecvFrom) ✅ Multiple Simultaneous Connections - Handle hundreds of clients with ease Advanced Features 🔒 Binary Data Transfer - Safe transmission with automatic Base64 encoding/decoding 🎯 Smart Connection Management - Automatic reconnection, timeouts, and error recovery 📡 Broadcasting - Send messages to all connected clients instantly 🔍 Client Management - Track, query, and control individual client connections ⚙️ Flexible Event System - Register custom callbacks for all network events Developer Experience 📚 Comprehensive Error Handling - Detailed @error/@extended codes for debugging 🎨 Clean API Design - Intuitive function names and consistent parameter patterns 📝 Well Documented - Complete function reference with examples 🚀 Production Ready - Battle-tested in real-world applications 📦 Installation Method 1: Quick Start Download WinSockUDF.au3 from this repository Place it in your AutoIt include directory (usually C:\Program Files (x86)\AutoIt3\Include) Include it in your script: #include <WinSockUDF.au3> Method 2: Project-Local Copy WinSockUDF.au3 to your project folder Include with relative path: #include "WinSockUDF.au3" Requirements: AutoIt v3.3.14.2 or higher Windows OS (XP or later) No external dependencies required Quick Start TCP Server Example #include "WinSockUDF.au3" _TCP_Startup() ; Create server on port 8080 $hServer = _TCP_Server_Create(8080) ; Register event callbacks _TCP_Server_OnNewClient($hServer, "OnNewClient") _TCP_Server_OnReceive($hServer, "OnReceive") _TCP_Server_OnDisconnect($hServer, "OnDisconnect") ; Event loop While 1 Sleep(10) WEnd Func OnNewClient($hClient, $iError) ConsoleWrite("New client connected: " & $hClient & @CRLF) _TCP_Send($hClient, "Welcome to server!" & @CRLF) EndFunc Func OnReceive($hClient, $sData, $iError) ConsoleWrite("Received: " & $sData & @CRLF) _TCP_Send($hClient, "Echo: " & $sData) EndFunc Func OnDisconnect($hClient, $iError) ConsoleWrite("Client disconnected: " & $hClient & @CRLF) EndFunc TCP Client Example #include "WinSockUDF.au3" _TCP_Startup() ; Connect to server $hClient = _TCP_Client_Create("127.0.0.1", 8080) ; Register event callbacks _TCP_Client_OnConnect($hClient, "OnConnect") _TCP_Client_OnReceive($hClient, "OnReceive") _TCP_Client_OnDisconnect($hClient, "OnDisconnect") ; Event loop While 1 Sleep(10) WEnd Func OnConnect($hSocket, $iError) If $iError Then ConsoleWrite("Connection failed: " & $iError & @CRLF) Else ConsoleWrite("Connected successfully!" & @CRLF) _TCP_Send($hSocket, "Hello Server!") EndIf EndFunc Func OnReceive($hSocket, $sData, $iError) ConsoleWrite("Received: " & $sData & @CRLF) EndFunc Func OnDisconnect($hSocket, $iError) ConsoleWrite("Disconnected from server" & @CRLF) EndFunc Function Reference Initialization Functions Function Description _TCP_Startup() Initialize Winsock and async system _TCP_Shutdown() Close all connections and free resources TCP Server Functions Function Description _TCP_Server_Create($iPort[, $sIP = "0.0.0.0"[, $iMaxPending = 5]]) Create TCP server _TCP_Server_Stop($hSocket) Stop server and close all clients _TCP_Server_ClientList() Get array of connected clients _TCP_Server_ClientIP($hSocket) Get client IP address _TCP_Server_DisconnectClient($hSocket) Disconnect specific client _TCP_Server_Broadcast($vData) Send data to all clients _TCP_Server_OnNewClient($hServer, $sCallback) Register new client callback _TCP_Server_OnReceive($hServer, $sCallback) Register receive callback _TCP_Server_OnSend($hServer, $sCallback) Register send ready callback _TCP_Server_OnDisconnect($hServer, $sCallback) Register disconnect callback TCP Client Functions Function Description _TCP_Client_Create($sIP, $iPort[, $sSourceIP = ""[, $iSourcePort = 0[, $iTimeout = 0]]]) Create TCP client connection _TCP_Client_Stop($hSocket) Close client connection _TCP_Client_OnConnect($hClient, $sCallback) Register connect callback _TCP_Client_OnReceive($hClient, $sCallback) Register receive callback _TCP_Client_OnSend($hClient, $sCallback) Register send ready callback _TCP_Client_OnDisconnect($hClient, $sCallback) Register disconnect callback Common TCP Functions Function Description _TCP_Send($hSocket, $vData[, $iFlag = 0]) Send data through socket _TCP_Recv($hSocket, $iMaxLen[, $iFlag = 0]) Receive data from socket _TCP_Send_Ex($hSocket, $vData[, $iFlag = 0]) Send with automatic Base64 encoding _TCP_Recv_Ex($hSocket, $iMaxLen[, $iFlag = 0]) Receive with automatic Base64 decoding _TCP_NameToIP($sName) Convert hostname to IP address _TCP_GetIPs([$sServerName = ""]) Get local and public IP addresses UDP Functions Function Description _UDP_Startup() Initialize UDP system _UDP_Shutdown() Shutdown UDP system _UDP_Bind([$sSourceIP = ""[, $iSourcePort = 0]]) Create and bind UDP socket _UDP_SendTo($sIP, $iPort, $vData[, $hSocket = 0]) Send UDP packet _UDP_RecvFrom($hSocket, $iMaxLen[, $iFlag = 0]) Receive UDP packet _UDP_CloseSocket($vSocket) Close UDP socket Base64 Functions Function Description _Base64Encode($bInput[, $bNoCRLF = True]) Encode binary data to Base64 string _Base64Decode($sInput[, $bReturnBinary = False[, $iDecodeType = 1]]) Decode Base64 string _Base64EncodeStr($sInput[, $iEncodeType = 4[, $bNoCRLF = True]]) Encode string to Base64 _Base64DecodeStr($sInput[, $iDecodeType = 4]) Decode Base64 to string Path Utility Functions Function Description _PathWithSlash($sPath) Add trailing backslash to path _PathRemoveTrail($sPath) Remove trailing backslashes from path Constants Data Flags $TCP_DEFAULT_DATA = 0 ; Default string data $TCP_BINARY_DATA = 1 ; Binary data mode $TCP_EOT_DATA = 2 ; End-of-transmission marker Event Types $TCP_EVENT_SEND = 1 ; Send ready event $TCP_EVENT_RECEIVE = 2 ; Data received event $TCP_EVENT_CONNECT = 4 ; Connection established $TCP_EVENT_DISCONNECT = 8 ; Connection closed $TCP_EVENT_NEWCLIENT = 16 ; New client connected (server) Advanced Features Binary File Transfer Use _TCP_Send_Ex() and _TCP_Recv_Ex() for automatic Base64 encoding/decoding of binary data: ; Send binary file Local $bData = FileRead("image.jpg") _TCP_Send_Ex($hSocket, $bData) ; Receive binary file Local $bData = _TCP_Recv_Ex($hSocket, 8192, $TCP_BINARY_DATA) FileWrite("received.jpg", $bData) Multiple Server Support The library supports running multiple servers on different ports simultaneously with independent callback handlers. Connection Timeout Client connections support timeout parameter: ; Wait up to 5 seconds for connection $hClient = _TCP_Client_Create("192.168.1.100", 8080, "", 0, 5000) Error Handling All functions set @error on failure: -1 = General error (check @extended for WSA error code) -2 = Failed to load Winsock DLL -4 = Invalid parameters or socket not found -5 = Connection failed -6 = Timeout Example: $hServer = _TCP_Server_Create(8080) If @error Then ConsoleWrite("Failed to create server. Error: " & @error & ", Extended: " & @extended & @CRLF) Exit EndIf 📚 Example Applications This repository includes three complete, production-ready example applications: TCP Chat System - Full-featured chat room with authentication, private messaging, and user management UDP Chat Application - Lightweight UDP-based chat demonstrating connectionless communication Lab Manager System - Professional client-server remote administration tool with system monitoring Each example includes both client and server implementations with complete source code. 💡 Use Cases 💬 Chat Applications - Real-time messaging systems with multi-user support 📁 File Transfer Tools - Binary file sharing with Base64 encoding 🖥️ Remote Administration - Control and monitor computers over network 🎮 Game Servers - Multiplayer game networking and matchmaking 🌐 IoT Communication - Device-to-device communication and control 🔌 API Servers - Custom protocol implementations and microservices 📊 Data Collection - Sensor data aggregation and monitoring systems 🔔 Notification Systems - Push notification and alert distribution Note: This library uses direct Winsock API calls for advanced networking features. Make sure to call _TCP_Startup() before using any TCP/UDP functions and _TCP_Shutdown() when done. UDF: ; #INDEX# ======================================================================================================================= ; Title .........: WinSockUDF ; AutoIt Version : 3.3.14.2+ ; Language ......: English ; Description ...: Advanced TCP/UDP networking library with async events, error handling, full Winsock2 API support ; Author(s) .....: Dao Van Trong - TRONG.PRO ; Version .......: 1.1 ; =============================================================================================================================== #include-once ; #CONSTANTS# =================================================================================================================== Global Const $TCP_DEFAULT_DATA = 0 Global Const $TCP_BINARY_DATA = 1 Global Const $TCP_EOT_DATA = 2 ; Async Events Global Const $TCP_EVENT_SEND = 1 Global Const $TCP_EVENT_RECEIVE = 2 Global Const $TCP_EVENT_CONNECT = 4 Global Const $TCP_EVENT_DISCONNECT = 8 Global Const $TCP_EVENT_NEWCLIENT = 16 ; Winsock Events (internal) Global Const $FD_READ = 1 Global Const $FD_WRITE = 2 Global Const $FD_OOB = 4 Global Const $FD_ACCEPT = 8 Global Const $FD_CONNECT = 16 Global Const $FD_CLOSE = 32 ; =============================================================================================================================== ; #VARIABLES# =================================================================================================================== Global $__TCP_hWs2_32 = -1 Global $__TCP_AsyncWindow = 0 Global $__TCP_Sockets[1][11] ; [socket, msgID, onRecv, onSend, onConnect, onDisconnect, onNewClient, ip, port, isServer, parentServer] Global $__TCP_Initialized = False ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ; Initialization ; _TCP_Startup ; _TCP_Shutdown ; ; Server Functions ; _TCP_Server_Create ; _TCP_Server_Stop ; _TCP_Server_ClientList ; _TCP_Server_ClientIP ; _TCP_Server_DisconnectClient ; _TCP_Server_Broadcast ; _TCP_Server_OnNewClient ; _TCP_Server_OnReceive ; _TCP_Server_OnSend ; _TCP_Server_OnDisconnect ; ; Client Functions ; _TCP_Client_Create ; _TCP_Client_Stop ; _TCP_Client_OnConnect ; _TCP_Client_OnReceive ; _TCP_Client_OnSend ; _TCP_Client_OnDisconnect ; ; Common Functions ; _TCP_Send ; _TCP_Recv ; _TCP_Send_Ex ; _TCP_Recv_Ex ; _TCP_RegisterEvent ; _TCP_NameToIP ; _TCP_GetIPs ; _TCP_OnConnect (alias for Client) ; _TCP_OnDisconnect (universal) ; _TCP_OnReceive (universal) ; _TCP_OnSend (universal) ; ; UDP Functions ; _UDP_Startup ; _UDP_Shutdown ; _UDP_Bind ; _UDP_SendTo ; _UDP_RecvFrom ; _UDP_CloseSocket ; ; Base64 Functions ; _Base64Encode ; _Base64Decode ; _Base64EncodeStr ; _Base64DecodeStr ; ; Path Functions ; _PathWithSlash ; _PathRemoveTrail ; ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Startup ; Description ...: Initialize Winsock and async system ; Syntax ........: _TCP_Startup() ; Return values .: Success - 1, Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Startup() If $__TCP_Initialized Then Return 1 Local $iResult = TCPStartup() If @error Then Return SetError(@error, 0, 0) $__TCP_hWs2_32 = DllOpen("Ws2_32.dll") If $__TCP_hWs2_32 = -1 Then Return SetError(-2, 0, 0) $__TCP_AsyncWindow = GUICreate("TCP_AsyncWindow_" & Random(1000, 9999, 1)) $__TCP_Initialized = True Return SetError(0, 0, 1) EndFunc ;==>_TCP_Startup ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Shutdown ; Description ...: Close all connections and free resources ; Syntax ........: _TCP_Shutdown() ; Return values .: Success - 1 ; =============================================================================================================================== Func _TCP_Shutdown() If Not $__TCP_Initialized Then Return 1 ; Close all sockets For $i = UBound($__TCP_Sockets) - 1 To 0 Step -1 If $__TCP_Sockets[$i][0] Then ___TCP_CloseSocket($__TCP_Sockets[$i][0]) EndIf Next ReDim $__TCP_Sockets[1][11] If $__TCP_hWs2_32 <> -1 Then DllClose($__TCP_hWs2_32) $__TCP_hWs2_32 = -1 TCPShutdown() $__TCP_Initialized = False Return 1 EndFunc ;==>_TCP_Shutdown ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_Create ; Description ...: Create TCP server with async support ; Syntax ........: _TCP_Server_Create($iPort[, $sIP = "0.0.0.0"[, $iMaxPending = 5]]) ; Parameters ....: $iPort - Port to listen on ; $sIP - [optional] IP address (default = "0.0.0.0" - all interfaces) ; $iMaxPending - [optional] Max pending connections (default = 5) ; Return values .: Success - Socket handle ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Server_Create($iPort, $sIP = "0.0.0.0", $iMaxPending = 5) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf Local $hSocket = ___TCP_Socket() If @error Then Return SetError(@error, 0, -1) ; Bind socket Local $tSockAddr = ___TCP_SockAddr($sIP, $iPort) If @error Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf ; Listen $aRet = DllCall($__TCP_hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf ; Setup async Local $iMsgID = 0x0400 + UBound($__TCP_Sockets) If Not ___TCP_AsyncSelect($hSocket, $__TCP_AsyncWindow, $iMsgID, $FD_ACCEPT) Then ___TCP_CloseSocket($hSocket) Return SetError(@error, @extended, -1) EndIf GUIRegisterMsg($iMsgID, "___TCP_Server_OnAccept") ; Store socket info ReDim $__TCP_Sockets[UBound($__TCP_Sockets) + 1][11] Local $idx = UBound($__TCP_Sockets) - 1 $__TCP_Sockets[$idx][0] = $hSocket $__TCP_Sockets[$idx][1] = $iMsgID $__TCP_Sockets[$idx][7] = $sIP $__TCP_Sockets[$idx][8] = $iPort $__TCP_Sockets[$idx][9] = True ; isServer $__TCP_Sockets[$idx][10] = 0 ; parentServer Return $hSocket EndFunc ;==>_TCP_Server_Create ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_Stop ; Description ...: Stop server and close all client connections ; Syntax ........: _TCP_Server_Stop($hSocket) ; Parameters ....: $hSocket - Server socket handle ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Server_Stop($hSocket) Local $iServerIdx = ___TCP_FindSocket($hSocket) If $iServerIdx < 0 Then Return SetError(-4, 0, 0) ; Close all clients of this server For $i = UBound($__TCP_Sockets) - 1 To 0 Step -1 If $i <> $iServerIdx And $__TCP_Sockets[$i][0] Then If Not $__TCP_Sockets[$i][9] Then ; Not a server ___TCP_CloseSocket($__TCP_Sockets[$i][0]) ___TCP_ArrayDelete($__TCP_Sockets, $i) EndIf EndIf Next ; Close server socket ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iServerIdx) Return 1 EndFunc ;==>_TCP_Server_Stop ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_Create ; Description ...: Create TCP client connection with timeout and async support ; Syntax ........: _TCP_Client_Create($sIP, $iPort[, $sSourceIP = ""[, $iSourcePort = 0[, $iTimeout = 0]]]) ; Parameters ....: $sIP - Server IP address ; $iPort - Server port ; $sSourceIP - [optional] Local IP to bind (default = "") ; $iSourcePort - [optional] Local port to bind (default = 0) ; $iTimeout - [optional] Connection timeout in ms (0 = async without waiting) ; Return values .: Success - Socket handle ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Client_Create($sIP, $iPort, $sSourceIP = "", $iSourcePort = 0, $iTimeout = 0) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf ; Validate parameters If Not ($iPort > 0 And $iPort < 65535) Then Return SetError(-4, 0, -1) If Not ($iSourcePort >= 0 And $iSourcePort < 65535) Then Return SetError(-4, 0, -1) Local $hSocket = ___TCP_Socket() If @error Then Return SetError(@error, 0, -1) ; Bind source if specified If $sSourceIP <> "" Or $iSourcePort > 0 Then Local $tSockAddr = ___TCP_SockAddr($sSourceIP <> "" ? $sSourceIP : "0.0.0.0", $iSourcePort) If @error Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf EndIf ; Store socket info BEFORE async setup ReDim $__TCP_Sockets[UBound($__TCP_Sockets) + 1][11] Local $idx = UBound($__TCP_Sockets) - 1 $__TCP_Sockets[$idx][0] = $hSocket $__TCP_Sockets[$idx][7] = $sIP $__TCP_Sockets[$idx][8] = $iPort $__TCP_Sockets[$idx][9] = False ; isClient $__TCP_Sockets[$idx][10] = 0 ; parentServer ; Setup async - IMPORTANT: Do this before connect Local $iMsgID = 0x0400 + $idx $__TCP_Sockets[$idx][1] = $iMsgID If Not ___TCP_AsyncSelect($hSocket, $__TCP_AsyncWindow, $iMsgID, BitOR($FD_READ, $FD_WRITE, $FD_CONNECT, $FD_CLOSE)) Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return SetError(@error, @extended, -1) EndIf GUIRegisterMsg($iMsgID, "___TCP_Client_OnSocketEvent") ; Connect Local $tSockAddr = ___TCP_SockAddr($sIP, $iPort) If @error Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return SetError(@error, 0, -1) EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) ; For async sockets, connect() returns SOCKET_ERROR with WSAEWOULDBLOCK Local $iError = ___TCP_WSAGetLastError() ; Check if connected immediately (rare for TCP) If Not @error And $aRet[0] = 0 Then ; Connected immediately - call connect callback if set Return $hSocket EndIf ; WSAEWOULDBLOCK (10035) is normal for async connect If $iError <> 10035 And $iError <> 0 Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return SetError(-1, $iError, -1) EndIf ; Wait for connection if timeout specified If $iTimeout > 0 Then Local $hTimer = TimerInit() Local $bConnected = False While TimerDiff($hTimer) < $iTimeout Sleep(10) ; Check if socket still exists (might have been connected via callback) Local $iCheckIdx = ___TCP_FindSocket($hSocket) If $iCheckIdx >= 0 Then ; Try to check connection status Local $tErr = DllStructCreate("int") Local $aCheck = DllCall($__TCP_hWs2_32, "int", "getsockopt", _ "uint", $hSocket, "int", 0xFFFF, "int", 0x1007, _ "ptr", DllStructGetPtr($tErr), "int*", DllStructGetSize($tErr)) ; SOL_SOCKET, SO_ERROR If Not @error And $aCheck[0] = 0 Then Local $iSockErr = DllStructGetData($tErr, 1) If $iSockErr = 0 Then ; Connected successfully $bConnected = True ExitLoop ElseIf $iSockErr <> 10035 Then ; Not WSAEWOULDBLOCK ; Connection error ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iCheckIdx) Return SetError(-1, $iSockErr, -1) EndIf EndIf Else ; Socket was removed (probably connected and then disconnected) ExitLoop EndIf WEnd ; Check timeout If Not $bConnected And TimerDiff($hTimer) >= $iTimeout Then Local $iCheckIdx = ___TCP_FindSocket($hSocket) If $iCheckIdx >= 0 Then ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iCheckIdx) EndIf Return SetError(-6, 0, -1) ; Timeout EndIf EndIf Return $hSocket EndFunc ;==>_TCP_Client_Create ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_Stop ; Description ...: Close client connection ; Syntax ........: _TCP_Client_Stop($hSocket) ; Parameters ....: $hSocket - Client socket handle ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Client_Stop($hSocket) Local $idx = ___TCP_FindSocket($hSocket) If $idx < 0 Then Return SetError(-4, 0, 0) ___TCP_Shutdown($hSocket) ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $idx) Return 1 EndFunc ;==>_TCP_Client_Stop ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Send ; Description ...: Send data through socket ; Syntax ........: _TCP_Send($hSocket, $vData[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $vData - Data to send (string or binary) ; $iFlag - [optional] $TCP_DEFAULT_DATA (0) or $TCP_EOT_DATA (2) ; Return values .: Success - Number of bytes sent ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Send($hSocket, $vData, $iFlag = 0) If BitAND($iFlag, $TCP_EOT_DATA) Then $vData = String($vData) & Chr(3) Local $iResult = TCPSend($hSocket, $vData) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCP_Send ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Recv ; Description ...: Receive data from socket ; Syntax ........: _TCP_Recv($hSocket, $iMaxLen[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $iMaxLen - Max bytes to receive ; $iFlag - [optional] $TCP_DEFAULT_DATA (0), $TCP_BINARY_DATA (1), or $TCP_EOT_DATA (2) ; Return values .: Success - Data received ; Failure - "" and sets @error/@extended ; Remarks .......: @extended = 1 if connection closed, = 2 if EOT reached ; =============================================================================================================================== Func _TCP_Recv($hSocket, $iMaxLen, $iFlag = 0) If Not $__TCP_Initialized Then Return SetError(-1, 0, "") Local $tBuf If BitAND($iFlag, $TCP_BINARY_DATA) Then $tBuf = DllStructCreate("byte[" & $iMaxLen & "]") Else $tBuf = DllStructCreate("char[" & $iMaxLen & "]") EndIf If Not ___TCP_SetNonBlocking($hSocket) Then Return SetError(@error, 0, "") Local $aRet = DllCall($__TCP_hWs2_32, "int", "recv", "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iMaxLen, "int", 0) If @error Then Return SetError(-1, 0, "") If $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $iError = 0 Or $iError = 10035 Then Return SetError(0, 0, "") ; WSAEWOULDBLOCK - no data Return SetError($iError, 0, "") EndIf If $aRet[0] = 0 Then Return SetError(0, 1, "") ; Connection closed Local $sResult = DllStructGetData($tBuf, 1) If BitAND($iFlag, $TCP_EOT_DATA) Then If StringRight($sResult, 1) = Chr(3) Then $sResult = StringTrimRight($sResult, 1) Return SetError(0, 2, $sResult) ; EOT reached EndIf EndIf Return SetError(0, 0, $sResult) EndFunc ;==>_TCP_Recv ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnNewClient ; Description ...: Register callback when new client connects ; Syntax ........: _TCP_Server_OnNewClient($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnNewClient($hClientSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnNewClient($hServer, "OnNewClient") ; Func OnNewClient($hClient, $iError) ; If $iError Then ConsoleWrite("Accept error: " & $iError & @CRLF) ; Else ConsoleWrite("New client: " & $hClient & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnNewClient($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_NEWCLIENT, $sFunction) EndFunc ;==>_TCP_Server_OnNewClient ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnReceive ; Description ...: Register callback when server receives data from client ; Syntax ........: _TCP_Server_OnReceive($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnReceive($hClientSocket, $sData, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnReceive($hServer, "OnReceive") ; Func OnReceive($hClient, $sData, $iError) ; If Not $iError Then _TCP_Send($hClient, "Echo: " & $sData) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnReceive($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_RECEIVE, $sFunction) EndFunc ;==>_TCP_Server_OnReceive ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnSend ; Description ...: Register callback when server is ready to send data ; Syntax ........: _TCP_Server_OnSend($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnSend($hClientSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnSend($hServer, "OnSend") ; Func OnSend($hClient, $iError) ; If Not $iError Then ConsoleWrite("Ready to send on: " & $hClient & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnSend($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_SEND, $sFunction) EndFunc ;==>_TCP_Server_OnSend ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_OnDisconnect ; Description ...: Register callback when client disconnects ; Syntax ........: _TCP_Server_OnDisconnect($hServerSocket, $sFunction) ; Parameters ....: $hServerSocket - Server socket handle ; $sFunction - Callback function name: Func OnDisconnect($hClientSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Server_OnDisconnect($hServer, "OnDisconnect") ; Func OnDisconnect($hClient, $iError) ; ConsoleWrite("Client disconnected: " & $hClient & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Server_OnDisconnect($hServerSocket, $sFunction) Return _TCP_RegisterEvent($hServerSocket, $TCP_EVENT_DISCONNECT, $sFunction) EndFunc ;==>_TCP_Server_OnDisconnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnConnect ; Description ...: Register callback when client connection succeeds/fails ; Syntax ........: _TCP_Client_OnConnect($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnConnect($hSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnConnect($hClient, "OnConnect") ; Func OnConnect($hSocket, $iError) ; If $iError Then ConsoleWrite("Connect failed: " & $iError & @CRLF) ; Else ConsoleWrite("Connected successfully!" & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnConnect($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_CONNECT, $sFunction) EndFunc ;==>_TCP_Client_OnConnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnReceive ; Description ...: Register callback when client receives data from server ; Syntax ........: _TCP_Client_OnReceive($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnReceive($hSocket, $sData, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnReceive($hClient, "OnReceive") ; Func OnReceive($hSocket, $sData, $iError) ; If Not $iError Then ConsoleWrite("Received: " & $sData & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnReceive($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_RECEIVE, $sFunction) EndFunc ;==>_TCP_Client_OnReceive ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnSend ; Description ...: Register callback when client is ready to send data ; Syntax ........: _TCP_Client_OnSend($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnSend($hSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnSend($hClient, "OnSend") ; Func OnSend($hSocket, $iError) ; If Not $iError Then ConsoleWrite("Ready to send" & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnSend($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_SEND, $sFunction) EndFunc ;==>_TCP_Client_OnSend ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Client_OnDisconnect ; Description ...: Register callback when client disconnects ; Syntax ........: _TCP_Client_OnDisconnect($hClientSocket, $sFunction) ; Parameters ....: $hClientSocket - Client socket handle ; $sFunction - Callback function name: Func OnDisconnect($hSocket, $iError) ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Example .......: _TCP_Client_OnDisconnect($hClient, "OnDisconnect") ; Func OnDisconnect($hSocket, $iError) ; ConsoleWrite("Disconnected from server" & @CRLF) ; EndFunc ; =============================================================================================================================== Func _TCP_Client_OnDisconnect($hClientSocket, $sFunction) Return _TCP_RegisterEvent($hClientSocket, $TCP_EVENT_DISCONNECT, $sFunction) EndFunc ;==>_TCP_Client_OnDisconnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnConnect ; Description ...: Alias of _TCP_Client_OnConnect for simpler syntax ; Syntax ........: _TCP_OnConnect($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_OnConnect($hSocket, $sFunction) Return _TCP_Client_OnConnect($hSocket, $sFunction) EndFunc ;==>_TCP_OnConnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnReceive ; Description ...: Universal callback for both client and server ; Syntax ........: _TCP_OnReceive($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle (client or server) ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Remarks .......: Can be used for both client and server sockets ; =============================================================================================================================== Func _TCP_OnReceive($hSocket, $sFunction) Return _TCP_RegisterEvent($hSocket, $TCP_EVENT_RECEIVE, $sFunction) EndFunc ;==>_TCP_OnReceive ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnSend ; Description ...: Universal callback for both client and server ; Syntax ........: _TCP_OnSend($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle (client or server) ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_OnSend($hSocket, $sFunction) Return _TCP_RegisterEvent($hSocket, $TCP_EVENT_SEND, $sFunction) EndFunc ;==>_TCP_OnSend ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_OnDisconnect ; Description ...: Universal callback for both client and server ; Syntax ........: _TCP_OnDisconnect($hSocket, $sFunction) ; Parameters ....: $hSocket - Socket handle (client or server) ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_OnDisconnect($hSocket, $sFunction) Return _TCP_RegisterEvent($hSocket, $TCP_EVENT_DISCONNECT, $sFunction) EndFunc ;==>_TCP_OnDisconnect ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_RegisterEvent ; Description ...: Internal function to register event callbacks ; Syntax ........: _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) ; Parameters ....: $hSocket - Socket handle ; $iEvent - Event type constant ; $sFunction - Callback function name ; Return values .: Success - 1 ; Failure - 0 and sets @error ; Remarks .......: This is an internal function. Use specific _TCP_*_On* functions instead ; =============================================================================================================================== Func _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) Local $idx = ___TCP_FindSocket($hSocket) If $idx < 0 Then Return SetError(-4, 0, 0) Switch $iEvent Case $TCP_EVENT_SEND $__TCP_Sockets[$idx][3] = $sFunction Case $TCP_EVENT_RECEIVE $__TCP_Sockets[$idx][2] = $sFunction Case $TCP_EVENT_CONNECT $__TCP_Sockets[$idx][4] = $sFunction Case $TCP_EVENT_DISCONNECT $__TCP_Sockets[$idx][5] = $sFunction Case $TCP_EVENT_NEWCLIENT $__TCP_Sockets[$idx][6] = $sFunction Case Else Return SetError(-4, 0, 0) EndSwitch Return 1 EndFunc ;==>_TCP_RegisterEvent ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_ClientList ; Description ...: Get list of client sockets ; Syntax ........: _TCP_Server_ClientList() ; Return values .: Array of client sockets, [0] = count ; =============================================================================================================================== Func _TCP_Server_ClientList() Local $aClients[1] = [0] For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] And Not $__TCP_Sockets[$i][9] Then ; Not a server socket ReDim $aClients[UBound($aClients) + 1] $aClients[UBound($aClients) - 1] = $__TCP_Sockets[$i][0] $aClients[0] += 1 EndIf Next Return $aClients EndFunc ;==>_TCP_Server_ClientList ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_ClientIP ; Description ...: Get IP address of client ; Syntax ........: _TCP_Server_ClientIP($hSocket) ; Parameters ....: $hSocket - Client socket handle ; Return values .: Success - IP address string ; Failure - "" and sets @error ; =============================================================================================================================== Func _TCP_Server_ClientIP($hSocket) Local $tSockAddr = DllStructCreate("short;ushort;uint;char[8]") Local $aRet = DllCall($__TCP_hWs2_32, "int", "getpeername", "int", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then Return SetError(-1, 0, "") $aRet = DllCall($__TCP_hWs2_32, "str", "inet_ntoa", "int", DllStructGetData($tSockAddr, 3)) If @error Then Return SetError(-1, 0, "") Return $aRet[0] EndFunc ;==>_TCP_Server_ClientIP ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_Broadcast ; Description ...: Send data to all clients ; Syntax ........: _TCP_Server_Broadcast($vData) ; Parameters ....: $vData - Data to broadcast ; Return values .: Number of clients sent to ; =============================================================================================================================== Func _TCP_Server_Broadcast($vData) Local $iCount = 0 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] And Not $__TCP_Sockets[$i][9] Then TCPSend($__TCP_Sockets[$i][0], $vData) $iCount += 1 EndIf Next Return $iCount EndFunc ;==>_TCP_Server_Broadcast ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Server_DisconnectClient ; Description ...: Disconnect a client ; Syntax ........: _TCP_Server_DisconnectClient($hSocket) ; Parameters ....: $hSocket - Client socket handle ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _TCP_Server_DisconnectClient($hSocket) Return _TCP_Client_Stop($hSocket) EndFunc ;==>_TCP_Server_DisconnectClient ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_NameToIP ; Description ...: Convert hostname to IP address ; Syntax ........: _TCP_NameToIP($sName) ; Parameters ....: $sName - Hostname ; Return values .: Success - IP address ; Failure - "" and sets @error ; =============================================================================================================================== Func _TCP_NameToIP($sName) Local $sIP = TCPNameToIP($sName) Return SetError(@error, 0, $sIP) EndFunc ;==>_TCP_NameToIP ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_GetIPs ; Description ...: Get local and public IP addresses ; Syntax ........: _TCP_GetIPs([$sServerName = ""]) ; Parameters ....: $sServerName - [optional] Server to check public IP ; Return values .: Success - Array [localIP, publicIP] ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_GetIPs($sServerName = "") If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf Local $aServers[][2] = [["www.myexternalip.com/raw"], ["checkip.dyndns.org/"], ["bot.whatismyipaddress.com/"]] If $sServerName <> "" Then ReDim $aServers[UBound($aServers) + 1][2] $aServers[UBound($aServers) - 1][0] = $sServerName EndIf Local $sLocalIP = "", $sPublicIP = "" Local $hSocket = ___TCP_Socket() If @error Then Return SetError(@error, 0, -1) For $i = 0 To UBound($aServers) - 1 Local $sHost = StringRegExp($aServers[$i][0], "^([^/]+)", 1) If @error Then ContinueLoop $sHost = $sHost[0] Local $sServerIP = TCPNameToIP($sHost) If $sServerIP = "" Then ContinueLoop ; Connect Local $tSockAddr = ___TCP_SockAddr($sServerIP, 80) If @error Then ContinueLoop ___TCP_SetNonBlocking($hSocket) DllCall($__TCP_hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) ; Wait for connection If Not ___TCP_WaitForConnect($hSocket, 2000) Then ___TCP_CloseSocket($hSocket) $hSocket = ___TCP_Socket() ContinueLoop EndIf ; Get local IP If $sLocalIP = "" Then Local $tLocalAddr = DllStructCreate("short;ushort;uint;char[8]") Local $aRet = DllCall($__TCP_hWs2_32, "int", "getsockname", "uint", $hSocket, "ptr", DllStructGetPtr($tLocalAddr), "int*", DllStructGetSize($tLocalAddr)) If Not @error And $aRet[0] = 0 Then $aRet = DllCall($__TCP_hWs2_32, "ptr", "inet_ntoa", "ulong", DllStructGetData($tLocalAddr, 3)) If Not @error And $aRet[0] <> Null Then $sLocalIP = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) EndIf EndIf EndIf ; Get public IP Local $sRequest = "GET /" & StringRegExpReplace($aServers[$i][0], "^[^/]+/?", "") & " HTTP/1.1" & @CRLF & _ "Host: " & $sHost & @CRLF & _ "Connection: close" & @CRLF & @CRLF TCPSend($hSocket, $sRequest) Sleep(500) Local $sRecv = "" Local $hTimer = TimerInit() While TimerDiff($hTimer) < 3000 Local $sChunk = _TCP_Recv($hSocket, 2048) If @extended = 1 Then ExitLoop ; Connection closed $sRecv &= $sChunk If $sChunk = "" Then Sleep(10) WEnd Local $aIP = StringRegExp($sRecv, "((?:\d{1,3}\.){3}\d{1,3})", 3) If Not @error And UBound($aIP) > 0 Then $sPublicIP = $aIP[0] ExitLoop EndIf ___TCP_CloseSocket($hSocket) $hSocket = ___TCP_Socket() Next ___TCP_CloseSocket($hSocket) If $sLocalIP = "" Or $sPublicIP = "" Then Return SetError(-6, 0, -1) Local $aResult[2] = [$sLocalIP, $sPublicIP] Return $aResult EndFunc ;==>_TCP_GetIPs ; #UDP FUNCTIONS# =============================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_Startup ; Description ...: Initialize UDP system ; Syntax ........: _UDP_Startup() ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _UDP_Startup() Local $iResult = UDPStartup() Return SetError(@error, 0, $iResult) EndFunc ;==>_UDP_Startup ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_Shutdown ; Description ...: Shutdown UDP system ; Syntax ........: _UDP_Shutdown() ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _UDP_Shutdown() Local $iResult = UDPShutdown() Return SetError(@error, 0, $iResult) EndFunc ;==>_UDP_Shutdown ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_Bind ; Description ...: Create and bind UDP socket ; Syntax ........: _UDP_Bind([$sSourceIP = ""[, $iSourcePort = 0]]) ; Parameters ....: $sSourceIP - [optional] Local IP to bind (default = "") ; $iSourcePort - [optional] Local port to bind (default = 0) ; Return values .: Success - Socket handle ; Failure - -1 and sets @error ; =============================================================================================================================== Func _UDP_Bind($sSourceIP = "", $iSourcePort = 0) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf If Not ($iSourcePort >= 0 And $iSourcePort < 65535) Then Return SetError(-4, 0, -1) Local $aRet = DllCall($__TCP_hWs2_32, "uint", "socket", "int", 2, "int", 2, "int", 17) ; AF_INET, SOCK_DGRAM, IPPROTO_UDP If @error Then Return SetError(-1, 0, -1) If $aRet[0] = 4294967295 Or $aRet[0] = -1 Then Return SetError(-1, ___TCP_WSAGetLastError(), -1) Local $hSocket = $aRet[0] ; Bind if IP or port specified If $sSourceIP <> "" Or $iSourcePort > 0 Then Local $tSockAddr = ___TCP_SockAddr($sSourceIP <> "" ? $sSourceIP : "0.0.0.0", $iSourcePort) If @error Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf $aRet = DllCall($__TCP_hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] <> 0 Then ___TCP_CloseSocket($hSocket) Return SetError(-1, ___TCP_WSAGetLastError(), -1) EndIf EndIf Return $hSocket EndFunc ;==>_UDP_Bind ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_SendTo ; Description ...: Send UDP packet to specified address ; Syntax ........: _UDP_SendTo($sIP, $iPort, $vData[, $hSocket = 0]) ; Parameters ....: $sIP - Destination IP address ; $iPort - Destination port ; $vData - Data to send (string or binary) ; $hSocket - [optional] Socket handle (0 = create temporary socket) ; Return values .: Success - Array [bytes_sent, socket_handle] ; Failure - -1 and sets @error ; =============================================================================================================================== Func _UDP_SendTo($sIP, $iPort, $vData, $hSocket = 0) If Not $__TCP_Initialized Then If Not _TCP_Startup() Then Return SetError(@error, 0, -1) EndIf If Not ($iPort > 0 And $iPort < 65535) Then Return SetError(-4, 0, -1) Local $bCloseAfter = False If $hSocket = 0 Then $hSocket = _UDP_Bind() If @error Then Return SetError(@error, 0, -1) $bCloseAfter = True EndIf Local $tSockAddr = ___TCP_SockAddr($sIP, $iPort) If @error Then If $bCloseAfter Then ___TCP_CloseSocket($hSocket) Return SetError(@error, 0, -1) EndIf Local $tBuf, $iLen If IsBinary($vData) Then $iLen = BinaryLen($vData) $tBuf = DllStructCreate("byte[" & $iLen & "]") DllStructSetData($tBuf, 1, $vData) Else $vData = String($vData) $iLen = StringLen($vData) $tBuf = DllStructCreate("char[" & $iLen & "]") DllStructSetData($tBuf, 1, $vData) EndIf ___TCP_SetNonBlocking($hSocket) Local $aRet = DllCall($__TCP_hWs2_32, "int", "sendto", _ "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iLen, "int", 0, _ "ptr", DllStructGetPtr($tSockAddr), "int", DllStructGetSize($tSockAddr)) If @error Or $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $bCloseAfter Then ___TCP_CloseSocket($hSocket) Return SetError($iError, 0, -1) EndIf Local $aResult[2] = [$aRet[0], $hSocket] If $bCloseAfter Then ___TCP_CloseSocket($hSocket) Return $aResult EndFunc ;==>_UDP_SendTo ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_RecvFrom ; Description ...: Receive UDP packet ; Syntax ........: _UDP_RecvFrom($hSocket, $iMaxLen[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $iMaxLen - Max bytes to receive ; $iFlag - [optional] 0 = string, 1 = binary ; Return values .: Success - Array [data, source_ip, source_port] ; Failure - -1 and sets @error ; =============================================================================================================================== Func _UDP_RecvFrom($hSocket, $iMaxLen, $iFlag = 0) If Not $__TCP_Initialized Then Return SetError(-1, 0, -1) If $iMaxLen < 1 Then Return SetError(-4, 0, -1) If $iFlag <> 0 And $iFlag <> 1 Then Return SetError(-4, 0, -1) ___TCP_SetNonBlocking($hSocket) Local $tSockAddr = DllStructCreate("short;ushort;uint;char[8]") Local $tBuf If $iFlag = 1 Then $tBuf = DllStructCreate("byte[" & $iMaxLen & "]") Else $tBuf = DllStructCreate("char[" & $iMaxLen & "]") EndIf Local $aRet = DllCall($__TCP_hWs2_32, "int", "recvfrom", _ "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iMaxLen, "int", 0, _ "ptr", DllStructGetPtr($tSockAddr), "int*", DllStructGetSize($tSockAddr)) If @error Then Return SetError(-1, 0, -1) If $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $iError = 0 Or $iError = 10035 Then Return SetError(0, 0, -1) ; WSAEWOULDBLOCK Return SetError($iError, 0, -1) EndIf Local $aResult[3] $aResult[0] = DllStructGetData($tBuf, 1) $aRet = DllCall($__TCP_hWs2_32, "ptr", "inet_ntoa", "ulong", DllStructGetData($tSockAddr, 3)) If @error Or $aRet[0] = Null Then Return SetError(-1, 0, -1) $aResult[1] = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) $aRet = DllCall($__TCP_hWs2_32, "ushort", "ntohs", "ushort", DllStructGetData($tSockAddr, 2)) If @error Then Return SetError(-1, 0, -1) $aResult[2] = $aRet[0] Return $aResult EndFunc ;==>_UDP_RecvFrom ; #FUNCTION# ==================================================================================================================== ; Name ..........: _UDP_CloseSocket ; Description ...: Close UDP socket ; Syntax ........: _UDP_CloseSocket($vSocket) ; Parameters ....: $vSocket - Socket handle or array from _UDP_SendTo ; Return values .: Success - 1 ; Failure - 0 and sets @error ; =============================================================================================================================== Func _UDP_CloseSocket($vSocket) Local $hSocket If IsArray($vSocket) And UBound($vSocket) = 2 Then $hSocket = $vSocket[1] Else $hSocket = $vSocket EndIf If $hSocket < 1 Then Return SetError(-4, 0, 0) Local $aRet = DllCall($__TCP_hWs2_32, "int", "closesocket", "uint", $hSocket) If @error Or $aRet[0] <> 0 Then Return SetError(___TCP_WSAGetLastError(), 0, 0) EndIf Return 1 EndFunc ;==>_UDP_CloseSocket ; #INTERNAL FUNCTIONS# ========================================================================================================== Func ___TCP_Socket() Local $aRet = DllCall($__TCP_hWs2_32, "uint", "socket", "int", 2, "int", 1, "int", 6) ; AF_INET, SOCK_STREAM, IPPROTO_TCP If @error Then Return SetError(-1, 0, -1) If $aRet[0] = 4294967295 Or $aRet[0] = -1 Then Return SetError(-1, ___TCP_WSAGetLastError(), -1) Return $aRet[0] EndFunc ;==>___TCP_Socket Func ___TCP_CloseSocket($hSocket) DllCall($__TCP_hWs2_32, "int", "closesocket", "uint", $hSocket) Return TCPCloseSocket($hSocket) EndFunc ;==>___TCP_CloseSocket Func ___TCP_Shutdown($hSocket) DllCall($__TCP_hWs2_32, "int", "shutdown", "uint", $hSocket, "int", 2) ; SD_BOTH EndFunc ;==>___TCP_Shutdown Func ___TCP_SockAddr($sIP, $iPort) Local $tAddr = DllStructCreate("short sin_family;ushort sin_port;uint S_addr;char sin_zero[8]") If @error Then Return SetError(-1, 0, False) DllStructSetData($tAddr, "sin_family", 2) ; AF_INET Local $aRet = DllCall($__TCP_hWs2_32, "ushort", "htons", "ushort", $iPort) If @error Then Return SetError(-1, 0, False) DllStructSetData($tAddr, "sin_port", $aRet[0]) If $sIP = "" Or $sIP = "0.0.0.0" Then DllStructSetData($tAddr, "S_addr", 0x00000000) Else $aRet = DllCall($__TCP_hWs2_32, "ulong", "inet_addr", "str", $sIP) If @error Or $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Return SetError(-4, 0, False) DllStructSetData($tAddr, "S_addr", $aRet[0]) EndIf Return $tAddr EndFunc ;==>___TCP_SockAddr Func ___TCP_SetNonBlocking($hSocket) Local $aRet = DllCall($__TCP_hWs2_32, "int", "ioctlsocket", "uint", $hSocket, "long", 0x8004667e, "ulong*", 1) ; FIONBIO If @error Or $aRet[0] <> 0 Then Return SetError(-1, ___TCP_WSAGetLastError(), False) Return True EndFunc ;==>___TCP_SetNonBlocking Func ___TCP_AsyncSelect($hSocket, $hWnd, $iMsg, $iEvents) ; WSAAsyncSelect automatically sets socket to non-blocking mode Local $aRet = DllCall($__TCP_hWs2_32, "int", "WSAAsyncSelect", _ "uint", $hSocket, "hwnd", $hWnd, "uint", $iMsg, "int", $iEvents) If @error Or $aRet[0] <> 0 Then Return SetError(-1, ___TCP_WSAGetLastError(), False) Return True EndFunc ;==>___TCP_AsyncSelect Func ___TCP_WaitForConnect($hSocket, $iTimeout) Local $tFdWrite = DllStructCreate("uint fd_count;uint fd_array[64]") Local $tFdExcept = DllStructCreate("uint fd_count;uint fd_array[64]") Local $tTimeval = DllStructCreate("long tv_sec;long tv_usec") DllStructSetData($tFdWrite, "fd_count", 1) DllStructSetData($tFdWrite, "fd_array", $hSocket, 1) DllStructSetData($tFdExcept, "fd_count", 1) DllStructSetData($tFdExcept, "fd_array", $hSocket, 1) DllStructSetData($tTimeval, "tv_sec", Floor($iTimeout / 1000)) DllStructSetData($tTimeval, "tv_usec", Mod($iTimeout, 1000) * 1000) Local $aRet = DllCall($__TCP_hWs2_32, "int", "select", _ "int", 0, "ptr", 0, "ptr", DllStructGetPtr($tFdWrite), _ "ptr", DllStructGetPtr($tFdExcept), "ptr", DllStructGetPtr($tTimeval)) If @error Then Return SetError(-1, 0, False) If $aRet[0] = 0 Then Return SetError(-6, 0, False) ; Timeout If $aRet[0] = -1 Then Return SetError(-1, ___TCP_WSAGetLastError(), False) ; Check if connected or error If DllStructGetData($tFdWrite, "fd_count") = 1 Then Return True If DllStructGetData($tFdExcept, "fd_count") = 1 Then Local $tErr = DllStructCreate("int") $aRet = DllCall($__TCP_hWs2_32, "int", "getsockopt", _ "uint", $hSocket, "int", 0xFFFF, "int", 0x1007, _ "ptr", DllStructGetPtr($tErr), "int*", DllStructGetSize($tErr)) ; SOL_SOCKET, SO_ERROR If Not @error And $aRet[0] = 0 Then Return SetError(DllStructGetData($tErr, 1), 0, False) EndIf EndIf Return SetError(-5, 0, False) ; Not connected EndFunc ;==>___TCP_WaitForConnect Func ___TCP_WSAGetLastError() Local $aRet = DllCall($__TCP_hWs2_32, "int", "WSAGetLastError") If @error Then Return 0 Return $aRet[0] EndFunc ;==>___TCP_WSAGetLastError Func ___TCP_FindSocket($hSocket) For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] = $hSocket Then Return $i Next Return -1 EndFunc ;==>___TCP_FindSocket Func ___TCP_LoWord($iValue) Return BitAND($iValue, 0xFFFF) EndFunc ;==>___TCP_LoWord Func ___TCP_HiWord($iValue) Return BitShift($iValue, 16) EndFunc ;==>___TCP_HiWord Func ___TCP_ArrayDelete(ByRef $aArray, $iElement) If Not IsArray($aArray) Then Return SetError(1, 0, 0) Local $iUBound = UBound($aArray, 1) - 1 If $iUBound < 0 Then Return 0 If $iElement < 0 Then $iElement = 0 If $iElement > $iUBound Then $iElement = $iUBound Switch UBound($aArray, 0) Case 1 For $i = $iElement To $iUBound - 1 $aArray[$i] = $aArray[$i + 1] Next ReDim $aArray[$iUBound] Case 2 Local $iSubMax = UBound($aArray, 2) - 1 For $i = $iElement To $iUBound - 1 For $j = 0 To $iSubMax $aArray[$i][$j] = $aArray[$i + 1][$j] Next Next ReDim $aArray[$iUBound][$iSubMax + 1] Case Else Return SetError(3, 0, 0) EndSwitch Return $iUBound EndFunc ;==>___TCP_ArrayDelete ; #ASYNC EVENT HANDLERS# ======================================================================================================== Func ___TCP_Server_OnAccept($hWnd, $iMsgID, $wParam, $lParam) Local $hSocket = $wParam Local $iError = ___TCP_HiWord($lParam) Local $iEvent = ___TCP_LoWord($lParam) Abs($hWnd) ; Suppress AU3Check warning ; Find server socket Local $iServerIdx = -1 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][1] = $iMsgID Then $iServerIdx = $i ExitLoop EndIf Next If $iServerIdx < 0 Then Return If $iEvent = $FD_ACCEPT Then If Not $iError Then Local $hClient = TCPAccept($hSocket) If $hClient < 0 Then Return ; Setup client async Local $iClientMsgID = 0x0400 + UBound($__TCP_Sockets) ___TCP_AsyncSelect($hClient, $__TCP_AsyncWindow, $iClientMsgID, BitOR($FD_READ, $FD_WRITE, $FD_CLOSE)) GUIRegisterMsg($iClientMsgID, "___TCP_Server_OnClientEvent") ; Store client ReDim $__TCP_Sockets[UBound($__TCP_Sockets) + 1][11] Local $idx = UBound($__TCP_Sockets) - 1 $__TCP_Sockets[$idx][0] = $hClient $__TCP_Sockets[$idx][1] = $iClientMsgID $__TCP_Sockets[$idx][7] = _TCP_Server_ClientIP($hClient) $__TCP_Sockets[$idx][9] = False ; isClient $__TCP_Sockets[$idx][10] = $hSocket ; parentServer ; Call callback If $__TCP_Sockets[$iServerIdx][6] <> "" Then Call($__TCP_Sockets[$iServerIdx][6], $hClient, $iError) EndIf Else ; Error accepting If $__TCP_Sockets[$iServerIdx][6] <> "" Then Call($__TCP_Sockets[$iServerIdx][6], 0, $iError) EndIf EndIf EndIf EndFunc ;==>___TCP_Server_OnAccept Func ___TCP_Server_OnClientEvent($hWnd, $iMsgID, $wParam, $lParam) Local $hSocket = $wParam Local $iError = ___TCP_HiWord($lParam) Local $iEvent = ___TCP_LoWord($lParam) Abs($hWnd) Local $iClientIdx = -1 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][1] = $iMsgID Then $iClientIdx = $i ; BUG FIX: Don't override the actual socket handle from $wParam ; $hSocket = $__TCP_Sockets[$i][0] ; This was causing socket mismatch! ExitLoop EndIf Next If $iClientIdx < 0 Then Return ; Find parent server for this client - CRITICAL FIX for multi-server support Local $iServerIdx = -1 Local $hParentServer = $__TCP_Sockets[$iClientIdx][10] If $hParentServer > 0 Then ; Find the parent server by socket handle For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][0] = $hParentServer And $__TCP_Sockets[$i][9] Then $iServerIdx = $i ExitLoop EndIf Next EndIf If $iServerIdx < 0 Then Return Switch $iEvent Case $FD_READ Local $sData = TCPRecv($hSocket, 4096) If $__TCP_Sockets[$iServerIdx][2] <> "" Then Call($__TCP_Sockets[$iServerIdx][2], $hSocket, $sData, $iError) EndIf Case $FD_WRITE If $__TCP_Sockets[$iServerIdx][3] <> "" Then Call($__TCP_Sockets[$iServerIdx][3], $hSocket, $iError) EndIf Case $FD_CLOSE If $__TCP_Sockets[$iServerIdx][5] <> "" Then Call($__TCP_Sockets[$iServerIdx][5], $hSocket, $iError) EndIf ___TCP_Shutdown($hSocket) ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iClientIdx) EndSwitch EndFunc ;==>___TCP_Server_OnClientEvent Func ___TCP_Client_OnSocketEvent($hWnd, $iMsgID, $wParam, $lParam) Local $hSocket = $wParam Local $iError = ___TCP_HiWord($lParam) Local $iEvent = ___TCP_LoWord($lParam) Abs($hWnd) Local $iClientIdx = -1 For $i = 0 To UBound($__TCP_Sockets) - 1 If $__TCP_Sockets[$i][1] = $iMsgID Then $iClientIdx = $i ; BUG FIX: Don't override the actual socket handle from $wParam ; $hSocket = $__TCP_Sockets[$i][0] ; This was causing socket mismatch! ExitLoop EndIf Next If $iClientIdx < 0 Then Return Switch $iEvent Case $FD_CONNECT ; Connection completed (success or failure) If $__TCP_Sockets[$iClientIdx][4] <> "" Then Call($__TCP_Sockets[$iClientIdx][4], $hSocket, $iError) EndIf Case $FD_READ Local $sData = TCPRecv($hSocket, 4096) If $__TCP_Sockets[$iClientIdx][2] <> "" Then Call($__TCP_Sockets[$iClientIdx][2], $hSocket, $sData, $iError) EndIf Case $FD_WRITE If $__TCP_Sockets[$iClientIdx][3] <> "" Then Call($__TCP_Sockets[$iClientIdx][3], $hSocket, $iError) EndIf Case $FD_CLOSE If $__TCP_Sockets[$iClientIdx][5] <> "" Then Call($__TCP_Sockets[$iClientIdx][5], $hSocket, $iError) EndIf ___TCP_Shutdown($hSocket) ___TCP_CloseSocket($hSocket) ___TCP_ArrayDelete($__TCP_Sockets, $iClientIdx) EndSwitch EndFunc ;==>___TCP_Client_OnSocketEvent ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Send_Ex ; Description ...: Send data through socket with automatic Base64 encoding ; Syntax ........: _TCP_Send_Ex($hSocket, $vData[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $vData - Data to send (string or binary) - auto Base64 encoded ; $iFlag - [optional] $TCP_DEFAULT_DATA (0) or $TCP_EOT_DATA (2) ; Return values .: Success - Number of bytes sent ; Failure - -1 and sets @error ; =============================================================================================================================== Func _TCP_Send_Ex($hSocket, $vData, $iFlag = 0) ; Auto encode to Base64 Local $sEncoded = _Base64Encode($vData) If @error Then Return SetError(@error, 0, -1) If BitAND($iFlag, $TCP_EOT_DATA) Then $sEncoded = $sEncoded & Chr(3) Local $iResult = TCPSend($hSocket, $sEncoded) Return SetError(@error, 0, $iResult) EndFunc ;==>_TCP_Send_Ex ; #FUNCTION# ==================================================================================================================== ; Name ..........: _TCP_Recv_Ex ; Description ...: Receive data from socket with automatic Base64 decoding ; Syntax ........: _TCP_Recv_Ex($hSocket, $iMaxLen[, $iFlag = 0]) ; Parameters ....: $hSocket - Socket handle ; $iMaxLen - Max bytes to receive (after decoding) ; $iFlag - [optional] $TCP_DEFAULT_DATA (0), $TCP_BINARY_DATA (1), or $TCP_EOT_DATA (2) ; Return values .: Success - Data received (decoded from Base64) ; Failure - "" and sets @error/@extended ; Remarks .......: @extended = 1 if connection closed, = 2 if EOT reached ; Data is automatically decoded from Base64 ; =============================================================================================================================== Func _TCP_Recv_Ex($hSocket, $iMaxLen, $iFlag = 0) If Not $__TCP_Initialized Then Return SetError(-1, 0, "") ; Calculate buffer size for Base64 (encoded is ~33% larger) Local $iBase64MaxLen = Int($iMaxLen * 1.35) + 100 Local $tBuf = DllStructCreate("char[" & $iBase64MaxLen & "]") If Not ___TCP_SetNonBlocking($hSocket) Then Return SetError(@error, 0, "") Local $aRet = DllCall($__TCP_hWs2_32, "int", "recv", "uint", $hSocket, "ptr", DllStructGetPtr($tBuf), "int", $iBase64MaxLen, "int", 0) If @error Then Return SetError(-1, 0, "") If $aRet[0] = -1 Or $aRet[0] = 4294967295 Then Local $iError = ___TCP_WSAGetLastError() If $iError = 0 Or $iError = 10035 Then Return SetError(0, 0, "") ; WSAEWOULDBLOCK - no data Return SetError($iError, 0, "") EndIf If $aRet[0] = 0 Then Return SetError(0, 1, "") ; Connection closed Local $sBase64Result = DllStructGetData($tBuf, 1) ; Check for EOT marker Local $bHasEOT = False If BitAND($iFlag, $TCP_EOT_DATA) Then If StringRight($sBase64Result, 1) = Chr(3) Then $sBase64Result = StringTrimRight($sBase64Result, 1) $bHasEOT = True EndIf EndIf ; Auto decode from Base64 Local $sDecoded = _Base64Decode($sBase64Result, True) ; Convert to binary if requested If BitAND($iFlag, $TCP_BINARY_DATA) Then $sDecoded = Binary($sDecoded) EndIf If $bHasEOT Then Return SetError(0, 2, $sDecoded) ; EOT reached EndIf Return SetError(0, 0, $sDecoded) EndFunc ;==>_TCP_Recv_Ex ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64Encode ; Description ...: Encode binary data to Base64 string ; Syntax ........: _Base64Encode($bInput[, $bNoCRLF = True]) ; Parameters ....: $bInput - Binary data to encode (can also accept ASCII string directly) ; $bNoCRLF - [optional] True: no line breaks, False: add CRLF every 76 chars (default = True) ; Return values .: Success - Base64 encoded string ; Failure - "" and sets @error ; Remarks .......: For ASCII strings, you can use this function directly. For UTF-8 strings, use _Base64EncodeStr() instead ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64Encode($bInput, $bNoCRLF = True) $bInput = Binary($bInput) Local $iFlags = 1 ; CRYPT_STRING_BASE64 If $bNoCRLF Then $iFlags = 0x40000001 ; CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF Local $tInput = DllStructCreate("byte[" & BinaryLen($bInput) & "]") DllStructSetData($tInput, 1, $bInput) ; Get required buffer size Local $aResult = DllCall("Crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tInput, _ "dword", DllStructGetSize($tInput), _ "dword", $iFlags, _ "ptr", 0, _ "dword*", 0) If @error Or Not $aResult[0] Then Return SetError(1, 0, "") Local $iSize = $aResult[5] Local $tOutput = DllStructCreate("wchar[" & $iSize & "]") ; Perform encoding $aResult = DllCall("Crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tInput, _ "dword", DllStructGetSize($tInput), _ "dword", $iFlags, _ "struct*", $tOutput, _ "dword*", $iSize) If @error Or Not $aResult[0] Then Return SetError(2, 0, "") Return DllStructGetData($tOutput, 1) EndFunc ;==>_Base64Encode ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64Decode ; Description ...: Decode Base64 string to binary or string ; Syntax ........: _Base64Decode($sInput[, $bReturnBinary = False[, $iDecodeType = 1]]) ; Parameters ....: $sInput - Base64 string to decode ; $bReturnBinary - [optional] False: return string, True: return binary (default = False) ; $iDecodeType - [optional] 1: ASCII, 4: UTF-8 (default = 1, only used when $bReturnBinary = False) ; Return values .: Success - Binary data or string ; Failure - Binary("") and sets @error ; Remarks .......: For ASCII-only data, use default parameters. For UTF-8 data, use $iDecodeType = 4. For binary data, use $bReturnBinary = True ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64Decode($sInput, $bReturnBinary = False, $iDecodeType = 1) If ($iDecodeType > 4) Or ($iDecodeType < 1) Then $iDecodeType = 4 ; Remove all whitespace and CRLF $sInput = StringRegExpReplace($sInput, "\s", "") If ($sInput = "") Then Return SetError(1, 0, ($bReturnBinary ? Binary("") : "")) Local $iFlags = 1 ; CRYPT_STRING_BASE64 ; Get required buffer size Local $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", _ "wstr", $sInput, _ "dword", StringLen($sInput), _ "dword", $iFlags, _ "ptr", 0, _ "dword*", 0, _ "ptr", 0, _ "ptr", 0) If @error Or Not $aResult[0] Then Return SetError(2, 0, ($bReturnBinary ? Binary("") : "")) Local $iSize = $aResult[5] Local $tOutput = DllStructCreate("byte[" & $iSize & "]") ; Perform decoding $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", _ "wstr", $sInput, _ "dword", StringLen($sInput), _ "dword", $iFlags, _ "struct*", $tOutput, _ "dword*", $iSize, _ "ptr", 0, _ "ptr", 0) If @error Or Not $aResult[0] Then Return SetError(3, 0, ($bReturnBinary ? Binary("") : "")) Local $bBinary = DllStructGetData($tOutput, 1) If $bReturnBinary Then Return $bBinary Else ; Convert binary to string with specified encoding Return BinaryToString($bBinary, $iDecodeType) EndIf EndFunc ;==>_Base64Decode ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64EncodeStr ; Description ...: Encode string to Base64 ; Syntax ........: _Base64EncodeStr($sInput[, $iEncodeType = 4[, $bNoCRLF = True]]) ; Parameters ....: $sInput - String to encode ; $iEncodeType - [optional] 1: ASCII, 4: UTF-8 (default = 4) ; $bNoCRLF - [optional] True: no line breaks, False: add CRLF (default = True) ; Return values .: Success - Base64 encoded string ; Failure - "" and sets @error ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64EncodeStr($sInput, $iEncodeType = 4, $bNoCRLF = True) If ($iEncodeType > 4) Or ($iEncodeType < 1) Then $iEncodeType = 4 Local $bBinary = StringToBinary($sInput, $iEncodeType) Return _Base64Encode($bBinary, $bNoCRLF) EndFunc ;==>_Base64EncodeStr ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Base64DecodeStr ; Description ...: Decode Base64 string to text string ; Syntax ........: _Base64DecodeStr($sInput[, $iDecodeType = 4]) ; Parameters ....: $sInput - Base64 string to decode ; $iDecodeType - [optional] 1: ASCII, 4: UTF-8 (default = 4) ; Return values .: Success - Text string ; Failure - "" and sets @error ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _Base64DecodeStr($sInput, $iDecodeType = 4) Return _Base64Decode($sInput, False, $iDecodeType) EndFunc ;==>_Base64DecodeStr ; #FUNCTION# ==================================================================================================================== ; Name ..........: _PathWithSlash ; Description ...: Add single backslash to path if not present ; Syntax ........: _PathWithSlash($sPath) ; Parameters ....: $sPath - Path string ; Return values .: Path with trailing backslash ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _PathWithSlash($sPath) Return _PathRemoveTrail($sPath) & '\' EndFunc ;==>_PathWithSlash ; #FUNCTION# ==================================================================================================================== ; Name ..........: _PathRemoveTrail ; Description ...: Remove trailing backslashes from path ; Syntax ........: _PathRemoveTrail($sPath) ; Parameters ....: $sPath - Path string ; Return values .: Path without trailing backslashes ; Author ........: Dao Van Trong - TRONG.PRO ; =============================================================================================================================== Func _PathRemoveTrail($sPath) $sPath = StringStripWS($sPath, 3) While (StringRight($sPath, 1) == '\') $sPath = StringTrimRight($sPath, 1) WEnd Return $sPath EndFunc ;==>_PathRemoveTrail1 point
-
WinSockUDF - TCP/UDP Networking Library for AutoIt
WildByDesign reacted to argumentum for a topic
If this forum had better themes and more formatting options I would agree but unfortunately none of that is there and a user is somewhat limited. On the other hand this post was formatted by AI and he just pasted it. Maybe pasting without formatting would do what you ask but would loose much of it's nice looking presentation. P.S.: It suck to come from the future @WildByDesign and having to wait for the past to catch up1 point -
WinSockUDF - TCP/UDP Networking Library for AutoIt
WildByDesign reacted to argumentum for a topic
1 point -
WinSockUDF - TCP/UDP Networking Library for AutoIt
WildByDesign reacted to water for a topic
Workaround: Use Ctrl+a to select all text of the page and make it readable1 point -
WinSockUDF - TCP/UDP Networking Library for AutoIt
WildByDesign reacted to argumentum for a topic
Poor coding does Change what you need 🤯1 point -
WinSockUDF - TCP/UDP Networking Library for AutoIt
WildByDesign reacted to water for a topic
Do you run the "AutoIt (Dark)" theme? The dark mode caused the unreadable text.1 point -
ntfy (notify) yourself and/or everyone
ioa747 reacted to argumentum for a topic
How would you like to run: curl -d "Finished running my script. All good." ntfy.sh/Testing_AutoIt_script or ConsoleWrite(ntfy_send("**All good**, all the time 😃") & @TAB & @error & @TAB & @extended & @CRLF) Func ntfy_send($sMsg, $sTopicName = "Testing_AutoIt_script") Local Static $iErr = 0, $oErr If IsObj($sMsg) Then If $sMsg.retcode Then $iErr = "0x" & Hex($sMsg.retcode, 8) Return EndIf If ObjEvent("AutoIt.Error") = "" Then $oErr = ObjEvent("AutoIt.Error", "ntfy_send") Local $sUrl = "https://ntfy.sh/" & $sTopicName Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1") $oHTTP.Open("POST", $sUrl, False) ; Open the connection using POST method (synchronous = False) $oHTTP.SetRequestHeader("Markdown", "yes") ; Set Markdown ON $oHTTP.SetRequestHeader("Tags", "heavy_check_mark,PC:" & "@ComputerName") ; https://docs.ntfy.sh/publish/#tags-emojis $oHTTP.Send($sMsg) ; Send the request If ObjEvent("AutoIt.Error") = "ntfy_send" Then $oErr = ObjEvent("AutoIt.Error", "") If $iErr Then Return SetError(2, $iErr, "oHTTP.Send FAILED") Return SetError(Int($oHTTP.Status <> 200), $oHTTP.Status, ($oHTTP.Status = 200 ? StringReplace($oHTTP.ResponseText, @LF, "") : $oHTTP.StatusText)) EndFunc ;==>ntfy_send and be notified in your phone, browser or ...basically any possible way ?!, meet ntfy.sh 🤩 Ok. How would you like to have your own AutoIt receiver for these notifications 🤯 For that you'll need the curl DLL, the curl UDF and something like this: #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** Opt("TrayAutoPause", 0) ; Script pauses when click on tray icon = OFF/0 Opt("TrayOnEventMode", 0) ; Enable/disable OnEvent functions notifications for the tray = OFF/0 Opt("GUICloseOnESC", 0) ; When ESC is pressed on a GUI the $GUI_EVENT_CLOSE message is sent = ON/1 If Not FileGetSize(@ScriptDir & '\curl-ca-bundle.crt') Then MsgBox(262144 + 64, @ScriptName, "The curl stuff needs to be in the same folder for this example", 30) Exit EndIf If Not @AutoItX64 Then MsgBox(262144 + 64, @ScriptName, "It needs to run x64", 30) Exit EndIf #include "Curl.au3" ; https://www.autoitscript.com/forum/topic/207859-curl-udf-libcurl-with-x64-support #include <GuiEdit.au3> ;_GUICtrlEdit_AppendText() ; GUI stuff #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #Region ### START Koda GUI section ### Form= Global $Form1 = GUICreate("Form1", 565, 425) Global $Group1 = GUICtrlCreateGroup("MyTopic", 8, 8, 305, 49) Global $Input1 = GUICtrlCreateInput("Testing_AutoIt_script", 16, 24, 281, 21) GUICtrlCreateGroup("", -99, -99, 1, 1) Global $Button1 = GUICtrlCreateButton("Gather all in cache", 320, 16, 131, 25) Global $Button2 = GUICtrlCreateButton("Listen ( start )", 464, 16, 91, 25) Global $Group2 = GUICtrlCreateGroup("Dump", 8, 96, 545, 321) Global $Edit1 = GUICtrlCreateEdit("", 16, 120, 529, 289) GUICtrlCreateGroup("", -99, -99, 1, 1) Global $Label1 = GUICtrlCreateLabel("last ""keepalive""", 8, 64, 548, 33, $SS_CENTER) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Global $g_nfty_CurlPeeked, $g_nfty_ListenStop = 1 Global $__g_nfty_RunningHandles, $__g_nfty_Curl = 0, $__g_nfty_Multi = 0 OnAutoItExitRegister(nfty_Listen_Cleanup) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE If $g_nfty_ListenStop = 1 Then GUIDelete() Exit EndIf GUICtrlSetState($Button2, $GUI_DISABLE) GUICtrlSetData($Button2, "Listen ( stoping )") $g_nfty_ListenStop = 2 Case $Button1 $g_nfty_ListenStop = 0 nfty_Listen_Start(GUICtrlRead($Input1), "?poll=1&since=all") nfty_Listen_Perform() Case $Button2 If $g_nfty_ListenStop Then GUICtrlSetState($Button1, $GUI_DISABLE) GUICtrlSetState($Button2, $GUI_DISABLE) $g_nfty_ListenStop = 0 GUICtrlSetData($Button2, "Listen ( starting )") nfty_Listen_Start(GUICtrlRead($Input1)) If @error Then $g_nfty_ListenStop = 1 GUICtrlSetData($Button2, "Listen ( start )") GUICtrlSetState($Button1, $GUI_ENABLE) GUICtrlSetState($Button2, $GUI_ENABLE) Else GUICtrlSetData($Button2, "Listen ( stop )") GUICtrlSetState($Button2, $GUI_ENABLE) EndIf Else GUICtrlSetState($Button2, $GUI_DISABLE) GUICtrlSetData($Button2, "Listen ( stoping )") $g_nfty_ListenStop = 2 EndIf EndSwitch Switch $g_nfty_ListenStop Case 1 ; was never running ContinueLoop Case 0 ; not stopped - is running nfty_Listen_Perform() Case 2 ; request to stop nfty_Listen_Cleanup() $g_nfty_ListenStop = 1 GUICtrlSetData($Button2, "Listen ( start )") GUICtrlSetState($Button1, $GUI_ENABLE) GUICtrlSetState($Button2, $GUI_ENABLE) EndSwitch WEnd Func nfty_Listen_Start($sTopic, $suffix = "") $__g_nfty_Curl = Curl_Easy_Init() If Not $__g_nfty_Curl Then $g_nfty_ListenStop = 0 Return SetError(1, 0, 1) EndIf Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_URL, "https://ntfy.sh/" & $sTopic & "/json" & $suffix) ;~ Curl_Easy_Setopt($Curl, $CURLOPT_USERAGENT, "AutoIt/Curl") Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_FOLLOWLOCATION, 1) Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_ACCEPT_ENCODING, "") Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_WRITEFUNCTION, Curl_DataWriteCallback_nfty()) Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_WRITEDATA, $__g_nfty_Curl) Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_TCP_KEEPALIVE, 1) If $suffix Then Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_TIMEOUT, 10) ; 10 sec timeout ;peer verification curl_easy_setopt($__g_nfty_Curl, $CURLOPT_CAINFO, @ScriptDir & '\curl-ca-bundle.crt') ; ;~ Curl_Easy_Setopt($__g_nfty_Curl, $CURLOPT_SSL_VERIFYPEER, 0) $__g_nfty_Multi = Curl_Multi_Init() If Not $__g_nfty_Multi Then $g_nfty_ListenStop = 0 nfty_Listen_Cleanup() Return SetError(2, 0, 2) EndIf Curl_Multi_Add_Handle($__g_nfty_Multi, $__g_nfty_Curl) EndFunc ;==>nfty_Listen_Start Func nfty_Listen_Perform() Local Static $MsgsInQueue, $hTimer = 0 If TimerDiff($hTimer) < 100 Then Return ; no need to ask so often $hTimer = TimerInit() ; let's restart the timer Curl_Multi_Perform($__g_nfty_Multi, $__g_nfty_RunningHandles) Local $CURLMsg = Curl_Multi_Info_Read($__g_nfty_Multi, $MsgsInQueue) If DllStructGetData($CURLMsg, "msg") = $CURLMSG_DONE Then Local $__g_nfty_Curl = DllStructGetData($CURLMsg, "easy_handle") Local $Code = DllStructGetData($CURLMsg, "data") If $Code = $CURLE_OK Then ;~ ConsoleWrite('@@(' & @ScriptLineNumber & ') : ' & @MIN & ':' & @SEC & '.' & @MSEC & @TAB & "Content Type: " & Curl_Easy_GetInfo($__g_nfty_Curl, $CURLINFO_CONTENT_TYPE) & @LF) ;~ ConsoleWrite('@@(' & @ScriptLineNumber & ') : ' & @MIN & ':' & @SEC & '.' & @MSEC & @TAB & "Download Size: " & Curl_Easy_GetInfo($__g_nfty_Curl, $CURLINFO_SIZE_DOWNLOAD) & @LF) ;~ ConsoleWrite('@@(' & @ScriptLineNumber & ') : ' & @MIN & ':' & @SEC & '.' & @MSEC & @TAB & '- Header >' & BinaryToString(Curl_Data_Get($__g_nfty_Curl + 1)) & '<' & @CRLF) ;~ ConsoleWrite('@@(' & @ScriptLineNumber & ') : ' & @MIN & ':' & @SEC & '.' & @MSEC & @TAB & '- Html >' & BinaryToString(Curl_Data_Get($__g_nfty_Curl)) & '<' & @CRLF) Else ConsoleWrite('@@(' & @ScriptLineNumber & ') : ' & @MIN & ':' & @SEC & '.' & @MSEC & @TAB & Curl_Easy_StrError($Code) & @LF) EndIf nfty_Listen_Cleanup() $g_nfty_ListenStop = 1 EndIf EndFunc ;==>nfty_Listen_Perform Func nfty_Listen_Cleanup() If $__g_nfty_Multi Then Curl_Multi_Remove_Handle($__g_nfty_Multi, $__g_nfty_Curl) Curl_Multi_Cleanup($__g_nfty_Multi) $__g_nfty_Multi = 0 EndIf Curl_Easy_Cleanup($__g_nfty_Curl) Curl_Data_Cleanup($__g_nfty_Curl) Curl_Data_Cleanup($__g_nfty_Curl + 1) $__g_nfty_Curl = 0 EndFunc ;==>nfty_Listen_Cleanup Func Curl_DataWriteCallback_nfty() Static $Ptr = DllCallbackGetPtr(DllCallbackRegister(__Curl_DataWriteCallback_nfty, (@AutoItX64 ? "uint_ptr" : "uint_ptr:cdecl"), "ptr;uint_ptr;uint_ptr;ptr")) Return $Ptr EndFunc ;==>Curl_DataWriteCallback_nfty Func __Curl_DataWriteCallback_nfty($Ptr, $Size, $Nmemb, $Handle) Local $Length = $Size * $Nmemb, $Data = __Curl_Peek("byte[" & $Length & "]", $Ptr) $g_nfty_CurlPeeked = StringReplace(BinaryToString($Data), @LF, @CRLF) If StringInStr($g_nfty_CurlPeeked, ',"event":"open","topic":"') Or StringInStr($g_nfty_CurlPeeked, ',"event":"keepalive","topic":"') Then ; not important GUICtrlSetData($Label1, @MIN & ":" & @SEC & " >" & StringStripCR($g_nfty_CurlPeeked) & "<") Else _GUICtrlEdit_AppendText($Edit1, $g_nfty_CurlPeeked & @CRLF) EndIf Return $Length EndFunc ;==>__Curl_DataWriteCallback_nfty Do place your scripts in the bin folder where libcurl-x64.dll is at, or this example will not work as is. This is just an example. FAQ: Q: Why the curl UDF ?, why not ... A: Because "the page" never finishes the download ( and is not meant to finish ). Couldn't find a way to peek into the message other than this. Q: Can you ... A: Maybe. But am busy, and not all that good at all these. If you code that you wish it had, do share it in the forum. ( Think GPLv2 ) Q: I sent a message but my receiver script wasn't running at the time / Lost internet for X hours. A: Text messages are likely to be available for up to 12 hours ( for what I read ). Just click "Gather all in cache" in this example. Q: How can I ... A: ntfy has excellent documentation. Read it. Q: Can I make my messages private ? A: Yes you can. Read the offers they have available for the service.1 point -
A simple fast IPC based on Windows Messaging
WildByDesign reacted to Nine for a topic
After seeing a number of threads talking about how to exchange efficiently messages between processes (Inter Process Communication), I decided to create a framework using Windows Messages WM_COPYDATA. What is new with this UDF you ask ? Well it will depends how familiar you are with IPC. One thing is sure, the simplicity of use and the fabulous speed are amazing. This is based on a Clients-Server approach. You can have an unlimited number of clients talking with a single server. You will have to define the protocol of communication between them, but the code you have to create is incredibly low. The UDF proposes 2 simple message properties of communication. The first (called data) is based on a number. You can decide what value 1,2,3, etc. means between your client and server. Server will react upon the value of the data field. Second, there is a string field where you can inscribe additional information on request, and where the server will respond to client request (if necessary). Version 2025-11-17 * Added support to x64 server and/or x64 clients * Added support to AutoIt version 3.3.18.0 Version 2020-06-27 * Allows processes with different levels of privilege to communicate with each other Here are the functions that I have wrapped around this : Func _WCD_CreateServer Func _WCD_CreateClient Func _WCD_GetServerHandle Func _WCD_IsServerAvailable Func _WCD_Send Func _WCD_WM_COPYDATA_CLIENT_HANDLER Func _WCD_Client_GetResponse Func _WCD_WM_COPYDATA_SERVER_HANDLER Func _WCD_Server_PeekRequest Func _WCD_Server_GetRequest Func _WCD_Server_IsRequestAvail Here an example of the server : #include <Constants.au3> #include <GUIConstants.au3> #include "WCD_IPC.au3" Opt ("MustDeclareVars", 1) $_WCD_Verbose = False ; make it True if you want to follow the convos. False is by default. Local $hServer = _WCD_CreateServer () Local $aReq, $iData While True If _WCD_Server_IsRequestAvail () Then $aReq = _WCD_Server_GetRequest () $iData = @extended Switch $iData Case 1 ; who are you _WCD_Send($hServer, $aReq[0], $iData, @ComputerName) Case 2 Switch Number($aReq[1]) Case 1 _WCD_Send($hServer, $aReq[0], $iData, @IPAddress1) Case 2 _WCD_Send($hServer, $aReq[0], $iData, @IPAddress2) Case 3 _WCD_Send($hServer, $aReq[0], $iData, @IPAddress3) Case 4 _WCD_Send($hServer, $aReq[0], $iData, @IPAddress4) Case Else _WCD_Send($hServer, $aReq[0], $iData, "Invalid parameter") EndSwitch EndSwitch EndIf Sleep (100) WEnd And the client : #include <Constants.au3> #include <GUIConstants.au3> #include "WCD_IPC.au3" Opt ("MustDeclareVars", 1) $_WCD_Verbose = True ; as for the server, you can decide to make client verbose or not Global $hWnd = _WCD_CreateClient ("Test WCD Client") Global $hWndServer = _WCD_GetServerHandle () _WCD_Send($hWnd, $hWndServer, 1) ; simple request - who are you ? Local $sString = WaitForResponse () ConsoleWrite ($sString & @CRLF) _WCD_Send($hWnd, $hWndServer, 2, "5") ; adding text to a more complex request $sString = WaitForResponse () ConsoleWrite ($sString & @CRLF) Func WaitForResponse () Local $sResp While _WCD_IsServerAvailable () $sResp = _WCD_Client_GetResponse () If $sResp <> "" Then Return $sResp Sleep (100) WEnd EndFunc As always, let me know if you got issues, comments, suggestions. I will be glad to answer. WCD_IPC.zip1 point -
A simple fast IPC based on Windows Messaging
argumentum reacted to Nine for a topic
New version available.1 point -
As usually I love your answer my friend. As always, I really liked your answer, my friend. All is clear for me. Thanks. So. @Parsix In your opinion, does this example fully meet your needs for using Au3Stripper with the @trancexx script , I mean all the possibilities of the /SO /PE /RM parameters?1 point
-
Now it is. Thanks. So here is my solution for this script: ;~ https://www.autoitscript.com/forum/topic/154081-avoid-autoit-error-message-box-in-unknown-errors/page/4/#findComment-1547476 #Region - AutoIt3Wrapper directives section ; General section #AutoIt3Wrapper_UseX64=n #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Compression=4 ; Au3Check section #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 6 -w 7 ; Au3Stripper section #AutoIt3Wrapper_Run_Au3Stripper=y ;~ #Au3Stripper_Parameters=/SO /PE #Au3Stripper_Parameters=/SO /PE /RM #AutoIt3Wrapper_Au3Stripper_OnError=f ;~ #Au3Stripper_Ignore_Funcs=Intercept_MessageBoxW ;~ #Au3Stripper_Ignore_Funcs=__AddHookApi_DllCallbackRegister_wrapper #EndRegion - AutoIt3Wrapper directives section #include <WinApi.au3> #Region - exmaple ;~ AddHookApi("user32.dll", "MessageBoxW", "Intercept_MessageBoxW", "int", "hwnd;wstr;wstr;uint") AddHookApi("user32.dll", "MessageBoxW", FuncName(Intercept_MessageBoxW), "int", "hwnd;wstr;wstr;uint") MsgBox(0, 'Test', 'Some normal MsgBox text') DllStructCreate("byte[123456789097]") ; This is a deliberate action intended to display an error, as this script demonstrates how to change error handling - interact with MsgBox's title and text. #EndRegion - exmaple #Region @trancexx - https://www.autoitscript.com/forum/topic/154081-avoid-autoit-error-message-box-in-unknown-errors/#findComment-1111917 Func Intercept_MessageBoxW($hWnd, $sText, $sTitle, $iType) If $sTitle = 'AutoIt' Then $sTitle = 'TESTING: ' & StringReplace($sTitle, "AutoIt", @ScriptName) Local $aCall = DllCall("user32.dll", "int", "MessageBoxW", _ "hwnd", $hWnd, _ "wstr", $sText, _ "wstr", $sTitle, _ "uint", $iType) If @error Or Not $aCall[0] Then Return 0 Return $aCall[0] EndFunc ;==>Intercept_MessageBoxW ; The magic is down below Func AddHookApi($sModuleName, $vFunctionName, $vNewFunction, $sRet = "", $sParams = "") Local Static $pImportDirectory, $hInstance Local Const $IMAGE_DIRECTORY_ENTRY_IMPORT = 1 If Not $pImportDirectory Then $hInstance = _WinAPI_GetModuleHandle(0) $pImportDirectory = ImageDirectoryEntryToData($hInstance, $IMAGE_DIRECTORY_ENTRY_IMPORT) If @error Then Return SetError(1, 0, 0) EndIf Local $iIsInt = IsInt($vFunctionName) Local $iRestore = Not IsString($vNewFunction) Local $tIMAGE_IMPORT_MODULE_DIRECTORY Local $pDirectoryOffset = $pImportDirectory Local $tModuleName Local $iInitialOffset, $iInitialOffset2 Local $iOffset2 Local $tBufferOffset2, $iBufferOffset2 Local $tBuffer, $tFunctionOffset, $pOld, $fMatch, $pModuleName, $pFuncName Local Const $PAGE_READWRITE = 0x04 While 1 $tIMAGE_IMPORT_MODULE_DIRECTORY = DllStructCreate("dword RVAOriginalFirstThunk;" & _ "dword TimeDateStamp;" & _ "dword ForwarderChain;" & _ "dword RVAModuleName;" & _ "dword RVAFirstThunk", _ $pDirectoryOffset) If Not DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") Then ExitLoop $pModuleName = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAModuleName") $tModuleName = DllStructCreate("char Name[" & _WinAPI_StringLenA($pModuleName) & "]", $pModuleName) If DllStructGetData($tModuleName, "Name") = $sModuleName Then ; function from this module $iInitialOffset = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAFirstThunk") $iInitialOffset2 = $hInstance + DllStructGetData($tIMAGE_IMPORT_MODULE_DIRECTORY, "RVAOriginalFirstThunk") If $iInitialOffset2 = $hInstance Then $iInitialOffset2 = $iInitialOffset $iOffset2 = 0 While 1 $tBufferOffset2 = DllStructCreate("dword_ptr", $iInitialOffset2 + $iOffset2) $iBufferOffset2 = DllStructGetData($tBufferOffset2, 1) If Not $iBufferOffset2 Then ExitLoop If $iIsInt Then If BitAND($iBufferOffset2, 0xFFFFFF) = $vFunctionName Then $fMatch = True ; wanted function Else $pFuncName = $hInstance + $iBufferOffset2 + 2 ; 2 is size od "word", see line below... $tBuffer = DllStructCreate("word Ordinal; char Name[" & _WinAPI_StringLenA($pFuncName) & "]", $hInstance + $iBufferOffset2) If DllStructGetData($tBuffer, "Name") == $vFunctionName Then $fMatch = True ; wanted function EndIf If $fMatch Then $tFunctionOffset = DllStructCreate("ptr", $iInitialOffset + $iOffset2) VirtualProtect(DllStructGetPtr($tFunctionOffset), DllStructGetSize($tFunctionOffset), $PAGE_READWRITE) If @error Then Return SetError(3, 0, 0) $pOld = DllStructGetData($tFunctionOffset, 1) If $iRestore Then DllStructSetData($tFunctionOffset, 1, $vNewFunction) Else #Region ; the #Au3Stripper_Off/#Au3Stripper_On directives, used in this place will lead to errors as /RM is used and all variables was changed in entire script but not within this region ;~ #Au3Stripper_Off ;~ DllStructSetData($tFunctionOffset, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction, $sRet, $sParams))) ;~ #Au3Stripper_On #EndRegion ; the #Au3Stripper_Off/#Au3Stripper_On directives, used in this place will lead to errors as /RM is used and all variables was changed in entire script but not within this region ; for this reason __AddHookApi_DllCallbackRegister_wrapper() was added and enclosed within #Au3Stripper_Off >>> #Au3Stripper_On section __AddHookApi_DllCallbackRegister_wrapper($tFunctionOffset, $vNewFunction, $sRet, $sParams) EndIf Return $pOld EndIf $iOffset2 += DllStructGetSize($tBufferOffset2) WEnd ExitLoop EndIf $pDirectoryOffset += 20 ; size of $tIMAGE_IMPORT_MODULE_DIRECTORY WEnd Return SetError(4, 0, 0) EndFunc ;==>AddHookApi #Au3Stripper_Off Func __AddHookApi_DllCallbackRegister_wrapper($tFunctionOffset__Wrapped, $vNewFunction__Wrapped, $sRet__Wrapped, $sParams__Wrapped) DllStructSetData($tFunctionOffset__Wrapped, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction__Wrapped, $sRet__Wrapped, $sParams__Wrapped))) EndFunc ;==>__AddHookApi_DllCallbackRegister_wrapper #Au3Stripper_On Func VirtualProtect($pAddress, $iSize, $iProtection) Local $aCall = DllCall("kernel32.dll", "bool", "VirtualProtect", "ptr", $pAddress, "dword_ptr", $iSize, "dword", $iProtection, "dword*", 0) If @error Or Not $aCall[0] Then Return SetError(1, 0, 0) Return 1 EndFunc ;==>VirtualProtect Func ImageDirectoryEntryToData($hInstance, $iDirectoryEntry) ; Get pointer to data Local $pPointer = $hInstance ; Start processing passed binary data. 'Reading' PE format follows. Local $tIMAGE_DOS_HEADER = DllStructCreate("char Magic[2];" & _ "word BytesOnLastPage;" & _ "word Pages;" & _ "word Relocations;" & _ "word SizeofHeader;" & _ "word MinimumExtra;" & _ "word MaximumExtra;" & _ "word SS;" & _ "word SP;" & _ "word Checksum;" & _ "word IP;" & _ "word CS;" & _ "word Relocation;" & _ "word Overlay;" & _ "char Reserved[8];" & _ "word OEMIdentifier;" & _ "word OEMInformation;" & _ "char Reserved2[20];" & _ "dword AddressOfNewExeHeader", _ $pPointer) Local $sMagic = DllStructGetData($tIMAGE_DOS_HEADER, "Magic") ; Check if it's valid format If Not ($sMagic == "MZ") Then Return SetError(1, 0, 0) ; MS-DOS header missing. Btw 'MZ' are the initials of Mark Zbikowski in case you didn't know. ; Move pointer $pPointer += DllStructGetData($tIMAGE_DOS_HEADER, "AddressOfNewExeHeader") ; move to PE file header ; In place of IMAGE_NT_SIGNATURE structure Local $tIMAGE_NT_SIGNATURE = DllStructCreate("dword Signature", $pPointer) ; Check signature If DllStructGetData($tIMAGE_NT_SIGNATURE, "Signature") <> 17744 Then ; IMAGE_NT_SIGNATURE Return SetError(2, 0, 0) ; wrong signature. For PE image should be "PE\0\0" or 17744 dword. EndIf ; Move pointer $pPointer += 4 ; size of $tIMAGE_NT_SIGNATURE structure ; In place of IMAGE_FILE_HEADER structure ; Move pointer $pPointer += 20 ; size of $tIMAGE_FILE_HEADER structure ; Determine the type Local $tMagic = DllStructCreate("word Magic;", $pPointer) Local $iMagic = DllStructGetData($tMagic, 1) Local $tIMAGE_OPTIONAL_HEADER If $iMagic = 267 Then ; x86 version ; Move pointer $pPointer += 96 ; size of $tIMAGE_OPTIONAL_HEADER ElseIf $iMagic = 523 Then ; x64 version ; Move pointer $pPointer += 112 ; size of $tIMAGE_OPTIONAL_HEADER Else Return SetError(3, 0, 0) ; unsupported module type EndIf ; Validate input by checking available number of structures that are in the module Local Const $IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 ; predefined value that PE modules always use (AutoIt certainly) If $iDirectoryEntry > $IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 Then Return SetError(4, 0, 0) ; invalid input ; Calculate the offset to wanted entry (every entry is 8 bytes) $pPointer += 8 * $iDirectoryEntry ; At place of correst directory entry Local $tIMAGE_DIRECTORY_ENTRY = DllStructCreate("dword VirtualAddress; dword Size", $pPointer) ; Collect data Local $pAddress = DllStructGetData($tIMAGE_DIRECTORY_ENTRY, "VirtualAddress") If $pAddress = 0 Then Return SetError(5, 0, 0) ; invalid input ; $pAddress is RVA, add it to base address Return $hInstance + $pAddress EndFunc ;==>ImageDirectoryEntryToData #EndRegion @trancexx - https://www.autoitscript.com/forum/topic/154081-avoid-autoit-error-message-box-in-unknown-errors/#findComment-1111917 Explanations: Using @trancexx code, in order to use: #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/so /pe #AutoIt3Wrapper_Au3Stripper_OnError=f there is also a need to use: #Au3Stripper_Ignore_Funcs=Intercept_MessageBoxW Because in other way: #Au3Stripper_Parameters=/so /pe Will strip down the function as she is not called directly. Only the function name is used but as a string and not directly like a "pointer" To prevent using: #Au3Stripper_Ignore_Funcs=Intercept_MessageBoxW The Intercept_MessageBoxW can be called as a parameter for FuncName(Intercept_MessageBoxW) this way: ;~ AddHookApi("user32.dll", "MessageBoxW", "Intercept_MessageBoxW", "int", "hwnd;wstr;wstr;uint") AddHookApi("user32.dll", "MessageBoxW", FuncName(Intercept_MessageBoxW), "int", "hwnd;wstr;wstr;uint") In such case Au3Stripper knows that Intercept_MessageBoxW was used and should not be stripped. REMARK: You can also notice that I used: #Au3Stripper_Parameters=/SO /PE /RM I mean the the most demanding/restrictive option /RM For this reason this following mod was added: ..... #Region ; the #Au3Stripper_Off/#Au3Stripper_On directives, used in this place will lead to errors as /RM is used and all variables was changed in entire script but not within this region ;~ #Au3Stripper_Off ;~ DllStructSetData($tFunctionOffset, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction, $sRet, $sParams))) ;~ #Au3Stripper_On #EndRegion ; the #Au3Stripper_Off/#Au3Stripper_On directives, used in this place will lead to errors as /RM is used and all variables was changed in entire script but not within this region ; for this reason __AddHookApi_DllCallbackRegister_wrapper() was added and enclosed within #Au3Stripper_Off >>> #Au3Stripper_On section __AddHookApi_DllCallbackRegister_wrapper($tFunctionOffset, $vNewFunction, $sRet, $sParams) ..... #Au3Stripper_Off Func __AddHookApi_DllCallbackRegister_wrapper($tFunctionOffset__Wrapped, $vNewFunction__Wrapped, $sRet__Wrapped, $sParams__Wrapped) DllStructSetData($tFunctionOffset__Wrapped, 1, DllCallbackGetPtr(DllCallbackRegister($vNewFunction__Wrapped, $sRet__Wrapped, $sParams__Wrapped))) EndFunc ;==>__AddHookApi_DllCallbackRegister_wrapper #Au3Stripper_On ..... The reason that I do not must to use: ;~ #Au3Stripper_Ignore_Funcs=__AddHookApi_DllCallbackRegister_wrapper is because __AddHookApi_DllCallbackRegister_wrapper() is used/called before the #Au3Stripper_Off / #Au3Stripper_Off sections occurs so Au3Stripper already dit the /RM action on the function name in entire script but at this moment do not touched $******__Wrapped variables. @Jos Does this example cover the whole topic of using Au3Stripper with this @trancexx script, I mean all releated with the /SO /PE /RM parameters? btw. I wonder whether, for the correctness of "code reading" and protection against possible changes in Au3Stripper, I should still use: #Au3Stripper_Ignore_Funcs=__AddHookApi_DllCallbackRegister_wrapper1 point
-
Guiscape -- A new GUI builder project!
jaberwacky reacted to MattyD for a topic
no worries at all! what I think is happening is: $NC_CLICKED is control Id of the dummy, which fires on WM_NCLBUTTONDOWN. The dummy's data is set to the hwnd param of the WM_ message. Fair enough... But then we handle events based on $event.Form - which is the dummy's parent. I guess Form1 is the last window built with GUICreate() before we setup the dummy, so that ends up owning the control. To find the hWnd of the captured WM_NCLBUTTONDOWN message, we need to: GuiCtrlRead($NC_CLICKED).1 point -
Something like this ? #include "Json.au3" ConsoleWrite("- Test8() : " & Test8() & @CRLF) Func Test8() ; Your three JSON strings Local $Json1 = '{"name":"John","age":30,"locations":[]}' Local $Json2 = '{"City":"Paris","Country":"France"}' Local $Json3 = '{"City":"London","Country":"England"}' ; Decode Local $obj1 = Json_Decode($Json1) Json_ObjPut($obj1,"locations", Json_Decode("[" & $Json2 & "," & $Json3 & "]")) Local $final = Json_Encode($obj1, $JSON_PRETTY_PRINT) ConsoleWrite($final & @CRLF) EndFunc ;==>Test81 point
-
1- you can put sleep anywhere / everywhere. It doesn't hurt except can slow down the script. You need to test and decide. 2- having a single delay ($iTimeOut) is a very bad idea. Sometimes, it requires more time, sometimes it requires less. You need to test and decide. 3- it is not because you paste something that it will be pasted instantly in the field. It may take some time. You need to test and decide.1 point
-
A simple fast IPC based on Windows Messaging
WildByDesign reacted to Nine for a topic
Thank you. Yes last AutoIt version messed up with the #include. Many of my scripts are breaking because of it. I'll update this one tomorrow. Anyway, the string is located in $aReq[1], as described in example.1 point -
Guiscape -- A new GUI builder project!
WildByDesign reacted to jaberwacky for a topic
Thank you! Check out the latest update. I didn't do much with your code tonight, but I did use your code from today to fix the window closing issues. I also removed the garish colors from the tab items (I put it in there for debugging (took me about 16 hours to get that ironed out.)) I also came up with a hack for a weird issue. So, when a title bar is clicked a message is sent to a dummy control. Inside of the dummy control function (GUIObjectEvents) the $hwnd is correct for each form. Click form1 title bar and you get the form1 hwnd. Click on form2 title bar and you get form2 hwnd. However, inside of the GUIObjectsHandler only form1 hwnd is there regardless of which form I click. I dunno. I had a long day so I'm callling it for tonight. Thank you again MattyD ... Your code saved me from hours of banging my forehead on the desk. I could not have come up with the code that you did.1 point -
AutoIt Resource Embedder A professional tool to convert binary files into self-contained AutoIt functions with advanced encoding and compression support. Author: Dao Van Trong - TRONG.PRO 🌟 Features Core Functionality Binary File Embedding - Convert any binary file (DLL, EXE, images, etc.) into AutoIt code Multiple Encoding Formats Hex String Encoding Base64 String Encoding (with Unicode support) LZNT Compression Level 1: Standard 4096-byte chunks Level 2: No chunking (maximum compression) Architecture Detection - Automatically detects PE file architecture (x86, x64, ARM, ARM64, IA64) Dual Operation Modes GUI Mode - User-friendly graphical interface CLI Mode - Command-line for automation/scripting Advanced Features Smart Helper Functions _DeployFile() for single file - Returns binary, hex string, or writes to file _GetBin($filename) for multiple files - Switch/Case based retrieval Automatic Decompression/Decoding - Generated code includes all necessary helper functions Error Handling - Comprehensive error checking and reporting Chunk Size Control - Configurable line length (100-4000 characters) Batch Processing - Process multiple files at once 🚀 Quick Start GUI Mode Run the script: Double-click "AutoIt Resource Embedder.au3" Add files: Click "Add Files..." button Select one or more binary files Files appear in the list with size and architecture info Configure encoding: Hex - Standard hex string encoding Base64 - Base64 string encoding Hex + LZNT - Hex encoding with compression Base64 + LZNT - Base64 encoding with compression Select LZNT Level (1 or 2) if using compression Generate code: Click "Generate All Functions" or "Preview Single" Code appears in the output window Save output: "Save All to File" - Single .au3 file with all functions "Save Separate Files" - Individual .au3 file per input file "Copy to Clipboard" - Copy generated code CLI Mode Process files from command line: AutoIt3.exe "AutoIt Resource Embedder.au3" file1.dll file2.exe Output: All_Embedded.au3 (or individual file if only one input) 📖 Usage Examples Example 1: Single File with Helper Function Input: myLib.dll Generated Code: ; Function containing encoded data Func _GetBinData_myLib_dll_x86() Local $sHexData = '0x4D5A90000300000004000000FFFF...' Return $sHexData EndFunc ; Helper function to deploy the file Func _DeployFile($sDestPath = "", $bReturnHex = False) Local $sHexData = _GetBinData_myLib_dll_x86() If $sHexData = "" Then Return SetError(1, 0, "") Local $bBinary = Binary($sHexData) ; If no destination path, return binary or hex string If $sDestPath = "" Then If $bReturnHex Then Return StringTrimLeft($bBinary, 2) Else Return $bBinary EndIf EndIf ; Write binary data to file Local $hFile = FileOpen($sDestPath, 18) If $hFile = -1 Then Return SetError(4, 0, "") FileWrite($hFile, $bBinary) FileClose($hFile) If Not FileExists($sDestPath) Then Return SetError(5, 0, "") Return $sDestPath EndFunc Usage: ; Get binary data $bData = _DeployFile() ; Get hex string $sHex = _DeployFile("", True) ; Write to file $sPath = _DeployFile(@TempDir & "\myLib.dll") Example 2: Multiple Files with _GetBin() Input: Multiple DLL files Generated Code: Func _GetBin($sName) Local $sData = "" Switch $sName Case "kernel32.dll" $sData = _GetBinData_kernel32_dll_x86() Case "user32.dll" $sData = _GetBinData_user32_dll_x86() Case "advapi32.dll" $sData = _GetBinData_advapi32_dll_x86() EndSwitch If $sData = "" Then Return SetError(1, 0, Binary("")) Local $bData = Binary($sData) Return $bData EndFunc Usage: ; Get any embedded file by name $bKernel32 = _GetBin("kernel32.dll") $bUser32 = _GetBin("user32.dll") $bAdvapi32 = _GetBin("advapi32.dll") Example 3: With Compression Enable LZNT Compression: Select "Hex + LZNT" or "Base64 + LZNT" Choose compression level (1 or 2) Generated code includes decompression function: Func _WinAPI_LZNTDecompress($bCompressed) Local $tInput = DllStructCreate("byte[" & BinaryLen($bCompressed) & "]") DllStructSetData($tInput, 1, $bCompressed) Local $tOutput = DllStructCreate("byte[" & (BinaryLen($bCompressed) * 10) & "]") Local $aRet = DllCall("ntdll.dll", "uint", "RtlDecompressBuffer", "ushort", 0x0002, "struct*", $tOutput, "ulong", DllStructGetSize($tOutput), "struct*", $tInput, "ulong", BinaryLen($bCompressed), "ulong*", 0) If @error Or $aRet[0] <> 0 Then Return SetError(1, 0, "") Return BinaryMid(DllStructGetData($tOutput, 1), 1, $aRet[6]) EndFunc ⚙️ Configuration Options Encoding Formats Option Description Use Case Hex Standard hexadecimal encoding General purpose, human-readable Base64 Base64 string encoding Smaller output, better for text Hex + LZNT Hex with compression Large files, need compression Base64 + LZNT Base64 with compression Maximum size reduction Compression Levels Level ChunkSize Description Level 1 4096 bytes Standard LZNT compression Level 2 0 (no chunking) Maximum compression ratio Line Length Range: 100 - 4000 characters Default: 4000 characters Purpose: Controls how long each line of encoded data is in the generated code 🎯 Use Cases DLL Embedding - Embed runtime libraries directly in your AutoIt scripts Resource Packaging - Package images, icons, or data files Portable Applications - Create single-file executables with all dependencies Obfuscation - Hide sensitive binary data within scripts Version Control - Include small binaries in source control as text Driver Deployment - Embed device drivers for automated installation Plugin Systems - Dynamically load plugins from embedded data 🏗️ Architecture Detection Automatically identifies PE file architecture: Architecture Machine Code Description x86 0x014C 32-bit Intel x64 0x8664 64-bit AMD/Intel ARM 0x01C0, 0x01C4 ARM processors ARM64 0xAA64 64-bit ARM IA64 0x0200 Intel Itanium Not PE - Non-executable files 🛠️ Technical Details Encoding Methods Hex Encoding: Binary($sHexData) ; Direct conversion from hex string Base64 Encoding: Uses Windows Crypto API (Crypt32.dll) Unicode support (CryptStringToBinaryW) Automatic whitespace removal Compression LZNT Algorithm: Windows native compression (ntdll.dll) RtlCompressBuffer / RtlDecompressBuffer Workspace allocation: 1MB (0x100000 bytes) Error handling with proper status codes Generated Code Structure 1. Header comments (file info, settings) 2. Data functions (_GetBinData_xxx) 3. Helper functions (decode/decompress) 4. Deployment functions (_DeployFile or _GetBin) 5. Usage examples (commented) 📝 Error Handling The tool provides comprehensive error handling: Error Code Description SetError 1 Cannot read file or invalid data SetError 2 Encoding/compression failed SetError 3 Decompression failed SetError 4 Cannot create output file SetError 5 File write verification failed Error Messages: Console output for debugging MessageBox alerts for critical errors Descriptive error messages in generated code 🔧 Advanced Features Custom Function Names Function names are automatically sanitized: Removes invalid characters Includes filename and architecture Format: _GetBinData_filename_architecture Helper Function Options For Single File: _DeployFile($sDestPath = "", $bReturnHex = False) Returns binary data (default) Returns hex string ($bReturnHex = True) Writes to file ($sDestPath provided) For Multiple Files: _GetBin($sName) Switch/Case based selection Returns binary data Includes all decode/decompress logic 📊 Performance Tips Compression Trade-offs: Level 1: Faster, moderate compression Level 2: Slower, better compression Skip compression for files < 10KB Encoding Selection: Use Hex for debugging (readable) Use Base64 for smaller output size ~33% size increase with Base64 vs binary Chunk Size: Larger chunks = fewer lines but harder to edit Smaller chunks = more readable but more lines Default 4000 is optimal for most cases 🔄 Version History Version 3.0 (Current) ✅ Added Base64 encoding support ✅ Integrated LZNT compression (Level 1 & 2) ✅ Redesigned GUI with radio buttons ✅ Added _GetBin() for multiple files ✅ Enhanced _DeployFile() with flexible return options ✅ Fixed function naming (sanitization) ✅ Improved error handling and reporting ✅ Unicode support for Base64 (CryptStringToBinaryW) ✅ Workspace allocation for LZNT compression ✅ Integrated Base64.au3 library Version 2.x Legacy hex-only encoding Basic helper functions GUI mode only 📄 License MIT License - Free to use, modify, and distribute. 🙏 Acknowledgments AutoIt Community for feedback and testing LZNT_Base64.au3 library implementation Windows API documentation for LZNT compression ⚡ Quick Reference Card ╔══════════════════════════════════════════════════════════════╗ ║ QUICK REFERENCE - AutoIt Resource Embedder v3.0 ║ ╠══════════════════════════════════════════════════════════════╣ ║ GUI Mode: Double-click script ║ ║ CLI Mode: AutoIt3.exe script.au3 file1 file2 ... ║ ║ ║ ║ Encoding Options: ║ ║ • Hex - Standard hex encoding ║ ║ • Base64 - Base64 encoding ║ ║ • Hex + LZNT - Hex with compression ║ ║ • Base64+LZNT - Base64 with compression ║ ║ ║ ║ Single File: _DeployFile($path, $bReturnHex) ║ ║ Multiple Files: _GetBin($filename) ║ ║ ║ ║ Line Length: 100 - 4000 characters (default: 4000) ║ ║ Compression: Level 1 (4096) or Level 2 (0) ║ ╚══════════════════════════════════════════════════════════════╝ Made with ❤️ by Dao Van Trong - TRONG.PRO Embed anything, anywhere! App Source: #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ; ================================================================================================= ; Title .........: AutoIt Resource Embedder ; Author(s) .....: Dao Van Trong - TRONG.PRO ; Version .......: 3.0 (Enhanced with multiple encoding formats and compression support) ; Description ...: A professional tool to convert binary files into self-contained AutoIt functions. ; Features: Hex/Base64 encoding, LZNT compression, architecture detection, ; GUI and CLI modes, helper functions with automatic decompression/decoding. ; ================================================================================================= #Region ; *** INCLUDES *** #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <ListViewConstants.au3> #include <ButtonConstants.au3> #include <ComboConstants.au3> #include <ListBoxConstants.au3> #include <EditConstants.au3> #include <StaticConstants.au3> #include <WinAPIError.au3> #include <Security.au3> #include <Memory.au3> #include <Clipboard.au3> #include <SendMessage.au3> #include <WinAPISys.au3> #include <WinAPISysWin.au3> #include <GuiStatusBar.au3> #include <Array.au3> #include <File.au3> #EndRegion ; *** INCLUDES *** #Region ; *** GLOBAL VARIABLES *** ; Global variables for GUI controls Global $g_hGUI, $g_hListView, $g_hEditOutput, $g_hInputChunkSize, $iStatusBar Global $g_hBtnAddFiles, $g_hBtnRemoveSelected, $g_hBtnClearAll, $g_hCheckAddHelpers, $g_hBtnGenerate, $g_hBtnPreview, $g_hBtnCopy, $g_hBtnSaveAll, $g_hBtnSaveSeparate, $g_hBtnExit Global $g_hRadioHex, $g_hRadioBase64, $g_hRadioHexLZNT, $g_hRadioBase64LZNT, $g_hComboCompression ; 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 Resource Embedder by Dao Van Trong - TRONG.PRO", 795, 555) GUISetFont(9, 400, 0, "Segoe UI", $g_hGUI, 5) GUISetBkColor(0xF0F0F0) _CreateGUI_Controls() $iStatusBar = _GUICtrlStatusBar_Create($g_hGUI) _GUICtrlStatusBar_SetText($iStatusBar, "Ready | AutoIt Resource Embedder v3.0") 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, $SS_CENTERIMAGE, $GUI_WS_EX_PARENTDRAG) GUICtrlSetFont(-1, 9, 800) $g_hBtnAddFiles = GUICtrlCreateButton("Add Files...", 162, 11, 100, 25, BitOR($BS_CENTER, $BS_VCENTER)) $g_hBtnRemoveSelected = GUICtrlCreateButton("Remove Selected", 272, 11, 120, 25, BitOR($BS_CENTER, $BS_VCENTER)) $g_hBtnClearAll = GUICtrlCreateButton("Clear All", 402, 11, 80, 25, BitOR($BS_CENTER, $BS_VCENTER)) $g_hListView = GUICtrlCreateListView("File Name|Size|Architecture|Function Name", 10, 38, 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, 195, 150, 20, $SS_CENTERIMAGE, $GUI_WS_EX_PARENTDRAG) GUICtrlSetFont(-1, 9, 800) GUICtrlCreateLabel("Output Format:", 4, 220, 132, 20, BitOR($SS_RIGHT, $SS_CENTERIMAGE), $GUI_WS_EX_PARENTDRAG) GUICtrlSetFont(-1, 8, 700, 2) $g_hRadioHex = GUICtrlCreateRadio("Hex", 172, 220, 76, 22) GUICtrlSetState(-1, $GUI_CHECKED) $g_hRadioBase64 = GUICtrlCreateRadio("Base64", 252, 220, 100, 22) $g_hRadioHexLZNT = GUICtrlCreateRadio("Hex + LZNT", 358, 220, 100, 22) $g_hRadioBase64LZNT = GUICtrlCreateRadio("Base64 + LZNT", 470, 220, 100, 22) GUICtrlCreateLabel("LZNT Level:", 584, 220, 100, 20, BitOR($SS_RIGHT, $SS_CENTERIMAGE), $GUI_WS_EX_PARENTDRAG) $g_hComboCompression = GUICtrlCreateCombo("", 688, 220, 96, 25, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_SIMPLE)) GUICtrlSetData($g_hComboCompression, "Level 1|Level 2", "Level 2") GUICtrlCreateLabel("Line Length (chars):", 584, 195, 100, 20, BitOR($SS_RIGHT, $SS_CENTERIMAGE), $GUI_WS_EX_PARENTDRAG) GUICtrlSetFont(-1, 8, 700, 2) $g_hInputChunkSize = GUICtrlCreateInput("4000", 688, 195, 96, 23) $g_hCheckAddHelpers = GUICtrlCreateCheckbox("Include helper functions", 172, 195, 200, 22) GUICtrlSetState(-1, $GUI_CHECKED) $g_hBtnGenerate = GUICtrlCreateButton("3. Generate All Functions", 210, 243, 304, 35, BitOR($BS_CENTER, $BS_VCENTER)) GUICtrlSetFont(-1, 10, 800) GUICtrlSetBkColor($g_hBtnGenerate, 0x90EE90) $g_hBtnPreview = GUICtrlCreateButton("Preview Single", 516, 243, 116, 35, BitOR($BS_CENTER, $BS_VCENTER)) GUICtrlCreateLabel("Generated Code:", 10, 252, 150, 20, $SS_CENTERIMAGE, $GUI_WS_EX_PARENTDRAG) GUICtrlSetFont(-1, 9, 800) $g_hEditOutput = GUICtrlCreateEdit("", 10, 280, 780, 220) GUICtrlSetData(-1, "") GUICtrlSetFont(-1, 9, 400) $g_hBtnCopy = GUICtrlCreateButton("Copy to Clipboard", 634, 243, 154, 35, BitOR($BS_CENTER, $BS_VCENTER)) GUICtrlSetFont(-1, 9, 800) $g_hBtnSaveAll = GUICtrlCreateButton("Save All to File", 14, 502, 130, 30, BitOR($BS_CENTER, $BS_VCENTER)) $g_hBtnSaveSeparate = GUICtrlCreateButton("Save Separate Files", 154, 502, 130, 30, BitOR($BS_CENTER, $BS_VCENTER)) $g_hBtnExit = GUICtrlCreateButton("Exit", 660, 502, 130, 30, BitOR($BS_CENTER, $BS_VCENTER)) 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 _GUICtrlStatusBar_SetText($iStatusBar, "File selection cancelled") Return EndIf Local $aNewFiles = StringSplit($sFiles, "|") Local $iAdded = 0, $iSkipped = 0 If $aNewFiles[0] = 1 Then ; Single file If _AddFileToList($aNewFiles[1]) Then $iAdded = 1 Else $iSkipped = 1 EndIf Else ; Multiple files Local $sBasePath = $aNewFiles[1] For $i = 2 To $aNewFiles[0] If _AddFileToList($sBasePath & "\" & $aNewFiles[$i]) Then $iAdded += 1 Else $iSkipped += 1 EndIf Next EndIf ; Update status bar with detailed information Local $sStatus = "" If $iAdded > 0 Then $sStatus = "Added " & $iAdded & " file" & ($iAdded > 1 ? "s" : "") If $iSkipped > 0 Then $sStatus &= ($sStatus <> "" ? " | " : "") & "Skipped " & $iSkipped & " duplicate" & ($iSkipped > 1 ? "s" : "") $sStatus &= " | Total: " & UBound($g_aSelectedFiles) & " file(s)" _GUICtrlStatusBar_SetText($iStatusBar, $sStatus) 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 _GUICtrlStatusBar_SetText($iStatusBar, "No file selected") Return EndIf _ArrayDelete($g_aSelectedFiles, $iIndex) GUICtrlSendMsg($g_hListView, $LVM_DELETEITEM, $iIndex, 0) _GUICtrlStatusBar_SetText($iStatusBar, "File removed | Total: " & UBound($g_aSelectedFiles) & " file(s)") 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, "") _GUICtrlStatusBar_SetText($iStatusBar, "All files cleared | Ready") 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)) ; Determine encoding/compression from radio buttons Local $bUseHex = False, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0 If GUICtrlRead($g_hRadioHex) = $GUI_CHECKED Then $bUseHex = True ElseIf GUICtrlRead($g_hRadioBase64) = $GUI_CHECKED Then $bUseBase64 = True ElseIf GUICtrlRead($g_hRadioHexLZNT) = $GUI_CHECKED Then $bUseHex = True $bUseCompression = True $iCompLevel = (GUICtrlRead($g_hComboCompression) = "Level 2") ? 2 : 1 ElseIf GUICtrlRead($g_hRadioBase64LZNT) = $GUI_CHECKED Then $bUseBase64 = True $bUseCompression = True $iCompLevel = (GUICtrlRead($g_hComboCompression) = "Level 2") ? 2 : 1 EndIf Local $sCode = _GenerateCodeBundle($g_aSelectedFiles, $bAddHelpers, $iChunkSize, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) GUICtrlSetData($g_hEditOutput, $sCode) _GUICtrlStatusBar_SetText($iStatusBar, "Code generated successfully for " & UBound($g_aSelectedFiles) & " file(s) | " & StringLen($sCode) & " characters") 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)) ; Determine encoding/compression from radio buttons Local $bUseHex = False, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0 If GUICtrlRead($g_hRadioHex) = $GUI_CHECKED Then $bUseHex = True ElseIf GUICtrlRead($g_hRadioBase64) = $GUI_CHECKED Then $bUseBase64 = True ElseIf GUICtrlRead($g_hRadioHexLZNT) = $GUI_CHECKED Then $bUseHex = True $bUseCompression = True $iCompLevel = (GUICtrlRead($g_hComboCompression) = "Level 2") ? 2 : 1 ElseIf GUICtrlRead($g_hRadioBase64LZNT) = $GUI_CHECKED Then $bUseBase64 = True $bUseCompression = True $iCompLevel = (GUICtrlRead($g_hComboCompression) = "Level 2") ? 2 : 1 EndIf Local $sOutput = "; Preview for: " & $g_aSelectedFiles[$iIndex][1] & @CRLF $sOutput &= "; Architecture: " & $g_aSelectedFiles[$iIndex][3] & @CRLF & @CRLF Local $sCode = _GenerateEncodedFunction($g_aSelectedFiles[$iIndex][0], $g_aSelectedFiles[$iIndex][4], $g_aSelectedFiles[$iIndex][1], $g_aSelectedFiles[$iIndex][3], $iChunkSize, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) If GUICtrlRead($g_hCheckAddHelpers) = $GUI_CHECKED Then $sCode &= @CRLF & @CRLF & _GenerateHelperFunction($g_aSelectedFiles[$iIndex][4], $g_aSelectedFiles[$iIndex][1], $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) EndIf GUICtrlSetData($g_hEditOutput, $sOutput & $sCode) _GUICtrlStatusBar_SetText($iStatusBar, "Preview generated for: " & $g_aSelectedFiles[$iIndex][1]) 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 _GUICtrlStatusBar_SetText($iStatusBar, "No code to copy") Return MsgBox(48, "Warning", "No code to copy. Please generate code first.") EndIf _ClipBoard_SetData($sCode) _GUICtrlStatusBar_SetText($iStatusBar, "Code copied to clipboard | " & StringLen($sCode) & " characters") MsgBox(64, "Success", "Code copied to clipboard successfully!") GUICtrlSetData($g_hEditOutput, $sCode) 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 @error Or Not _SaveStringToFile($sSaveFile, $sCode) Then _GUICtrlStatusBar_SetText($iStatusBar, "Save failed: " & $sSaveFile) Return MsgBox(16, "Error", "Failed to save file: " & $sSaveFile) EndIf _GUICtrlStatusBar_SetText($iStatusBar, "File saved: " & $sSaveFile & " | " & _FormatFileSize(FileGetSize($sSaveFile))) MsgBox(64, "Success", "File saved successfully: " & $sSaveFile) 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) ; Determine encoding/compression from radio buttons Local $bUseHex = False, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0 If GUICtrlRead($g_hRadioHex) = $GUI_CHECKED Then $bUseHex = True ElseIf GUICtrlRead($g_hRadioBase64) = $GUI_CHECKED Then $bUseBase64 = True ElseIf GUICtrlRead($g_hRadioHexLZNT) = $GUI_CHECKED Then $bUseHex = True $bUseCompression = True $iCompLevel = (GUICtrlRead($g_hComboCompression) = "Level 2") ? 2 : 1 ElseIf GUICtrlRead($g_hRadioBase64LZNT) = $GUI_CHECKED Then $bUseBase64 = True $bUseCompression = True $iCompLevel = (GUICtrlRead($g_hComboCompression) = "Level 2") ? 2 : 1 EndIf 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 &= _GenerateEncodedFunction($sFilePath, $sFuncName, $sFileName, $sArch, $iChunkSize, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) If $bAddHelpers Then $sCode &= _GenerateHelperFunction($sFuncName, $sFileName, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) EndIf If _SaveStringToFile($sSaveFile, $sCode) Then $iSaved += 1 Next _GUICtrlStatusBar_SetText($iStatusBar, "Saved " & $iSaved & " of " & UBound($g_aSelectedFiles) & " file(s) to: " & $sSaveDir) 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, True, False, False, 0) 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. ; Prevents duplicate files from being added. ; ------------------------------------------------------------------------------------------------- Func _AddFileToList($sFilePath) ; Validate file exists If Not FileExists($sFilePath) Then _GUICtrlStatusBar_SetText($iStatusBar, "File not found: " & $sFilePath) Return False EndIf ; Check for duplicate - exact path match For $i = 0 To UBound($g_aSelectedFiles) - 1 If $g_aSelectedFiles[$i][0] = $sFilePath Then Local $sFileName = _GetFileName($sFilePath) _GUICtrlStatusBar_SetText($iStatusBar, "Duplicate skipped: " & $sFileName & " (already in list)") Return False EndIf Next ; Add new file 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) Return True 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) & "_" & _SanitizeName($sArch) EndFunc ;==>_PopulateFileInfo #EndRegion ; *** FILE AND DATA HANDLING *** #Region ; *** CORE CODE GENERATION *** ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateCodeBundle(ByRef $aFiles, $bAddHelpers, $iChunkSize, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) ; Purpose: The main code generation engine. Creates the full script content. ; ------------------------------------------------------------------------------------------------- Func _GenerateCodeBundle(ByRef $aFiles, $bAddHelpers, $iChunkSize, $bUseHex = True, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0) Local $sOutput = "; Generated by AutoIt Resource Embedder - TRONG.PRO" & @CRLF $sOutput &= "; Total files: " & UBound($aFiles) & @CRLF $sOutput &= "; Encoding: " & ($bUseHex ? "Hex " : "") & ($bUseBase64 ? "Base64 " : "") & @CRLF $sOutput &= "; Compression: " & ($bUseCompression And $iCompLevel > 0 ? "LZNT Level " & $iCompLevel : "None") & @CRLF $sOutput &= "; Generated on: " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF For $i = 0 To UBound($aFiles) - 1 $sOutput &= _GenerateEncodedFunction($aFiles[$i][0], $aFiles[$i][4], $aFiles[$i][1], $aFiles[$i][3], $iChunkSize, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) & @CRLF & @CRLF Next If $bAddHelpers Then If UBound($aFiles) = 1 Then $sOutput &= _GenerateHelperFunction($aFiles[0][4], $aFiles[0][1], $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) Else $sOutput &= _GenerateMasterHelperFunctionFromArray($aFiles, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) EndIf EndIf Return $sOutput EndFunc ;==>_GenerateCodeBundle ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateEncodedFunction($sFilePath, $sFuncName, $sFileName, $sArch, $iChunkSize, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) ; Purpose: Reads a binary file and wraps its encoded content in an AutoIt function. ; ------------------------------------------------------------------------------------------------- Func _GenerateEncodedFunction($sFilePath, $sFuncName, $sFileName, $sArch, $iChunkSize = 4000, $bUseHex = True, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0) 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 ; Apply compression if requested Local $bProcessedData = $bData If $bUseCompression And $iCompLevel > 0 Then Local $iEngine = ($iCompLevel = 2) ? 258 : 2 ; 2=Standard, 258=Maximum $bProcessedData = _LZNT_Compress($bData, 16, $iEngine, False) ; Updated library signature If @error Then ConsoleWrite("! Error: LZNT compression failed for file: " & $sFilePath & @CRLF) MsgBox(16, "Compression Error", "Failed to compress file: " & $sFileName & @CRLF & @CRLF & "Please try again or disable compression.") Return "" EndIf ConsoleWrite("+ Compressed " & $sFileName & ": " & _FormatFileSize(BinaryLen($bData)) & " → " & _FormatFileSize(BinaryLen($bProcessedData)) & @CRLF) EndIf ; Generate function header Local $sOutput = "Func " & $sFuncName & "()" & @CRLF $sOutput &= @TAB & '; This function holds the encoded data for ' & $sFileName & @CRLF $sOutput &= @TAB & '; File size: ' & _FormatFileSize(FileGetSize($sFilePath)) & @CRLF $sOutput &= @TAB & '; Architecture: ' & $sArch & @CRLF $sOutput &= @TAB & '; Encoding: ' & ($bUseHex ? "Hex " : "") & ($bUseBase64 ? "Base64 " : "") & @CRLF $sOutput &= @TAB & '; Compression: ' & ($bUseCompression And $iCompLevel > 0 ? "LZNT Level " & $iCompLevel : "None") & @CRLF $sOutput &= @TAB & '; Generated by AutoIt Resource Embedder' & @CRLF ; Generate Hex data if requested If $bUseHex Then Local $sHexWithPrefix = String($bProcessedData) Local $iHexLen = StringLen($sHexWithPrefix) $sOutput &= @TAB & "Local $sHexData = '" & StringMid($sHexWithPrefix, 1, $iChunkSize) & "'" & @CRLF For $i = $iChunkSize + 1 To $iHexLen Step $iChunkSize $sOutput &= @TAB & "$sHexData &= '" & StringMid($sHexWithPrefix, $i, $iChunkSize) & "'" & @CRLF Next EndIf ; Generate Base64 data if requested If $bUseBase64 Then Local $sBase64 = _Base64Encode($bProcessedData, 0) ; 0 = no line breaks If @error Or $sBase64 = "" Then ConsoleWrite("! Error: Base64 encoding failed for file: " & $sFilePath & @CRLF) MsgBox(16, "Encoding Error", "Failed to encode file to Base64: " & $sFileName & @CRLF & @CRLF & "Please try again or use Hex encoding.") Return "" EndIf Local $iB64Len = StringLen($sBase64) $sOutput &= @TAB & "Local $sBase64Data = '" & StringMid($sBase64, 1, $iChunkSize) & "'" & @CRLF For $i = $iChunkSize + 1 To $iB64Len Step $iChunkSize $sOutput &= @TAB & "$sBase64Data &= '" & StringMid($sBase64, $i, $iChunkSize) & "'" & @CRLF Next EndIf ; Return appropriate data based on encoding options $sOutput &= @CRLF If $bUseHex And $bUseBase64 Then $sOutput &= @TAB & '; Returns array: [0] = Hex, [1] = Base64' & @CRLF $sOutput &= @TAB & 'Local $aData[2] = [$sHexData, $sBase64Data]' & @CRLF $sOutput &= @TAB & 'Return $aData' & @CRLF ElseIf $bUseHex Then $sOutput &= @TAB & 'Return $sHexData' & @CRLF Else $sOutput &= @TAB & 'Return $sBase64Data' & @CRLF EndIf $sOutput &= "EndFunc ;==>" & $sFuncName Return $sOutput EndFunc ;==>_GenerateEncodedFunction ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateHelperFunction($sFuncName, $sOriginalFileName, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) ; Purpose: Generates a helper function to deploy a single embedded file with decode/decompress support. ; ------------------------------------------------------------------------------------------------- Func _GenerateHelperFunction($sFuncName, $sOriginalFileName, $bUseHex = True, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0) Local $sHelperFunc = @CRLF & @CRLF ; Add Base64 decode function if needed If $bUseBase64 Then $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= '; Base64 Decode Function (Unicode version - matches Base64.au3 encoder)' & @CRLF $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= 'Func _Base64Decode($sB64String)' & @CRLF $sHelperFunc &= @TAB & '; Remove whitespace' & @CRLF $sHelperFunc &= @TAB & '$sB64String = StringRegExpReplace($sB64String, "\s", "")' & @CRLF $sHelperFunc &= @TAB & 'If $sB64String = "" Then Return SetError(1, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & '; Get required buffer size' & @CRLF $sHelperFunc &= @TAB & 'Local $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", "wstr", $sB64String, "dword", StringLen($sB64String), "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0)' & @CRLF $sHelperFunc &= @TAB & 'If @error Or Not $aResult[0] Then Return SetError(2, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Local $iSize = $aResult[5]' & @CRLF $sHelperFunc &= @TAB & 'Local $tOutput = DllStructCreate("byte[" & $iSize & "]")' & @CRLF $sHelperFunc &= @TAB & '; Perform decoding' & @CRLF $sHelperFunc &= @TAB & '$aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", "wstr", $sB64String, "dword", StringLen($sB64String), "dword", 1, "struct*", $tOutput, "dword*", $iSize, "ptr", 0, "ptr", 0)' & @CRLF $sHelperFunc &= @TAB & 'If @error Or Not $aResult[0] Then Return SetError(3, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Return DllStructGetData($tOutput, 1)' & @CRLF $sHelperFunc &= 'EndFunc ;==>_Base64Decode' & @CRLF & @CRLF EndIf ; Add LZNT decompress function if needed If $bUseCompression And $iCompLevel > 0 Then Local $iEngine = ($iCompLevel = 2) ? 258 : 2 $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= '; LZNT Decompress Function (Engine: ' & $iEngine & ', Level: ' & $iCompLevel & ')' & @CRLF $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= 'Func _LZNT_Decompress($bCompressed)' & @CRLF $sHelperFunc &= @TAB & 'Local $tInput = DllStructCreate("byte[" & BinaryLen($bCompressed) & "]")' & @CRLF $sHelperFunc &= @TAB & 'DllStructSetData($tInput, 1, $bCompressed)' & @CRLF $sHelperFunc &= @TAB & 'Local $tOutput = DllStructCreate("byte[" & (BinaryLen($bCompressed) * 16) & "]")' & @CRLF $sHelperFunc &= @TAB & 'Local $aRet = DllCall("ntdll.dll", "int", "RtlDecompressBuffer", "ushort", ' & $iEngine & ', "ptr", DllStructGetPtr($tOutput), "dword", DllStructGetSize($tOutput), "ptr", DllStructGetPtr($tInput), "dword", DllStructGetSize($tInput), "dword*", 0)' & @CRLF $sHelperFunc &= @TAB & 'If @error Or $aRet[0] <> 0 Then Return SetError(1, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Local $tOut = DllStructCreate("byte[" & $aRet[6] & "]", DllStructGetPtr($tOutput))' & @CRLF $sHelperFunc &= @TAB & 'Return DllStructGetData($tOut, 1)' & @CRLF $sHelperFunc &= 'EndFunc ;==>_LZNT_Decompress' & @CRLF & @CRLF EndIf ; Add WriteBinaryFile helper function $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= '; Write Binary File Function' & @CRLF $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= 'Func _WriteBinaryFile($sFilePath, $bBinaryData)' & @CRLF $sHelperFunc &= @TAB & 'If Not IsBinary($bBinaryData) Then Return SetError(1, 0, False)' & @CRLF $sHelperFunc &= @TAB & 'If BinaryLen($bBinaryData) = 0 Then Return SetError(2, 0, False)' & @CRLF $sHelperFunc &= @TAB & '; Remove existing file/folder' & @CRLF $sHelperFunc &= @TAB & 'If FileExists($sFilePath) Then' & @CRLF $sHelperFunc &= @TAB & @TAB & 'FileSetAttrib($sFilePath, "-RASH", 1)' & @CRLF $sHelperFunc &= @TAB & @TAB & 'DirRemove($sFilePath, 1)' & @CRLF $sHelperFunc &= @TAB & @TAB & 'FileDelete($sFilePath)' & @CRLF $sHelperFunc &= @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & '; Write binary data' & @CRLF $sHelperFunc &= @TAB & 'Local $hFile = FileOpen($sFilePath, 2 + 8 + 16) ; Write + Create + Binary' & @CRLF $sHelperFunc &= @TAB & 'If $hFile = -1 Then Return SetError(3, 0, False)' & @CRLF $sHelperFunc &= @TAB & 'FileWrite($hFile, $bBinaryData)' & @CRLF $sHelperFunc &= @TAB & 'FileClose($hFile)' & @CRLF $sHelperFunc &= @TAB & 'Return FileExists($sFilePath)' & @CRLF $sHelperFunc &= 'EndFunc ;==>_WriteBinaryFile' & @CRLF & @CRLF ; Generate deployment function $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= '; Helper function to deploy the file from encoded data.' & @CRLF $sHelperFunc &= '; Parameters: $sDestPath - File path to write (empty = return binary)' & @CRLF $sHelperFunc &= '; $bReturnHex - Return hex string instead of binary (Default: False)' & @CRLF $sHelperFunc &= '; Encoding: ' & ($bUseHex ? "Hex " : "") & ($bUseBase64 ? "Base64 " : "") & @CRLF $sHelperFunc &= '; Compression: ' & ($bUseCompression And $iCompLevel > 0 ? "LZNT Level " & $iCompLevel : "None") & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= 'Func _DeployFile($sDestPath = "", $bReturnHex = False)' & @CRLF $sHelperFunc &= @TAB & '; Get encoded data from main function' & @CRLF ; Handle data retrieval based on encoding options If $bUseHex And $bUseBase64 Then $sHelperFunc &= @TAB & 'Local $aData = ' & $sFuncName & '()' & @CRLF $sHelperFunc &= @TAB & 'If Not IsArray($aData) Then Return SetError(1, 0, "")' & @CRLF $sHelperFunc &= @TAB & 'Local $bBinary = Binary($aData[0]) ; Use Hex data' & @CRLF ElseIf $bUseHex Then $sHelperFunc &= @TAB & 'Local $sHexData = ' & $sFuncName & '()' & @CRLF $sHelperFunc &= @TAB & 'If $sHexData = "" Then Return SetError(1, 0, "")' & @CRLF $sHelperFunc &= @TAB & 'Local $bBinary = Binary($sHexData)' & @CRLF Else $sHelperFunc &= @TAB & 'Local $sBase64Data = ' & $sFuncName & '()' & @CRLF $sHelperFunc &= @TAB & 'If $sBase64Data = "" Then Return SetError(1, 0, "")' & @CRLF $sHelperFunc &= @TAB & 'Local $bBinary = _Base64Decode($sBase64Data)' & @CRLF $sHelperFunc &= @TAB & 'If @error Then Return SetError(2, 0, "")' & @CRLF EndIf ; Add decompression if needed If $bUseCompression And $iCompLevel > 0 Then $sHelperFunc &= @CRLF & @TAB & '; Decompress the data' & @CRLF $sHelperFunc &= @TAB & '$bBinary = _LZNT_Decompress($bBinary)' & @CRLF $sHelperFunc &= @TAB & 'If @error Then Return SetError(3, 0, "")' & @CRLF EndIf ; Return binary/hex or write to file $sHelperFunc &= @CRLF & @TAB & '; If no destination path, return binary or hex string' & @CRLF $sHelperFunc &= @TAB & 'If $sDestPath = "" Then' & @CRLF $sHelperFunc &= @TAB & @TAB & 'If $bReturnHex Then' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'Return StringTrimLeft($bBinary, 2) ; Remove "0x" prefix' & @CRLF $sHelperFunc &= @TAB & @TAB & 'Else' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & 'Return $bBinary' & @CRLF $sHelperFunc &= @TAB & @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & 'EndIf' & @CRLF $sHelperFunc &= @CRLF & @TAB & '; Write binary data to file' & @CRLF $sHelperFunc &= @TAB & 'If Not _WriteBinaryFile($sDestPath, $bBinary) Then Return SetError(4, 0, "")' & @CRLF $sHelperFunc &= @TAB & 'Return $sDestPath' & @CRLF $sHelperFunc &= 'EndFunc ;==>_DeployFile' & @CRLF & @CRLF $sHelperFunc &= '; Example usage:' & @CRLF $sHelperFunc &= '; $bBinary = _DeployFile() ; Get binary data' & @CRLF $sHelperFunc &= '; $sHex = _DeployFile("", True) ; Get hex string' & @CRLF $sHelperFunc &= '; $sPath = _DeployFile(@TempDir & "\' & $sOriginalFileName & '") ; Write to file' & @CRLF Return $sHelperFunc EndFunc ;==>_GenerateHelperFunction ; ------------------------------------------------------------------------------------------------- ; Function: _GenerateMasterHelperFunctionFromArray(ByRef $aFiles, $bUseHex, $bUseBase64, $bUseCompression, $iCompLevel) ; Purpose: Generates _GetBin() function with Switch/Case for all embedded files. ; ------------------------------------------------------------------------------------------------- Func _GenerateMasterHelperFunctionFromArray(ByRef $aFiles, $bUseHex = True, $bUseBase64 = False, $bUseCompression = False, $iCompLevel = 0) Local $sHelperFunc = @CRLF & @CRLF ; Add Base64 decode function if needed If $bUseBase64 Then $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= '; Base64 Decode Function (Unicode version - matches Base64.au3 encoder)' & @CRLF $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= 'Func _Base64Decode($sB64String)' & @CRLF $sHelperFunc &= @TAB & '; Remove whitespace' & @CRLF $sHelperFunc &= @TAB & '$sB64String = StringRegExpReplace($sB64String, "\s", "")' & @CRLF $sHelperFunc &= @TAB & 'If $sB64String = "" Then Return SetError(1, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & '; Get required buffer size' & @CRLF $sHelperFunc &= @TAB & 'Local $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", "wstr", $sB64String, "dword", StringLen($sB64String), "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0)' & @CRLF $sHelperFunc &= @TAB & 'If @error Or Not $aResult[0] Then Return SetError(2, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Local $iSize = $aResult[5]' & @CRLF $sHelperFunc &= @TAB & 'Local $tOutput = DllStructCreate("byte[" & $iSize & "]")' & @CRLF $sHelperFunc &= @TAB & '; Perform decoding' & @CRLF $sHelperFunc &= @TAB & '$aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", "wstr", $sB64String, "dword", StringLen($sB64String), "dword", 1, "struct*", $tOutput, "dword*", $iSize, "ptr", 0, "ptr", 0)' & @CRLF $sHelperFunc &= @TAB & 'If @error Or Not $aResult[0] Then Return SetError(3, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Return DllStructGetData($tOutput, 1)' & @CRLF $sHelperFunc &= 'EndFunc ;==>_Base64Decode' & @CRLF & @CRLF EndIf ; Add LZNT decompress function if needed If $bUseCompression And $iCompLevel > 0 Then Local $iEngine = ($iCompLevel = 2) ? 258 : 2 $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= '; LZNT Decompress Function (Engine: ' & $iEngine & ', Level: ' & $iCompLevel & ')' & @CRLF $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= 'Func _LZNT_Decompress($bCompressed)' & @CRLF $sHelperFunc &= @TAB & 'Local $tInput = DllStructCreate("byte[" & BinaryLen($bCompressed) & "]")' & @CRLF $sHelperFunc &= @TAB & 'DllStructSetData($tInput, 1, $bCompressed)' & @CRLF $sHelperFunc &= @TAB & 'Local $tOutput = DllStructCreate("byte[" & (BinaryLen($bCompressed) * 16) & "]")' & @CRLF $sHelperFunc &= @TAB & 'Local $aRet = DllCall("ntdll.dll", "int", "RtlDecompressBuffer", "ushort", ' & $iEngine & ', "ptr", DllStructGetPtr($tOutput), "dword", DllStructGetSize($tOutput), "ptr", DllStructGetPtr($tInput), "dword", DllStructGetSize($tInput), "dword*", 0)' & @CRLF $sHelperFunc &= @TAB & 'If @error Or $aRet[0] <> 0 Then Return SetError(1, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Local $tOut = DllStructCreate("byte[" & $aRet[6] & "]", DllStructGetPtr($tOutput))' & @CRLF $sHelperFunc &= @TAB & 'Return DllStructGetData($tOut, 1)' & @CRLF $sHelperFunc &= 'EndFunc ;==>_LZNT_Decompress' & @CRLF & @CRLF EndIf ; Add WriteBinaryFile helper function $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= '; Write Binary File Function' & @CRLF $sHelperFunc &= '; -------------------------------------------------------------------------------------------------' & @CRLF $sHelperFunc &= 'Func _WriteBinaryFile($sFilePath, $bBinaryData)' & @CRLF $sHelperFunc &= @TAB & 'If Not IsBinary($bBinaryData) Then Return SetError(1, 0, False)' & @CRLF $sHelperFunc &= @TAB & 'If BinaryLen($bBinaryData) = 0 Then Return SetError(2, 0, False)' & @CRLF $sHelperFunc &= @TAB & '; Remove existing file/folder' & @CRLF $sHelperFunc &= @TAB & 'If FileExists($sFilePath) Then' & @CRLF $sHelperFunc &= @TAB & @TAB & 'FileSetAttrib($sFilePath, "-RASH", 1)' & @CRLF $sHelperFunc &= @TAB & @TAB & 'DirRemove($sFilePath, 1)' & @CRLF $sHelperFunc &= @TAB & @TAB & 'FileDelete($sFilePath)' & @CRLF $sHelperFunc &= @TAB & 'EndIf' & @CRLF $sHelperFunc &= @TAB & '; Write binary data' & @CRLF $sHelperFunc &= @TAB & 'Local $hFile = FileOpen($sFilePath, 2 + 8 + 16) ; Write + Create + Binary' & @CRLF $sHelperFunc &= @TAB & 'If $hFile = -1 Then Return SetError(3, 0, False)' & @CRLF $sHelperFunc &= @TAB & 'FileWrite($hFile, $bBinaryData)' & @CRLF $sHelperFunc &= @TAB & 'FileClose($hFile)' & @CRLF $sHelperFunc &= @TAB & 'Return FileExists($sFilePath)' & @CRLF $sHelperFunc &= 'EndFunc ;==>_WriteBinaryFile' & @CRLF & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= '; Helper function to get binary data by filename.' & @CRLF $sHelperFunc &= '; Usage: $bData = _GetBin("filename.ext")' & @CRLF $sHelperFunc &= '; Encoding: ' & ($bUseHex ? "Hex " : "") & ($bUseBase64 ? "Base64 " : "") & @CRLF $sHelperFunc &= '; Compression: ' & ($bUseCompression And $iCompLevel > 0 ? "LZNT Level " & $iCompLevel : "None") & @CRLF $sHelperFunc &= '; =================================================================' & @CRLF $sHelperFunc &= 'Func _GetBin($sName)' & @CRLF $sHelperFunc &= @TAB & 'Local $sData = ""' & @CRLF $sHelperFunc &= @TAB & 'Switch $sName' & @CRLF ; Generate Switch cases for each file For $i = 0 To UBound($aFiles) - 1 Local $sFileName = $aFiles[$i][1] Local $sFuncName = $aFiles[$i][4] $sHelperFunc &= @TAB & @TAB & 'Case "' & $sFileName & '"' & @CRLF $sHelperFunc &= @TAB & @TAB & @TAB & '$sData = ' & $sFuncName & '()' & @CRLF Next $sHelperFunc &= @TAB & 'EndSwitch' & @CRLF $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & '; Decode from encoding format to binary' & @CRLF $sHelperFunc &= @TAB & 'If $sData = "" Then Return SetError(1, 0, Binary(""))' & @CRLF $sHelperFunc &= @TAB & 'Local $bData' & @CRLF If $bUseBase64 Then $sHelperFunc &= @TAB & '$bData = _Base64Decode($sData)' & @CRLF $sHelperFunc &= @TAB & 'If @error Then Return SetError(2, 0, Binary(""))' & @CRLF Else $sHelperFunc &= @TAB & '$bData = Binary($sData) ; Hex to binary' & @CRLF EndIf ; Add decompression if needed If $bUseCompression And $iCompLevel > 0 Then $sHelperFunc &= @CRLF & @TAB & '; Decompress the data' & @CRLF $sHelperFunc &= @TAB & '$bData = _LZNT_Decompress($bData)' & @CRLF $sHelperFunc &= @TAB & 'If @error Then Return SetError(3, 0, Binary(""))' & @CRLF EndIf $sHelperFunc &= @CRLF $sHelperFunc &= @TAB & 'Return $bData' & @CRLF $sHelperFunc &= 'EndFunc ;==>_GetBin' & @CRLF & @CRLF $sHelperFunc &= '; Example usage:' & @CRLF For $i = 0 To UBound($aFiles) - 1 Local $sFileName = $aFiles[$i][1] $sHelperFunc &= '; $bData = _GetBin("' & $sFileName & '")' & @CRLF $sHelperFunc &= '; _WriteBinaryFile(@TempDir & "\\' & $sFileName & '", $bData)' & @CRLF Next 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 Func _LZNT_Compress($bInput, $iOrigSize = 16, $iEngine = 258, $bBase64 = False, $iLineLen = 1024) $bInput = Binary($bInput) If (BinaryLen($bInput) < 1) Then Return SetError(-1, 0, "") If $iEngine <> 2 And $iEngine <> 258 Then $iEngine = 258 Local $tInput = DllStructCreate("byte[" & BinaryLen($bInput) & "]") DllStructSetData($tInput, 1, $bInput) Local $aCall = DllCall("ntdll.dll", "int", "RtlGetCompressionWorkSpaceSize", _ "ushort", $iEngine, "dword*", 0, "dword*", 0) If @error Or $aCall[0] Then Return SetError(1, 0, "") Local $tWork = DllStructCreate("byte[" & $aCall[2] & "]") If ($iOrigSize < 1) Then $iOrigSize = 16 Local $iLen = $iOrigSize * DllStructGetSize($tInput) Local $tBuffer = DllStructCreate("byte[" & $iLen & "]") $aCall = DllCall("ntdll.dll", "int", "RtlCompressBuffer", _ "ushort", $iEngine, _ "ptr", DllStructGetPtr($tInput), "dword", DllStructGetSize($tInput), _ "ptr", DllStructGetPtr($tBuffer), "dword", DllStructGetSize($tBuffer), _ "dword", 4096, "dword*", 0, "ptr", DllStructGetPtr($tWork)) If @error Or $aCall[0] Then Return SetError(2, 0, "") Local $tOut = DllStructCreate("byte[" & $aCall[7] & "]", DllStructGetPtr($tBuffer)) Local $bOut = DllStructGetData($tOut, 1) If $bBase64 Then Return SetError(0, DllStructGetSize($tInput), _Base64Encode($bOut, $iLineLen)) Return SetError(0, DllStructGetSize($tInput), $bOut) EndFunc ;==>_LZNT_Compress Func _LZNT_Decompress($vInput, $iOrigSize = 16, $iEngine = 258, $bBase64 = False) Local $bInput If $bBase64 Then $bInput = _Base64Decode($vInput) Else $bInput = $vInput EndIf $bInput = Binary($bInput) If (BinaryLen($bInput) < 1) Then Return SetError(-1, 0, "") If $iEngine <> 2 And $iEngine <> 258 Then $iEngine = 258 Local $tInput = DllStructCreate("byte[" & BinaryLen($bInput) & "]") DllStructSetData($tInput, 1, $bInput) If ($iOrigSize < 1) Then $iOrigSize = 16 Local $iLen = $iOrigSize * DllStructGetSize($tInput) Local $tBuffer = DllStructCreate("byte[" & $iLen & "]") Local $aCall = DllCall("ntdll.dll", "int", "RtlDecompressBuffer", _ "ushort", $iEngine, _ "ptr", DllStructGetPtr($tBuffer), "dword", DllStructGetSize($tBuffer), _ "ptr", DllStructGetPtr($tInput), "dword", DllStructGetSize($tInput), _ "dword*", 0) If @error Or $aCall[0] Then Return SetError(1, 0, "") Local $tOut = DllStructCreate("byte[" & $aCall[6] & "]", DllStructGetPtr($tBuffer)) Return SetError(0, $aCall[6], DllStructGetData($tOut, 1)) EndFunc ;==>_LZNT_Decompress Func _LZNT_CompressStr($sInput, $iOrigSize = 16, $iEncoding = 4, $iEngine = 2, $bBase64 = False, $iLineLen = 1024) Local $bData = StringToBinary($sInput, $iEncoding) Local $sReturn = _LZNT_Compress($bData, $iOrigSize, $iEngine, $bBase64, $iLineLen) Return SetError(@error, @extended, $sReturn) EndFunc ;==>_LZNT_CompressStr Func _LZNT_DecompressStr($vInput, $iOrigSize = 16, $iEncoding = 4, $iEngine = 2, $bBase64 = False) Local $bData = _LZNT_Decompress($vInput, $iOrigSize, $iEngine, $bBase64) If @error Then Return SetError(1, 0, "") Return BinaryToString($bData, $iEncoding) EndFunc ;==>_LZNT_DecompressStr Func _Base64Encode($bData, $iLineLen = 0) If ($iLineLen < 1) Then $iLineLen = 0 $bData = Binary($bData) Local $tInput = DllStructCreate("byte[" & BinaryLen($bData) & "]") DllStructSetData($tInput, 1, $bData) Local $iFlags = 0x40000001 ; CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF ; Get required buffer size Local $aResult = DllCall("Crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tInput, _ "dword", DllStructGetSize($tInput), _ "dword", $iFlags, _ "ptr", 0, _ "dword*", 0) If @error Or Not $aResult[0] Then Return SetError(1, 0, "") Local $iSize = $aResult[5] Local $tOutput = DllStructCreate("wchar[" & $iSize & "]") ; Perform encoding $aResult = DllCall("Crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tInput, _ "dword", DllStructGetSize($tInput), _ "dword", $iFlags, _ "struct*", $tOutput, _ "dword*", $iSize) If @error Or Not $aResult[0] Then Return SetError(2, 0, "") Local $sOut = DllStructGetData($tOutput, 1) ; Manual wrap for embedding in AutoIt source If ($iLineLen > 0) And (StringLen($sOut) > $iLineLen) Then Local $sWrapped = "" For $i = 1 To StringLen($sOut) Step $iLineLen $sWrapped &= StringMid($sOut, $i, $iLineLen) & @CRLF Next $sOut = StringTrimRight($sWrapped, 2) EndIf Return $sOut EndFunc ;==>_Base64Encode Func _Base64EncodeStr($sInput, $iLineLen = 0, $iEncodeType = 4) If ($iLineLen < 1) Then $iLineLen = 0 If ($iEncodeType > 4) Or ($iEncodeType < 1) Then $iEncodeType = 4 Local $bBinary = StringToBinary($sInput, $iEncodeType) Local $sReturn = _Base64Encode($bBinary, $iLineLen) Return SetError(@error, @extended, $sReturn) EndFunc ;==>_Base64EncodeStr Func _Base64Decode($sInput, $bReturnType = 0) If ($bReturnType > 4) Or ($bReturnType < 1) Then $bReturnType = 0 ; Remove all whitespace and CRLF $sInput = StringRegExpReplace($sInput, "\s", "") If $sInput = "" Then Return SetError(1, 0, Binary("")) Local $iFlags = 0x1 ; CRYPT_STRING_BASE64 ; Get required buffer size Local $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", _ "wstr", $sInput, _ "dword", StringLen($sInput), _ "dword", $iFlags, _ "ptr", 0, _ "dword*", 0, _ "ptr", 0, _ "ptr", 0) If @error Or Not $aResult[0] Then Return SetError(2, 0, Binary("")) Local $iSize = $aResult[5] Local $tOutput = DllStructCreate("byte[" & $iSize & "]") ; Perform decoding $aResult = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryW", _ "wstr", $sInput, _ "dword", StringLen($sInput), _ "dword", $iFlags, _ "struct*", $tOutput, _ "dword*", $iSize, _ "ptr", 0, _ "ptr", 0) If @error Or Not $aResult[0] Then Return SetError(3, 0, Binary("")) Local $bBinary = DllStructGetData($tOutput, 1) If ($bReturnType = 0) Then Return $bBinary Else ; Convert binary to string with specified encoding Return BinaryToString($bBinary, $bReturnType) EndIf EndFunc ;==>_Base64Decode Func _Base64DecodeStr($sInput, $iDecodeType = 4) Local $sReturn = _Base64Decode($sInput, $iDecodeType) Return SetError(@error, @extended, $sReturn) EndFunc ;==>_Base64DecodeStr #EndRegion ; *** UTILITY FUNCTIONS ***1 point
-
IPC - Medium Integrity to High Integrity Process
Nine reacted to WildByDesign for a topic
@Nine I was doing some testing with your WCD IPC UDF and I was very impressed with it. It really is quite simple yet such a genius idea and very efficient as well. Testing with your scripts worked perfectly. But it didn't work when I integrated it into my script. Is it possible that it didn't work with my script because my script is already a GUI script? I checked with System Informer and there wasn't a window titled "WCDServer". It would've shown there whether it was hidden or not. EDIT: I figured out the problem. I was using _WinAPI_SetWindowText to set the title for the AutoIt window specifically but it was changing the title from "WCDServer" to the other title that I was using previously. This is something that I can work around. Your UDF is the perfect solution to my problem. Thank you.1 point -
Guiscape -- A new GUI builder project!
jaberwacky reacted to MattyD for a topic
Actually, maybe this would be better... Case $WM_DESTROY _WinAPI_RemoveWindowSubclass($hwnd, $pWndProc, $iIdSubclass) $iRet = _WinAPI_DefSubclassProc($hwnd, $iMsg, $wParam, $lParam) And we must do this before exiting. GUIDelete($Guiscape.Canvas.Hwnd)1 point -
Guiscape -- A new GUI builder project!
jaberwacky reacted to MattyD for a topic
Perhaps add this to WndProc? - it should allow you exit cleanly Case $WM_DESTROY _WinAPI_RemoveWindowSubclass($hwnd, $pWndProc, $iIdSubclass) GUIDelete($hWnd)1 point -
Guiscape -- A new GUI builder project!
MattyD reacted to jaberwacky for a topic
Check it out! https://github.com/matthewrg/Guiscape1 point -
You're probably missing the proper vc_redist dll's since you're on such old OS. https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-1701 point
-
Bug in map ( and how to avoid it )
WildByDesign reacted to AspirinJunkie for a topic
First, I pared down the script to the essentials: For $i = 1 To 20 ; create new(!) map, add one element to the string index "c" (which calculated position in the internal list is index 8) Global $m1[] $m1["c"] = 1 ; check if there`s a value at the index 8 (shouldn`t) If $m1[8] Then ConsoleWrite($m1[8] & @CRLF) ; create another map and add value at the same integer index as the one $m1 checked Global $m2[] $m2[8] = 1 Next I made the following observations: 1. It does not occur with all string indexes, but only with some. It is noticeable that each string index has a fixed associated integer index. If you use a different integer index, the phenomenon does not occur. So far, I have found the following combinations in which the phenomenon occurs: | String-Index | Integer-Index | | ------------ | ------------- | | "[" | 0 | | "<" | 1 | | "" | 5 | | "c" | 8 | | "D" | 9 | | "%" | 10 | | "k" | 16 | | "L" | 17 | | "-" | 18 | | "s" | 24 | | "T" | 25 | | "{" | 32 | | "\" | 33 | | "=" | 34 | These relationships can be explained well using hash index collisions. AutoIt uses the DJB2 hash function in its maps. If you use this for the letters and then scale it to the table size using modulo, you get exactly the corresponding integer indices. Only the table size is obviously not fixed, as the index sometimes fits for 32 elements and sometimes for 64. For example: “c” has a DJB2 hash value of 177672. If we assume that the map in AutoIt has 32 elements at that point, the index for “c” is calculated as 177672 % 32 = 8. This also works for the other string indexes. E.g., “D” --> 177641 % 32 = 9 or “” --> 5381 % 32 = 5. Only the size of the hash table is obviously variable, as some fit for a size of 32 elements and some for 64. However, thanks to the bug, we can learn a lot about the internal structure of AutoIt maps. They are DJB2-based hash tables that start with 32 or 64 elements. 2. This behavior only occurs when the map $m2 is created and an element is created with the same integer index as in $m1. If only this index is set, a match is reported very often. If other indexes are also set, the match does not occur as frequently. One possible explanation for this behavior is as follows: A hash table is essentially an array with a specific size. This size is fundamentally independent of the number of elements it contains (resizing makes sense but is not mandatory). In this case, a map is obviously initially populated with either 32 or 64 elements. When a value is added to the hash table, the hash value of the key is calculated and this calculated value is mapped to the array size using modulo. If the key is “c”, for example, the DJB2 hash (the hash algorithm used in AutoIt) is 177672. To obtain an index for our array in the map, we have to reduce this hash value to the range 32 or 64. This is easy to do using the modulo operator. And with 177672 % 32, we get 8 as the result. The value for the key “c” is therefore stored in the internal array at index 8. However, since several keys could end up at index 8, we need to create a way to hold multiple elements there. For each index, a list is created (a “bucket”) that contains all elements whose key matches this index. The key and value of these elements are then simply stored one after the other in the bucket itself. When a value is queried, the index is first calculated and then this bucket is traversed linearly to see if the specific key is contained in it. In AutoIt, these buckets do not necessarily seem to be used only by one map instance. At some point, two maps share a bucket, resulting in a phenomenon like the one we see here. So you would have to take a closer look at the initialization of the map to see exactly where the problem lies.1 point -
Guiscape -- A new GUI builder project!
MattyD reacted to jaberwacky for a topic
I'm taking the hi word, that's not the same as $hwnd? Let me test it ... :forehead smack: Durrrrr .... thank you!1 point -
Guiscape -- A new GUI builder project!
jaberwacky reacted to MattyD for a topic
looks like a malformed window handle to me... around about line 70: GUICtrlSendToDummy($dummy, _WinAPI_MakeLong($NC_CLICKED, $hwnd)) so you're sending part of a window handle (the hi word part), and a in the lo work you have $NC_CLICKED.1 point -
Sudden Spike in zPlayer Downloads — Any Idea Why?
CYCho reacted to argumentum for a topic
...If, there are very many distributed workloads and the "master" overwhelmed itself, then you see what you just witnessed. All this is painfully stupid. More bandwidth than brains. Idea: we should offer torrents ( in a throttle ). With a bit of luck they can feed each other the files 🤪1 point -
StringReplace it replaces the same string in all the strings founded
Musashi reacted to pixelsearch for a topic
@Musashi hello I think OP wants to replace each "%" (preceded with digits & eventual dot) with "\%" while keeping a log of each replacement using _FileWriteToLine . But maybe not all "%" must be processed, as we'll see in the script below. @Delai I tried another approach, because the way you scripted it (by splitting the sentence) makes it hard to find the position you need in the original sentence, when comes the replacement part. Local $sLineIn, $sLineOut, $sPattern, $nMode, $iOffset, $aArray $sLineIn = "This % sign for test (not preceded with digits) . " & _ "En un estudio sobre la presencia de mujeres en las empresas tecnológicas se observa que el 20 % de los operarios, " & _ "el 40 % de los ingenieros y el 30 % de los directivos son mujeres. Se sabe que en estas empresas el 20 % de las plantillas " & _ "son directivos, el 35 % son ingenieros y el resto son operarios. Se elige un trabajador al azar de una de estas empresas." $sPattern = '(?U).*\d*\.?\d+ *(%).*' $nMode = 2 ; $STR_REGEXPARRAYFULLMATCH $iOffset = 1 While 1 $aArray = StringRegExp($sLineIn, $sPattern, $nMode, $iOffset) If @error Then $sLineOut &= StringMid($sLineIn, $iOffset) ExitLoop EndIf $iOffset = @extended $sLineOut &= StringTrimRight($aArray[0], 1) & "\%" ; your _FileWriteToLine here WEnd MsgBox(0, "$sLineOut", $sLineOut) Hope it helps1 point -
Avoid "AutoIt Error" message box in unknown errors
WildByDesign reacted to argumentum for a topic
The wrapper I put together ( @trancexx's code ) works just fine in 32 and 64 bit. I have not seen it fail.1 point -
If you're running this script in a loop, then you are not leaving enough time to the last click to complete.1 point
-
No, but... Your last MouseClick is not followed by a Sleep. Probably the reason.1 point
-
WinRT Object Libraries
WildByDesign reacted to MattyD for a topic
Ok, so it's far from perfect - but I've finally thrown everything together for a v1.5 release. It's just as "point in time" upload I guess, because there has been a ton of dev since v1.4. For those following along there shouldn't be too many surprises, we now have: - Added a bunch of libraries that were missing in 1.4. I believe there we a ton of statics interfaces that were missed. - Added _WinRT_SwitchInterface($pObj, $sIID), which is a QueryInterface, and Release call in one. (tidies code quite a lot!) - Added Windows.UI libraries (native XAML libs) - Added WindowsAppSDK v1.8 libraries (WinUI3 libs) - Removed _WinRT_Col* funcs. That was a glorified VectorView wrapper - so just use the IVectorView lib! - Added support for paramatised interfaces. You can also determine PIIDs yourselves if need be. Local $sIID_IVector_1_IAudioEffectDefinition_ = _WinRT_GetParameterizedTypeInstanceIID("Windows.Foundation.Collections.IVector`1<Windows.Media.Effects.IAudioEffectDefinition>") _WinRT_SwitchInterface($pInNode_EffectDefs, $sIID_IVector_1_IAudioEffectDefinition_) -Added support for creating delegates (the "type" param is optional - but some objects won't let you register the delegate without specifying this) Local $pFileCompletedDgt = _WinRT_CreateDelegate("_FileCompleted", "Windows.Foundation.TypedEventHandler`2<Windows.Media.Audio.AudioFileInputNode, Object>") Local $iFileCompletedTkn = IAudioFileInputNode_AddHdlrFileCompleted($pAG_InNode, $pFileCompletedDgt) ;.... IAudioFileInputNode_RemoveHdlrFileCompleted($pAG_InNode, $iFileCompletedTkn) _WinRT_DestroyDelegate($pFileCompletedDgt) ;.... Func _FileCompleted($pThis, $pObj, $pArgs) ConsoleWrite("File Completed" & @CRLF) EndFunc - Updated class explorer And probably a bunch of other things that I've forgotten about over the last year!1 point -
AutoIt Snippets
ioa747 reacted to WildByDesign for a topic
System Tray Menu Auto-Light/Dark Mode: If your system theme is a light mode theme, it will make the system tray menu light. Dark theme will show dark tray menu. I used to apply dark mode to the system tray menu before by creating a GUI that was never shown. But now I realized that I don't have to create that GUI and simply get the handle for the hidden AutoIt window and apply to that handle. #NoTrayIcon #include <MsgBoxConstants.au3> #include <StringConstants.au3> #include <TrayConstants.au3> #include <SendMessage.au3> #include <WindowsNotifsConstants.au3> Global $hTray = _GetHwndFromPID(@AutoItPID) Global $bIsDarkMode = _WinAPI_ShouldAppsUseDarkMode() ; DPI Awareness DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -2) Opt("TrayMenuMode", 3) Example() Func Example() ; Create a tray item with the radio item parameter selected. TrayCreateItem("Radio 1", -1, -1, $TRAY_ITEM_RADIO) TrayItemSetState(-1, $TRAY_CHECKED) TrayCreateItem("Radio 2", -1, -1, $TRAY_ITEM_RADIO) TrayCreateItem("Radio 3", -1, -1, $TRAY_ITEM_RADIO) TrayCreateItem("") ; Create a separator line. Local $idExit = TrayCreateItem("Exit") TraySetState($TRAY_ICONSTATE_SHOW) ; Show the tray menu. If $bIsDarkMode Then DarkMode($hTray, True) While 1 Switch TrayGetMsg() Case $idExit ; Exit the loop. ExitLoop EndSwitch WEnd EndFunc ;==>Example ;-------------------------------------------------------------------------------------------------------------------------------- ; https://www.autoitscript.com/forum/topic/211475-darkmode-udf-for-autoits-win32guis/#comment-1530103 ;-------------------------------------------------------------------------------------------------------------------------------- Func DarkMode($hWnd, $bDarkMode = True) ; DarkMode Local Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 Local $iRet = _WinAPI_DwmSetWindowAttribute_unr($hWnd, $DWMWA_USE_IMMERSIVE_DARK_MODE, $bDarkMode) If Not $iRet Then Return SetError(1, 0, -1) _SetCtrlColorMode($hWnd, $bDarkMode) EndFunc ;==>DarkMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _SetCtrlColorMode($hWnd, $bDarkMode = True, $sName = Default) ; 'Explorer', 'CFD', 'DarkMode_ItemsView', etc. If $sName = Default Then $sName = $bDarkMode ? 'DarkMode_Explorer' : 'Explorer' $bDarkMode = Not Not $bDarkMode ; https://www.vbforums.com/showthread.php?900444-Windows-10-Dark-Mode-amp-VB6-apps If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local Enum $eDefault, $eAllowDark, $eForceDark, $eForceLight, $eMax ; enum PreferredAppMode DllCall('uxtheme.dll', 'bool', 133, 'hwnd', $hWnd, 'bool', $bDarkMode) ; fnAllowDarkModeForWindow = 133 DllCall('uxtheme.dll', 'int', 135, 'int', ($bDarkMode ? $eForceDark : $eForceLight)) ; fnAllowDarkModeForApp = 135 _WinAPI_SetWindowTheme_unr($hWnd, $sName) ; https://www.autoitscript.com/forum/index.php?showtopic=211475&view=findpost&p=1530103 DllCall('uxtheme.dll', 'none', 104) ; fnRefreshImmersiveColorPolicyState = 104 ; not needed ? _SendMessage($hWnd, $WM_THEMECHANGED, 0, 0) ; not needed ? EndFunc ;==>_SetCtrlColorMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_SetWindowTheme_unr($hWnd, $sName = Null, $sList = Null) ; #include <WinAPITheme.au3> ; unthoughtful unrestricting mod. ;Causes a window to use a different set of visual style information than its class normally uses Local $sResult = DllCall('UxTheme.dll', 'long', 'SetWindowTheme', 'hwnd', $hWnd, 'wstr', $sName, 'wstr', $sList) If @error Then Return SetError(@error, @extended, 0) If $sResult[0] Then Return SetError(10, $sResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetWindowTheme_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_DwmSetWindowAttribute_unr($hWnd, $iAttribute, $iData) ; #include <WinAPIGdi.au3> ; unthoughtful unrestricting mod. ;Sets the value of the specified attributes for non-client rendering to apply to the window Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_ShouldAppsUseDarkMode() Local $fnShouldAppsUseDarkMode = 132 Local $aResult = DllCall('UxTheme.dll', 'bool', $fnShouldAppsUseDarkMode) If @error Then Return SetError(@error, @extended, False) Return $aResult[0] EndFunc ;==>_WinAPI_ShouldAppsUseDarkMode ;-------------------------------------------------------------------------------------------------------------------------------- ; Function for getting HWND from PID Func _GetHwndFromPID($PID) $hWnd = 0 $winlist = WinList() For $i = 1 To $winlist[0][0] If $winlist[$i][0] <> "" Then $iPID2 = WinGetProcess($winlist[$i][1]) If $iPID2 = $PID Then $hWnd = $winlist[$i][1] ExitLoop EndIf EndIf Next Return $hWnd EndFunc ;==>_GetHwndFromPID1 point -
my question is why don't you do it like that? (Unless you want it to wait for you to press enter manually) ; ----------------------------------------------- #include <AutoItConstants.au3> ; ----------------------------------------------- Global $iTimeOut = 100 Global $iX = 711, $iY = 80 ; For F12 ; ----------------------------------------------- UpdateScenesF12($iX, $iY) ; ----------------------------------------------- Func UpdateScenesF12($iX, $iY) ConsoleWrite("UpdateScenes(" & $iX & ", " & $iY & ")" & @CRLF) Local $hSAC_MAIN = "[CLASS:SAC_MAIN]" Local $hSAC_SCENES = "[CLASS:SAC_SCENES]" Local $hSAC_SCENEPROPERTIES = "[CLASS:SAC_SCENEPROPERTIES]" ; ----------------------------------------------- WinActivate($hSAC_MAIN) WinActivate($hSAC_SCENES) ; ----------------------------------------------- ; <<<<==== Script Intervention ====>>>> Send("{End}") ; Select [End Of List] ; ----------------------------------------------- Sleep($iTimeOut) MouseClick($MOUSE_CLICK_LEFT, 188, 118, 1, 0) ; Select [New], the [Enter Scene Name] dialog is displayed. ; ----------------------------------------------- Send("{CTRLDOWN}") Send("v") ; Enter Scene Name Send("{CTRLUP}") ; ---------------------- ;~ Send("{ENTER}") ; Select [Ok], the [Enter Scene Name] dialog is exited...and the [Scene Properties] dialog is displayed Sleep($iTimeOut) MouseClick($MOUSE_CLICK_LEFT, 134, 163, 2, 0) ; Perform mouse click ⚠️ ; ----------------------------------------------- Sleep($iTimeOut) WinMove($hSAC_SCENEPROPERTIES, "", $iX, $iY) ; The [Scene Properties] dialog is repositioned ; ----------------------------------------------- Sleep($iTimeOut) MouseMove(1000, 550, 0) ; The mouse is positioned within the [Scene Properties] dialog EndFunc ;==>UpdateScenesF12 ; ----------------------------------------------- Edit: ; ----------------------------------------------- #include <AutoItConstants.au3> ; ----------------------------------------------- Global $iTimeOut = 100 Global $iX = 711, $iY = 80 ; For F12 ; Set the hotkey for [Enter] to trigger MouseClickAction HotKeySet("{ENTER}", "MouseClickAction") ; ----------------------------------------------- UpdateScenesF12($iX, $iY) ; ----------------------------------------------- Func UpdateScenesF12($iX, $iY) ; Various script stuff ; ----------------------------------------------- ; When [ENTER] is selected [for the [OK] button] then ; Wait for [Enter] to be pressed and handled by MouseClickAction While $bActive Sleep(100) ; Keeps the loop alive, waiting for the [Enter] hotkey action WEnd MouseClick($MOUSE_CLICK_LEFT, 134, 163, 2, 0) Exit script EndFunc ;==>UpdateScenesF12 ; ----------------------------------------------- Func MouseClickAction() HotKeySet("{ENTER}") ; Disable hotkey to prevent repeated clicks ;~ Send("{ENTER}") ; if you want to deliver the Enter key too MouseClick($MOUSE_CLICK_LEFT, 134, 163, 2, 0) ; Perform mouse click $bActive = False ; Exit loop in UpdateScenesF12 EndFunc Or alternately ; ----------------------------------------------- #include <AutoItConstants.au3> ; ----------------------------------------------- Global $iTimeOut = 100 Global $iX = 711, $iY = 80 ; For F12 ; ----------------------------------------------- UpdateScenesF12($iX, $iY) ; ----------------------------------------------- Func UpdateScenesF12($iX, $iY) ; Various script stuff ; ----------------------------------------------- ; When [ENTER] is selected [for the [OK] button] then WinWaitClose("the window that closes the ok") MouseClick($MOUSE_CLICK_LEFT, 134, 163, 2, 0) Exit script EndFunc ;==>UpdateScenesF12 ; -----------------------------------------------1 point
-
I have already posted the script in the German forum, but I would like to make it available here as well. Highlighting the active tab item in SciTE Individual: Frame color Text color Background color Text color if not saved Marker "Inactive item unsaved" Marker position "Inactive item unsaved" optionally 'top' / 'bottom' / 'none' Active item marking can be deactivated (if only unsaved marking is desired). The active item then receives the same marking as the inactive item when "unsaved". Colors can be loaded as a scheme via INI The compiled script can be ended with CMDLine parameter "/Exit". Since Windows 10, the windows have a very "flat" look. One of the consequences of this is that it is not immediately apparent which item is active in a Tab-Ctrl. When programming in SciTE, I usually have many tabs open at the same time. To make the active tab more visible, I draw it with a colored frame. In addition, unsaved tabs are marked separately with coloring of the top or bottom edge. The colors used for this can be stored individually as a scheme in an INI file. Some schemes are predefined at the beginning of the script. Just try out what you like best. I start the script via the autostart folder when Windows starts. Here are a few pictures: Active Tab Active Tab, unsaved Active Tab, BG: blue / Text: white ... BG: green / Text: white Active Tab, left & right idle unsaved Tabs Active Tab unsaved too ;-- TIME_STAMP 2023-03-23 10:16:34 v 0.5 #cs v 0.5 [fixed] Flickering, a variable assignment was incorrect [fixed] Marking has failed by using keys ("F6", "Shift+F6") to change the buffer selection v 0.4 [added] Exit via CMDLine with parameter "/Exit" [added] Optionally adjustable via INI [appearance]: - Mark active item: rect_highlight=true/false - Position of the marker for "Inactive item unsaved": idlepos=top/bottom/none v 0.3 [added] Separate marker (colored line top) for "Inactive item unsaved". v 0.2 [added] Separate marking (text color) for unsaved files. [added] Loading of colors from an INI (color schemes) possible #ce #include <FontConstants.au3> #include <GuiTab.au3> #include <Misc.au3> #include <WinAPIGdi.au3> #include <WinAPISys.au3> #include <WinAPIMisc.au3> #include <WindowsConstants.au3> Opt('TrayIconHide', 1) If $CMDLINE[0] And $CMDLINE[1] = '/Exit' Then ; CMD-Line: "@ScriptName.exe /Exit" Local $aProcessList = ProcessList(@ScriptName) For $i = 1 To $aProcessList[0][0] Step 1 If $aProcessList[$i][1] <> @AutoItPID Then ProcessClose($aProcessList[$i][1]) Next EndIf _Singleton(@ScriptName) ;~ HotKeySet("!{F8}", _End) ; <Alt><F8> Beenden OnAutoItExitRegister(_End) Global $sINI = StringFormat("%s\%s.ini", @ScriptDir, StringTrimRight(@ScriptName, 4)) Global $gm_SciTE[] $gm_SciTE.ExistsLast = 0 $gm_SciTE.ExistsCurr = 0 #cs The colors can be defined in an INI file in the script folder. If INI is not available, default colors are loaded. INI-Name = Name_of_the_Exe.ini [appearance] ; rect_highlight=true/false "false" does NOT highlight the active item, default: "true". rect_highlight=true ; idlepos=top/bottom/none "none" does NOT mark unsaved inactive files, default: "top". idlepos=top [scheme] ; Specify which of the defined schemes should be active. current=default ; One section for each scheme. [default] rect=0xCC483F text=0x800020 bg=0xFFFFFF unsaved=0x3030FF idle=0x3030FF [blue_invers] rect=0xCC483F text=0xFFF0F0 bg=0x800020 unsaved=0xA9A5F7 idle=0xA9A5F7 [green_invers] rect=0x005F00 text=0xEDFFED bg=0x409340 unsaved=0x1DE6B5 idle=0x1DE6B5 #ce ; appearance $gm_SciTE.bHighlight = (_IniOrDefault($sINI, 'rect_highlight', 'true', 'appearance') = 'true') $gm_SciTE.IdlePos = _IniOrDefault($sINI, 'idlepos', 'top', 'appearance') ; scheme: default (blue): $gm_SciTE.RectColor = _IniOrDefault($sINI, 'rect' , 0xCC483F) ; BGR $gm_SciTE.TextColor = _IniOrDefault($sINI, 'text' , 0x800020) ; BGR $gm_SciTE.BGColor = _IniOrDefault($sINI, 'bg' , 0xFFFFFF) ; BGR $gm_SciTE.TextColorUnsaved = _IniOrDefault($sINI, 'unsaved', 0x3030FF) ; BGR $gm_SciTE.IdleUnsaved = _IniOrDefault($sINI, 'idle' , 0x3030FF) ; BGR _CheckSciTE() ; the effect takes place immediately AdlibRegister(_CheckSciTE, 750) While True Sleep(5000) WEnd Func _End() AdlibUnRegister(_CheckSciTE) ;~ MsgBox(0, 'SciTE TabItem', 'Beendet!') Exit EndFunc Func _CheckSciTE() If ProcessExists("SciTE.exe") Then $gm_SciTE.ExistsCurr = 1 If $gm_SciTE.ExistsLast = 0 Then $gm_SciTE.ExistsLast = 1 If $gm_SciTE.bHighlight Then _DrawTabItem() AdlibRegister(_MouseHoversTab, 150) EndIf _MarkUnsavedIdleTab() Else $gm_SciTE.ExistsCurr = 0 If $gm_SciTE.ExistsLast = 1 Then $gm_SciTE.ExistsLast = 0 If $gm_SciTE.bHighlight Then AdlibUnRegister(_MouseHoversTab) EndIf EndIf EndFunc Func _MouseHoversTab() Local Static $iHoverLast = 1 ; when starting the program, exit from the item must be simulated Local $mTab = _SciTE_GetActiveTabInfo() If @error Then Return Local $tPoint = _WinAPI_GetMousePos(True, $mTab.hTab) Local $tRect = $mTab.RectItem Local $isHover = _WinAPI_PtInRect($tRect, $tPoint) If $isHover = 1 And $iHoverLast = 0 Then $iHoverLast = 1 ElseIf $isHover = 0 And $iHoverLast = 1 Then $iHoverLast = 0 Return _DrawTabItem() EndIf EndFunc Func _MarkUnsavedIdleTab() If $gm_SciTE.IdlePos = 'none' Then Return Local $hTab = __GetHwnd_SciTeTabCtrl() If @error Then Return SetError(1) Local $iActive = _GUICtrlTab_GetCurFocus($hTab) For $i = 0 To _GUICtrlTab_GetItemCount($hTab) -1 If $i = $iActive And $gm_SciTE.bHighlight Then ContinueLoop If StringRight(_GUICtrlTab_GetItemText($hTab, $i), 1) = '*' Then _DrawMarkerUnsaved($hTab, $i) EndIf Next EndFunc Func _DrawMarkerUnsaved($_hTab, $_iItem) Local $tRect = _GUICtrlTab_GetItemRectEx($_hTab, $_iItem) Local $tRectDraw = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct") If $gm_SciTE.IdlePos = 'top' Then $tRectDraw.Left = $tRect.Left $tRectDraw.Top = $tRect.Top -1 $tRectDraw.Right = $tRect.Right $tRectDraw.Bottom = $tRect.Top Else $tRectDraw.Left = $tRect.Left $tRectDraw.Top = $tRect.Bottom +2 $tRectDraw.Right = $tRect.Right $tRectDraw.Bottom = $tRect.Bottom +3 EndIf Local $hDC = _WinAPI_GetDC($_hTab) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 2, $gm_SciTE.IdleUnsaved) Local $hOldPen = _WinAPI_SelectObject($hDC, $hPen) _WinAPI_Rectangle($hDC, $tRectDraw) _WinAPI_SelectObject($hDC, $hOldPen) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc Func _DrawTabItem() Local $mTab = _SciTE_GetActiveTabInfo() If @error Then Return Local $hDC = _WinAPI_GetDC($mTab.hTab) Local $hFont = _WinAPI_CreateFont(14.5, 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _ $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Lucida Sans Unicode Standard') Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) Local $tRect = $mTab.RectItem ; extract to variable - otherwise no ByRef access possible Local $dY = (@OSVersion = "Win_7" ? 2 : 1) _WinAPI_InflateRect($tRect, 2, $dY) ; enlarge rectangle _WinAPI_OffsetRect($tRect, 0, 1) ; move rectangle down by 1px ; draw and fill rect Local $hPen = _WinAPI_CreatePen($PS_SOLID, 2, $gm_SciTE.RectColor) Local $hBrush = _WinAPI_CreateSolidBrush($gm_SciTE.BGColor) Local $hOldPen = _WinAPI_SelectObject($hDC, $hPen) Local $hOldBrush = _WinAPI_SelectObject($hDC, $hBrush) _WinAPI_Rectangle($hDC, $tRECT) ; draw text If StringRight($mTab.Item, 1) = '*' Then _WinAPI_SetTextColor($hDC, $gm_SciTE.TextColorUnsaved) Else _WinAPI_SetTextColor($hDC, $gm_SciTE.TextColor) EndIf _WinAPI_SetBkColor($hDC, $gm_SciTE.BGColor) ; move the text down a bit more _WinAPI_OffsetRect($tRect, 0, 3) _WinAPI_DrawText($hDC, $mTab.Item, $tRect, BitOR($DT_BOTTOM,$DT_CENTER)) ; clear ressources _WinAPI_SelectObject($hDC, $hOldFont) _WinAPI_DeleteObject($hFont) _WinAPI_SelectObject($hDC, $hOldPen) _WinAPI_DeleteObject($hPen) _WinAPI_SelectObject($hDC, $hOldBrush) _WinAPI_DeleteObject($hBrush) _WinAPI_ReleaseDC(0, $hDC) EndFunc Func _SciTE_GetActiveTabInfo() Local $mResult[], $hTab = __GetHwnd_SciTeTabCtrl() If @error Then Return SetError(1) $mResult.hTab = $hTab $mResult.Index = _GUICtrlTab_GetCurFocus($hTab) $mResult.Item = _GUICtrlTab_GetItemText($hTab, $mResult.Index) $mResult.RectItem = _GUICtrlTab_GetItemRectEx($hTab, $mResult.Index) Return $mResult EndFunc Func __GetHwnd_SciTE() Local $hScite = WinGetHandle('[ACTIVE]') If _WinAPI_GetClassName($hScite) = 'SciTEWindow' Then Return $hScite Else Return SetError(1, 0, Null) EndIf EndFunc Func __GetHwnd_SciTeTabCtrl() Local $hScite = __GetHwnd_SciTE() If @error Then Return SetError(1, 0, Null) Local $aChild, $hWndTab = Null $aChild = _WinAPI_EnumChildWindows($hScite) ; only visible If Not @error Then For $i = 1 To $aChild[0][0] If $aChild[$i][1] = "SciTeTabCtrl" Then $hWndTab = $aChild[$i][0] ExitLoop EndIf Next EndIf Return SetError(($hWndTab = Null ? 1 : 0), 0, $hWndTab) EndFunc ; read from INI if exists Func _IniOrDefault($_sINI, $_sKey, $_sDefault, $_sec=Null) Local $sVal = $_sDefault, $sSec = $_sec = Null ? 'scheme' : $_sec If FileExists($_sINI) Then If $sSec = 'scheme' Then $sSec = IniRead($_sINI, 'scheme', 'current', 'default') $sVal = IniRead($_sINI, $sSec, $_sKey, $_sDefault) EndIf Return $sVal EndFunc SciTE_DrawTabItem.au31 point
-
This small library includes only one function, which allows to set resizing for elements created with UDF (_GUICtrl*_Create). It works just the same as standard GUICtrlSetResizing. Also this function compatible/works with standard controls. Example: #include <GUIRichEdit.au3> #include <GUIComboBox.au3> #include 'GUICtrlSetResizingEx.au3' $hForm = GUICreate('GUICtrlSetResizingEx Example 1', 380, 330, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_THICKFRAME, $WS_OVERLAPPEDWINDOW, $WS_TILEDWINDOW, $WS_TABSTOP), $WS_EX_COMPOSITED) $hRichEdit = _GUICtrlRichEdit_Create($hForm, 'Edit1', 5, 5, 250, 250) _GUICtrlSetResizingEx($hRichEdit, BitOR($GUI_DOCKLEFT, $GUI_DOCKRIGHT, $GUI_DOCKTOP)) $hCombo = _GUICtrlComboBox_Create($hForm, 'Item', 5, 280, 250, 50, $CBS_DROPDOWNLIST) _GUICtrlComboBox_SetCurSel($hCombo, 0) _GUICtrlSetResizingEx($hCombo, BitOR($GUI_DOCKLEFT, $GUI_DOCKRIGHT, $GUI_DOCKBOTTOM)) $iButton = GUICtrlCreateButton('Native Button', 270, 5, 100, 25) _GUICtrlSetResizingEx(-1, BitOR($GUI_DOCKRIGHT, $GUI_DOCKTOP, $GUI_DOCKSIZE)) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIDelete($hForm) Exit EndSwitch WEnd GUICtrlSetResizingEx_1.3.zip1 point