Private/GlobalStore.ps1
class GlobalStore { $originalTitle = $null $originalPrompt = $null $isPromptReplaced = $false $originalPSConsoleHostReadLine = $null $isReadLineReplaced = $false $isInLegacyApplicationMode = $false $titleUpdateThread = $null $backgroundThreadTimerJobs = @() $promptCallbacks = @() $commandPreExecutionCallbacks = @() [void] Clear() { if ($this.isInLegacyApplicationMode) { $this.ExitLegacyApplicationMode() } $this.ClearTitleUpdateThread() foreach ($timerJob in $this.backgroundThreadTimerJobs) { StopThread $timerJob.Thread } $this.backgroundThreadTimerJobs = @() $this.RestorePrompt() $this.RestorePSConsoleHostReadLine() } [void] ClearTitleUpdateThread() { if ($this.titleUpdateThread) { StopThread $this.titleUpdateThread $this.titleUpdateThread = $null } if ($null -ne $this.originalTitle) { (Get-Host).UI.RawUI.WindowTitle = $this.originalTitle $this.originalTitle = $null } } [void] EnterLegacyApplicationMode() { if ($this.isInLegacyApplicationMode) { Write-Error -Message 'Already in Legacy Application Mode.' -Category InvalidOperation return } (Get-Host).NotifyBeginApplication() $this.isInLegacyApplicationMode = $true } [void] ExitLegacyApplicationMode() { if (-not $this.isInLegacyApplicationMode) { Write-Error -Message 'Not in Legacy Application Mode.' -Category InvalidOperation return } (Get-Host).NotifyEndApplication() $this.isInLegacyApplicationMode = $false } [void] SetTitleUpdateThread($thread, [string]$originalTitle) { $this.titleUpdateThread = $thread $this.originalTitle = $originalTitle } [void] AddBackgroundThreadTimerJob($job) { $this.backgroundThreadTimerJobs += $job } [void] ReplacePrompt() { if ($this.isPromptReplaced) { return } $this.isPromptReplaced = $true $this.originalPrompt = $function:global:Prompt $function:global:Prompt = { $script:globalStore.InvokePrompt() } } [void] RestorePrompt() { if (-not $this.isPromptReplaced) { return } $function:global:Prompt = $this.originalPrompt $this.isPromptReplaced = $false $this.promptCallbacks = @() } [void] AddPromptCallback([ScriptBlock]$scriptBlock, $arguments) { $this.promptCallbacks += ,@($scriptBlock, $arguments) } [string] InvokePrompt() { foreach ($private:callback in $this.promptCallbacks) { $private:scriptBlock = $callback[0] $private:arguments = $callback[1] try { $scriptBlock.Invoke($arguments) } catch { $_ | Out-Default } } return $this.originalPrompt.Invoke() } [void] ReplacePSConsoleHostReadLine() { if ($this.isReadLineReplaced) { return } $this.isReadLineReplaced = $true $this.originalPSConsoleHostReadLine = $function:global:PSConsoleHostReadLine $function:global:PSConsoleHostReadLine = { $script:globalStore.InvokePSConsoleHostReadLine() } } [void] RestorePSConsoleHostReadLine() { if (-not $this.isReadLineReplaced) { return } $function:global:PSConsoleHostReadLine = $this.originalPSConsoleHostReadLine $this.isReadLineReplaced = $false $this.commandPreExecutionCallbacks = @() } [void] AddCommandPreExecutionCallback([ScriptBlock]$scriptBlock, $arguments) { $this.commandPreExecutionCallbacks += ,@($scriptBlock, $arguments) } [Object] InvokePSConsoleHostReadLine() { $private:command = $this.originalPSConsoleHostReadLine.Invoke() foreach ($private:callback in $this.commandPreExecutionCallbacks) { $private:scriptBlock = $callback[0] $private:arguments = $callback[1] $arguments.command = $command try { $scriptBlock.Invoke($arguments) } catch { $_ | Out-Default } } return $command } } $script:globalStore = [GlobalStore]::new() |