Jump to content

Recommended Posts

  • Solution
Posted (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 by argumentum
added list of posts

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

Posted (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
Global $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 by argumentum

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

Posted

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

#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

#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  image.gif.922e3a93535f431de08b31ee669cc446.gif
autoit_scripter_blue_userbar.png

Posted (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
#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 by argumentum

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

Posted (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
#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
#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 by argumentum
more

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

Posted (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
#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, "&nbsp;", " ")
        $sCleanText = StringReplace($sCleanText, "&amp;", "&")
        $sCleanText = StringReplace($sCleanText, "&lt;", "<")
        $sCleanText = StringReplace($sCleanText, "&gt;", ">")
        $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 by argumentum

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

  • 2 weeks later...
Posted (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 🤔

  image.png.aaa96418e6eaf9b8e62868beb1332011.png  or image.png.be07f8e5f6bb6ea94ffad1f2f8e28f95.png

Spoiler
#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 by argumentum
added rounded corners

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

Posted (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! smiley

Name City Age
John Chicago 23
Lucy Wisconsin 19
Amanda Madison 22

This is a table you can experiment with.

..be creative :) 

 

Edited by argumentum

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

Posted (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
#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.
  1. Save SciTEUser.properties (Ctrl+S).
  2. Open any .au3 script in SciTE.
  3. 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 by argumentum
new version "2026.10.08"

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

Posted (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 by argumentum

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

Posted (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
#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
#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 )
snap_20261008_222427.png   ..and an icon for it: GitHubUploader.ico

Spoiler
#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 by argumentum
better

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

Posted (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 by argumentum

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...