argumentum Posted September 12 Posted September 12 ..where did I put that code I had... somewhere 🤷♂️ Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
Solution argumentum Posted September 12 Author Solution Posted September 12 (edited) It's here in this thread. Don't go losing the code again, ..you hear ! 01) I use SciTE portable but don't have the context menus as when properly installed 02) Have a bunch of RDP windows open and when they close ( some error ) I don't know from what PC it was from. 03) I use Dark reader and makes html copy/paste a mess for those not using it 🤷♂️ 04) Want to download torrents sequentially by default, but there is no default that I can find in qBittorrent 😭 05) _WinAPI_ShellGetKnownFolderPath() has a bunch of GUIDs and I'd like to know what paths work/return something 🤔 06) star trek stardate generator 07) highlighting of icons on the desktop 08) How can I draft and preview formatted posts elsewhere to copy and paste into the forum ? 09) How to format AutoIt source code by aligning assignment operators and inline comments. 10) Need to make a function for a small file on disk or clipboard that I can edit in a function, to customize said file in the script. 11) Script to upload images ( from file or clipboard image ) to GitHub. 12) Create a shortcut to your script to run it uncompiled ( using your icon if there ). MAP display - Display the contents of a MAP-type variable in a TreeView. SciTE_OverlayTab. I rather not have conversations in this thread. If you would like to chat about a post in this thread, open one in the help area, mentioning me and the post, and we'll chat there. Edited 5 hours ago by argumentum added list of posts WildByDesign 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted September 12 Author Posted September 12 (edited) Problem I use SciTE portable but don't have the context menus as when properly installed Solution Add the registry entries to show a context menu for .au3 in SystemFileAssociations for the current user Spoiler expandcollapse popupGlobal $g_AutoIt3root = StringLeft(@AutoItExe, StringInStr(@AutoItExe, '\', 0, -1) - 1) Global $g_sSysAssoc = "HKCU\Software\Classes\SystemFileAssociations\.au3\shell" Global $g_sTemplate = $g_AutoIt3root & "\SciTE\Template\Script.au3" AutoIt_Portable_ContextMenu_Remove(0) AutoIt_Portable_ContextMenu_Add() Func AutoIt_Portable_ContextMenu_Add($iShowMsgbox = 1) RegWrite("HKCU\Software\Classes\.au3", "PerceivedType", "REG_SZ", "text") RegWrite("HKCU\Software\Classes\.au3", "Content Type", "REG_SZ", "text/plain") RegWrite("HKCU\Software\Classes\.au3", "", "REG_SZ", "AutoIt3Script.Portable") RegWrite("HKCU\Software\Classes\AutoIt3Script.Portable", "", "REG_SZ", "AutoIt v3 Script Portable") ScriptTemplateWrite() If FileExists($g_sTemplate) Then RegWrite("HKCU\Software\Classes\.au3\ShellNew", "FileName", "REG_SZ", $g_sTemplate) Else RegWrite("HKCU\Software\Classes\.au3\ShellNew", "NullFile", "REG_SZ", "") EndIf RegWriteContextMenuCommand("RunX86", "Run Script (x86 Portable)", '"' & $g_AutoIt3root & '\AutoIt3.exe" "%1" %*') RegWriteContextMenuCommand("RunX64", "Run Script (x64 Portable)", '"' & $g_AutoIt3root & '\AutoIt3_x64.exe" "%1" %*') RegWriteContextMenuCommand("EditWSciTE", "Edit Script (SciTE Portable)", '"' & $g_AutoIt3root & '\SciTE\SciTE.exe" "%1"') RegWriteContextMenuCommand("Compile with Options", "Compile with Options (Portable)", '"' & $g_AutoIt3root & '\AutoIt3.exe" "' & $g_AutoIt3root & '\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /ShowGui /in "%l"') RegWriteContextMenuCommand("CompileX86", "Compile Script (x86 Portable)", '"' & $g_AutoIt3root & '\Aut2Exe\Aut2Exe.exe" /in "%1" /x86') RegWriteContextMenuCommand("CompileX64", "Compile Script (x64 Portable)", '"' & $g_AutoIt3root & '\Aut2Exe\Aut2Exe.exe" /in "%1" /x64') RegWriteContextMenuCommand("Tidy", "Tidy (Portable)", '"' & $g_AutoIt3root & '\SciTE\Tidy\Tidy.exe" "%1"') RefreshWindowsExplorerShellCache() If $iShowMsgbox Then MsgBox(64, "Registration Complete", "SystemFileAssociations context menu entries registered.") EndFunc ;==>AutoIt_Portable_ContextMenu_Add Func RegWriteContextMenuCommand($sEntry, $sDesc, $sCommand) RegWrite($g_sSysAssoc & "\" & $sEntry, "", "REG_SZ", $sDesc) RegWrite($g_sSysAssoc & "\" & $sEntry & "\command", "", "REG_SZ", $sCommand) EndFunc ;==>RegWriteContextMenuCommand Func RefreshWindowsExplorerShellCache() DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x08000000, "uint", 0, "ptr", 0, "ptr", 0) EndFunc ;==>RefreshWindowsExplorerShellCache Func AutoIt_Portable_ContextMenu_Remove($iShowMsgbox = 1) ; Delete SystemFileAssociations extension key and all associated verbs RegDelete("HKCU\Software\Classes\SystemFileAssociations\.au3") RefreshWindowsExplorerShellCache() If $iShowMsgbox Then MsgBox(64, "Unregister Complete", "SystemFileAssociations and portable AutoIt registry entries removed.") EndFunc ;==>AutoIt_Portable_ContextMenu_Remove Func ScriptTemplateWrite($iOverwrite = 0) If Not $iOverwrite And FileGetSize($g_sTemplate) Then Return Local $hFileOpen = FileOpen($g_sTemplate, 138) ; $FO_OVERWRITE (2) + $FO_CREATEPATH (8) + $FO_UTF8 (128) FileWrite($hFileOpen, ScriptTemplateStr()) FileClose($hFileOpen) EndFunc ;==>ScriptTemplateWrite Func ScriptTemplateStr() Local $sStr = "" $sStr &= '#Region ;**** Directives created by AutoIt3Wrapper_GUI ****' $sStr &= @CRLF & '#AutoIt3Wrapper_UseX64=y' $sStr &= @CRLF & '#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7' $sStr &= @CRLF & '#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****' $sStr &= @CRLF & '' $sStr &= @CRLF & '#cs ----------------------------------------------------------------------------' $sStr &= @CRLF & '' $sStr &= @CRLF & ' AutoIt Version: ' & @AutoItVersion $sStr &= @CRLF & ' Author: myName' $sStr &= @CRLF & '' $sStr &= @CRLF & ' Script Function:' $sStr &= @CRLF & ' Template AutoIt script.' $sStr &= @CRLF & '' $sStr &= @CRLF & '#ce ----------------------------------------------------------------------------' $sStr &= @CRLF & '' $sStr &= @CRLF & '; Script Start - Add your code below here' $sStr &= @CRLF & '' $sStr &= @CRLF & '' Return $sStr EndFunc ;==>ScriptTemplateStr Edited September 23 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted September 12 Author Posted September 12 Problem Have a bunch of RDP windows open and when they close ( some error ) I don't know from what PC it was from. Solution Keep this script running in the tray and it will find the name of the connection and place it in the MsgBox's error title. Spoiler WhatRdpWasIt.au3 expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=WhatRdpWasIt.ico #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Res_ProductName=WhatRdpWasIt.exe #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <WinAPISys.au3> #include <WinAPIProc.au3> #include <WinAPISysWin.au3> Global Enum $eRdpFromPID_32770, $eRdpFromPID_TscShellContainer, $eRdpFromPID_TscPopupParentWND, $eRdpFromPID_UBound If WinExists(StringTrimRight(@ScriptName, 4) & "_STUB") Then Exit 4 AutoItWinSetTitle(StringTrimRight(@ScriptName, 4) & "_STUB") Opt("TrayAutoPause", 0) Opt("TrayOnEventMode", 1) Opt("TrayMenuMode", 2) ;0=append, 1=no default menu, 2=no automatic check, 4=menuitemID not return If FileGetSize(StringTrimRight(@ScriptFullPath, 4) & ".ico") Then TraySetIcon(StringTrimRight(@ScriptFullPath, 4) & ".ico") EndIf TrayCreateItem("Open this folder") TrayItemSetOnEvent(-1, "Open_this_folder") Global $g_hWinHook = DllCallbackRegister('_WinEventProc', 'none', 'ptr;dword;hwnd;long;long;dword;dword') Global $g_hEventProc = _WinAPI_SetWinEventHook($EVENT_OBJECT_STATECHANGE, $EVENT_OBJECT_STATECHANGE, DllCallbackGetPtr($g_hWinHook)) If $g_hEventProc Then OnAutoItExitRegister('WinUnHook') Else Exit 5 EndIf While Sleep(100) WEnd Func Open_this_folder() ShellExecute(@WindowsDir & "\explorer.exe", '/n,/select,"' & @ScriptFullPath & '"', "") EndFunc ;==>Open_this_folder Func WinUnHook() If $g_hWinHook Then _WinAPI_UnhookWinEvent($g_hWinHook) If $g_hEventProc Then DllCallbackFree($g_hEventProc) $g_hWinHook = 0 $g_hEventProc = 0 EndFunc ;==>WinUnHook Func _WinEventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime) #forceref $hEventHook, $iEvent, $iObjectID, $iChildID, $iThreadId, $iEventTime If Not $hWnd Then Return Local $sTitle = WinGetTitle($hWnd) If Not StringInStr($sTitle, "Remote Desktop Connection") Then Return Local $sProcessName = "", $iPid = WinGetProcess($hWnd) If $iPid < 4 Then Return If $iPid > 1 Then $sProcessName = _WinAPI_GetProcessName($iPid) If $sProcessName <> "mstsc.exe" Then Return WinListRdpFromPID($iPid) EndFunc ;==>_WinEventProc Func WinListRdpFromPID($iPid, $sWinTitle = "Remote Desktop Connection") Local $aFound[$eRdpFromPID_UBound][2], $iEcho = 0 If $iPid < 2 Then Return SetError(2, 0, $aFound) Local Static $hTimer = TimerInit(), $aWinList = WinList($sWinTitle) Local $iOpt_WinTitleMatchMode = Opt("WinTitleMatchMode", 2) If TimerDiff($hTimer) > 1000 Then $hTimer = TimerInit() $aWinList = WinList($sWinTitle) EndIf If $iEcho Then ConsoleWrite('$aWinList[0][0] = ' & $aWinList[0][0] & @CRLF) For $i = 1 To $aWinList[0][0] If WinGetProcess($aWinList[$i][1]) = $iPid Then Switch _WinAPI_GetClassName($aWinList[$i][1]) Case "TSC_POPUP_PARENT_WNDCLASS" $aFound[$eRdpFromPID_TscPopupParentWND][0] = $aWinList[$i][1] ; "" $aFound[$eRdpFromPID_TscPopupParentWND][1] = $aWinList[$i][0] Case "TscShellContainerClass" $aFound[$eRdpFromPID_TscShellContainer][0] = $aWinList[$i][1] ; XPS8700K - Remote Desktop Connection $aFound[$eRdpFromPID_TscShellContainer][1] = $aWinList[$i][0] Case "#32770" If StringInStr(WinGetText($aWinList[$i][1]), @LF & @LF & "OK" & @LF) And $aWinList[$i][0] = "Remote Desktop Connection" Then $aFound[$eRdpFromPID_32770][0] = $aWinList[$i][1] ; Remote Desktop Connection $aFound[$eRdpFromPID_32770][1] = $aWinList[$i][0] If $iEcho Then ConsoleWrite('!' & $aWinList[$i][1] & @TAB & '[' & _WinAPI_GetClassName($aWinList[$i][1]) & ']' & @TAB & '[' & StringReplace(StringReplace(WinGetText($aWinList[$i][1]), @CR, "@CR"), @LF, "@LF") & ']' & @TAB & $aWinList[$i][0] & @CRLF) EndIf EndSwitch If $iEcho Then ConsoleWrite('+' & $aWinList[$i][1] & @TAB & '[' & _WinAPI_GetClassName($aWinList[$i][1]) & ']' & @TAB & '[' & StringReplace(StringReplace(WinGetText($aWinList[$i][1]), @CR, ">"), @LF, "~") & ']' & @TAB & $aWinList[$i][0] & @CRLF) Else If $iEcho Then ConsoleWrite('-' & $aWinList[$i][1] & @TAB & '[' & _WinAPI_GetClassName($aWinList[$i][1]) & ']' & @TAB & '[' & StringReplace(StringReplace(WinGetText($aWinList[$i][1]), @CR, ">"), @LF, "~") & ']' & @TAB & $aWinList[$i][0] & @CRLF) EndIf Next Opt("WinTitleMatchMode", $iOpt_WinTitleMatchMode) If $aFound[$eRdpFromPID_32770][0] Then _WinAPI_DwmSetWindowAttribute__($aFound[$eRdpFromPID_32770][0], 34, _WinAPI_SwitchColor(0x00AA00)) WinSetOnTop($aFound[$eRdpFromPID_32770][0], "", 1) WinSetTitle($aFound[$eRdpFromPID_32770][0], "", $aFound[$eRdpFromPID_TscShellContainer][1]) EndIf Return SetError(Not $aWinList[0][0], Int($aFound[$eRdpFromPID_32770][0]), $aFound) EndFunc ;==>WinListRdpFromPID Func _WinAPI_DwmSetWindowAttribute__($hWnd, $attribute = 34, $value = 0x00FF00, $valLen = 4) Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $attribute, 'dword*', $value, 'dword', $valLen) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute__ WhatRdpWasIt-icon-gen.au3 expandcollapse popup#NoTrayIcon #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Global $g_hGraphics = 0 Global $g_hBitmap = 0 WhatRdpWasIt_IcoGen() Func WhatRdpWasIt_IcoGen() _GDIPlus_Startup() Local Const $iWidth = 600 Local Const $iHeight = 600 Local $hGUI = GUICreate("GDI+ WhatRdpWasIt icon/png generator", $iWidth, $iHeight) $g_hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) $g_hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $g_hGraphics) Local $hBuffer = _GDIPlus_ImageGetGraphicsContext($g_hBitmap) _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 4) ; Palette Colors (ARGB: 0xAA RRGGBB) Local Const $iBgColor = 0x00000000 ; Fully transparent background Local Const $iCircleColor = 0xFFC48A20 ; Golden-ochre Local Const $iArrowColor = 0xFFECECEC ; Off-white / light grey Local $hBrushCircle = _GDIPlus_BrushCreateSolid($iCircleColor) Local Const $fPenWidth = 75.0 Local $hPenArrow = _GDIPlus_PenCreate($iArrowColor, $fPenWidth) _GDIPlus_PenSetLineJoin($hPenArrow, 2) _GDIPlus_PenSetStartCap($hPenArrow, 2) _GDIPlus_PenSetEndCap($hPenArrow, 2) ; Clear Canvas to Transparent ARGB _GDIPlus_GraphicsClear($hBuffer, $iBgColor) ; Main Circle _GDIPlus_GraphicsFillEllipse($hBuffer, 50, 50, 500, 500, $hBrushCircle) ; Upper Chevron Lines _GDIPlus_GraphicsDrawLine($hBuffer, 415, 155, 330, 240, $hPenArrow) _GDIPlus_GraphicsDrawLine($hBuffer, 330, 240, 395 + 20, 305 + 20, $hPenArrow) ; Lower Chevron Lines _GDIPlus_GraphicsDrawLine($hBuffer, 185, 445, 270, 360, $hPenArrow) _GDIPlus_GraphicsDrawLine($hBuffer, 270, 360, 205 - 20, 295 - 20, $hPenArrow) ; --- SAVE TRANSPARENT PNG AND ICO --- _GDIPlus_ImageSaveToFile($g_hBitmap, @ScriptDir & "\WhatRdpWasIt.png") _SaveBitmapToIco($g_hBitmap, @ScriptDir & "\WhatRdpWasIt.ico", 256) GUIRegisterMsg(0x000F, "_WM_PAINT") GUISetState(@SW_SHOW, $hGUI) _GDIPlus_GraphicsDrawImage($g_hGraphics, $g_hBitmap, 0, 0) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _GDIPlus_PenDispose($hPenArrow) _GDIPlus_BrushDispose($hBrushCircle) _GDIPlus_GraphicsDispose($hBuffer) _GDIPlus_BitmapDispose($g_hBitmap) _GDIPlus_GraphicsDispose($g_hGraphics) _GDIPlus_Shutdown() GUIDelete() EndFunc ;==>WhatRdpWasIt_IcoGen Func _WM_PAINT($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam If $g_hGraphics And $g_hBitmap Then _GDIPlus_GraphicsDrawImage($g_hGraphics, $g_hBitmap, 0, 0) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>_WM_PAINT Func _SaveBitmapToIco($hSrcBitmap, $sIcoPath, $iIconSize = 256) Local $hBitmap256 = _GDIPlus_BitmapCreateFromScan0($iIconSize, $iIconSize) Local $hCtx256 = _GDIPlus_ImageGetGraphicsContext($hBitmap256) _GDIPlus_GraphicsClear($hCtx256, 0x00000000) _GDIPlus_GraphicsSetSmoothingMode($hCtx256, 4) _GDIPlus_GraphicsSetInterpolationMode($hCtx256, 7) _GDIPlus_GraphicsDrawImageRect($hCtx256, $hSrcBitmap, 0, 0, $iIconSize, $iIconSize) Local $sTempPNG = @TempDir & "\~tmpIcon_" & Random(1000, 9999, 1) & ".png" _GDIPlus_ImageSaveToFile($hBitmap256, $sTempPNG) _GDIPlus_GraphicsDispose($hCtx256) _GDIPlus_BitmapDispose($hBitmap256) Local $hFile = FileOpen($sTempPNG, 16) Local $bPngData = FileRead($hFile) FileClose($hFile) FileDelete($sTempPNG) Local $iPngSize = BinaryLen($bPngData) If $iPngSize = 0 Then Return False Local $tHeader = DllStructCreate("align 1; word; word; word; byte; byte; byte; byte; word; word; dword; dword") DllStructSetData($tHeader, 1, 0) DllStructSetData($tHeader, 2, 1) DllStructSetData($tHeader, 3, 1) DllStructSetData($tHeader, 4, ($iIconSize >= 256) ? 0 : $iIconSize) DllStructSetData($tHeader, 5, ($iIconSize >= 256) ? 0 : $iIconSize) DllStructSetData($tHeader, 6, 0) DllStructSetData($tHeader, 7, 0) DllStructSetData($tHeader, 8, 1) DllStructSetData($tHeader, 9, 32) DllStructSetData($tHeader, 10, $iPngSize) DllStructSetData($tHeader, 11, 22) Local $tBytes = DllStructCreate("byte[22]", DllStructGetPtr($tHeader)) Local $bHeader = DllStructGetData($tBytes, 1) Local $hIcoFile = FileOpen($sIcoPath, 18) FileWrite($hIcoFile, $bHeader) FileWrite($hIcoFile, $bPngData) FileClose($hIcoFile) Return True EndFunc ;==>_SaveBitmapToIco Add it to shell:startup to run on login. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted September 14 Author Posted September 14 (edited) Problem I use Dark reader and makes html copy/paste a mess for those not using it 🤷♂️ Solution Run this function to remove the background coloring from the clipboard Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Clipboard.au3> #include <Memory.au3> #include <String.au3> Exit _PasteCleanRichText(0) ; Bind to a hotkey: Ctrl + Alt + Shift + V HotKeySet("^!+v", "_HotKey_PasteCleanRichText") While 1 Sleep(100) WEnd Func _HotKey_PasteCleanRichText() _PasteCleanRichText() EndFunc Func _PasteCleanRichText($iSendCtrlV = 1) ; https://www.autoitscript.com/forum/topic/213874-solved-help-for-argumentum/#findComment-1554648 _ClipBoard_Open(0) Local $iFormat = _ClipBoard_RegisterFormat("HTML Format") If Not _ClipBoard_IsFormatAvailable($iFormat) Then _ClipBoard_Close() If $iSendCtrlV Then Send("^v") Return EndIf ; 1. Get binary data and convert to UTF-8 string Local $vBinData = _ClipBoard_GetData($iFormat) _ClipBoard_Close() If @error Or Not IsBinary($vBinData) Then If $iSendCtrlV Then Send("^v") Return EndIf Local $sRawHTML = BinaryToString($vBinData, 4) ; 4 = UTF-8 ; 2. Extract the fragment part between <!--StartFragment--> and <!--EndFragment--> Local $aMatch = StringRegExp($sRawHTML, "(?s)<!--StartFragment-->(.*?)<!--EndFragment-->", 3) Local $sFragment = "" If @error Then ; Fallback if tags aren't found: use the whole raw string $sFragment = $sRawHTML Else $sFragment = $aMatch[0] EndIf ; 3. Strip out forced dark-mode styles from the fragment $sFragment = StringRegExpReplace($sFragment, "color:\s*[^;]+;", "") $sFragment = StringRegExpReplace($sFragment, "background-color:\s*[^;]+;", "") $sFragment = StringRegExpReplace($sFragment, "background:\s*[^;]+;", "") $sFragment = StringRegExpReplace($sFragment, 'style="\s*"', "") ; 4. Build a brand-new, perfectly calculated CF_HTML payload Local $sPrefix = "Version:0.9" & @CRLF & _ "StartHTML:00000097" & @CRLF & _ "EndHTML:" & StringFormat("%010d", 135 + StringLen($sFragment) + 55) & @CRLF & _ "StartFragment:00000135" & @CRLF & _ "EndFragment:" & StringFormat("%010d", 135 + StringLen($sFragment)) & @CRLF & _ "<html><body><!--StartFragment-->" Local $sSuffix = "<!--EndFragment--></body></html>" Local $sFinalHTML = $sPrefix & $sFragment & $sSuffix ; 5. Allocate global memory and push to clipboard Local $vUtf8Bin = StringToBinary($sFinalHTML, 4) Local $iLen = BinaryLen($vUtf8Bin) + 1 Local $hMem = _MemGlobalAlloc($iLen, 0x0002) ; $GMEM_MOVEABLE If Not $hMem Then If $iSendCtrlV Then Send("^v") Return EndIf Local $pMem = _MemGlobalLock($hMem) DllStructSetData(DllStructCreate("byte[" & $iLen & "]", $pMem), 1, $vUtf8Bin) _MemGlobalUnlock($hMem) _ClipBoard_Open(0) _ClipBoard_Empty() _ClipBoard_SetDataEx($hMem, $iFormat) _ClipBoard_Close() ; 6. Send paste command If $iSendCtrlV Then Send("^v") EndFunc making this background formatted clipboard: Spoiler While traditional WebDriver acts like a remote-control robot interacting with a web page from the outside (clicking buttons, typing text as a user would), the Chrome DevTools Protocol (CDP) plugs directly into the browser's engine. Because of this deep access, CDP can do several low-level tasks that standard WebDriver cannot easily do: Browserbase+ 1 1. Advanced Network Interception & Mocking What CDP can do: You can intercept, modify, mock, or drop network requests and responses on the fly. For example, you can intercept an API call returning user data and change the JSON payload mid-flight to test how your app handles specific data without altering the backend database. Testplane Why WebDriver struggles: Standard WebDriver has very limited network control; it mostly just tells the browser to navigate and lets whatever happens on the network happen passively. 2. Device, Geolocation, and Sensor Emulation What CDP can do: It allows you to deeply mock physical device metrics. You can dynamically override geolocation coordinates, timezones, CPU throttling (simulate a slow phone processor), network offline/online states, and even device orientation or touch events. Why WebDriver struggles: While modern WebDriver implementations have added basic geolocation or mobile emulation hooks, they are often rigid and restricted compared to the granular parameters you can pass directly through CDP's emulation domains. 3. Real-Time Event Streaming & Console Logging What CDP can do: It streams browser events natively over WebSockets. You can instantly capture unhandled JavaScript exceptions, browser console logs, performance metrics, and storage/cookie updates the exact millisecond they happen. Obsidian Publish+ 1 Why WebDriver struggles: WebDriver historically relies on a request-response polling model. To get console logs or errors, WebDriver usually has to ask the browser for them after the fact rather than streaming them live. 4. Performance Tracing and Profiling What CDP can do: You can record deep performance traces, generate CPU profiles, and measure memory heaps. This lets developers programmatic check for memory leaks or find out exactly why a page load is lagging down to the millisecond. Why WebDriver struggles: WebDriver has no native capability to inspect memory consumption, JavaScript execution timelines, or deep rendering metrics. 5. Managing Browser Contexts and Service Workers What CDP can do: It gives you granular control over background processes like Service Workers, Web Workers, out-of-process iframes, and isolated incognito storage partitions (Browser Contexts) without needing to spin up separate browser windows. Browserbase Summary: Think of WebDriver as a user sitting in front of a monitor using a mouse and keyboard. Think of CDP as an engineer plugged directly into the browser's electrical wiring with a diagnostic kit. look better: Spoiler While traditional WebDriver acts like a remote-control robot interacting with a web page from the outside (clicking buttons, typing text as a user would), the Chrome DevTools Protocol (CDP) plugs directly into the browser's engine. Because of this deep access, CDP can do several low-level tasks that standard WebDriver cannot easily do: Browserbase+ 1 1. Advanced Network Interception & Mocking What CDP can do: You can intercept, modify, mock, or drop network requests and responses on the fly. For example, you can intercept an API call returning user data and change the JSON payload mid-flight to test how your app handles specific data without altering the backend database. Testplane Why WebDriver struggles: Standard WebDriver has very limited network control; it mostly just tells the browser to navigate and lets whatever happens on the network happen passively. 2. Device, Geolocation, and Sensor Emulation What CDP can do: It allows you to deeply mock physical device metrics. You can dynamically override geolocation coordinates, timezones, CPU throttling (simulate a slow phone processor), network offline/online states, and even device orientation or touch events. Why WebDriver struggles: While modern WebDriver implementations have added basic geolocation or mobile emulation hooks, they are often rigid and restricted compared to the granular parameters you can pass directly through CDP's emulation domains. 3. Real-Time Event Streaming & Console Logging What CDP can do: It streams browser events natively over WebSockets. You can instantly capture unhandled JavaScript exceptions, browser console logs, performance metrics, and storage/cookie updates the exact millisecond they happen. Obsidian Publish+ 1 Why WebDriver struggles: WebDriver historically relies on a request-response polling model. To get console logs or errors, WebDriver usually has to ask the browser for them after the fact rather than streaming them live. 4. Performance Tracing and Profiling What CDP can do: You can record deep performance traces, generate CPU profiles, and measure memory heaps. This lets developers programmatic check for memory leaks or find out exactly why a page load is lagging down to the millisecond. Why WebDriver struggles: WebDriver has no native capability to inspect memory consumption, JavaScript execution timelines, or deep rendering metrics. 5. Managing Browser Contexts and Service Workers What CDP can do: It gives you granular control over background processes like Service Workers, Web Workers, out-of-process iframes, and isolated incognito storage partitions (Browser Contexts) without needing to spin up separate browser windows. Browserbase Summary: Think of WebDriver as a user sitting in front of a monitor using a mouse and keyboard. Think of CDP as an engineer plugged directly into the browser's electrical wiring with a diagnostic kit. Edited September 28 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted September 15 Author Posted September 15 (edited) Problem Want to download torrents sequentially by default, but there is no default that I can find in qBittorrent 😭 The reason for "the problem" ...that works against the swarm and spirit of the protocol. So it will never have a default sequential setting. Solution #1 If you must have it then register your own handler to do it via WebUI. Go to: Tools > Options > WebUI and enable it. Then compile and register the script below with your user, password and port. Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=qBittorrAdd.ico #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Res_Comment=qBittorrAdd #AutoIt3Wrapper_Res_Description=qBittorrAdd #AutoIt3Wrapper_Res_Fileversion=0.2608.6.7 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y #AutoIt3Wrapper_Res_ProductName=qBittorrAdd.exe #AutoIt3Wrapper_Res_ProductVersion=0.2608.6.0 #AutoIt3Wrapper_Res_CompanyName=. #AutoIt3Wrapper_Res_LegalCopyright=. #AutoIt3Wrapper_Res_LegalTradeMarks=. #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/mo #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <MsgBoxConstants.au3> #include <FileConstants.au3> ;~ #RequireAdmin ; Run this once as Administrator to register magnet links ;~ Exit _RegisterMagnetProtocol() ; Prevent AutoIt hard crashes on COM errors Global $oCOMError = ObjEvent("AutoIt.Error", "_COMErrHandler") ; --- Configuration --- Local $sWebUiUrl = "https://127.0.0.1:8080" Local $sUsername = "YOUR_USERNAME_HERE" Local $sPassword = "YOUR_PASSWORD_HERE" ; Set to your active Web UI password ; Check if a magnet link, URL, or file path was passed via command line Local $sTarget = "" If $CmdLine[0] > 0 Then $sTarget = $CmdLine[1] Else $sTarget = InputBox("qBittorrent Sequential Add", "Enter Torrent URL, Magnet Link, or File Path:") If @error Or $sTarget = "" Then Exit EndIf ; Strip surrounding quotes if dragged & dropped or passed via CMD $sTarget = StringRegExpReplace($sTarget, '^"|"$', '') ; Create HTTP Object Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") ; Configure SSL (Ignore self-signed errors & Force TLS 1.2) Const $WinHttpRequestOption_SslErrorIgnoreFlags = 4 Const $WinHttpRequestOption_SecureProtocols = 9 $oHTTP.Option($WinHttpRequestOption_SslErrorIgnoreFlags) = 13056 $oHTTP.Option($WinHttpRequestOption_SecureProtocols) = 2048 ; --- Step 1: Login --- Local $sLoginBody = "username=" & _URLEncode($sUsername) & "&password=" & _URLEncode($sPassword) $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/auth/login", False) $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) $oHTTP.Send($sLoginBody) ; Validate status code (200 or 204 indicates success) If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then MsgBox($MB_ICONERROR, "Auth Error", "Login failed! HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 5) Exit EndIf ; --- Step 2: Add Torrent with Sequential Download Enabled --- $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/torrents/add", False) $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) If FileExists($sTarget) Then ; --- Handle Local .torrent File (multipart/form-data) --- Local $sBoundary = "----AutoItBoundary" & Hex(Random(100000, 999999, 1)) Local $sFileName = StringRegExpReplace($sTarget, "^.*[\\/]", "") ; Read file as binary Local $hFile = FileOpen($sTarget, $FO_BINARY) Local $bFileContent = FileRead($hFile) FileClose($hFile) ; 1. Build options header FIRST before the file bytes Local $sParamsPart = "" $sParamsPart &= "--" & $sBoundary & @CRLF $sParamsPart &= 'Content-Disposition: form-data; name="sequentialDownload"' & @CRLF & @CRLF $sParamsPart &= "true" & @CRLF $sParamsPart &= "--" & $sBoundary & @CRLF $sParamsPart &= 'Content-Disposition: form-data; name="firstLastPiecePrio"' & @CRLF & @CRLF $sParamsPart &= "false" & @CRLF $sParamsPart &= "--" & $sBoundary & @CRLF $sParamsPart &= 'Content-Disposition: form-data; name="torrents"; filename="' & $sFileName & '"' & @CRLF $sParamsPart &= "Content-Type: application/x-bittorrent" & @CRLF & @CRLF ; 2. Closing boundary after binary file content Local $sEndPart = @CRLF & "--" & $sBoundary & "--" & @CRLF ; 3. Combine header/parameters, file bytes, and closing boundary Local $bPayload = Binary($sParamsPart) & $bFileContent & Binary($sEndPart) $oHTTP.SetRequestHeader("Content-Type", "multipart/form-data; boundary=" & $sBoundary) $oHTTP.Send($bPayload) Else ; --- Handle Magnet Link or Web URL (application/x-www-form-urlencoded) --- Local $sAddBody = "urls=" & _URLEncode($sTarget) & "&sequentialDownload=true&firstLastPiecePrio=false" $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.Send($sAddBody) EndIf Func _RegisterMagnetProtocol() Local $sExePath = StringTrimRight(@ScriptFullPath, 4) & ".exe" Local $sAppProgID = StringTrimRight(@ScriptName, 4) If IsAdmin() Then ; Register 'magnet:' protocol in Windows Registry RegWrite("HKCR\magnet", "", "REG_SZ", "URL:Magnet link") RegWrite("HKCR\magnet", "URL Protocol", "REG_SZ", "") RegWrite("HKCR\magnet\shell\open\command", "", "REG_SZ", '"' & $sExePath & '" "%1"') If Not @error Then MsgBox($MB_ICONINFORMATION, "Success", "Registered magnet links to:" & @CRLF & $sExePath, 10) Else MsgBox($MB_ICONERROR, "Error", "Failed to write registry keys.", 10) EndIf EndIf ; 1. Define Protocol Class RegWrite("HKCU\Software\Classes\" & $sAppProgID, "", "REG_SZ", "URL:Magnet link") RegWrite("HKCU\Software\Classes\" & $sAppProgID, "URL Protocol", "REG_SZ", "") RegWrite("HKCU\Software\Classes\" & $sAppProgID & "\shell\open\command", "", "REG_SZ", '"' & $sExePath & '" "%1"') ; 2. Register as Windows Capability (makes it show up in Default Apps) RegWrite("HKCU\Software\" & $sAppProgID & "\Capabilities", "ApplicationName", "REG_SZ", "qBittorrent Sequential Handler") RegWrite("HKCU\Software\" & $sAppProgID & "\Capabilities\URLAssociations", "magnet", "REG_SZ", $sAppProgID) RegWrite("HKCU\Software\RegisteredApplications", $sAppProgID, "REG_SZ", "Software\" & $sAppProgID & "\Capabilities") MsgBox($MB_ICONINFORMATION, "Done", "App registered in Windows Default Apps menu!", 10) EndFunc ;==>_RegisterMagnetProtocol ; Check response If $oHTTP.Status = 200 Or $oHTTP.Status = 204 Then ToolTip("Torrent added sequentially via HTTPS!", 10, 10, "qBittorrent", 1) Sleep(2000) Else MsgBox($MB_ICONERROR, "qBittorrent Error", "Failed to add torrent. HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 3) EndIf ; --- Helper Function to URL-Encode Form Data --- Func _URLEncode($sData) Local $aArray = StringSplit($sData, ""), $sEncoded = "", $iAsc For $i = 1 To $aArray[0] $iAsc = Asc($aArray[$i]) Select Case ($iAsc >= 48 And $iAsc <= 57) Or ($iAsc >= 65 And $iAsc <= 90) Or ($iAsc >= 97 And $iAsc <= 122) $sEncoded &= $aArray[$i] Case $aArray[$i] = " " $sEncoded &= "+" Case Else $sEncoded &= "%" & Hex($iAsc, 2) EndSelect Next Return $sEncoded EndFunc ;==>_URLEncode Func _COMErrHandler($oError) EndFunc ;==>_COMErrHandler Solution #2 ( simpler but i didn't think of it before ) Go to Tools > Options > Downloads, then on Run external program, Run on torrent added: "C:\Utilities\qBittorrAddSeq.exe" "/I:%I" "/J:%J" Spoiler expandcollapse popup#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <MsgBoxConstants.au3> ; "C:\Utilities\qBittorrAddSeq.exe" "/I:%I" "/J:%J" ; Prevent AutoIt hard crashes on COM errors Global $oCOMError = ObjEvent("AutoIt.Error", "_COMErrHandler") qTorr_AddSequentialViaWebUI() Func qTorr_AddSequentialViaWebUI($sWebUiUrl = "https://127.0.0.1:8080", $sUsername = "YOUR_USERNAME_HERE", $sPassword = "YOUR_PASSWORD_HERE") ; --- Parameter Parsing --- Local $sHash = "" Local $sHashV1 = "" Local $sHashV2 = "" ; Loop through all arguments looking for /I: or /J: If $CmdLine[0] > 0 Then For $i = 1 To $CmdLine[0] If StringLeft($CmdLine[$i], 3) = "/I:" Then $sHashV1 = StringMid($CmdLine[$i], 4) ElseIf StringLeft($CmdLine[$i], 3) = "/J:" Then $sHashV2 = StringMid($CmdLine[$i], 4) EndIf Next EndIf ; Combine them if both exist, otherwise use whichever is populated If $sHashV1 <> "" And $sHashV2 <> "" Then $sHash = $sHashV1 & "|" & $sHashV2 ElseIf $sHashV1 <> "" Then $sHash = $sHashV1 Else $sHash = $sHashV2 EndIf ; Exit silently if no valid hash was passed If $sHash = "" Then Exit 4 ; --- HTTP Web API Transmission --- Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") ; Configure SSL (Ignore self-signed errors & Force TLS 1.2) Const $WinHttpRequestOption_SslErrorIgnoreFlags = 4 Const $WinHttpRequestOption_SecureProtocols = 9 $oHTTP.Option($WinHttpRequestOption_SslErrorIgnoreFlags) = 13056 $oHTTP.Option($WinHttpRequestOption_SecureProtocols) = 2048 ; Step 1: Login to get session cookie Local $sLoginBody = "username=" & _URLEncode($sUsername) & "&password=" & _URLEncode($sPassword) $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/auth/login", False) $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) $oHTTP.Send($sLoginBody) ; Validate status code (200 or 204 indicates success) If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then MsgBox($MB_ICONERROR, StringTrimRight(@ScriptName, 4) & " Error", "Login failed!" & @CRLF & " HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 60) Exit 5 EndIf ; Step 2: Toggle Sequential Download Using the Extracted Hash $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/torrents/toggleSequentialDownload", False) $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) $oHTTP.Send("hashes=" & $sHash) ; Validate status code (200 or 204 indicates success) If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then MsgBox($MB_ICONERROR, StringTrimRight(@ScriptName, 4) & " Error", "toggleSequentialDownload failed!" & @CRLF & " HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 60) Exit 6 EndIf ;~ ; Step 3: Automatically prioritize the first and last pieces ;~ $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/torrents/toggleFirstLastPiecePrio", False) ;~ $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") ;~ $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) ;~ $oHTTP.Send("hashes=" & $sHash) ;~ ; Validate status code (200 or 204 indicates success) ;~ If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then ;~ MsgBox($MB_ICONERROR, StringTrimRight(@ScriptName, 4) & " Error", "toggleFirstLastPiecePrio failed!" & @CRLF & " HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 60) ;~ Exit 7 ;~ EndIf Exit 0 ; all good. EndFunc ;==>qTorr_AddSequentialViaWebUI ; --- Helper Function to URL-Encode Form Data --- Func _URLEncode($sData) Local $aArray = StringSplit($sData, ""), $sEncoded = "", $iAsc For $i = 1 To $aArray[0] $iAsc = Asc($aArray[$i]) Select Case ($iAsc >= 48 And $iAsc <= 57) Or ($iAsc >= 65 And $iAsc <= 90) Or ($iAsc >= 97 And $iAsc <= 122) $sEncoded &= $aArray[$i] Case $aArray[$i] = " " $sEncoded &= "+" Case Else $sEncoded &= "%" & Hex($iAsc, 2) EndSelect Next Return $sEncoded EndFunc ;==>_URLEncode Func _COMErrHandler($oError) EndFunc ;==>_COMErrHandler Edited September 15 by argumentum more Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted September 19 Author Posted September 19 (edited) Problem _WinAPI_ShellGetKnownFolderPath() has a bunch of GUIDs and I'd like to know what paths work/return something 🤔 Solution Get the table from MSDN and try each 🤷♂️ Do read the help file regarding $iFlags and $hToken. Spoiler expandcollapse popup#AutoIt3Wrapper_UseX64=y #include <WinAPIShellEx.au3> #include <NetShare.au3> #include <Debug.au3> Exit _knownfolderid2array() Func _knownfolderid2array() If Not FileGetSize("knownfolderid.htm") Then Local $sSource = InetRead("https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid") $sSource = BinaryToString($sSource) FileWrite("knownfolderid.htm", $sSource) EndIf Local $sHTML = FileRead("knownfolderid.htm") Local $oHTML = ObjCreate("HTMLFile") ; Parse HTML using the MSXML HTMLFile COM object If Not IsObj($oHTML) Then MsgBox(16, "oops", "Failed to create HTMLFile object.") Exit EndIf $oHTML.Open() $oHTML.Write($sHTML) $oHTML.Close() Local $oTargetTable, $oTables = $oHTML.getElementsByTagName("table") ; Locate target Constants table For $i = 0 To $oTables.length - 1 Local $sTableText = $oTables.item($i).innerText If StringInStr($sTableText, "FOLDERID_") Or StringInStr($sTableText, "Constant") Then $oTargetTable = $oTables.item($i) ExitLoop EndIf Next If Not IsObj($oTargetTable) Then Exit MsgBox(48, "oops", "Could not locate the Constants table.") Local $sCleanText, $oCells, $oRows = $oTargetTable.rows Local $sCellHTML, $iRowCount = $oRows.length Local $aConstantsData[$iRowCount][9] $aConstantsData[0][0] = "Constant Name" $aConstantsData[0][1] = "Path" $aConstantsData[0][2] = "GUID" $aConstantsData[0][3] = "Display Name" $aConstantsData[0][4] = "Folder Type" $aConstantsData[0][5] = "Default Path" $aConstantsData[0][6] = "CSIDL Equivalent" $aConstantsData[0][7] = "Legacy Display Name" $aConstantsData[0][8] = "Legacy Default Path" For $r = 1 To $iRowCount - 1 ; Populate Array and Subdivide Description Fields $oCells = $oRows.item($r).cells If $oCells.length < 2 Then ContinueLoop $aConstantsData[$r][0] = StringStripWS($oCells.item(0).innerText, 3) $sCellHTML = $oCells.item(1).innerHTML $sCellHTML = StringRegExpReplace($sCellHTML, "(?i)</?(?:p|div|tr|td|br|dt|dd)[^>]*>", @CRLF) $sCleanText = StringRegExpReplace($sCellHTML, "<[^>]+>", "") $sCleanText = StringReplace($sCleanText, " ", " ") $sCleanText = StringReplace($sCleanText, "&", "&") $sCleanText = StringReplace($sCleanText, "<", "<") $sCleanText = StringReplace($sCleanText, ">", ">") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bLegacy Display Name\b", "KEY_LEGACY_DISPLAY_NAME:") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bLegacy Default Path\b", "KEY_LEGACY_DEFAULT_PATH:") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bDisplay Name\b", "KEY_DISPLAY_NAME:") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bDefault Path\b", "KEY_DEFAULT_PATH:") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bFolder Type\b", "KEY_FOLDER_TYPE:") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bCSIDL Equivalent[s]?\b", "KEY_CSIDL:") $sCleanText = StringRegExpReplace($sCleanText, "(?i)\bGUID\b", "KEY_GUID:") $aConstantsData[$r][2] = _ExtractTagValue($sCleanText, "KEY_GUID") $aConstantsData[$r][3] = _ExtractTagValue($sCleanText, "KEY_DISPLAY_NAME") $aConstantsData[$r][4] = _ExtractTagValue($sCleanText, "KEY_FOLDER_TYPE") $aConstantsData[$r][5] = _ExtractTagValue($sCleanText, "KEY_DEFAULT_PATH") $aConstantsData[$r][6] = _ExtractTagValue($sCleanText, "KEY_CSIDL") $aConstantsData[$r][7] = _ExtractTagValue($sCleanText, "KEY_LEGACY_DISPLAY_NAME") $aConstantsData[$r][8] = _ExtractTagValue($sCleanText, "KEY_LEGACY_DEFAULT_PATH") Next For $r = 1 To UBound($aConstantsData) - 1 If $aConstantsData[$r][2] = "" Then ContinueLoop $aConstantsData[$r][1] = _WinAPI_ShellGetKnownFolderPath($aConstantsData[$r][2]) If $aConstantsData[$r][1] <> "" Then ConsoleWrite('- ' & $aConstantsData[$r][2] & @TAB & $aConstantsData[$r][1] & @CRLF) EndIf Next ;~ _DebugArrayDisplay($aConstantsData, "KnownFolderID Table", "", 0, Default, _ ;~ "Constant Name|Path|GUID|Display Name|Folder Type|Default Path|CSIDL Equivalent|Legacy Display Name|Legacy Default Path") Return $aConstantsData EndFunc ;==>_knownfolderid2array Func _ExtractTagValue($sText, $sTag) Local $sPattern = "(?is)" & $sTag & ":\s*(.*?)(?=\s*KEY_[A-Z_]+:|\z)" Local $aMatch = StringRegExp($sText, $sPattern, 1) If @error Or UBound($aMatch) = 0 Then Return "" Return StringStripWS($aMatch[0], 3) EndFunc ;==>_ExtractTagValue Edited September 23 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted September 29 Author Posted September 29 (edited) Problem 23 hours ago, TheSaint said: Take for instance, highlighting of an icon on the desktop. You can barely tell if the icon is highlighted, and quite often cannot really. Solution 23 hours ago, argumentum said: ..the icons on the desktop are in a Listview. It'd be a good project to get the selected entry and draw a frame around it 🤔 or Spoiler expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=y #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #include <WinAPI.au3> ; 1. Enable Per-Monitor V2 DPI Awareness for accurate physical pixel reporting _EnableDPIAwareness() ; WinEvent Hook Constants ;~ Global Const $EVENT_OBJECT_SELECTION = 0x8006 ;~ Global Const $EVENT_OBJECT_LOCATIONCHANGE = 0x800B ;~ Global Const $WINEVENT_OUTOFCONTEXT = 0x0000 Global $g_hWndLV = _GetDesktopListViewHandle() If Not $g_hWndLV Then MsgBox(16, 'Error', 'Cannot obtain Desktop ListView handle.', 60) Exit 4 EndIf Global $g_hEventCallback = 0, $g_pEventCallback = 0 Global $g_aBorderGUIs[1] = [0] Global $g_sLastSelectedState = "", $g_RoundCorners = True Global $g_hHook = _SetWinEventHook() If Not $g_hHook Then MsgBox(16, 'Error', 'Failed to install WinEvent hook.', 60) DllCallbackFree($g_hEventCallback) Exit 5 EndIf OnAutoItExitRegister("_OnExit") HotKeySet("{ESC}", "_ExitScript") _UpdateDesktopIconHighlights() While 1 Sleep(100) WEnd Func _ExitScript() Exit EndFunc ;==>_ExitScript Func _OnExit() If $g_hHook Then DllCall("user32.dll", "bool", "UnhookWinEvent", "handle", $g_hHook) If $g_hEventCallback Then DllCallbackFree($g_hEventCallback) _ClearBorderGUIs() EndFunc ;==>_OnExit Func _SetWinEventHook() ; Retrieve Process ID and Thread ID of Desktop Explorer Local $iPID = 0, $iThreadID = _WinAPI_GetWindowThreadProcessId($g_hWndLV, $iPID) ; Register C-style callback for WinEvents $g_hEventCallback = DllCallbackRegister("_WinEventProc", "none", "ptr;uint;hwnd;long;long;dword;dword") $g_pEventCallback = DllCallbackGetPtr($g_hEventCallback) ; Install WinEventHook targeting Explorer process Local $aHookCall = DllCall("user32.dll", "handle", "SetWinEventHook", _ "uint", $EVENT_OBJECT_SELECTION, _ "uint", $EVENT_OBJECT_LOCATIONCHANGE, _ "ptr", 0, _ "ptr", $g_pEventCallback, _ "dword", $iPID, _ "dword", $iThreadID, _ "uint", $WINEVENT_OUTOFCONTEXT) Return $aHookCall[0] EndFunc ;==>_SetWinEventHook Func _WinEventProc($hWinEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iEventThread, $iEventTime) #forceref $hWinEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iEventThread, $iEventTime _UpdateDesktopIconHighlights() EndFunc ;==>_WinEventProc Func _UpdateDesktopIconHighlights() Local $iCount = _GUICtrlListView_GetItemCount($g_hWndLV) If $iCount = 0 Then Return Local $sCurrentState = "" Local $aSelectedIndices[1] = [0] For $i = 0 To $iCount - 1 If _GUICtrlListView_GetItemSelected($g_hWndLV, $i) Then $aSelectedIndices[0] += 1 ReDim $aSelectedIndices[$aSelectedIndices[0] + 1] $aSelectedIndices[$aSelectedIndices[0]] = $i $sCurrentState &= $i & "|" EndIf Next If $sCurrentState == $g_sLastSelectedState Then Return $g_sLastSelectedState = $sCurrentState _ClearBorderGUIs() If $aSelectedIndices[0] = 0 Then Return ReDim $g_aBorderGUIs[$aSelectedIndices[0] + 1] $g_aBorderGUIs[0] = $aSelectedIndices[0] ; Retrieve Desktop DPI scale factor ;~ Local $fDPIScale = _GetWindowDPIScale($g_hWndLV) Local $fDPIScale = _WinAPI_GetDpiForMonitor_FromMousePos() Local $iX, $iY, $iW, $iH, $iBaseBorderThickness = 2 Local $iScaledThickness = Ceiling($iBaseBorderThickness * $fDPIScale) Local $aRect, $hBorderGUI For $k = 1 To $aSelectedIndices[0] #cs ; Highlight ONLY the icon graphic (1 = $LVIR_ICON) $aRect = _GUICtrlListView_GetItemRect($g_hWndLV, $aSelectedIndices[$k], 1) ; Highlight ONLY the text label (2 = $LVIR_LABEL) $aRect = _GUICtrlListView_GetItemRect($g_hWndLV, $aSelectedIndices[$k], 2) ; Highlight full item - icon + text combined (0 = $LVIR_BOUNDS - Default) $aRect = _GUICtrlListView_GetItemRect($g_hWndLV, $aSelectedIndices[$k], 0) This is useful if you want a subtle highlight around just the desktop shortcut image itself rather than extending all the way down around long multi-line file names #ce $aRect = _GUICtrlListView_GetItemRect($g_hWndLV, $aSelectedIndices[$k]) $iX = $aRect[0] $iY = $aRect[1] $iW = $aRect[2] - $aRect[0] $iH = $aRect[3] - $aRect[1] If $iW > 0 And $iH > 0 Then Switch $g_RoundCorners Case 1, True $hBorderGUI = _CreateBorderOverlay_v2($iX, $iY, $iW, $iH, 0xFF0000, $iScaledThickness, $fDPIScale) Case Else $hBorderGUI = _CreateBorderOverlay_v1($iX, $iY, $iW, $iH, 0xFF0000, $iScaledThickness, $fDPIScale) EndSwitch $g_aBorderGUIs[$k] = $hBorderGUI EndIf Next EndFunc ;==>_UpdateDesktopIconHighlights ; Creates a hollow rounded border overlay with corner rounding. Or use v1 Func _CreateBorderOverlay_v2($iX, $iY, $iW, $iH, $iColor = 0xFF0000, $iThickness = 1, $fDPIScale = 1.0, $iBaseRadius = 4) Local $hGUI = GUICreate("", $iW, $iH, $iX, $iY, BitOR($WS_CHILD, $WS_VISIBLE), BitOR($WS_EX_LAYERED, $WS_EX_TRANSPARENT), $g_hWndLV) GUISetBkColor($iColor, $hGUI) ; Set layered window opacity (255 = 100% opaque) DllCall("user32.dll", "bool", "SetLayeredWindowAttributes", "hwnd", $hGUI, "dword", 0, "byte", 255, "dword", 2) ; Subtle corner radius (3-4px base) eliminates jagged stair-stepping Local $iRadius = Round($iBaseRadius * $fDPIScale, 0) ;~ ToolTip('$fDPIScale: ' & $fDPIScale & @LF & _ ;~ '$iThickness: ' & $iThickness & @LF & _ ;~ '$iRadius: ' & $iRadius & @LF & _ ;~ '') If $iRadius > 0 Then Local $iInnerRadius = ($iRadius > $iThickness) ? ($iRadius - $iThickness) : 0 ; 1. Outer rounded boundary Local $aRgnOuter = DllCall("gdi32.dll", "handle", "CreateRoundRectRgn", "int", 0, "int", 0, "int", $iW + 1, "int", $iH + 1, "int", $iRadius * 2, "int", $iRadius * 2) Local $hRgnOuter = $aRgnOuter[0] ; 2. Inner rounded boundary (inset by $iThickness) Local $aRgnInner = DllCall("gdi32.dll", "handle", "CreateRoundRectRgn", "int", $iThickness, "int", $iThickness, "int", $iW - $iThickness + 1, "int", $iH - $iThickness + 1, "int", $iInnerRadius * 2, "int", $iInnerRadius * 2) Local $hRgnInner = $aRgnInner[0] ; 3. Subtract inner region from outer (3 = RGN_DIFF) DllCall("gdi32.dll", "int", "CombineRgn", "handle", $hRgnOuter, "handle", $hRgnOuter, "handle", $hRgnInner, "int", 3) ; 4. Apply region to window DllCall("user32.dll", "int", "SetWindowRgn", "hwnd", $hGUI, "handle", $hRgnOuter, "bool", True) _WinAPI_DeleteObject($hRgnInner) EndIf _WinAPI_SetParent($hGUI, $g_hWndLV) GUISetState(@SW_SHOWNOACTIVATE, $hGUI) Return $hGUI EndFunc ;==>_CreateBorderOverlay_v2 ; Creates a transparent border GUI scaled to DPI settings Func _CreateBorderOverlay_v1($iX, $iY, $iW, $iH, $iColor = 0xFF0000, $iThickness = 3, $fDPIScale = 1.0) #forceref $fDPIScale Local $hGUI = GUICreate("", $iW, $iH, $iX, $iY, BitOR($WS_CHILD, $WS_VISIBLE), BitOR($WS_EX_LAYERED, $WS_EX_TRANSPARENT), $g_hWndLV) Local $iTransColor = 0x00FF00FF GUISetBkColor($iTransColor, $hGUI) _WinAPI_SetLayeredWindowAttributes($hGUI, $iTransColor, 255, $LWA_COLORKEY) ; Border Edges GUICtrlCreateLabel("", 0, 0, $iW, $iThickness) GUICtrlSetBkColor(-1, $iColor) GUICtrlCreateLabel("", 0, $iH - $iThickness, $iW, $iThickness) GUICtrlSetBkColor(-1, $iColor) GUICtrlCreateLabel("", 0, 0, $iThickness, $iH) GUICtrlSetBkColor(-1, $iColor) GUICtrlCreateLabel("", $iW - $iThickness, 0, $iThickness, $iH) GUICtrlSetBkColor(-1, $iColor) _WinAPI_SetParent($hGUI, $g_hWndLV) GUISetState(@SW_SHOWNOACTIVATE, $hGUI) Return $hGUI EndFunc ;==>_CreateBorderOverlay_v1 Func _ClearBorderGUIs() If $g_aBorderGUIs[0] > 0 Then For $i = 1 To $g_aBorderGUIs[0] If IsHWnd($g_aBorderGUIs[$i]) Then GUIDelete($g_aBorderGUIs[$i]) Next $g_aBorderGUIs[0] = 0 EndIf EndFunc ;==>_ClearBorderGUIs ;~ ; Calculates screen DPI scaling ratio (100% = 1.0, 225% = 2.25) ;~ Func _GetWindowDPIScale($hWnd) ;~ Local $aRet = DllCall("User32.dll", "uint", "GetDpiForWindow", "hwnd", $hWnd) ;~ If Not @error And $aRet[0] > 0 Then Return $aRet[0] / 96.0 ;~ ; Fallback for Windows builds without GetDpiForWindow ;~ Local $hDC = _WinAPI_GetDC($hWnd) ;~ Local $iDPI = _WinAPI_GetDeviceCaps($hDC, 88) ; LOGPIXELSX = 88 ;~ _WinAPI_ReleaseDC($hWnd, $hDC) ;~ Return Round((($iDPI > 0) ? ($iDPI / 96.0) : 1.0), 0) ;~ EndFunc ;==>_GetWindowDPIScale ; Sets Per-Monitor V2 DPI awareness context (-4 = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) Func _EnableDPIAwareness() DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext", "ptr", -4) EndFunc ;==>_EnableDPIAwareness Func _GetDesktopListViewHandle() Local $hDesktop = WinGetHandle('[CLASS:Progman]') ; https://www.autoitscript.com/forum/topic/139260-autoit-snippets/page/29/#comment-1554812 Local $hLV = ControlGetHandle($hDesktop, '', '[CLASS:SysListView32;Instance:1]') If Not $hLV Then Local $hWorkerW = _WinAPI_FindWindowEx(0, 0, 'WorkerW', '') While $hWorkerW $hLV = ControlGetHandle($hWorkerW, '', '[CLASS:SysListView32;Instance:1]') If $hLV Then ExitLoop $hWorkerW = _WinAPI_FindWindowEx(0, $hWorkerW, 'WorkerW', '') WEnd EndIf Return $hLV EndFunc ;==>_GetDesktopListViewHandle Func _WinAPI_FindWindowEx($hWndParent, $hWndChildAfter, $sClass = '', $sWindow = '') Local $sTypeClass = ($sClass = '' Or $sClass = 0) ? 'ptr' : 'wstr' Local $vClass = ($sTypeClass = 'ptr') ? 0 : $sClass Local $sTypeWindow = ($sWindow = '' Or $sWindow = 0) ? 'ptr' : 'wstr' Local $vWindow = ($sTypeWindow = 'ptr') ? 0 : $sWindow Local $aRet = DllCall('user32.dll', 'hwnd', 'FindWindowExW', _ 'hwnd', $hWndParent, 'hwnd', $hWndChildAfter, _ $sTypeClass, $vClass, $sTypeWindow, $vWindow) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc ;==>_WinAPI_FindWindowEx Func _WinAPI_GetDpiForMonitor_FromMousePos() Local $tPos = _WinAPI_GetMousePos() Local $hMonitor = _WinAPI_MonitorFromPoint($tPos) Local $aDPI = _WinAPI_GetDpiForMonitor($hMonitor) Return $aDPI[0] / 96 EndFunc ;==>_WinAPI_GetDpiForMonitor_FromMousePos Func _WinAPI_GetDpiForMonitor($hMonitor, $dpiType = 0) Local $X, $Y, $aDPI[2] = [96, 96] ; https://www.autoitscript.com/forum/topic/205087-pixelgetcolor-return-value-is-not-correct-when-xy-reported-by-au3info-moved/#comment-1474583 Local $aRet = DllCall("Shcore.dll", "long", "GetDpiForMonitor", "long", $hMonitor, "int", $dpiType, "uint*", $X, "uint*", $Y) If @error Or Not IsArray($aRet) Then Return SetError(1, 0, $aDPI) Dim $aDPI[2] = [$aRet[3], $aRet[4]] Return $aDPI EndFunc ;==>_WinAPI_GetDpiForMonitor ..example only. You'd make a tray icon and menus, etc. Edited September 30 by argumentum added rounded corners TheDcoder 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted October 2 Author Posted October 2 (edited) Problem This forum has a limited set of formatting. What can I do. Solution Write it elsewhere and paste the preview here. Out of the top of my head you can use https://html5-editor.net/ or https://html-online.com/html-editor/ or even https://www.w3schools.com/html/ Spoiler Welcome To The Best Online HTML Web Editor! You can type your text directly in the editor or paste it from a Word Doc, PDF, Excel etc. The visual editor on the right and the source editor on the left are linked together and the changes are reflected in the other one as you type! Name City Age John Chicago 23 Lucy Wisconsin 19 Amanda Madison 22 This is a table you can experiment with. ..be creative Edited October 2 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted Tuesday at 10:22 PM Author Posted Tuesday at 10:22 PM (edited) Problem I code something looking like Global $thisThing = "ok" ; yes, important Global $thisOtherThing = 2 ; also important run tidy and Global $thisThing = "ok" ; yes, important Global $thisOtherThing = 2 ; also important And I love tidy but ... I'd like to keep those alignments as such Solution Run the tidy up script on this "au3align.au3" and it'll format AutoIt source code and align assignment operators and inline comments for you. Spoiler expandcollapse popup#include-once #NoTrayIcon #NoComplainIfYouDontLikeIt ; 😜 #Region ; **** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64 = y #AutoIt3Wrapper_AU3Check_Parameters = -q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ; **** Directives created by AutoIt3Wrapper_GUI **** #include <File.au3> ; #INDEX# ======================================================================================================================= ; Title .........: Au3Align ; AutoIt Version : 3.3.14.5+ ; Language ......: English ; Description ...: Formats AutoIt source code by aligning assignment operators and inline comments. ; Author(s) .....: argumentum ; =============================================================================================================================== Global Const $g_au3align_VERSION = "2026.10.08" ; #CURRENT# ===================================================================================================================== ; _au3align_Version ; _au3align_CmdLine ; _au3align_align ; _au3align_BackupSourceFile ; =============================================================================================================================== ; #INTERNAL_USE_ONLY# =========================================================================================================== ; __au3align_FlushAssignBlock ; __au3align_ParseAssignmentLine ; __au3align_FormatTokens ; __au3align_IsBlockCommentStart ; __au3align_IsBlockCommentEnd ; __au3align_GetLineEnding ; =============================================================================================================================== ; #FUNCTION# ==================================================================================================================== ; Name...........: _au3align_CmdLine ; Description ...: Main entry point when executed via command line parameters or standalone. ; Syntax.........: _au3align_CmdLine() ; Parameters ....: None ; Return values .: None ; Author ........: argumentum ; Remarks .......: Aligns file specified in $CmdLine[1] or prints formatted current script to console if run manually. ; Related .......: _au3align_align ; =============================================================================================================================== _au3align_CmdLine() Func _au3align_CmdLine() Local $sSource If $CmdLine[0] > 0 Then Local $sFilePath = $CmdLine[1] If FileExists($sFilePath) Then Local $hTimer = TimerInit() ConsoleWrite('- au3align start >' & $CmdLine[1] & '<' & @CRLF) ; Create backup prior to alignment modification ; added on v2026.10.08 Local $sBackup = _au3align_BackupSourceFile($sFilePath) If @error Then ConsoleWrite("! Backup failed with @error = " & @error & @CRLF) ConsoleWrite('! au3align aborted (' & Round(TimerDiff($hTimer), 4) & ' ms.)' & @CRLF) Return SetError(4, 0, 4) Else ConsoleWrite("+ Backup created: " & $sBackup & @CRLF) EndIf Local $iFileGetEncoding = FileGetEncoding($sSource) $iFileGetEncoding = ($iFileGetEncoding = -1 ? 0 : $iFileGetEncoding) $sSource = FileRead($sFilePath) Local $sFormatted = _au3align_align($sSource) Local $hFile = FileOpen($sFilePath, 2 + $iFileGetEncoding) ; 2 = Overwrite mode + FileGetEncoding FileWrite($hFile, $sFormatted) FileClose($hFile) Local $hWnd = WinGetHandle("[CLASS:SciTEWindow]") ; reload file trigger for SciTE4AutoIt3 If $hWnd Then ControlSend($hWnd, "", "Scintilla1", "^r") ; ..then again, is all I use. ; added on v2026.10.08 ConsoleWrite('- au3align finished (' & Round(TimerDiff($hTimer), 4) & ' ms.)' & @CRLF) EndIf Else ; Standalone testing mode if run manually $sSource = FileRead(@ScriptFullPath) ConsoleWrite(_au3align_align($sSource)) EndIf EndFunc ; ==>_au3align_CmdLine ; #FUNCTION# ==================================================================================================================== ; Name...........: _au3align_align ; Description ...: Formats AutoIt source code and aligns assignment operators and inline comments. ; Syntax.........: _au3align_align(Const $sAu3Source) ; Parameters ....: $sAu3Source - Const string containing raw AutoIt source code. ; Return values .: Success - Aligned and formatted AutoIt source string. ; Author ........: argumentum ; Related .......: __au3align_FlushAssignBlock, __au3align_ParseAssignmentLine ; =============================================================================================================================== Func _au3align_align(Const $sAu3Source) Local $sCleanSource = StringReplace($sAu3Source, @CRLF, @LF) $sCleanSource = StringReplace($sCleanSource, @CR, @LF) Local $aLines = StringSplit($sCleanSource, @LF) Local $sFormatted = "" Local $bInBlockComment = False ; Assignment block buffers Local $aBlock_Indent[1000] Local $aBlock_LHS[1000] Local $aBlock_Op[1000] Local $aBlock_RHS[1000] Local $aBlock_Comment[1000] Local $iBlockCount = 0 Local $iMaxLHSLen = 0 For $k = 1 To $aLines[0] Local $sLine = $aLines[$k] ; 1. Handle Multiline Comments (#cs / #comments-start) If $bInBlockComment Then __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) $sFormatted &= $sLine & __au3align_GetLineEnding($k, $aLines[0]) If __au3align_IsBlockCommentEnd($sLine) Then $bInBlockComment = False ContinueLoop EndIf If __au3align_IsBlockCommentStart($sLine) Then __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) $bInBlockComment = True $sFormatted &= $sLine & __au3align_GetLineEnding($k, $aLines[0]) ContinueLoop EndIf Local $sTrimmed = StringStripWS($sLine, 3) ; 2. SciTE Toggle Comments (;~) - Pass through completely untouched If StringLeft($sTrimmed, 2) = ";~" Then __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) $sFormatted &= $sLine & __au3align_GetLineEnding($k, $aLines[0]) ContinueLoop EndIf ; 3. Standard comment-only or empty lines break assignment blocks and stay untouched If $sTrimmed = "" Or StringLeft($sTrimmed, 1) = ";" Then __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) $sFormatted &= $sLine & __au3align_GetLineEnding($k, $aLines[0]) ContinueLoop EndIf ; 4. Check for Assignment Line ($LHS = $RHS ; $Comment) Local $sIndent = "", $sLHS = "", $sOp = "", $sRHS = "", $sComment = "" If __au3align_ParseAssignmentLine($sLine, $sIndent, $sLHS, $sOp, $sRHS, $sComment) Then ; Flush block if indentation level changes If $iBlockCount > 0 And $aBlock_Indent[0] <> $sIndent Then __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) EndIf $aBlock_Indent[$iBlockCount] = $sIndent ; a comment $aBlock_LHS[$iBlockCount] = $sLHS ; another comment $aBlock_Op[$iBlockCount] = $sOp ; more comments $aBlock_RHS[$iBlockCount] = $sRHS $aBlock_Comment[$iBlockCount] = $sComment ; comment $iBlockCount += 1 Local $iLHSLen = StringLen($sLHS) If $iLHSLen > $iMaxLHSLen Then $iMaxLHSLen = $iLHSLen Else ; Non-assignment line -> Flush assignment block __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) ; Directives starting with '#' pass through without token formatting If StringLeft($sTrimmed, 1) = "#" Then $sFormatted &= $sLine & __au3align_GetLineEnding($k, $aLines[0]) Else $sFormatted &= __au3align_FormatTokens($sLine) & __au3align_GetLineEnding($k, $aLines[0]) EndIf EndIf Next __au3align_FlushAssignBlock($sFormatted, $aBlock_Indent, $aBlock_LHS, $aBlock_Op, $aBlock_RHS, $aBlock_Comment, $iBlockCount, $iMaxLHSLen) Return $sFormatted EndFunc ; ==>_au3align_align ; #FUNCTION# ==================================================================================================================== ; Name...........: _au3align_BackupSourceFile ; Description ...: Creates a numbered backup (_oldN.au3) in a 'BackUp' subfolder relative to the source file. ; Syntax.........: _au3align_BackupSourceFile($sFilePath) ; Parameters ....: $sFilePath - Full path to the source file to back up. ; Return values .: Success - Returns the full path of the newly created backup file. ; Failure - Returns "" and sets @error: ; |1 - Source file does not exist. ; |2 - Failed to create 'BackUp' directory. ; |3 - FileCopy failed. ; Author ........: argumentum ; =============================================================================================================================== Func _au3align_BackupSourceFile($sFilePath) If Not FileExists($sFilePath) Then Return SetError(1, 0, "") ; Split path into drive, directory, filename, and extension Local $sDrive = "", $sDir = "", $sFileName = "", $sExt = "" _PathSplit($sFilePath, $sDrive, $sDir, $sFileName, $sExt) ; Target backup directory relative to the source file Local $sBackupDir = $sDrive & $sDir & "BackUp" ; Ensure BackUp directory exists If Not FileExists($sBackupDir) Then If Not DirCreate($sBackupDir) Then Return SetError(2, 0, "") EndIf ; Find the next available _oldN sequence index Local $iIndex = 0 Local $sBackupPath = "" Do $iIndex += 1 $sBackupPath = $sBackupDir & "\" & $sFileName & "_old" & $iIndex & $sExt Until Not FileExists($sBackupPath) If FileCopy($sFilePath, $sBackupPath, 0) Then Return $sBackupPath EndIf Return SetError(3, 0, "") EndFunc ; ==>_au3align_BackupSourceFile ; #FUNCTION# ==================================================================================================================== ; Name...........: _au3align_Version ; Description ...: Returns the current version string of Au3Align. ; Syntax.........: _au3align_Version() ; Parameters ....: None ; Return values .: String containing current version. ; Author ........: argumentum ; Related .......: _au3align_CmdLine ; =============================================================================================================================== Func _au3align_Version() Return $g_au3align_VERSION EndFunc ; ==>_au3align_Version ; #INTERNAL_FUNCTION# ==================================================================================================== ; Name...........: __au3align_FlushAssignBlock ; Description ...: Flushes buffered assignment statements and aligns their operators and comments. ; Syntax.........: __au3align_FlushAssignBlock(ByRef $sOut, ByRef $aIndent, ByRef $aLHS, ByRef $aOp, ByRef $aRHS, ByRef $aComment, ByRef $iCount, ByRef $iMaxLen) ; Parameters ....: $sOut - ByRef string to append formatted lines to. ; $aIndent - ByRef array of line indentation strings. ; $aLHS - ByRef array of left-hand side expressions. ; $aOp - ByRef array of assignment operators. ; $aRHS - ByRef array of right-hand side expressions. ; $aComment - ByRef array of inline comments. ; $iCount - ByRef integer count of stored statements. ; $iMaxLen - ByRef integer tracking max LHS length. ; Return values .: None ; Author ........: argumentum ; Remarks .......: Resets $iCount and $iMaxLen to 0 upon completion. ; =============================================================================================================================== Func __au3align_FlushAssignBlock(ByRef $sOut, ByRef $aIndent, ByRef $aLHS, ByRef $aOp, ByRef $aRHS, ByRef $aComment, ByRef $iCount, ByRef $iMaxLen) If $iCount = 0 Then Return Local $sCodeLine, $aCodeParts[$iCount] Local $iMaxCodeLen = 0 ; Pass 1: Align LHS / Op / RHS and compute maximum code length for comment positioning For $idx = 0 To $iCount - 1 Local $sL = $aLHS[$idx] Local $sR = $aRHS[$idx] Local $sOp = $aOp[$idx] Local $sInd = $aIndent[$idx] Local $iPad = $iMaxLen - StringLen($sL) Local $sPad = "" For $p = 1 To $iPad $sPad &= " " Next $sCodeLine = "" If $sR <> "" Then $sCodeLine = $sInd & $sL & $sPad & " " & $sOp & " " & $sR Else $sCodeLine = $sInd & $sL & $sPad & " " & $sOp EndIf $aCodeParts[$idx] = $sCodeLine If $aComment[$idx] <> "" Then Local $iCodeLen = StringLen($sCodeLine) If $iCodeLen > $iMaxCodeLen Then $iMaxCodeLen = $iCodeLen EndIf Next ; Pass 2: Append comments aligned to the maximum code length column For $idx = 0 To $iCount - 1 $sCodeLine = $aCodeParts[$idx] Local $sCmt = $aComment[$idx] If $sCmt <> "" Then Local $iPadComment = $iMaxCodeLen - StringLen($sCodeLine) Local $sCommentPad = "" For $p = 1 To $iPadComment $sCommentPad &= " " Next $sOut &= $sCodeLine & $sCommentPad & " " & $sCmt & @CRLF Else $sOut &= $sCodeLine & @CRLF EndIf Next $iCount = 0 $iMaxLen = 0 EndFunc ; ==>__au3align_FlushAssignBlock ; #INTERNAL_FUNCTION# ==================================================================================================== ; Name...........: __au3align_ParseAssignmentLine ; Description ...: Parses a line to determine if it is a valid assignment statement and extracts components. ; Syntax.........: __au3align_ParseAssignmentLine($sLine, ByRef $sIndent, ByRef $sLHS, ByRef $sOp, ByRef $sRHS, ByRef $sComment) ; Parameters ....: $sLine - Raw source line string. ; $sIndent - ByRef string receiving indentation. ; $sLHS - ByRef string receiving formatted left-hand side. ; $sOp - ByRef string receiving assignment operator. ; $sRHS - ByRef string receiving formatted right-hand side. ; $sComment - ByRef string receiving inline comment. ; Return values .: True if line is a valid top-level assignment or contains comment, False otherwise. ; Author ........: AutoIt Community ; =============================================================================================================================== Func __au3align_ParseAssignmentLine($sLine, ByRef $sIndent, ByRef $sLHS, ByRef $sOp, ByRef $sRHS, ByRef $sComment) Local $c, $iLen = StringLen($sLine) Local $iNonWS = 1 While $iNonWS <= $iLen And (StringMid($sLine, $iNonWS, 1) = " " Or StringMid($sLine, $iNonWS, 1) = @TAB) $iNonWS += 1 WEnd $sIndent = StringLeft($sLine, $iNonWS - 1) Local $sTrimmed = StringMid($sLine, $iNonWS) ; Ignore lines starting with control-flow keywords Local $aReserved[21] = ["if", "elseif", "else", "while", "wend", "until", "do", "for", "next", "select", "case", "switch", "endswitch", "return", "func", "endfunc", "with", "endwith", "exitloop", "continueloop", "redim"] Local $sFirstWord = StringLower(StringRegExpReplace($sTrimmed, "[\s\(].*", "")) For $r In $aReserved If $sFirstWord = $r Then Return False Next Local $bInSQ = False, $bInDQ = False Local $iCommentPos = 0 ; Separate code from inline comment (first ';' outside quotes) Local $iTrimLen = StringLen($sTrimmed) For $i = 1 To $iTrimLen $c = StringMid($sTrimmed, $i, 1) If $c = '"' And Not $bInSQ Then $bInDQ = Not $bInDQ ContinueLoop ElseIf $c = "'" And Not $bInDQ Then $bInSQ = Not $bInSQ ContinueLoop EndIf If Not $bInSQ And Not $bInDQ And $c = ";" Then $iCommentPos = $i ExitLoop EndIf Next Local $sCodePart = $sTrimmed $sComment = "" If $iCommentPos > 0 Then $sCodePart = StringLeft($sTrimmed, $iCommentPos - 1) Local $sRawComment = StringMid($sTrimmed, $iCommentPos) $sComment = StringStripWS($sRawComment, 2) ; Preserve exact comment string (including ;~) EndIf Local $bIsDirective = (StringLeft($sTrimmed, 1) = "#") ; --- Check for multi-variable lines (containing top-level commas) --- Local $iParenDepth = 0, $iBracketDepth = 0 Local $iCodeLen = StringLen($sCodePart) Local $bHasTopLevelComma = False $bInSQ = False $bInDQ = False For $i = 1 To $iCodeLen $c = StringMid($sCodePart, $i, 1) If $c = '"' And Not $bInSQ Then $bInDQ = Not $bInDQ ElseIf $c = "'" And Not $bInDQ Then $bInSQ = Not $bInSQ ElseIf Not $bInSQ And Not $bInDQ Then If $c = "(" Then $iParenDepth += 1 ElseIf $c = ")" Then If $iParenDepth > 0 Then $iParenDepth -= 1 ElseIf $c = "[" Then $iBracketDepth += 1 ElseIf $c = "]" Then If $iBracketDepth > 0 Then $iBracketDepth -= 1 ElseIf $iParenDepth = 0 And $iBracketDepth = 0 And $c = "," Then $bHasTopLevelComma = True ExitLoop EndIf EndIf Next ; If multi-variable declaration, skip '=' alignment but keep in block for comment alignment If $bHasTopLevelComma Then If $bIsDirective Then $sLHS = $sCodePart Else $sLHS = __au3align_FormatTokens($sCodePart) EndIf $sOp = "" $sRHS = "" Return True EndIf ; Parse $sCodePart for assignment operator Local $iOpPos = 0, $iOpLen = 1 Local $sFoundOp = "" $iParenDepth = 0 $iBracketDepth = 0 $bInSQ = False $bInDQ = False For $i = 1 To $iCodeLen $c = StringMid($sCodePart, $i, 1) If $c = '"' And Not $bInSQ Then $bInDQ = Not $bInDQ ContinueLoop ElseIf $c = "'" And Not $bInDQ Then $bInSQ = Not $bInSQ ContinueLoop EndIf If $bInSQ Or $bInDQ Then ContinueLoop If $c = "(" Then $iParenDepth += 1 ElseIf $c = ")" Then If $iParenDepth > 0 Then $iParenDepth -= 1 ElseIf $c = "[" Then $iBracketDepth += 1 ElseIf $c = "]" Then If $iBracketDepth > 0 Then $iBracketDepth -= 1 EndIf If $iParenDepth = 0 And $iBracketDepth = 0 Then Local $two = StringMid($sCodePart, $i, 2) If $two = "+=" Or $two = "-=" Or $two = "*=" Or $two = "/=" Or $two = "&=" Or $two = "^=" Then $iOpPos = $i $iOpLen = 2 $sFoundOp = $two ExitLoop ElseIf $two = "==" Or $two = "<=" Or $two = ">=" Or $two = "<>" Then $i += 1 ContinueLoop ElseIf $c = "=" Then $iOpPos = $i $iOpLen = 1 $sFoundOp = "=" ExitLoop EndIf EndIf Next If $iOpPos = 0 Then Return False If $bIsDirective Then $sLHS = StringStripWS(StringLeft($sCodePart, $iOpPos - 1), 3) $sOp = $sFoundOp $sRHS = StringStripWS(StringMid($sCodePart, $iOpPos + $iOpLen), 3) Else $sLHS = __au3align_FormatTokens(StringStripWS(StringLeft($sCodePart, $iOpPos - 1), 3)) $sOp = $sFoundOp $sRHS = __au3align_FormatTokens(StringStripWS(StringMid($sCodePart, $iOpPos + $iOpLen), 3)) EndIf Return True EndFunc ; ==>__au3align_ParseAssignmentLine ; #INTERNAL_FUNCTION# ==================================================================================================== ; Name...........: __au3align_FormatTokens ; Description ...: Formats expression tokens with standardized spacing around operators, commas, and comments. ; Syntax.........: __au3align_FormatTokens($sCode) ; Parameters ....: $sCode - Raw expression code string. ; Return values .: Formatted expression string. ; Author ........: argumentum ; =============================================================================================================================== Func __au3align_FormatTokens($sCode) If $sCode = "" Then Return "" Local $sPrev, $iLen = StringLen($sCode) Local $sOut = "" Local $bInSQ = False, $bInDQ = False Local $i = 1 While $i <= $iLen Local $c = StringMid($sCode, $i, 1) If $c = '"' And Not $bInSQ Then $bInDQ = Not $bInDQ $sOut &= $c $i += 1 ContinueLoop ElseIf $c = "'" And Not $bInDQ Then $bInSQ = Not $bInSQ $sOut &= $c $i += 1 ContinueLoop EndIf If $bInSQ Or $bInDQ Then $sOut &= $c $i += 1 ContinueLoop EndIf If $c = ";" Then ; If inline comment starts with ;~, keep it intact If StringMid($sCode, $i, 2) = ";~" Then $sOut &= StringMid($sCode, $i) ExitLoop EndIf $sPrev = StringRight($sOut, 1) If $sPrev <> "" And $sPrev <> " " And $sPrev <> @TAB Then $sOut &= " " $sOut &= ";" $i += 1 While $i <= $iLen And StringMid($sCode, $i, 1) = " " $i += 1 WEnd If $i <= $iLen Then $sOut &= " " While $i <= $iLen $sOut &= StringMid($sCode, $i, 1) $i += 1 WEnd ExitLoop EndIf If $c = "," Then While StringRight($sOut, 1) = " " $sOut = StringTrimRight($sOut, 1) WEnd $sOut &= ", " $i += 1 While $i <= $iLen And StringMid($sCode, $i, 1) = " " $i += 1 WEnd ContinueLoop EndIf If StringInStr("+-*/^&?:", $c) > 0 Then Local $two = StringMid($sCode, $i, 2) If $two = "==" Or $two = "<=" Or $two = ">=" Or $two = "<>" Or _ $two = "+=" Or $two = "-=" Or $two = "*=" Or $two = "/=" Or $two = "&=" Or $two = "^=" Then $sPrev = StringRight($sOut, 1) If $sPrev <> "" And $sPrev <> " " And $sPrev <> "(" And $sPrev <> "[" Then $sOut &= " " $sOut &= $two & " " $i += 2 While $i <= $iLen And StringMid($sCode, $i, 1) = " " $i += 1 WEnd ContinueLoop EndIf Local $bIsUnary = False If $c = "-" Or $c = "+" Then Local $sTrimmedPrev = StringStripWS($sOut, 2) Local $sLast = StringRight($sTrimmedPrev, 1) If $sLast = "" Or StringInStr("(=+-*/^&<>,:?[", $sLast) > 0 Then $bIsUnary = True Else Local $sLastWord = StringLower(StringRegExpReplace($sTrimmedPrev, "^.*?\b(\w+)$", "$1")) If StringInStr("|return|to|step|and|or|not|then|else|case|with|in|by|", "|" & $sLastWord & "|") > 0 Then $bIsUnary = True EndIf EndIf EndIf If $bIsUnary Then $sOut &= $c $i += 1 ContinueLoop EndIf $sPrev = StringRight($sOut, 1) If $sPrev <> "" And $sPrev <> " " Then $sOut &= " " $sOut &= $c & " " $i += 1 While $i <= $iLen And StringMid($sCode, $i, 1) = " " $i += 1 WEnd ContinueLoop EndIf If $c = "(" Or $c = "[" Then $sOut &= $c $i += 1 While $i <= $iLen And StringMid($sCode, $i, 1) = " " $i += 1 WEnd ContinueLoop ElseIf $c = ")" Or $c = "]" Then While StringRight($sOut, 1) = " " $sOut = StringTrimRight($sOut, 1) WEnd $sOut &= $c $i += 1 ContinueLoop EndIf If $c = " " Then If StringRight($sOut, 1) <> " " And StringRight($sOut, 1) <> "" Then $sOut &= " " EndIf $i += 1 ContinueLoop EndIf $sOut &= $c $i += 1 WEnd Return $sOut EndFunc ; ==>__au3align_FormatTokens ; #INTERNAL_FUNCTION# ==================================================================================================== ; Name...........: __au3align_IsBlockCommentStart ; Description ...: Checks if a line initiates a multi-line block comment (#cs / #comments-start). ; Syntax.........: __au3align_IsBlockCommentStart($sLine) ; Parameters ....: $sLine - Line string to evaluate. ; Return values .: True if line starts a block comment, False otherwise. ; Author ........: argumentum ; =============================================================================================================================== Func __au3align_IsBlockCommentStart($sLine) Local $sT = StringStripWS($sLine, 3) Return (StringLeft($sT, 3) = "#cs" Or StringLeft($sT, 15) = "#comments-start") EndFunc ; ==>__au3align_IsBlockCommentStart ; #INTERNAL_FUNCTION# ==================================================================================================== ; Name...........: __au3align_IsBlockCommentEnd ; Description ...: Checks if a line terminates a multi-line block comment (#ce / #comments-end). ; Syntax.........: __au3align_IsBlockCommentEnd($sLine) ; Parameters ....: $sLine - Line string to evaluate. ; Return values .: True if line ends a block comment, False otherwise. ; Author ........: argumentum ; =============================================================================================================================== Func __au3align_IsBlockCommentEnd($sLine) Local $sT = StringStripWS($sLine, 3) Return (StringLeft($sT, 3) = "#ce" Or StringLeft($sT, 13) = "#comments-end") EndFunc ; ==>__au3align_IsBlockCommentEnd ; #INTERNAL_FUNCTION# ==================================================================================================== ; Name...........: __au3align_GetLineEnding ; Description ...: Determines line termination character based on current position in total lines. ; Syntax.........: __au3align_GetLineEnding($iCurrentIndex, $iTotalLines) ; Parameters ....: $iCurrentIndex - 1-based index of current line. ; $iTotalLines - Total number of lines. ; Return values .: @CRLF if not on last line, empty string otherwise. ; Author ........: argumentum ; =============================================================================================================================== Func __au3align_GetLineEnding($iCurrentIndex, $iTotalLines) If $iCurrentIndex < $iTotalLines Then Return @CRLF Return "" EndFunc ; ==>__au3align_GetLineEnding ..could also be added to SciTE Spoiler 1.Open SciTEUser.properties:Access your personal SciTE configuration. In SciTE, open your user settings file by navigating to: Options $\rightarrow$ Open SciTEUser.properties (or press Ctrl+Shift+U). 2.Add the Tool Configuration:Define the menu item, path, and shortcut key. Paste the following configuration at the end of your SciTEUser.properties file. Replace C:\Path\To\Au3Align.au3 with the actual full path to where you saved the AutoIt aligner script: Properties # Custom Tool: AutoIt Code Aligner # Use an unused slot number (slots 36–50 are typically free for user tools) command.name.36.$(au3)=Align Code command.36.$(au3)="$(AutoIt3Dir)\AutoIt3.exe" "C:\Path\To\Au3Align.au3" "$(FilePath)" command.shortcut.36.$(au3)=Ctrl+Shift+A command.mode.36.$(au3)=subsystem:4,savebefore:yes 3.Save and Test the Shortcut:Run the tool on an open AutoIt file. Save SciTEUser.properties (Ctrl+S). Open any .au3 script in SciTE. Press Ctrl+Shift+A (or select Tools $\rightarrow$ Align Code from the top menu). SciTE will automatically save the active file, run Au3Align.au3 against it, and reload the newly aligned code on disk. Configuration Breakdown command.name.36.$(au3): Registers the tool under SciTE's Tools menu for .au3 files. command.36.$(au3): Executes AutoIt3.exe using SciTE's internal variable $(AutoIt3Dir), passing the target script path and $(FilePath) as $CmdLine[1]. command.shortcut.36.$(au3): Sets the keybinding (Ctrl+Shift+A). You can change this to any preferred key combination. command.mode.36.$(au3)=subsystem:4,savebefore:yes: Saves open edits to disk prior to running the script so the aligner reads the latest changes. Note: ..testing in SciTE v5.5.6 ( Jun 5 2025 10:01:05 ) the block that worked ( on \AutoIt3\SciTE\Properties\au3.properties ) was: # Custom Tool: AutoIt Code Aligner # Use an unused slot number (slots 36–50 are typically free for user tools) command.36.$(au3)=$(SciteDefaultHome)\..\Autoit3_x64.exe "$(SciteDefaultHome)\Au3Align\Au3Align.au3" "$(FilePath)" command.name.36.$(au3)=Align Code command.subsystem.36.$(au3)=0 command.save.before.36.$(au3)=1 command.shortcut.36.$(au3)=Ctrl+Shift+A so be careful with what you do ..or other tweaks Edited yesterday at 12:26 AM by argumentum new version "2026.10.08" ioa747 and WildByDesign 2 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted 20 hours ago Author Posted 20 hours ago (edited) Problem Need to make a function for a small file on disk or clipboard that I can edit in a function, to customize said file in the script. Solution Use this code. Ain't much but should be sufficient for common small files . Spoiler ;~ clip2Str2Func() Func clip2Str2Func() ;~ Local $sStr = Str2Func(FileRead( @ScriptFullPath )) Local $sStr = Str2Func(ClipGet()) ConsoleWrite(@CRLF & $sStr & @CRLF) ClipPut($sStr) EndFunc ;==>clip2Str2Func Func Str2Func($sStr) Local $sRet = 'Func _TODO_ChangeFuncName()' & @CRLF & @TAB & 'Local $sStr = "" & @CRLF' & @CRLF Local $aArray = StringSplit($sStr, @CRLF, 1) For $n = 1 To $aArray[0] $sRet &= @TAB & '$sStr &= "' & StringReplace($aArray[$n], '"', '""') & '" & @CRLF' & @CRLF Next $sRet &= @TAB & "Return $sStr" & @CRLF & "EndFunc" & @CRLF Return $sRet EndFunc ;==>Str2Func Edited 19 hours ago by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted 12 hours ago Author Posted 12 hours ago (edited) Problem Am using a GitHub repo as an image holder. But is a pain to do by hand as the count of images in that path increase 😱 Solution Use this code to upload the image and get the "raw" link to use in the forum. Version 1 ( only file upload ) Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Constants.au3> #include <MsgBoxConstants.au3> ; --- CONFIGURATION --- Global Const $sToken = "YOUR_GITHUB_PAT_HERE" ; GitHub Personal Access Token (repo scope) Global Const $sOwner = "YourGitHubUsername" ; Your GitHub username or organization Global Const $sRepo = "YourRepositoryName" ; Your repository name Global Const $sBranch = "main" ; Branch name (main or master) Global Const $sTargetDir = "images/" ; Folder path inside your repo (trailing slash required) ; --------------------- Exit main() Func main() ; 1. Select image file via standard File Open Dialog Local $sFilePath = FileOpenDialog("Select Image to Upload", @ScriptDir, "Images (*.png;*.jpg;*.jpeg;*.gif;*.webp)", $FD_FILEMUSTEXIST) If @error Then Exit ; Extract filename and construct repository path Local $sFileName = StringRegExpReplace($sFilePath, "^.*\\", "") Local $sRepoPath = $sTargetDir & $sFileName ; 2. Read file as binary and encode to Base64 Local $sBase64 = _FileToBase64($sFilePath) If $sBase64 = "" Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to read or encode the image file.") Exit EndIf ; 3. Construct JSON Payload ; Note: If the file already exists in the repo, the GitHub API requires the existing file's "sha" key ; to update it. For simple write-once uploads, this payload is sufficient. Local $sJson = '{"message": "Upload ' & $sFileName & ' via AutoIt automation", "content": "' & $sBase64 & '", "branch": "' & $sBranch & '"}' ; 4. Send PUT request to GitHub Contents API Local $sUrl = "https://api.github.com/repos/" & $sOwner & "/" & $sRepo & "/contents/" & $sRepoPath Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") $oHTTP.Open("PUT", $sUrl, False) $oHTTP.SetRequestHeader("Authorization", "Bearer " & $sToken) $oHTTP.SetRequestHeader("Accept", "application/vnd.github+json") $oHTTP.SetRequestHeader("User-Agent", "AutoIt-GitHubUploader") $oHTTP.SetRequestHeader("Content-Type", "application/json") $oHTTP.Send($sJson) ; 5. Handle Response & Copy Raw Link If $oHTTP.Status = 201 Or $oHTTP.Status = 200 Then ; Construct raw content URL Local $sRawUrl = "https://raw.githubusercontent.com/" & $sOwner & "/" & $sRepo & "/" & $sBranch & "/" & $sRepoPath ClipPut($sRawUrl) ConsoleWrite(@CRLF & $sRawUrl & @CRLF & @CRLF) MsgBox($MB_SYSTEMMODAL, "Success!", "Image uploaded successfully!" & @CRLF & @CRLF & "Raw URL copied to clipboard:" & @CRLF & $sRawUrl) Else MsgBox($MB_SYSTEMMODAL, "Upload Failed (HTTP " & $oHTTP.Status & ")", $oHTTP.ResponseText) EndIf EndFunc ;==>main ; --- Helper Function: Base64 Encoding via MSXML --- Func _FileToBase64($sPath) Local $hFile = FileOpen($sPath, $FO_BINARY) If $hFile = -1 Then Return "" Local $bData = FileRead($hFile) FileClose($hFile) Local $oXML = ObjCreate("MSXML2.DOMDocument") If Not IsObj($oXML) Then Return "" Local $oNode = $oXML.createElement("b64") $oNode.dataType = "bin.base64" $oNode.nodeTypedValue = $bData ; Strip all whitespace / line breaks inserted by MSXML Return StringRegExpReplace($oNode.text, "\s+", "") EndFunc v2026.10.09 Version 2 ( If there's an image in the clipboard will upload that, else, will ask to select a file ) Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64 = y #AutoIt3Wrapper_AU3Check_Parameters = -q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Constants.au3> #include <MsgBoxConstants.au3> #include <Clipboard.au3> #include <GDIPlus.au3> #include <WinAPI.au3> ; --- CONFIGURATION --- Global Const $sToken = "YOUR_GITHUB_PAT_HERE" ; GitHub Personal Access Token Global Const $sOwner = "YourGitHubUsername" ; Your GitHub username Global Const $sRepo = "YourRepositoryName" ; Your repository name Global Const $sBranch = "main" ; Branch name (main or master) Global Const $sTargetDir = "images/" ; Folder path inside your repo ; --------------------- Exit main() Func main() ; 1. Check if an image/bitmap is in the clipboard Local $sFileName, $sFilePath = "" _ClipBoard_Open(0) Local $hBitmap = _ClipBoard_GetDataEx($CF_BITMAP) _ClipBoard_Close() If $hBitmap Then ; Extract clipboard bitmap using GDI+ and save to a temporary PNG file _GDIPlus_Startup() Local $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) $sFileName = "snap_" & @YEAR & @MON & @MDAY & "_" & @HOUR & @MIN & @SEC & ".png" $sFilePath = @TempDir & "\" & $sFileName _GDIPlus_ImageSaveToFile($hImage, $sFilePath) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() _WinAPI_DeleteObject($hBitmap) Else ; Fallback: Open File Dialog if no image is in the clipboard $sFilePath = FileOpenDialog("Select Image to Upload", @ScriptDir, "Images (*.png;*.jpg;*.jpeg;*.gif;*.webp)", $FD_FILEMUSTEXIST) If @error Then Exit $sFileName = StringRegExpReplace($sFilePath, "^.*\\", "") EndIf ; Extract filename and construct repository path $sFileName = StringRegExpReplace($sFilePath, "^.*\\", "") Local $sRepoPath = $sTargetDir & $sFileName ; 2. Read file as binary and encode to Base64 Local $sBase64 = _FileToBase64($sFilePath) If $sBase64 = "" Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to read or encode the image file.") Exit EndIf ; 3. Construct JSON Payload Local $sJson = '{"message": "Upload ' & $sFileName & ' via AutoIt automation", "content": "' & $sBase64 & '", "branch": "' & $sBranch & '"}' ; 4. Send PUT request to GitHub Contents API Local $sUrl = "https://api.github.com/repos/" & $sOwner & "/" & $sRepo & "/contents/" & $sRepoPath Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") $oHTTP.Open("PUT", $sUrl, False) $oHTTP.SetRequestHeader("Authorization", "Bearer " & $sToken) $oHTTP.SetRequestHeader("Accept", "application/vnd.github+json") $oHTTP.SetRequestHeader("User-Agent", "AutoIt-GitHubUploader") $oHTTP.SetRequestHeader("Content-Type", "application/json") $oHTTP.Send($sJson) ; 5. Handle Response & Copy Raw Link If $oHTTP.Status = 201 Or $oHTTP.Status = 200 Then Local $sRawUrl = "https://raw.githubusercontent.com/" & $sOwner & "/" & $sRepo & "/" & $sBranch & "/" & $sRepoPath ClipPut($sRawUrl) MsgBox($MB_SYSTEMMODAL, "Success!", "Image uploaded successfully!" & @CRLF & @CRLF & "Raw URL copied to clipboard:" & @CRLF & $sRawUrl) Else MsgBox($MB_SYSTEMMODAL, "Upload Failed (HTTP " & $oHTTP.Status & ")", $oHTTP.ResponseText) EndIf EndFunc ;==>main ; --- Helper Function: Base64 Encoding via MSXML --- Func _FileToBase64($sPath) Local $hFile = FileOpen($sPath, $FO_BINARY) If $hFile = -1 Then Return "" Local $bData = FileRead($hFile) FileClose($hFile) Local $oXML = ObjCreate("MSXML2.DOMDocument") If Not IsObj($oXML) Then Return "" Local $oNode = $oXML.createElement("b64") $oNode.dataType = "bin.base64" $oNode.nodeTypedValue = $bData Return StringRegExpReplace($oNode.text, "\s+", "") EndFunc ;==>_FileToBase64 Version 3 ( same as version 2 but with a preview GUI to accept or cancel the image upload ) ..and an icon for it: Spoiler expandcollapse popup#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64 = y #AutoIt3Wrapper_AU3Check_Parameters = -q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Constants.au3> #include <MsgBoxConstants.au3> #include <Clipboard.au3> #include <GDIPlus.au3> #include <WinAPI.au3> #include <GUIConstantsEx.au3> #include <SendMessage.au3> ; --- CONFIGURATION --- Global Const $sToken = "YOUR_GITHUB_PAT_HERE" ; GitHub Personal Access Token Global Const $sOwner = "YourGitHubUsername" ; Your GitHub username Global Const $sRepo = "YourRepositoryName" ; Your repository name Global Const $sBranch = "main" ; Branch name (main or master) Global Const $sTargetDir = "images/" ; Folder path inside your repo ; --------------------- ; --- PREVIEW WINDOW DIMENSIONS --- Global Const $iMaxPreviewW = 640 Global Const $iMaxPreviewH = 480 Exit main() Func main() ; https://www.autoitscript.com/forum/topic/213874-solved-help-for-argumentum/#findComment-1555185 ; 1. Check if an image/bitmap is in the clipboard Local $sFilePath = "", $sFileName = "", $sTimestamp = @YEAR & @MON & @MDAY & "_" & @HOUR & @MIN & @SEC _ClipBoard_Open(0) Local $hBitmap = _ClipBoard_GetDataEx($CF_BITMAP) _ClipBoard_Close() If $hBitmap Then ; Extract clipboard bitmap using GDI+ and save to a temporary PNG file _GDIPlus_Startup() Local $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) $sFileName = "snap_" & $sTimestamp & ".png" $sFilePath = @TempDir & "\" & $sFileName _GDIPlus_ImageSaveToFile($hImage, $sFilePath) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() _WinAPI_DeleteObject($hBitmap) Else ; Fallback: Open File Dialog if no image is in the clipboard $sFilePath = FileOpenDialog("GitHub Image Uploader - Select Image to Upload", "{374DE290-123F-4565-9164-39C4925E467B}", "Images (*.png;*.jpg;*.jpeg;*.gif;*.webp)", $FD_FILEMUSTEXIST) If @error Then Exit 5 $sFileName = StringRegExpReplace($sFilePath, "^.*\\", "") EndIf ; 2. Show Preview GUI & Ask for Confirmation (Passing max dimensions) If Not _ConfirmImageUpload($sFilePath, $sFileName, $iMaxPreviewW, $iMaxPreviewH) Then ; Clean up temp file if canceled If StringInStr($sFilePath, @TempDir) And FileExists($sFilePath) Then FileDelete($sFilePath) Exit 4 EndIf ; 3. Construct repository path Local $sRepoPath = $sTargetDir & $sFileName ; 4. Read file as binary and encode to Base64 Local $sBase64 = _FileToBase64($sFilePath) ; Clean up temp file after reading If StringInStr($sFilePath, @TempDir) And FileExists($sFilePath) Then FileDelete($sFilePath) If $sBase64 = "" Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to read or encode the image file.") Exit 6 EndIf ; 5. Construct JSON Payload Local $sJson = '{"message": "Upload ' & $sFileName & ' via AutoIt automation", "content": "' & $sBase64 & '", "branch": "' & $sBranch & '"}' ; 6. Send PUT request to GitHub Contents API Local $sUrl = "https://api.github.com/repos/" & $sOwner & "/" & $sRepo & "/contents/" & $sRepoPath Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") $oHTTP.Open("PUT", $sUrl, False) $oHTTP.SetRequestHeader("Authorization", "Bearer " & $sToken) $oHTTP.SetRequestHeader("Accept", "application/vnd.github+json") $oHTTP.SetRequestHeader("User-Agent", "AutoIt-GitHubUploader") $oHTTP.SetRequestHeader("Content-Type", "application/json") $oHTTP.Send($sJson) ; 7. Handle Response & Copy Raw Link If $oHTTP.Status = 201 Or $oHTTP.Status = 200 Then Local $sRawUrl = "https://raw.githubusercontent.com/" & $sOwner & "/" & $sRepo & "/" & $sBranch & "/" & $sRepoPath ClipPut($sRawUrl) FileWriteLine(StringTrimRight(@ScriptFullPath, 4) & ".log", $sTimestamp & ' | ' & $sFilePath & ' | ' & $sRawUrl & @CRLF) MsgBox($MB_SYSTEMMODAL, "Success!", "Image uploaded successfully!" & @CRLF & @CRLF & "Raw URL copied to clipboard:" & @CRLF & $sRawUrl) Else MsgBox($MB_SYSTEMMODAL, "Upload Failed (HTTP " & $oHTTP.Status & ")", $oHTTP.ResponseText) EndIf EndFunc ;==>main ; --- GUI Preview Function --- Func _ConfirmImageUpload($sImagePath, $sName, $iMaxWidth, $iMaxHeight, $iMinWidth = 300) _GDIPlus_Startup() Local $hImage = _GDIPlus_ImageLoadFromFile($sImagePath) Local $iOriginalW = _GDIPlus_ImageGetWidth($hImage) Local $iOriginalH = _GDIPlus_ImageGetHeight($hImage) ; Calculate aspect ratio Local $fRatio = $iOriginalW / $iOriginalH Local $iNewW = $iOriginalW Local $iNewH = $iOriginalH ; Resize logic: Determine which dimension exceeds limits If $iOriginalW > $iMaxWidth Or $iOriginalH > $iMaxHeight Then If $fRatio > 1 Then ; Wide image $iNewW = $iMaxWidth $iNewH = $iMaxWidth / $fRatio Else ; Tall or square image $iNewH = $iMaxHeight $iNewW = $iMaxHeight * $fRatio EndIf EndIf ; Create scaled HBITMAP in memory Local $hResizedBmp = _GDIPlus_BitmapCreateFromGraphics($iNewW, $iNewH, _GDIPlus_GraphicsCreateFromHWND(0)) Local $hGfx = _GDIPlus_ImageGetGraphicsContext($hResizedBmp) _GDIPlus_GraphicsSetInterpolationMode($hGfx, 7) ; HighQualityBicubic _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage, 0, 0, $iNewW, $iNewH) Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hResizedBmp) ; Clean up GDI+ objects _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_BitmapDispose($hResizedBmp) _GDIPlus_ImageDispose($hImage) _GDIPlus_Shutdown() ; Create GUI (Centered, slightly larger than max preview for padding) Local $iGuiW = $iNewW + 40 Local $iGuiH = $iNewH + 100 Local $hGUI = GUICreate("GitHub Image Uploader - Confirm Image (Preview)", ($iGuiW < $iMinWidth ? $iMinWidth : $iGuiW), $iGuiH, -1, -1) GUISetIcon(StringTrimRight(@ScriptFullPath, 4) & ".ico") GUISetBkColor(0x333333) ; Create picture control using the scaled HBITMAP Local $idPic = GUICtrlCreatePic("", 20, 20, $iNewW, $iNewH) _SendMessage(GUICtrlGetHandle($idPic), 0x0172, 0, $hHBitmap) ; STM_SETIMAGE _WinAPI_DeleteObject($hHBitmap) $iNewW = ($iNewW < $iMinWidth ? $iMinWidth - 40 : $iNewW) ; UI Elements GUICtrlCreateLabel("File: " & $sName, 20, $iNewH + 30, $iNewW, 20) GUICtrlSetColor(-1, 0xEEEEEE) Local $idBtnCancel = GUICtrlCreateButton("&Cancel", ($iNewW / 2) + 30, $iNewH + 60, ($iNewW / 2) - 5, 35) GUICtrlSetColor(-1, 0xEEEEEE) GUICtrlSetBkColor(-1, 0x222222) Local $idBtnUpload = GUICtrlCreateButton("&Upload to GitHub", 20, $iNewH + 60, ($iNewW / 2) - 5, 35) GUICtrlSetColor(-1, 0xEEEEEE) GUICtrlSetBkColor(-1, 0x222222) GUISetState(@SW_SHOW, $hGUI) Local $bConfirmed = False While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $idBtnCancel ExitLoop Case $idBtnUpload $bConfirmed = True ExitLoop EndSwitch WEnd GUIDelete($hGUI) Return $bConfirmed EndFunc ;==>_ConfirmImageUpload ; --- Helper Function: Base64 Encoding via MSXML --- Func _FileToBase64($sPath) Local $hFile = FileOpen($sPath, $FO_BINARY) If $hFile = -1 Then Return "" Local $bData = FileRead($hFile) FileClose($hFile) Local $oXML = ObjCreate("MSXML2.DOMDocument") If Not IsObj($oXML) Then Return "" Local $oNode = $oXML.createElement("b64") $oNode.dataType = "bin.base64" $oNode.nodeTypedValue = $bData Return StringRegExpReplace($oNode.text, "\s+", "") EndFunc ;==>_FileToBase64 update: 2026.10.09 To get the GitHub PAT ( Personal Access Token ): Go to Settings > Developer Settings > Personal Access Tokens. Get a "Fine-Grained Token". Set the Repository access to "Only select repositories" and select the repo to use. In Repository permissions > Contents: Set to "Read and write" (this gives the API permission to create and push new image files to your repo). Once you set that, scroll down, click Generate token, and paste the string into the script at YOUR_GITHUB_PAT_HERE. Enjoy Edited 8 hours ago by argumentum better TheDcoder and ioa747 2 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted 5 hours ago Author Posted 5 hours ago (edited) Problem To add a script to the Start menu, I need a shortcut of my script. Solution Run this script. It'll copy it's own shortcut to the SendTo folder. When you want to make a shortcut for your script, select it and SendTo > "AutoIt3ScriptCreateLink - shortcut" ( or however you name it ) in explorer, and that will create a shortcut to your script and using your icon if the name is the same that of the script. Spoiler #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <WinAPIShellEx.au3> #include <WinAPISys.au3> Exit main() Func main() Local $sAutoItExe = _GetPath(@AutoItExe) & '\autoit3_x64.exe' ; choose the exe Local $sAutoItIcon = _GetPath(@AutoItExe) & '\Icons\au3.ico' ; choose the default icon Local $sIco, $sSelfLnk = StringTrimRight(@ScriptFullPath, 4) & " - Shortcut.lnk" If Not FileGetSize($sSelfLnk) Then FileCreateShortcut($sAutoItExe, $sSelfLnk, "", '/AutoIt3ExecuteScript "' & @ScriptFullPath & '"', "Create AutoIt script shortcuts", $sAutoItIcon) FileCopy($sSelfLnk, _WinAPI_ShellGetKnownFolderPath($FOLDERID_SendTo), 1) ; right click > SendTo > thisScript to create the shortcut for your script EndIf If $CmdLine[0] = 1 Then ; if there's an icon wiht the same name as the script, use that, else, use $sAutoItIcon $sIco = StringTrimRight($CmdLine[1], 4) & ".ico" If Not FileGetSize($sIco) Then $sIco = $sAutoItIcon FileCreateShortcut($sAutoItExe, StringTrimRight($CmdLine[1], 4) & " - Shortcut.lnk", "", '/AutoIt3ExecuteScript "' & $CmdLine[1] & '"', "AutoIt script", $sIco) EndIf EndFunc ;==>main Func _GetPath($sFullpath) Return StringLeft($sFullpath, StringInStr($sFullpath, "\", 0, -1) - 1) EndFunc ;==>_GetPath To "Pin to start" successfully, you'll need to Pin it, then unpin it, then pin it again ( thank you M$ 🤷♂️ ) Edited 5 hours ago by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now