argumentum Posted Saturday at 04:10 PM Posted Saturday at 04:10 PM ..where did I put that code I had... somewhere 🤷♂️ Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
Solution argumentum Posted Saturday at 04:11 PM Author Solution Posted Saturday at 04:11 PM It's here in this thread. Don't go loosing your code again, ..you hear ! WildByDesign 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted Saturday at 04:13 PM Author Posted Saturday at 04:13 PM (edited) Problem I use SciTE portable but don't have the context menus as when properly installed Solution Add the registry entries to show a context menu for .au3 in SystemFileAssociations for the current user Spoiler expandcollapse popupGlobal $g_AutoIt3root = StringLeft(@AutoItExe, StringInStr(@AutoItExe, '\', 0, -1) - 1) Global $g_sSysAssoc = "HKCU\Software\Classes\SystemFileAssociations\.au3\shell" Global $g_sTemplate = $g_AutoIt3root & "\SciTE\Template\Script.au3" AutoIt_Portable_ContextMenu_Remove(0) AutoIt_Portable_ContextMenu_Add() Func AutoIt_Portable_ContextMenu_Add($iShowMsgbox = 1) RegWrite("HKCU\Software\Classes\.au3", "PerceivedType", "REG_SZ", "text") RegWrite("HKCU\Software\Classes\.au3", "Content Type", "REG_SZ", "text/plain") RegWrite("HKCU\Software\Classes\.au3", "", "REG_SZ", "AutoIt3Script.Portable") RegWrite("HKCU\Software\Classes\AutoIt3Script.Portable", "", "REG_SZ", "AutoIt v3 Script Portable") ScriptTemplateWrite() If FileExists($g_sTemplate) Then RegWrite("HKCU\Software\Classes\.au3\ShellNew", "FileName", "REG_SZ", $g_sTemplate) Else RegWrite("HKCU\Software\Classes\.au3\ShellNew", "NullFile", "REG_SZ", "") EndIf RegWriteContextMenuCommand("RunX86", "Run Script (x86 Portable)", '"' & $g_AutoIt3root & '\AutoIt3.exe" "%1" %*') RegWriteContextMenuCommand("RunX64", "Run Script (x64 Portable)", '"' & $g_AutoIt3root & '\AutoIt3_x64.exe" "%1" %*') RegWriteContextMenuCommand("EditWSciTE", "Edit Script (SciTE Portable)", '"' & $g_AutoIt3root & '\SciTE\SciTE.exe" "%1"') RegWriteContextMenuCommand("Compile with Options", "Compile with Options (Portable)", '"' & $g_AutoIt3root & '\AutoIt3.exe" "' & $g_AutoIt3root & '\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /ShowGui /in "%l"') RegWriteContextMenuCommand("CompileX86", "Compile Script (x86 Portable)", '"' & $g_AutoIt3root & '\Aut2Exe\Aut2Exe.exe" /in "%1" /x86') RegWriteContextMenuCommand("CompileX64", "Compile Script (x64 Portable)", '"' & $g_AutoIt3root & '\Aut2Exe\Aut2Exe.exe" /in "%1" /x64') RegWriteContextMenuCommand("Tidy", "Tidy (Portable)", '"' & $g_AutoIt3root & '\SciTE\Tidy\Tidy.exe" "%1"') RefreshWindowsExplorerShellCache() If $iShowMsgbox Then MsgBox(64, "Registration Complete", "SystemFileAssociations context menu entries registered.") EndFunc ;==>AutoIt_Portable_ContextMenu_Add Func RegWriteContextMenuCommand($sEntry, $sDesc, $sCommand) RegWrite($g_sSysAssoc & "\" & $sEntry, "", "REG_SZ", $sDesc) RegWrite($g_sSysAssoc & "\" & $sEntry & "\command", "", "REG_SZ", $sCommand) EndFunc ;==>RegWriteContextMenuCommand Func RefreshWindowsExplorerShellCache() DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x08000000, "uint", 0, "ptr", 0, "ptr", 0) EndFunc ;==>RefreshWindowsExplorerShellCache Func AutoIt_Portable_ContextMenu_Remove($iShowMsgbox = 1) ; Delete SystemFileAssociations extension key and all associated verbs RegDelete("HKCU\Software\Classes\SystemFileAssociations\.au3") RefreshWindowsExplorerShellCache() If $iShowMsgbox Then MsgBox(64, "Unregister Complete", "SystemFileAssociations and portable AutoIt registry entries removed.") EndFunc ;==>AutoIt_Portable_ContextMenu_Remove Func ScriptTemplateWrite($iOverwrite = 0) If Not $iOverwrite And FileGetSize($g_sTemplate) Then Return Local $hFileOpen = FileOpen($g_sTemplate, 138) ; $FO_OVERWRITE (2) + $FO_CREATEPATH (8) + $FO_UTF8 (128) FileWrite($hFileOpen, ScriptTemplateStr()) FileClose($hFileOpen) EndFunc ;==>ScriptTemplateWrite Func ScriptTemplateStr() Local $sStr = "" $sStr &= '#Region ;**** Directives created by AutoIt3Wrapper_GUI ****' $sStr &= @CRLF & '#AutoIt3Wrapper_UseX64=y' $sStr &= @CRLF & '#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7' $sStr &= @CRLF & '#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****' $sStr &= @CRLF & '' $sStr &= @CRLF & '#cs ----------------------------------------------------------------------------' $sStr &= @CRLF & '' $sStr &= @CRLF & ' AutoIt Version: ' & @AutoItVersion $sStr &= @CRLF & ' Author: myName' $sStr &= @CRLF & '' $sStr &= @CRLF & ' Script Function:' $sStr &= @CRLF & ' Template AutoIt script.' $sStr &= @CRLF & '' $sStr &= @CRLF & '#ce ----------------------------------------------------------------------------' $sStr &= @CRLF & '' $sStr &= @CRLF & '; Script Start - Add your code below here' $sStr &= @CRLF & '' $sStr &= @CRLF & '' Return $sStr EndFunc ;==>ScriptTemplateStr Edited Monday at 01:57 PM by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted Saturday at 08:34 PM Author Posted Saturday at 08:34 PM Problem Have a bunch of RDP windows open and when they close ( some error ) I don't know from what PC it was from. Solution Keep this script running in the tray and it will find the name of the connection and place it in the MsgBox's error title. Spoiler WhatRdpWasIt.au3 expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=WhatRdpWasIt.ico #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Res_ProductName=WhatRdpWasIt.exe #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <WinAPISys.au3> #include <WinAPIProc.au3> #include <WinAPISysWin.au3> Global Enum $eRdpFromPID_32770, $eRdpFromPID_TscShellContainer, $eRdpFromPID_TscPopupParentWND, $eRdpFromPID_UBound If WinExists(StringTrimRight(@ScriptName, 4) & "_STUB") Then Exit 4 AutoItWinSetTitle(StringTrimRight(@ScriptName, 4) & "_STUB") Opt("TrayAutoPause", 0) Opt("TrayOnEventMode", 1) Opt("TrayMenuMode", 2) ;0=append, 1=no default menu, 2=no automatic check, 4=menuitemID not return If FileGetSize(StringTrimRight(@ScriptFullPath, 4) & ".ico") Then TraySetIcon(StringTrimRight(@ScriptFullPath, 4) & ".ico") EndIf TrayCreateItem("Open this folder") TrayItemSetOnEvent(-1, "Open_this_folder") Global $g_hWinHook = DllCallbackRegister('_WinEventProc', 'none', 'ptr;dword;hwnd;long;long;dword;dword') Global $g_hEventProc = _WinAPI_SetWinEventHook($EVENT_OBJECT_STATECHANGE, $EVENT_OBJECT_STATECHANGE, DllCallbackGetPtr($g_hWinHook)) If $g_hEventProc Then OnAutoItExitRegister('WinUnHook') Else Exit 5 EndIf While Sleep(100) WEnd Func Open_this_folder() ShellExecute(@WindowsDir & "\explorer.exe", '/n,/select,"' & @ScriptFullPath & '"', "") EndFunc ;==>Open_this_folder Func WinUnHook() If $g_hWinHook Then _WinAPI_UnhookWinEvent($g_hWinHook) If $g_hEventProc Then DllCallbackFree($g_hEventProc) $g_hWinHook = 0 $g_hEventProc = 0 EndFunc ;==>WinUnHook Func _WinEventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime) #forceref $hEventHook, $iEvent, $iObjectID, $iChildID, $iThreadId, $iEventTime If Not $hWnd Then Return Local $sTitle = WinGetTitle($hWnd) If Not StringInStr($sTitle, "Remote Desktop Connection") Then Return Local $sProcessName = "", $iPid = WinGetProcess($hWnd) If $iPid < 4 Then Return If $iPid > 1 Then $sProcessName = _WinAPI_GetProcessName($iPid) If $sProcessName <> "mstsc.exe" Then Return WinListRdpFromPID($iPid) EndFunc ;==>_WinEventProc Func WinListRdpFromPID($iPid, $sWinTitle = "Remote Desktop Connection") Local $aFound[$eRdpFromPID_UBound][2], $iEcho = 0 If $iPid < 2 Then Return SetError(2, 0, $aFound) Local Static $hTimer = TimerInit(), $aWinList = WinList($sWinTitle) Local $iOpt_WinTitleMatchMode = Opt("WinTitleMatchMode", 2) If TimerDiff($hTimer) > 1000 Then $hTimer = TimerInit() $aWinList = WinList($sWinTitle) EndIf If $iEcho Then ConsoleWrite('$aWinList[0][0] = ' & $aWinList[0][0] & @CRLF) For $i = 1 To $aWinList[0][0] If WinGetProcess($aWinList[$i][1]) = $iPid Then Switch _WinAPI_GetClassName($aWinList[$i][1]) Case "TSC_POPUP_PARENT_WNDCLASS" $aFound[$eRdpFromPID_TscPopupParentWND][0] = $aWinList[$i][1] ; "" $aFound[$eRdpFromPID_TscPopupParentWND][1] = $aWinList[$i][0] Case "TscShellContainerClass" $aFound[$eRdpFromPID_TscShellContainer][0] = $aWinList[$i][1] ; XPS8700K - Remote Desktop Connection $aFound[$eRdpFromPID_TscShellContainer][1] = $aWinList[$i][0] Case "#32770" If StringInStr(WinGetText($aWinList[$i][1]), @LF & @LF & "OK" & @LF) And $aWinList[$i][0] = "Remote Desktop Connection" Then $aFound[$eRdpFromPID_32770][0] = $aWinList[$i][1] ; Remote Desktop Connection $aFound[$eRdpFromPID_32770][1] = $aWinList[$i][0] If $iEcho Then ConsoleWrite('!' & $aWinList[$i][1] & @TAB & '[' & _WinAPI_GetClassName($aWinList[$i][1]) & ']' & @TAB & '[' & StringReplace(StringReplace(WinGetText($aWinList[$i][1]), @CR, "@CR"), @LF, "@LF") & ']' & @TAB & $aWinList[$i][0] & @CRLF) EndIf EndSwitch If $iEcho Then ConsoleWrite('+' & $aWinList[$i][1] & @TAB & '[' & _WinAPI_GetClassName($aWinList[$i][1]) & ']' & @TAB & '[' & StringReplace(StringReplace(WinGetText($aWinList[$i][1]), @CR, ">"), @LF, "~") & ']' & @TAB & $aWinList[$i][0] & @CRLF) Else If $iEcho Then ConsoleWrite('-' & $aWinList[$i][1] & @TAB & '[' & _WinAPI_GetClassName($aWinList[$i][1]) & ']' & @TAB & '[' & StringReplace(StringReplace(WinGetText($aWinList[$i][1]), @CR, ">"), @LF, "~") & ']' & @TAB & $aWinList[$i][0] & @CRLF) EndIf Next Opt("WinTitleMatchMode", $iOpt_WinTitleMatchMode) If $aFound[$eRdpFromPID_32770][0] Then _WinAPI_DwmSetWindowAttribute__($aFound[$eRdpFromPID_32770][0], 34, _WinAPI_SwitchColor(0x00AA00)) WinSetOnTop($aFound[$eRdpFromPID_32770][0], "", 1) WinSetTitle($aFound[$eRdpFromPID_32770][0], "", $aFound[$eRdpFromPID_TscShellContainer][1]) EndIf Return SetError(Not $aWinList[0][0], Int($aFound[$eRdpFromPID_32770][0]), $aFound) EndFunc ;==>WinListRdpFromPID Func _WinAPI_DwmSetWindowAttribute__($hWnd, $attribute = 34, $value = 0x00FF00, $valLen = 4) Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $attribute, 'dword*', $value, 'dword', $valLen) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute__ WhatRdpWasIt-icon-gen.au3 expandcollapse popup#NoTrayIcon #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Global $g_hGraphics = 0 Global $g_hBitmap = 0 WhatRdpWasIt_IcoGen() Func WhatRdpWasIt_IcoGen() _GDIPlus_Startup() Local Const $iWidth = 600 Local Const $iHeight = 600 Local $hGUI = GUICreate("GDI+ WhatRdpWasIt icon/png generator", $iWidth, $iHeight) $g_hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) $g_hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $g_hGraphics) Local $hBuffer = _GDIPlus_ImageGetGraphicsContext($g_hBitmap) _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 4) ; Palette Colors (ARGB: 0xAA RRGGBB) Local Const $iBgColor = 0x00000000 ; Fully transparent background Local Const $iCircleColor = 0xFFC48A20 ; Golden-ochre Local Const $iArrowColor = 0xFFECECEC ; Off-white / light grey Local $hBrushCircle = _GDIPlus_BrushCreateSolid($iCircleColor) Local Const $fPenWidth = 75.0 Local $hPenArrow = _GDIPlus_PenCreate($iArrowColor, $fPenWidth) _GDIPlus_PenSetLineJoin($hPenArrow, 2) _GDIPlus_PenSetStartCap($hPenArrow, 2) _GDIPlus_PenSetEndCap($hPenArrow, 2) ; Clear Canvas to Transparent ARGB _GDIPlus_GraphicsClear($hBuffer, $iBgColor) ; Main Circle _GDIPlus_GraphicsFillEllipse($hBuffer, 50, 50, 500, 500, $hBrushCircle) ; Upper Chevron Lines _GDIPlus_GraphicsDrawLine($hBuffer, 415, 155, 330, 240, $hPenArrow) _GDIPlus_GraphicsDrawLine($hBuffer, 330, 240, 395 + 20, 305 + 20, $hPenArrow) ; Lower Chevron Lines _GDIPlus_GraphicsDrawLine($hBuffer, 185, 445, 270, 360, $hPenArrow) _GDIPlus_GraphicsDrawLine($hBuffer, 270, 360, 205 - 20, 295 - 20, $hPenArrow) ; --- SAVE TRANSPARENT PNG AND ICO --- _GDIPlus_ImageSaveToFile($g_hBitmap, @ScriptDir & "\WhatRdpWasIt.png") _SaveBitmapToIco($g_hBitmap, @ScriptDir & "\WhatRdpWasIt.ico", 256) GUIRegisterMsg(0x000F, "_WM_PAINT") GUISetState(@SW_SHOW, $hGUI) _GDIPlus_GraphicsDrawImage($g_hGraphics, $g_hBitmap, 0, 0) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _GDIPlus_PenDispose($hPenArrow) _GDIPlus_BrushDispose($hBrushCircle) _GDIPlus_GraphicsDispose($hBuffer) _GDIPlus_BitmapDispose($g_hBitmap) _GDIPlus_GraphicsDispose($g_hGraphics) _GDIPlus_Shutdown() GUIDelete() EndFunc ;==>WhatRdpWasIt_IcoGen Func _WM_PAINT($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam If $g_hGraphics And $g_hBitmap Then _GDIPlus_GraphicsDrawImage($g_hGraphics, $g_hBitmap, 0, 0) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>_WM_PAINT Func _SaveBitmapToIco($hSrcBitmap, $sIcoPath, $iIconSize = 256) Local $hBitmap256 = _GDIPlus_BitmapCreateFromScan0($iIconSize, $iIconSize) Local $hCtx256 = _GDIPlus_ImageGetGraphicsContext($hBitmap256) _GDIPlus_GraphicsClear($hCtx256, 0x00000000) _GDIPlus_GraphicsSetSmoothingMode($hCtx256, 4) _GDIPlus_GraphicsSetInterpolationMode($hCtx256, 7) _GDIPlus_GraphicsDrawImageRect($hCtx256, $hSrcBitmap, 0, 0, $iIconSize, $iIconSize) Local $sTempPNG = @TempDir & "\~tmpIcon_" & Random(1000, 9999, 1) & ".png" _GDIPlus_ImageSaveToFile($hBitmap256, $sTempPNG) _GDIPlus_GraphicsDispose($hCtx256) _GDIPlus_BitmapDispose($hBitmap256) Local $hFile = FileOpen($sTempPNG, 16) Local $bPngData = FileRead($hFile) FileClose($hFile) FileDelete($sTempPNG) Local $iPngSize = BinaryLen($bPngData) If $iPngSize = 0 Then Return False Local $tHeader = DllStructCreate("align 1; word; word; word; byte; byte; byte; byte; word; word; dword; dword") DllStructSetData($tHeader, 1, 0) DllStructSetData($tHeader, 2, 1) DllStructSetData($tHeader, 3, 1) DllStructSetData($tHeader, 4, ($iIconSize >= 256) ? 0 : $iIconSize) DllStructSetData($tHeader, 5, ($iIconSize >= 256) ? 0 : $iIconSize) DllStructSetData($tHeader, 6, 0) DllStructSetData($tHeader, 7, 0) DllStructSetData($tHeader, 8, 1) DllStructSetData($tHeader, 9, 32) DllStructSetData($tHeader, 10, $iPngSize) DllStructSetData($tHeader, 11, 22) Local $tBytes = DllStructCreate("byte[22]", DllStructGetPtr($tHeader)) Local $bHeader = DllStructGetData($tBytes, 1) Local $hIcoFile = FileOpen($sIcoPath, 18) FileWrite($hIcoFile, $bHeader) FileWrite($hIcoFile, $bPngData) FileClose($hIcoFile) Return True EndFunc ;==>_SaveBitmapToIco Add it to shell:startup to run on login. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted Monday at 01:03 PM Author Posted Monday at 01:03 PM (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 Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Clipboard.au3> #include <Memory.au3> #include <String.au3> Exit _PasteCleanRichText(0) ; Bind to a hotkey: Ctrl + Alt + Shift + V HotKeySet("^!+v", "_HotKey_PasteCleanRichText") While 1 Sleep(100) WEnd Func _HotKey_PasteCleanRichText() _PasteCleanRichText() EndFunc Func _PasteCleanRichText($iSendCtrlV = 1) ; https://www.autoitscript.com/forum/topic/213874-solved-help-for-argumentum/#findComment-1554648 _ClipBoard_Open(0) Local $iFormat = _ClipBoard_RegisterFormat("HTML Format") If Not _ClipBoard_IsFormatAvailable($iFormat) Then _ClipBoard_Close() If $iSendCtrlV Then Send("^v") Return EndIf ; 1. Get binary data and convert to UTF-8 string Local $vBinData = _ClipBoard_GetData($iFormat) _ClipBoard_Close() If @error Or Not IsBinary($vBinData) Then If $iSendCtrlV Then Send("^v") Return EndIf Local $sRawHTML = BinaryToString($vBinData, 4) ; 4 = UTF-8 ; 2. Extract the fragment part between <!--StartFragment--> and <!--EndFragment--> Local $aMatch = StringRegExp($sRawHTML, "(?s)<!--StartFragment-->(.*?)<!--EndFragment-->", 3) Local $sFragment = "" If @error Then ; Fallback if tags aren't found: use the whole raw string $sFragment = $sRawHTML Else $sFragment = $aMatch[0] EndIf ; 3. Strip out forced dark-mode styles from the fragment $sFragment = StringRegExpReplace($sFragment, "color:\s*[^;]+;", "") $sFragment = StringRegExpReplace($sFragment, "background-color:\s*[^;]+;", "") $sFragment = StringRegExpReplace($sFragment, "background:\s*[^;]+;", "") $sFragment = StringRegExpReplace($sFragment, 'style="\s*"', "") ; 4. Build a brand-new, perfectly calculated CF_HTML payload Local $sPrefix = "Version:0.9" & @CRLF & _ "StartHTML:00000097" & @CRLF & _ "EndHTML:" & StringFormat("%010d", 135 + StringLen($sFragment) + 55) & @CRLF & _ "StartFragment:00000135" & @CRLF & _ "EndFragment:" & StringFormat("%010d", 135 + StringLen($sFragment)) & @CRLF & _ "<html><body><!--StartFragment-->" Local $sSuffix = "<!--EndFragment--></body></html>" Local $sFinalHTML = $sPrefix & $sFragment & $sSuffix ; 5. Allocate global memory and push to clipboard Local $vUtf8Bin = StringToBinary($sFinalHTML, 4) Local $iLen = BinaryLen($vUtf8Bin) + 1 Local $hMem = _MemGlobalAlloc($iLen, 0x0002) ; $GMEM_MOVEABLE If Not $hMem Then If $iSendCtrlV Then Send("^v") Return EndIf Local $pMem = _MemGlobalLock($hMem) DllStructSetData(DllStructCreate("byte[" & $iLen & "]", $pMem), 1, $vUtf8Bin) _MemGlobalUnlock($hMem) _ClipBoard_Open(0) _ClipBoard_Empty() _ClipBoard_SetDataEx($hMem, $iFormat) _ClipBoard_Close() ; 6. Send paste command If $iSendCtrlV Then Send("^v") EndFunc making this background formatted clipboard: Spoiler While traditional WebDriver acts like a remote-control robot interacting with a web page from the outside (clicking buttons, typing text as a user would), the Chrome DevTools Protocol (CDP) plugs directly into the browser's engine. Because of this deep access, CDP can do several low-level tasks that standard WebDriver cannot easily do: Browserbase+ 1 1. Advanced Network Interception & Mocking What CDP can do: You can intercept, modify, mock, or drop network requests and responses on the fly. For example, you can intercept an API call returning user data and change the JSON payload mid-flight to test how your app handles specific data without altering the backend database. Testplane Why WebDriver struggles: Standard WebDriver has very limited network control; it mostly just tells the browser to navigate and lets whatever happens on the network happen passively. 2. Device, Geolocation, and Sensor Emulation What CDP can do: It allows you to deeply mock physical device metrics. You can dynamically override geolocation coordinates, timezones, CPU throttling (simulate a slow phone processor), network offline/online states, and even device orientation or touch events. Why WebDriver struggles: While modern WebDriver implementations have added basic geolocation or mobile emulation hooks, they are often rigid and restricted compared to the granular parameters you can pass directly through CDP's emulation domains. 3. Real-Time Event Streaming & Console Logging What CDP can do: It streams browser events natively over WebSockets. You can instantly capture unhandled JavaScript exceptions, browser console logs, performance metrics, and storage/cookie updates the exact millisecond they happen. Obsidian Publish+ 1 Why WebDriver struggles: WebDriver historically relies on a request-response polling model. To get console logs or errors, WebDriver usually has to ask the browser for them after the fact rather than streaming them live. 4. Performance Tracing and Profiling What CDP can do: You can record deep performance traces, generate CPU profiles, and measure memory heaps. This lets developers programmatic check for memory leaks or find out exactly why a page load is lagging down to the millisecond. Why WebDriver struggles: WebDriver has no native capability to inspect memory consumption, JavaScript execution timelines, or deep rendering metrics. 5. Managing Browser Contexts and Service Workers What CDP can do: It gives you granular control over background processes like Service Workers, Web Workers, out-of-process iframes, and isolated incognito storage partitions (Browser Contexts) without needing to spin up separate browser windows. Browserbase Summary: Think of WebDriver as a user sitting in front of a monitor using a mouse and keyboard. Think of CDP as an engineer plugged directly into the browser's electrical wiring with a diagnostic kit. look better: Spoiler While traditional WebDriver acts like a remote-control robot interacting with a web page from the outside (clicking buttons, typing text as a user would), the Chrome DevTools Protocol (CDP) plugs directly into the browser's engine. Because of this deep access, CDP can do several low-level tasks that standard WebDriver cannot easily do: Browserbase+ 1 1. Advanced Network Interception & Mocking What CDP can do: You can intercept, modify, mock, or drop network requests and responses on the fly. For example, you can intercept an API call returning user data and change the JSON payload mid-flight to test how your app handles specific data without altering the backend database. Testplane Why WebDriver struggles: Standard WebDriver has very limited network control; it mostly just tells the browser to navigate and lets whatever happens on the network happen passively. 2. Device, Geolocation, and Sensor Emulation What CDP can do: It allows you to deeply mock physical device metrics. You can dynamically override geolocation coordinates, timezones, CPU throttling (simulate a slow phone processor), network offline/online states, and even device orientation or touch events. Why WebDriver struggles: While modern WebDriver implementations have added basic geolocation or mobile emulation hooks, they are often rigid and restricted compared to the granular parameters you can pass directly through CDP's emulation domains. 3. Real-Time Event Streaming & Console Logging What CDP can do: It streams browser events natively over WebSockets. You can instantly capture unhandled JavaScript exceptions, browser console logs, performance metrics, and storage/cookie updates the exact millisecond they happen. Obsidian Publish+ 1 Why WebDriver struggles: WebDriver historically relies on a request-response polling model. To get console logs or errors, WebDriver usually has to ask the browser for them after the fact rather than streaming them live. 4. Performance Tracing and Profiling What CDP can do: You can record deep performance traces, generate CPU profiles, and measure memory heaps. This lets developers programmatic check for memory leaks or find out exactly why a page load is lagging down to the millisecond. Why WebDriver struggles: WebDriver has no native capability to inspect memory consumption, JavaScript execution timelines, or deep rendering metrics. 5. Managing Browser Contexts and Service Workers What CDP can do: It gives you granular control over background processes like Service Workers, Web Workers, out-of-process iframes, and isolated incognito storage partitions (Browser Contexts) without needing to spin up separate browser windows. Browserbase Summary: Think of WebDriver as a user sitting in front of a monitor using a mouse and keyboard. Think of CDP as an engineer plugged directly into the browser's electrical wiring with a diagnostic kit. Edited Monday at 01:41 PM by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted Tuesday at 04:06 AM Author Posted Tuesday at 04:06 AM (edited) Problem Want to download torrents sequentially by default, but there is no default that I can find in qBittorrent 😭 The reason for "the problem" ...that works against the swarm and spirit of the protocol. So it will never have a default sequential setting. Solution #1 If you must have it then register your own handler to do it via WebUI. Go to: Tools > Options > WebUI and enable it. Then compile and register the script below with your user, password and port. Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=qBittorrAdd.ico #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Res_Comment=qBittorrAdd #AutoIt3Wrapper_Res_Description=qBittorrAdd #AutoIt3Wrapper_Res_Fileversion=0.2608.6.7 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y #AutoIt3Wrapper_Res_ProductName=qBittorrAdd.exe #AutoIt3Wrapper_Res_ProductVersion=0.2608.6.0 #AutoIt3Wrapper_Res_CompanyName=. #AutoIt3Wrapper_Res_LegalCopyright=. #AutoIt3Wrapper_Res_LegalTradeMarks=. #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/mo #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <MsgBoxConstants.au3> #include <FileConstants.au3> ;~ #RequireAdmin ; Run this once as Administrator to register magnet links ;~ Exit _RegisterMagnetProtocol() ; Prevent AutoIt hard crashes on COM errors Global $oCOMError = ObjEvent("AutoIt.Error", "_COMErrHandler") ; --- Configuration --- Local $sWebUiUrl = "https://127.0.0.1:8080" Local $sUsername = "YOUR_USERNAME_HERE" Local $sPassword = "YOUR_PASSWORD_HERE" ; Set to your active Web UI password ; Check if a magnet link, URL, or file path was passed via command line Local $sTarget = "" If $CmdLine[0] > 0 Then $sTarget = $CmdLine[1] Else $sTarget = InputBox("qBittorrent Sequential Add", "Enter Torrent URL, Magnet Link, or File Path:") If @error Or $sTarget = "" Then Exit EndIf ; Strip surrounding quotes if dragged & dropped or passed via CMD $sTarget = StringRegExpReplace($sTarget, '^"|"$', '') ; Create HTTP Object Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") ; Configure SSL (Ignore self-signed errors & Force TLS 1.2) Const $WinHttpRequestOption_SslErrorIgnoreFlags = 4 Const $WinHttpRequestOption_SecureProtocols = 9 $oHTTP.Option($WinHttpRequestOption_SslErrorIgnoreFlags) = 13056 $oHTTP.Option($WinHttpRequestOption_SecureProtocols) = 2048 ; --- Step 1: Login --- Local $sLoginBody = "username=" & _URLEncode($sUsername) & "&password=" & _URLEncode($sPassword) $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/auth/login", False) $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) $oHTTP.Send($sLoginBody) ; Validate status code (200 or 204 indicates success) If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then MsgBox($MB_ICONERROR, "Auth Error", "Login failed! HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 5) Exit EndIf ; --- Step 2: Add Torrent with Sequential Download Enabled --- $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/torrents/add", False) $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) If FileExists($sTarget) Then ; --- Handle Local .torrent File (multipart/form-data) --- Local $sBoundary = "----AutoItBoundary" & Hex(Random(100000, 999999, 1)) Local $sFileName = StringRegExpReplace($sTarget, "^.*[\\/]", "") ; Read file as binary Local $hFile = FileOpen($sTarget, $FO_BINARY) Local $bFileContent = FileRead($hFile) FileClose($hFile) ; 1. Build options header FIRST before the file bytes Local $sParamsPart = "" $sParamsPart &= "--" & $sBoundary & @CRLF $sParamsPart &= 'Content-Disposition: form-data; name="sequentialDownload"' & @CRLF & @CRLF $sParamsPart &= "true" & @CRLF $sParamsPart &= "--" & $sBoundary & @CRLF $sParamsPart &= 'Content-Disposition: form-data; name="firstLastPiecePrio"' & @CRLF & @CRLF $sParamsPart &= "false" & @CRLF $sParamsPart &= "--" & $sBoundary & @CRLF $sParamsPart &= 'Content-Disposition: form-data; name="torrents"; filename="' & $sFileName & '"' & @CRLF $sParamsPart &= "Content-Type: application/x-bittorrent" & @CRLF & @CRLF ; 2. Closing boundary after binary file content Local $sEndPart = @CRLF & "--" & $sBoundary & "--" & @CRLF ; 3. Combine header/parameters, file bytes, and closing boundary Local $bPayload = Binary($sParamsPart) & $bFileContent & Binary($sEndPart) $oHTTP.SetRequestHeader("Content-Type", "multipart/form-data; boundary=" & $sBoundary) $oHTTP.Send($bPayload) Else ; --- Handle Magnet Link or Web URL (application/x-www-form-urlencoded) --- Local $sAddBody = "urls=" & _URLEncode($sTarget) & "&sequentialDownload=true&firstLastPiecePrio=false" $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.Send($sAddBody) EndIf Func _RegisterMagnetProtocol() Local $sExePath = StringTrimRight(@ScriptFullPath, 4) & ".exe" Local $sAppProgID = StringTrimRight(@ScriptName, 4) If IsAdmin() Then ; Register 'magnet:' protocol in Windows Registry RegWrite("HKCR\magnet", "", "REG_SZ", "URL:Magnet link") RegWrite("HKCR\magnet", "URL Protocol", "REG_SZ", "") RegWrite("HKCR\magnet\shell\open\command", "", "REG_SZ", '"' & $sExePath & '" "%1"') If Not @error Then MsgBox($MB_ICONINFORMATION, "Success", "Registered magnet links to:" & @CRLF & $sExePath, 10) Else MsgBox($MB_ICONERROR, "Error", "Failed to write registry keys.", 10) EndIf EndIf ; 1. Define Protocol Class RegWrite("HKCU\Software\Classes\" & $sAppProgID, "", "REG_SZ", "URL:Magnet link") RegWrite("HKCU\Software\Classes\" & $sAppProgID, "URL Protocol", "REG_SZ", "") RegWrite("HKCU\Software\Classes\" & $sAppProgID & "\shell\open\command", "", "REG_SZ", '"' & $sExePath & '" "%1"') ; 2. Register as Windows Capability (makes it show up in Default Apps) RegWrite("HKCU\Software\" & $sAppProgID & "\Capabilities", "ApplicationName", "REG_SZ", "qBittorrent Sequential Handler") RegWrite("HKCU\Software\" & $sAppProgID & "\Capabilities\URLAssociations", "magnet", "REG_SZ", $sAppProgID) RegWrite("HKCU\Software\RegisteredApplications", $sAppProgID, "REG_SZ", "Software\" & $sAppProgID & "\Capabilities") MsgBox($MB_ICONINFORMATION, "Done", "App registered in Windows Default Apps menu!", 10) EndFunc ;==>_RegisterMagnetProtocol ; Check response If $oHTTP.Status = 200 Or $oHTTP.Status = 204 Then ToolTip("Torrent added sequentially via HTTPS!", 10, 10, "qBittorrent", 1) Sleep(2000) Else MsgBox($MB_ICONERROR, "qBittorrent Error", "Failed to add torrent. HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 3) EndIf ; --- Helper Function to URL-Encode Form Data --- Func _URLEncode($sData) Local $aArray = StringSplit($sData, ""), $sEncoded = "", $iAsc For $i = 1 To $aArray[0] $iAsc = Asc($aArray[$i]) Select Case ($iAsc >= 48 And $iAsc <= 57) Or ($iAsc >= 65 And $iAsc <= 90) Or ($iAsc >= 97 And $iAsc <= 122) $sEncoded &= $aArray[$i] Case $aArray[$i] = " " $sEncoded &= "+" Case Else $sEncoded &= "%" & Hex($iAsc, 2) EndSelect Next Return $sEncoded EndFunc ;==>_URLEncode Func _COMErrHandler($oError) EndFunc ;==>_COMErrHandler Solution #2 ( simpler but i didn't think of it before ) Go to Tools > Options > Downloads, then on Run external program, Run on torrent added: "C:\Utilities\qBittorrAddSeq.exe" "/I:%I" "/J:%J" Spoiler expandcollapse popup#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <MsgBoxConstants.au3> ; "C:\Utilities\qBittorrAddSeq.exe" "/I:%I" "/J:%J" ; Prevent AutoIt hard crashes on COM errors Global $oCOMError = ObjEvent("AutoIt.Error", "_COMErrHandler") qTorr_AddSequentialViaWebUI() Func qTorr_AddSequentialViaWebUI($sWebUiUrl = "https://127.0.0.1:8080", $sUsername = "YOUR_USERNAME_HERE", $sPassword = "YOUR_PASSWORD_HERE") ; --- Parameter Parsing --- Local $sHash = "" Local $sHashV1 = "" Local $sHashV2 = "" ; Loop through all arguments looking for /I: or /J: If $CmdLine[0] > 0 Then For $i = 1 To $CmdLine[0] If StringLeft($CmdLine[$i], 3) = "/I:" Then $sHashV1 = StringMid($CmdLine[$i], 4) ElseIf StringLeft($CmdLine[$i], 3) = "/J:" Then $sHashV2 = StringMid($CmdLine[$i], 4) EndIf Next EndIf ; Combine them if both exist, otherwise use whichever is populated If $sHashV1 <> "" And $sHashV2 <> "" Then $sHash = $sHashV1 & "|" & $sHashV2 ElseIf $sHashV1 <> "" Then $sHash = $sHashV1 Else $sHash = $sHashV2 EndIf ; Exit silently if no valid hash was passed If $sHash = "" Then Exit 4 ; --- HTTP Web API Transmission --- Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1") ; Configure SSL (Ignore self-signed errors & Force TLS 1.2) Const $WinHttpRequestOption_SslErrorIgnoreFlags = 4 Const $WinHttpRequestOption_SecureProtocols = 9 $oHTTP.Option($WinHttpRequestOption_SslErrorIgnoreFlags) = 13056 $oHTTP.Option($WinHttpRequestOption_SecureProtocols) = 2048 ; Step 1: Login to get session cookie Local $sLoginBody = "username=" & _URLEncode($sUsername) & "&password=" & _URLEncode($sPassword) $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/auth/login", False) $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) $oHTTP.Send($sLoginBody) ; Validate status code (200 or 204 indicates success) If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then MsgBox($MB_ICONERROR, StringTrimRight(@ScriptName, 4) & " Error", "Login failed!" & @CRLF & " HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 60) Exit 5 EndIf ; Step 2: Toggle Sequential Download Using the Extracted Hash $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/torrents/toggleSequentialDownload", False) $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) $oHTTP.Send("hashes=" & $sHash) ; Validate status code (200 or 204 indicates success) If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then MsgBox($MB_ICONERROR, StringTrimRight(@ScriptName, 4) & " Error", "toggleSequentialDownload failed!" & @CRLF & " HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 60) Exit 6 EndIf ;~ ; Step 3: Automatically prioritize the first and last pieces ;~ $oHTTP.Open("POST", $sWebUiUrl & "/api/v2/torrents/toggleFirstLastPiecePrio", False) ;~ $oHTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded") ;~ $oHTTP.SetRequestHeader("Referer", $sWebUiUrl) ;~ $oHTTP.Send("hashes=" & $sHash) ;~ ; Validate status code (200 or 204 indicates success) ;~ If $oHTTP.Status <> 200 And $oHTTP.Status <> 204 Then ;~ MsgBox($MB_ICONERROR, StringTrimRight(@ScriptName, 4) & " Error", "toggleFirstLastPiecePrio failed!" & @CRLF & " HTTP Status: " & $oHTTP.Status & @CRLF & "Response: " & $oHTTP.ResponseText, 60) ;~ Exit 7 ;~ EndIf Exit 0 ; all good. EndFunc ;==>qTorr_AddSequentialViaWebUI ; --- Helper Function to URL-Encode Form Data --- Func _URLEncode($sData) Local $aArray = StringSplit($sData, ""), $sEncoded = "", $iAsc For $i = 1 To $aArray[0] $iAsc = Asc($aArray[$i]) Select Case ($iAsc >= 48 And $iAsc <= 57) Or ($iAsc >= 65 And $iAsc <= 90) Or ($iAsc >= 97 And $iAsc <= 122) $sEncoded &= $aArray[$i] Case $aArray[$i] = " " $sEncoded &= "+" Case Else $sEncoded &= "%" & Hex($iAsc, 2) EndSelect Next Return $sEncoded EndFunc ;==>_URLEncode Func _COMErrHandler($oError) EndFunc ;==>_COMErrHandler Edited Tuesday at 03:38 PM by argumentum more Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now