{"record":{"id":"8bad338ceca06798","repo":"JosefNemec/Playnite","slug":"interactive-session-is-already-running","errorCode":null,"errorMessage":"Interactive session is already running","messagePattern":"Interactive session is already running","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"source/Playnite/Scripting/PowerShell/PowerShell.cs","lineNumber":130,"sourceCode":"            powershell = System.Management.Automation.PowerShell.Create(initialSessionState);\r\n            runspace = powershell.Runspace;\r\n            runspace.Name = runspaceName;\r\n            SetVariable(\"ErrorActionPreference\", \"Stop\");\r\n            SetVariable(\"__logger\", LogManager.GetLogger(runspaceName));\r\n        }\r\n\r\n        public void Dispose()\r\n        {\r\n            IsDisposed = true;\r\n            runspace.Close();\r\n            runspace.Dispose();\r\n        }\r\n\r\n        public static void StartInteractiveSession(Dictionary<string, object> variables = null)\r\n        {\r\n            if (interactiveRuntime != null)\r\n            {\r\n                throw new Exception(\"Interactive session is already running\");\r\n            }\r\n\r\n            interactiveRuntime = new PowerShellRuntime(\"PSInteractive\");\r\n            variables?.ForEach(a => interactiveRuntime.SetVariable(a.Key, a.Value));\r\n            interactiveProcess = new Process();\r\n            interactiveProcess.StartInfo.FileName = @\"c:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\";\r\n\r\n            // This is really sad solution, but there's currently no way how to initialize these variables automatically, because:\r\n            // - Enter-PSHostProcess is blocking so we can't pass any command after it\r\n            // - We can't redirect stdin because then user wouldn't be able to interact witht the console\r\n            // - Messages like WM_PASTE don't work on PowerShell console\r\n            // - Passing CTLR-V and ENTER is not possible, because the only reliable method works globaly and can't be sent directly to window handle\r\n            interactiveProcess.StartInfo.Arguments = $\"-NoExit -Command \\\"\" +\r\n                $\"Write-Host \\\"`n\" +\r\n                $\"`tConnected to Playnite process.`n\" +\r\n                $\"`tUse CTLR-V and ENTER to paste commands to initialize basic SDK variables.`n\" +\r\n                $\"`tMore information at:`n\" +\r\n                $\"`thttps://playnite.link/docs/master/tutorials/extensions/scriptingDebugging.html`n\" +\r","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Playnite/Scripting/PowerShell/PowerShell.cs#L112-L148","documentation":"Thrown by PowerShellRuntime.StartInteractiveSession when a previous interactive PowerShell session (interactiveRuntime) is still alive. Playnite supports only one attached interactive PS host at a time because it shares a single runspace ('PSInteractive') with the host process, so a second start is refused.","triggerScenarios":"StartInteractiveSession is invoked while interactiveRuntime != null (line 128). The previous process may still be running because its Exited handler only nulls interactiveRuntime after the powershell.exe process exits.","commonSituations":"User opened the interactive PowerShell debug session, then triggered Open Interactive Session again without closing the first. The previous powershell.exe window was closed via the X button but the process hadn't fully terminated and fired Exited yet. A crashed earlier session left interactiveRuntime non-null.","solutions":["Close the existing interactive PowerShell window (type 'exit' or close it) so the Exited handler disposes interactiveRuntime.","If the field is stuck non-null after a crash, restart Playnite to reset static state.","Before calling StartInteractiveSession again, confirm interactiveRuntime is null / IsDisposed.","Avoid issuing multiple Open Interactive Session commands in rapid succession."],"exampleFix":"// before\nPowerShellRuntime.StartInteractiveSession(vars);\nPowerShellRuntime.StartInteractiveSession(vars); // throws\n\n// after\nPowerShellRuntime.StartInteractiveSession(vars);\n// ... user works, closes the window, Exited handler nulls interactiveRuntime ...\nPowerShellRuntime.StartInteractiveSession(vars); // ok","handlingStrategy":"validation","validationCode":"// No public getter is exposed; track liveness at the call site before starting:\n// (reflective/field check is internal — callers should keep a single owner of StartInteractiveSession)\nif (interactiveSessionStarted) { /* inform user a session is already running */ return; }\nPowerShellRuntime.StartInteractiveSession(vars);\ninteractiveSessionStarted = true;","typeGuard":"// Not externally type-guardable; guard at the command/UI layer:\nbool CanStartInteractiveSession() => !interactiveSessionStarted;","tryCatchPattern":"try { PowerShellRuntime.StartInteractiveSession(vars); }\ncatch (Exception ex) when (ex.Message.Contains(\"already running\")) { /* tell user to close the existing window */ }","preventionTips":["Bind the 'Open Interactive Session' command's CanExecute to a flag tracking whether one is running.","Always close the prior window before starting a new one.","On app shutdown, dispose the interactive runtime to reset static state."],"tags":["scripting","powershell","debugging","state","playnite"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}