DuskDegree9667

ProfileManager.ahk

Jun 25th, 2025 (edited)
2,894
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ############################################################################
  2. ; ## Profile Manager v2
  3. ; ## Monitors active applications and switches AutoHotkey profiles accordingly.
  4. ; ##===========================================================================
  5.  
  6. #Requires AutoHotkey v2.0
  7. #SingleInstance Force
  8. A_WorkingDir := A_ScriptDir
  9. if !A_IsAdmin {
  10.     Run('*RunAs "' A_ScriptFullPath '"')
  11.     ExitApp()
  12. }
  13. Persistent()
  14. InstallKeybdHook()
  15. InstallMouseHook()
  16.  
  17. ; ############################################################################
  18. ; ## Configuration
  19. ; ##===========================================================================
  20.  
  21. #Include "ProfileManagerConfig.ahk"
  22. ScriptsPath := "C:\Users\user\Apps & Utilities\Custom Scripts - AutoHotkey\"
  23. CheckInterval := 500  ; Check every 0.5 seconds
  24.  
  25. ; ############################################################################
  26. ; ## Global Variables
  27. ; ##===========================================================================
  28.  
  29. global AppProfiles := GetAppProfiles()
  30. global ComplexProfiles := GetComplexProfiles()
  31. global SpecializedScripts := GetSpecializedScripts()
  32. global CurrentProfile := ""
  33. global CurrentScriptPIDs := []
  34. global SpecializedScriptPIDs := Map()
  35. global LastActiveProcess := ""
  36. global LastActiveTitle := ""
  37. global LastAdobeAutohide := "off"
  38.  
  39. ; ############################################################################
  40. ; ## Process Helper Functions
  41. ; ##===========================================================================
  42.  
  43. ; Returns an array of PIDs for all processes matching the given exe name
  44. ProcessGetList_PM(Name) {
  45.     list := []
  46.     for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where Name='" Name "'")
  47.         list.Push(process.ProcessId)
  48.     return list
  49. }
  50.  
  51. ; Returns the command line of a process given its PID
  52. ProcessGetCommandLine(PID) {
  53.     for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process where ProcessId=" PID)
  54.         return process.CommandLine
  55.     return ""
  56. }
  57.  
  58. ; ############################################################################
  59. ; ## Main Monitoring Loop
  60. ; ##===========================================================================
  61.  
  62. SetTimer(CheckActiveWindow, CheckInterval)
  63. MonitorSpecializedScripts() ; Initial check
  64. SetTimer(MonitorSpecializedScripts, 3000)
  65.  
  66. CheckActiveWindow() {
  67.     global LastActiveProcess, LastActiveTitle, CurrentProfile, AppProfiles, ComplexProfiles
  68.     try {
  69.         ActiveProcess := WinGetProcessName("A")
  70.         ActiveTitle := WinGetTitle("A")
  71.     } catch {
  72.         return ; No active window, skip this check
  73.     }
  74.  
  75.     ; Only check if the active window's process or title has changed (performance)
  76.     if (ActiveProcess != LastActiveProcess || ActiveTitle != LastActiveTitle) {
  77.         LastActiveProcess := ActiveProcess
  78.         LastActiveTitle := ActiveTitle
  79.  
  80.         ; Determine which profile to use, defaulting to Desktop
  81.         TargetProfile := ""
  82.  
  83.         ; 1. Check complex profiles (process + title match)
  84.         for _, rule in ComplexProfiles {
  85.             if (ActiveProcess = rule.process && ActiveTitle = rule.title) {
  86.                 TargetProfile := rule.script
  87.                 break
  88.             }
  89.         }
  90.  
  91.         ; 2. If no complex match, check simple app profiles (process match)
  92.         if (TargetProfile = "") {
  93.             TargetProfile := AppProfiles.Has(ActiveProcess) ? AppProfiles[ActiveProcess] : "Desktop.ahk"
  94.         }
  95.  
  96.         ; Compare profiles to see if a switch is needed
  97.         isSame := false
  98.         if (Type(TargetProfile) = Type(CurrentProfile)) {
  99.             if IsObject(TargetProfile) {
  100.                 if TargetProfile.Length == CurrentProfile.Length {
  101.                     isSame := true
  102.                     loop TargetProfile.Length {
  103.                         if (TargetProfile[A_Index] != CurrentProfile[A_Index]) {
  104.                             isSame := false
  105.                             break
  106.                         }
  107.                     }
  108.                 }
  109.             } else {
  110.                 if (TargetProfile = CurrentProfile) {
  111.                     isSame := true
  112.                 }
  113.             }
  114.         }
  115.  
  116.         if (!isSame) {
  117.             SwitchToProfile(TargetProfile)
  118.         }
  119.     }
  120. }
  121.  
  122. ; ############################################################################
  123. ; ## Specialized Script Monitoring
  124. ; ##===========================================================================
  125.  
  126. MonitorSpecializedScripts() {
  127.     global ScriptsPath, SpecializedScripts, SpecializedScriptPIDs
  128.  
  129.     for scriptName, exeList in SpecializedScripts {
  130.         isTargetRunning := false
  131.         for _, exeName in exeList {
  132.             if WinExist("ahk_exe " . exeName) {
  133.                 isTargetRunning := true
  134.                 break
  135.             }
  136.         }
  137.  
  138.         isScriptRunning := false
  139.         if (SpecializedScriptPIDs.Has(scriptName)) {
  140.             pid := SpecializedScriptPIDs[scriptName]
  141.             if (ProcessExist(pid)) {
  142.                 isScriptRunning := true
  143.             } else {
  144.                 ; The script terminated itself, so remove it from our map
  145.                 SpecializedScriptPIDs.Delete(scriptName)
  146.             }
  147.         }
  148.  
  149.         if (isTargetRunning && !isScriptRunning) {
  150.             ; Launch the script
  151.             fullPath := ScriptsPath . scriptName
  152.             if (FileExist(fullPath)) {
  153.                 Run('*RunAs "' A_AhkPath '" "' fullPath '"', , , &newPID)
  154.                 SpecializedScriptPIDs[scriptName] := newPID
  155.                 TrayTip('Profile Manager', 'Launched: ' . scriptName, 1)
  156.             }
  157.         }
  158.     }
  159. }
  160.  
  161. ; ############################################################################
  162. ; ## Core Functions
  163. ; ##===========================================================================
  164.  
  165. SwitchToProfile(NewProfile) {
  166.     global ScriptsPath, CurrentScriptPIDs, CurrentProfile
  167.     ProfileManagerPID := DllCall("GetCurrentProcessId")
  168.  
  169.     ; Close the existing scripts
  170.     for pid in CurrentScriptPIDs {
  171.         if (pid > 0 && pid != ProfileManagerPID) {
  172.             ProcessClose(pid)
  173.         }
  174.     }
  175.     CurrentScriptPIDs := []
  176.  
  177.     CurrentProfile := NewProfile
  178.     ScriptsToLaunch := IsObject(NewProfile) ? NewProfile : [NewProfile]
  179.  
  180.     for ScriptName in ScriptsToLaunch {
  181.         FullPath := ScriptsPath . ScriptName
  182.         if (FileExist(FullPath)) {
  183.             Run('*RunAs "' A_AhkPath '" "' FullPath '"', , , &NewPID)
  184.             CurrentScriptPIDs.Push(NewPID)
  185.             TrayTip() ; Clear any previous notifications
  186.             TrayTip('Profile Manager', 'Switched to: ' ScriptName, 1)
  187.         }
  188.     }
  189.  
  190.     ; If no scripts were launched for the profile (e.g., file not found),
  191.     ; and it's not the default desktop profile, fall back to desktop.
  192.     if (CurrentScriptPIDs.Length = 0) {
  193.         PrimaryNewProfile := IsObject(NewProfile) ? NewProfile[1] : NewProfile
  194.         if (PrimaryNewProfile != "Desktop.ahk") {
  195.             SwitchToProfile("Desktop.ahk")
  196.         }
  197.     }
  198. }
  199.  
  200. ; ############################################################################
  201. ; ## Hotkeys
  202. ; ##===========================================================================
  203.  
  204. ; Hotkey to manually reload ProfileManager
  205. ^!r:: { ; Control + Alt + R
  206.     if !A_IsAdmin {
  207.         Run('*RunAs "' A_ScriptFullPath '"')
  208.         ExitApp()
  209.     } else {
  210.         Reload()
  211.     }
  212. }
  213.  
  214. ; Hotkey to show current profile (for debugging)
  215. ^!p:: { ; Control + Alt + P
  216.     ProfileText := ""
  217.     if IsObject(CurrentProfile) {
  218.         ProfileText := ""
  219.         for i, script in CurrentProfile {
  220.             ProfileText .= script . (i == CurrentProfile.Length ? "" : ", ")
  221.         }
  222.     } else {
  223.         ProfileText := CurrentProfile
  224.     }
  225.     TrayTip('Profile Manager', 'Current Profile: ' ProfileText, 2)
  226. }
  227.  
  228. ; ############################################################################
  229. ; ## Exit Handling
  230. ; ##===========================================================================
  231.  
  232. OnExit(CleanupAndExit)
  233.  
  234. CleanupAndExit(*) {
  235.     global CurrentScriptPIDs, SpecializedScriptPIDs
  236.     for pid in CurrentScriptPIDs {
  237.         if (pid && pid > 0) {
  238.             ProcessClose(pid)
  239.         }
  240.     }
  241.     for _, pid in SpecializedScriptPIDs {
  242.         if (pid && pid > 0) {
  243.             ProcessClose(pid)
  244.         }
  245.     }
  246.     ExitApp()
  247. }
  248.  
Advertisement
Add Comment
Please, Sign In to add comment