#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=icons\USB.ico #AutoIt3Wrapper_Compile_Both=y #AutoIt3Wrapper_UseX64=y #EndRegion #include #include #include #include #include #include #include #include #include #include #include ; ==================================================================================================== ; GLOBAL CONSTANTS & VARIABLES ; ==================================================================================================== Global Const $g_sVersion = "3.3.18.0" Global Const $g_sIniFile = @AppDataDir & "\Launcher\Launcher.ini" Global Const $g_sSectionGen = "General" Global Const $g_sSectionItem = "Item" Global Const $g_sRemoteSrc = "http://www.shrum.net/sean/code/launcher/launcher.au3" Global Const $g_sRemoteExe = "http://www.shrum.net/sean/code/launcher/launcher.exe" Global Const $g_sStartupLnk = @StartupDir & "\Launcher.lnk" Global Const $g_sLogDir = @AppDataDir & "\Launcher" Global Const $g_sLogFile = $g_sLogDir & "\Launcher.log" Global Const $DBT_DEVICEARRIVAL = 0x8000 Global Const $DBT_DEVICEREMOVECOMPLETE = 0x8004 Global $g_bSystrayMode = False Global $g_hGUI = 0 Global $g_lvItems = 0 Global $g_idAdd = 0, $g_idEdit = 0, $g_idDel = 0, $g_idHomepage = 0, $g_idSupport = 0, $g_idClose = 0, $g_idQuit = 0 Global $g_idTrayOpen = 0, $g_idTrayHome = 0, $g_idTraySupport = 0, $g_idTrayLogFile = 0, $g_idTrayExit = 0, $g_idTrayStartup = 0 Global $g_bDeviceChange = False Global $g_bDeviceChangeArrival = False Global $g_sPendingDrive = "" Global $g_bDebug = True ; toggle console debug ; ==================================================================================================== ; ENTRY POINT ; ==================================================================================================== _ParseCmdLine() _EnsureLogFolder() _CheckVersion() _CheckFirstRun() _InitTray() _InitGUI() _LoadConfig() _RefreshList() If $g_bSystrayMode Then GUISetState(@SW_HIDE, $g_hGUI) Else GUISetState(@SW_SHOW, $g_hGUI) EndIf HotKeySet("^!l", "_Hotkey_ShowGUI") _UnifiedMainLoop() Exit ; ==================================================================================================== ; LOGGING / DEBUG ; ==================================================================================================== Func _EnsureLogFolder() If Not FileExists($g_sLogDir) Then DirCreate($g_sLogDir) EndFunc Func _Log($sText) Local $h = FileOpen($g_sLogFile, $FO_APPEND) If $h <> -1 Then FileWriteLine($h, "[" & _NowCalc() & "] " & $sText) FileClose($h) EndIf EndFunc Func _Dbg($sText) If $g_bDebug Then ConsoleWrite("DBG: " & $sText & @CRLF) EndFunc ; ==================================================================================================== ; COMMAND LINE PARSING ; ==================================================================================================== Func _ParseCmdLine() If $CmdLine[0] > 0 Then For $i = 1 To $CmdLine[0] Switch StringLower($CmdLine[$i]) Case "-s", "/s", "--systray" $g_bSystrayMode = True Case "-update" If $CmdLine[0] >= 3 Then _RunUpdater($CmdLine[2], $CmdLine[3]) Exit EndSwitch Next EndIf EndFunc ; ==================================================================================================== ; VERSION CHECKING & AUTO-UPDATER ; ==================================================================================================== Func _CheckVersion() Local $sTmp = @TempDir & "\launcher_remote.au3" InetGet($g_sRemoteSrc, $sTmp, 1, 0) If @error Then Return Local $sData = FileRead($sTmp) FileDelete($sTmp) If @error Or $sData = "" Then Return Local $aMatch = StringRegExp($sData, 'Global Const \$g_sVersion\s*=\s*"([^"]+)"', 1) If @error Or UBound($aMatch) = 0 Then Return Local $sRemoteVer = $aMatch[0] Local $iCmp = _VersionCompare($sRemoteVer, $g_sVersion) If $iCmp = 1 Then Local $iAns = MsgBox(4 + 32, "Launcher Update", _ "A newer version is available (" & $sRemoteVer & ", current " & $g_sVersion & ")." & @CRLF & _ "Do you want to download and install it now?") If $iAns = 6 Then _StartUpdate() EndIf EndFunc Func _StartUpdate() Local $sNew = @TempDir & "\launcher_new.exe" InetGet($g_sRemoteExe, $sNew, 1, 0) If @error Then MsgBox(16, "Launcher Update", "Failed to download new version.") Return EndIf Local $sBat = @TempDir & "\launcher_update.bat" Local $h = FileOpen($sBat, $FO_OVERWRITE) If $h <> -1 Then FileWriteLine($h, "@echo off") FileWriteLine($h, "ping 127.0.0.1 -n 3 >nul") FileWriteLine($h, "del """ & @ScriptFullPath & """") FileWriteLine($h, "move """ & $sNew & """ """ & @ScriptFullPath & """") FileWriteLine($h, "start """" """ & @ScriptFullPath & """ -s") FileClose($h) EndIf Run('"' & $sBat & '"', "", @SW_HIDE) Exit EndFunc Func _RunUpdater($sOld, $sNew) Sleep(2000) For $i = 1 To 10 If FileDelete($sOld) Then ExitLoop Sleep(500) Next FileMove($sNew, $sOld, 9) Run('"' & $sOld & '" -s', "", @SW_SHOWNORMAL) Exit EndFunc ; ==================================================================================================== ; FIRST RUN CHECK → CREATE STARTUP SHORTCUT ; ==================================================================================================== Func _CheckFirstRun() If Not FileExists($g_sIniFile) Then DirCreate($g_sLogDir) _EnsureStartupShortcut() IniWrite($g_sIniFile, $g_sSectionGen, "Initialized", "1") EndIf EndFunc Func _EnsureStartupShortcut() If Not FileExists($g_sStartupLnk) Then FileCreateShortcut(@ScriptFullPath, _ $g_sStartupLnk, _ @ScriptDir, _ "-s", _ "Launcher", _ @ScriptFullPath) EndIf EndFunc ; ==================================================================================================== ; GUI INITIALIZATION ; ==================================================================================================== Func _InitGUI() Opt("GUIOnEventMode", 0) $g_hGUI = GUICreate("Launcher v" & $g_sVersion, 650, 350) GUIRegisterMsg($WM_DEVICECHANGE, "_OnDeviceChange") GUICtrlCreateLabel("[ Volume label / filename ] monitor && launch pairs when removable media detected. ADD/EDIT/DELETE using the buttons below.", 10, 10, 640, 20) $g_lvItems = GUICtrlCreateListView( _ "Monitor for|Launch file|Prompt?|Mode", _ 10, 30, 630, 270, _ BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS)) _GUICtrlListView_SetExtendedListViewStyle($g_lvItems, _ BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) GUICtrlSendMsg($g_lvItems, $LVM_SETCOLUMNWIDTH, 0, 160) GUICtrlSendMsg($g_lvItems, $LVM_SETCOLUMNWIDTH, 1, 295) GUICtrlSendMsg($g_lvItems, $LVM_SETCOLUMNWIDTH, 2, 70) GUICtrlSendMsg($g_lvItems, $LVM_SETCOLUMNWIDTH, 3, 100) Local $yBtn = 310, $wBtn = 80, $hBtn = 28, $x = 10 $g_idAdd = GUICtrlCreateButton("&Add", $x, $yBtn, $wBtn, $hBtn) $x += $wBtn + 10 $g_idEdit = GUICtrlCreateButton("&Edit", $x, $yBtn, $wBtn, $hBtn) $x += $wBtn + 10 $g_idDel = GUICtrlCreateButton("&Delete", $x, $yBtn, $wBtn, $hBtn) $x += $wBtn + 10 $g_idHomepage = GUICtrlCreateButton("&Homepage", $x, $yBtn, $wBtn, $hBtn) $x += $wBtn + 10 $g_idSupport = GUICtrlCreateButton("&Support", $x, $yBtn, $wBtn, $hBtn) $x += $wBtn + 10 $g_idClose = GUICtrlCreateButton("&Close", $x, $yBtn, $wBtn, $hBtn) $x += $wBtn + 10 $g_idQuit = GUICtrlCreateButton("&Quit", $x, $yBtn, $wBtn, $hBtn) GUICtrlSetTip($g_idAdd, "Add a new monitored entry") GUICtrlSetTip($g_idEdit, "Edit the selected entry") GUICtrlSetTip($g_idDel, "Delete the selected entry") GUICtrlSetTip($g_idHomepage, "Open the project homepage") GUICtrlSetTip($g_idSupport, "Open the support page") GUICtrlSetTip($g_idClose, "Close window -> Systray mode") GUICtrlSetTip($g_idQuit, "Quit application") EndFunc ; ==================================================================================================== ; UNIFIED MAIN LOOP (GUI + TRAY + USB) ; ==================================================================================================== Func _UnifiedMainLoop() AdlibRegister("_CheckNewDrives", 500) While 1 Local $gmsg = GUIGetMsg() Switch $gmsg Case $GUI_EVENT_CLOSE, $g_idClose GUISetState(@SW_HIDE, $g_hGUI) Case $g_idQuit Exit Case $g_idAdd _EditItemDialog(-1) Case $g_idEdit Local $iSel = _GetSelectedIndex() If $iSel < 0 Then MsgBox(48, "Launcher", "Please select an entry to edit.") Else _EditItemDialog($iSel + 1) EndIf Case $g_idDel Local $iSel2 = _GetSelectedIndex() If $iSel2 < 0 Then MsgBox(48, "Launcher", "Please select an entry to delete.") Else _DeleteItem($iSel2 + 1) EndIf Case $g_idHomepage ShellExecute("https://www.shrum.net/sean/code/launcher") Case $g_idSupport ShellExecute("https://www.shrum.net/cats.php?dir=/sean/code/launcher&body=/sean/support.shtml") EndSwitch ; Tray events Local $tmsg = TrayGetMsg() Switch $tmsg Case $g_idTrayOpen _Hotkey_ShowGUI() Case $g_idTrayHome _TrayHomepage() Case $g_idTraySupport _TraySupport() Case $g_idTrayLogFile _TrayLogFile() Case $g_idTrayExit Exit EndSwitch Sleep(50) WEnd EndFunc ; ==================================================================================================== ; LISTVIEW SUPPORT ; ==================================================================================================== Func _RefreshList() If $g_lvItems = 0 Then Return _GUICtrlListView_DeleteAllItems($g_lvItems) Local $iCount = _GetItemCount() For $i = 1 To $iCount Local $a = _LoadItem($i) Local $sName = $a[0] Local $sCmd = $a[1] Local $sPrompt = (Number($a[2]) <> 0) ? "Yes" : "No" Local $sMode = $a[3] If StringStripWS($sCmd, 8) = "" Then $sCmd = $sName GUICtrlCreateListViewItem($sName & "|" & $sCmd & "|" & $sPrompt & "|" & $sMode, $g_lvItems) Next EndFunc Func _GetSelectedIndex() Local $vSel = _GUICtrlListView_GetSelectedIndices($g_lvItems) If $vSel = "" Then Return -1 Return Number($vSel) EndFunc ; ==================================================================================================== ; ADD / EDIT ITEM DIALOG ; ==================================================================================================== Func _EditItemDialog($iIndex) Local $bNew = ($iIndex = -1) Local $aItem[4] If $bNew Then $aItem[0] = "" $aItem[1] = "" $aItem[2] = "1" $aItem[3] = "Normal" Else $aItem = _LoadItem($iIndex) EndIf Local $hDlg = GUICreate($bNew ? "Add Entry" : "Edit Entry", 480, 190, -1, -1, -1, -1, $g_hGUI) GUICtrlCreateLabel("Monitored volume label or filename from root of newly detected USB:", 10, 10, 450, 20) Local $idFile = GUICtrlCreateInput($aItem[0], 10, 30, 450, 22) GUICtrlCreateLabel("Command to launch (blank = monitored name):", 10, 65, 300, 20) Local $idCmd = GUICtrlCreateInput($aItem[1], 10, 85, 430, 22) Local $idCmdBrowse = GUICtrlCreateButton("...", 440, 85, 25, 22) GUICtrlSetTip($idCmdBrowse, "...") Local $idPrompt = GUICtrlCreateCheckbox("Show 10s confirmation prompt", 10, 120, 300, 20) GUICtrlSetState($idPrompt, Number($aItem[2]) <> 0 ? $GUI_CHECKED : $GUI_UNCHECKED) GUICtrlCreateLabel("Window mode:", 10, 155, 100, 20) Local $idMode = GUICtrlCreateCombo("", 110, 152, 150, 22, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL)) GUICtrlSetData($idMode, "Normal|Maximized|Minimized|Hidden", $aItem[3]) Local $idOK = GUICtrlCreateButton("&OK", 290, 148, 80, 28) Local $idCancel = GUICtrlCreateButton("&Cancel", 380, 148, 80, 28) GUICtrlSetTip($idOK, "Save the currently listed settings") GUICtrlSetTip($idCancel, "Cancel changes") GUISetState(@SW_SHOW, $hDlg) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $idCancel GUIDelete($hDlg) Return Case $idOK ExitLoop Case $idCmdBrowse Local $sFile = FileOpenDialog("Select file to launch", @ScriptDir, _ "Programs (*.exe;*.bat;*.cmd)|All Files (*.*)", 1) If Not @error Then GUICtrlSetData($idCmd, $sFile) EndSwitch WEnd $aItem[0] = StringStripWS(GUICtrlRead($idFile), 3) $aItem[1] = StringStripWS(GUICtrlRead($idCmd), 3) $aItem[2] = BitAND(GUICtrlRead($idPrompt), $GUI_CHECKED) <> 0 ? "1" : "0" $aItem[3] = GUICtrlRead($idMode) If $aItem[0] = "" Then MsgBox(48, "Launcher", "Monitored volume label / filename cannot be empty.") GUIDelete($hDlg) Return EndIf If $bNew Then Local $iCount = _GetItemCount() + 1 _SetItemCount($iCount) _SaveItem($iCount, $aItem) Else _SaveItem($iIndex, $aItem) EndIf GUIDelete($hDlg) _RefreshList() _UpdateTrayTip() EndFunc ; ==================================================================================================== ; HOTKEY HANDLER ; ==================================================================================================== Func _Hotkey_ShowGUI() If $g_hGUI = 0 Then _InitGUI() _RefreshList() EndIf If BitAND(WinGetState($g_hGUI), 2) Then WinActivate($g_hGUI) Else GUISetState(@SW_SHOW, $g_hGUI) WinActivate($g_hGUI) EndIf EndFunc ; ==================================================================================================== ; TRAY INITIALIZATION ; ==================================================================================================== Func _InitTray() Opt("TrayMenuMode", 3) Opt("TrayOnEventMode", 1) TraySetIcon(@ScriptFullPath, 0) TraySetToolTip("Launcher") $g_idTrayOpen = TrayCreateItem("Open Launcher (Ctrl+Alt+L)") TrayItemSetOnEvent(-1, "_TrayOpen") $g_idTrayLogFIle = TrayCreateItem("Open log file") TrayItemSetOnEvent(-1, "_TrayLogFile") $g_idTrayStartup = TrayCreateItem("Run at startup") TrayItemSetOnEvent(-1, "_TrayStartupToggle") ; Set initial check state If FileExists($g_sStartupLnk) Then TrayItemSetState($g_idTrayStartup, $TRAY_CHECKED) Else TrayItemSetState($g_idTrayStartup, $TRAY_UNCHECKED) EndIf TrayCreateItem("") $g_idTrayHome = TrayCreateItem("Homepage") TrayItemSetOnEvent(-1, "_TrayHomepage") $g_idTraySupport = TrayCreateItem("Support") TrayItemSetOnEvent(-1, "_TraySupport") TrayCreateItem("") $g_idTrayExit = TrayCreateItem("Quit") TrayItemSetOnEvent(-1, "_TrayExit") TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "_TrayOpen") TraySetState() EndFunc Func _TrayOpen() _Hotkey_ShowGUI() EndFunc Func _TrayStartupToggle() If FileExists($g_sStartupLnk) Then ; Remove shortcut FileDelete($g_sStartupLnk) TrayItemSetState($g_idTrayStartup, $TRAY_UNCHECKED) Else ; Create shortcut FileCreateShortcut(@ScriptFullPath, $g_sStartupLnk, @ScriptDir) TrayItemSetState($g_idTrayStartup, $TRAY_CHECKED) EndIf EndFunc Func _TrayHomepage() ShellExecute("https://www.shrum.net/sean/code/launcher") EndFunc Func _TraySupport() ShellExecute("https://www.shrum.net/cats.php?dir=/sean/code/launcher&body=/sean/support.shtml") EndFunc Func _TrayExit() Exit EndFunc Func _TrayLogFile() _Log("Opening log file: " & $g_sLogFile) _Dbg("Opening log file: " & $g_sLogFile) ShellExecute($g_sLogFile) EndFunc Func _UpdateTrayTip() Local $iCount = _GetItemCount() If $iCount = 0 Then TraySetToolTip("Launcher - no monitored volume / files") Return EndIf Local $s = "Launcher - monitoring:" & @CRLF For $i = 1 To $iCount Local $a = _LoadItem($i) $s &= " - " & $a[0] & @CRLF Next TraySetToolTip($s) EndFunc ; ==================================================================================================== ; DRIVE DETECTION ; ==================================================================================================== Func _OnDeviceChange($hWnd, $Msg, $wParam, $lParam) Switch $wParam Case $DBT_DEVICEARRIVAL _Dbg("WM_DEVICECHANGE: ARRIVAL (0x8000)") Local $tDev = DllStructCreate("dword size; dword type; dword reserved; dword mask", $lParam) Local $iMask = DllStructGetData($tDev, "mask") If $iMask > 0 Then Local $iBit = 0 While BitShift($iMask, $iBit) <> 1 $iBit += 1 WEnd $g_sPendingDrive = Chr(Asc("A") + $iBit) & ":\" _Dbg("Detected drive letter from WM_DEVICECHANGE: " & $g_sPendingDrive) $g_bDeviceChange = True $g_bDeviceChangeArrival = True Else _Dbg("Arrival event but mask=0 — ignoring.") EndIf Case $DBT_DEVICEREMOVECOMPLETE _Dbg("WM_DEVICECHANGE: REMOVAL (0x8004)") $g_bDeviceChange = True $g_bDeviceChangeArrival = False EndSwitch Return $GUI_RUNDEFMSG EndFunc Func _CheckNewDrives() If Not $g_bDeviceChange Then Return _Dbg("=== _CheckNewDrives triggered ===") Local $bWasArrival = $g_bDeviceChangeArrival $g_bDeviceChange = False ; REMOVAL — nothing to do If Not $bWasArrival Then _Dbg("Device removal detected — no arrival processing.") Return EndIf ; ARRIVAL — use the drive letter extracted from WM_DEVICECHANGE If $g_sPendingDrive = "" Then _Dbg("Arrival event but no pending drive letter.") Return EndIf Local $sDrive = $g_sPendingDrive $g_sPendingDrive = "" _Dbg("Processing arrival for drive: " & $sDrive) ; Process the drive _ProcessDrive($sDrive) _Dbg("=== _CheckNewDrives complete ===") EndFunc ; ==================================================================================================== ; PROCESS A NEWLY CONNECTED DRIVE ; ==================================================================================================== Func _ProcessDrive($sDrive) Local $iCount = _GetItemCount() If $iCount = 0 Then _Dbg("No items configured; skipping drive " & $sDrive) Return EndIf ; --- Get volume label once per drive --- Local $sVolLabel = DriveGetLabel($sDrive) If @error Then $sVolLabel = "" ; Normalize actual volume label Local $sVolNorm = StringLower(StringStripWS($sVolLabel, 3)) If StringRight($sVolNorm, 1) = ":" Then _ $sVolNorm = StringTrimRight($sVolNorm, 1) For $i = 1 To $iCount Local $a = _LoadItem($i) ; a[0] = monitored item (filename OR volume label) ; a[1] = command ; a[2] = confirm flag ; a[3] = working directory ; --- Unified monitored item --- Local $sMon = $a[0] ; Sanitize monitored item (strip leading slashes) While StringLeft($sMon, 1) = "\" Or StringLeft($sMon, 1) = "/" $sMon = StringTrimLeft($sMon, 1) WEnd ; Normalized monitored item Local $sMonNorm = StringLower(StringStripWS($sMon, 3)) If StringRight($sMonNorm, 1) = ":" Then _ $sMonNorm = StringTrimRight($sMonNorm, 1) ; --- Condition A: File exists --- Local $sFile = $sDrive & $sMon Local $bFileMatch = FileExists($sFile) ; --- Condition B: Volume label matches monitored item --- Local $bVolMatch = ($sMonNorm = $sVolNorm) ; --- Skip if neither matches --- If Not ($bFileMatch Or $bVolMatch) Then ContinueLoop ; --- Log what triggered --- If $bFileMatch Then _Log("Monitored file found: " & $sFile) _Dbg("Monitored file found: " & $sFile) EndIf If $bVolMatch Then _Log("Monitored volume label match: " & $sVolLabel) _Dbg("Monitored volume label match: " & $sVolLabel) EndIf ; --- Determine command --- Local $sCmd = $a[1] If $sCmd = "" Then If $bFileMatch Then ; Default to file path if file triggered $sCmd = $sFile Else ; Volume-only trigger requires explicit command _Dbg("Volume match but no command defined; skipping") ContinueLoop EndIf EndIf ; ===================================================================== ; PRE-PROMPT VALIDATION: Ensure the launch command file exists ; ===================================================================== Local $sCmdCheck = $sCmd ; If command is relative (no drive letter), prepend drive If StringLeft($sCmdCheck, 2) <> $sDrive And _ StringMid($sCmdCheck, 2, 1) <> ":" Then $sCmdCheck = $sDrive & $sCmdCheck EndIf ; If command points to a file, ensure it exists If StringInStr($sCmdCheck, "\") Or StringInStr($sCmdCheck, "/") Then If Not FileExists($sCmdCheck) Then _Log("ERROR: Launch command missing: " & $sCmdCheck) _Dbg("ERROR: Launch command missing: " & $sCmdCheck) ; --- Ask user if they want to search for the file --- Local $iAns = MsgBox(4 + 32, "Launcher", _ "Command file not found:" & @CRLF & @CRLF & _ $sCmdCheck & @CRLF & @CRLF & _ "Do you want to search for it now?") ; NO → treat as cancelled run If $iAns = 7 Then _Dbg("User declined to search for missing command; skipping entry") _Log("User declined to search for missing command for entry " & $i) ContinueLoop EndIf ; YES → open Edit dialog Local $bEdited = _EditItemDialog($i) ; If user CANCELLED the edit dialog → treat as cancelled run If Not $bEdited Then _Dbg("User cancelled Edit dialog; skipping entry") _Log("User cancelled Edit dialog for entry " & $i) ContinueLoop EndIf ; If user SAVED changes → reprocess drive _Dbg("Reprocessing drive after user edit: " & $sDrive) _ProcessDrive($sDrive) Return EndIf EndIf ; ===================================================================== ; CONFIRMATION PROMPT (only shown AFTER validation passes) ; ===================================================================== Local $bRun = True If Number($a[2]) <> 0 Then Local $sTriggerInfo = "" If $bFileMatch Then $sTriggerInfo &= "File: " & $sFile & @CRLF If $bVolMatch Then $sTriggerInfo &= "Volume: " & $sVolLabel & @CRLF Local $iAns = MsgBox(4 + 32 + 256, "Launcher", _ "Trigger detected:" & @CRLF & $sTriggerInfo & @CRLF & _ "Run command?" & @CRLF & $sCmd, 10) If $iAns <> 6 Then _Log("User cancelled or timed out execution for: " & $sCmd) _Dbg("User cancelled or timed out execution for: " & $sCmd) $bRun = False EndIf EndIf ; --- Execute --- If $bRun Then _RunCommand($sCmd, $sDrive, $a[3]) Next EndFunc ; ==================================================================================================== ; RUN COMMAND ; ==================================================================================================== Func _RunCommand($sCmd, $sDrive, $sMode) Local $iShow = _ModeToShowFlag($sMode) _Log("Launching command: " & $sCmd & " (Mode=" & $sMode & ")") _Dbg("Launching command: " & $sCmd & " (Mode=" & $sMode & "), WorkDir=" & $sDrive) TrayTip("Launcher", "Executing: " & $sCmd, 5, $TIP_ICONASTERISK) Run('"' & $sCmd & '"', $sDrive, $iShow) EndFunc Func _ModeToShowFlag($sMode) Switch StringLower($sMode) Case "maximized" Return @SW_SHOWMAXIMIZED Case "minimized" Return @SW_SHOWMINNOACTIVE Case "hidden" Return @SW_HIDE Case Else Return @SW_SHOWNORMAL EndSwitch EndFunc ; ==================================================================================================== ; CONFIGURATION / INI ; ==================================================================================================== Func _LoadConfig() If Not FileExists($g_sIniFile) Then _SetItemCount(0) EndFunc Func _GetItemCount() Return Number(IniRead($g_sIniFile, $g_sSectionGen, "Count", 0)) EndFunc Func _SetItemCount($iCount) IniWrite($g_sIniFile, $g_sSectionGen, "Count", $iCount) EndFunc Func _LoadItem($iIndex) Local $sSec = $g_sSectionItem & $iIndex Local $a[4] $a[0] = IniRead($g_sIniFile, $sSec, "FileName", "") $a[1] = IniRead($g_sIniFile, $sSec, "Command", "") $a[2] = IniRead($g_sIniFile, $sSec, "Prompt", "0") $a[3] = IniRead($g_sIniFile, $sSec, "Mode", "Normal") Return $a EndFunc Func _SaveItem($iIndex, ByRef $aItem) Local $sSec = $g_sSectionItem & $iIndex IniWrite($g_sIniFile, $sSec, "FileName", $aItem[0]) IniWrite($g_sIniFile, $sSec, "Command", $aItem[1]) IniWrite($g_sIniFile, $sSec, "Prompt", $aItem[2]) IniWrite($g_sIniFile, $sSec, "Mode", $aItem[3]) EndFunc Func _DeleteItem($iIndex) Local $iCount = _GetItemCount() If $iIndex < 1 Or $iIndex > $iCount Then Return For $i = $iIndex To $iCount - 1 Local $a = _LoadItem($i + 1) _SaveItem($i, $a) Next IniDelete($g_sIniFile, $g_sSectionItem & $iCount) _SetItemCount($iCount - 1) _RefreshList() _UpdateTrayTip() EndFunc ; ==================================================================================================== ; TIMESTAMP ; ==================================================================================================== Func _NowCalc() Return @YEAR & "-" & StringFormat("%02d", @MON) & "-" & StringFormat("%02d", @MDAY) & " " & _ StringFormat("%02d", @HOUR) & ":" & StringFormat("%02d", @MIN) & ":" & StringFormat("%02d", @SEC) EndFunc