Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
HelpersDebugger.psm1225 linesDownload Raw Back to HelpersDebugger
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4# Ensure that terminating errors terminate when importing the module.5trap {throw $_}6 7# Strict mode FTW.8Set-StrictMode -Version 3.09 10# Enable explicit export so that there are no surprises with commands exported from the module.11Export-ModuleMember12 13# Grab the internal ScriptPosition property once and re-use it in the ps1xml file14$internalExtentProperty = [System.Management.Automation.InvocationInfo].GetProperty('ScriptPosition', [System.Reflection.BindingFlags]'NonPublic,Instance')15 16# A debugger handler that can be used to automatically control the debugger17$debuggerStopHandler = {18    param($s, $e)19    # If we're not handling a debugger stop event during the execution of20    # Test-Debugger, then simply continue execution21    if (@(Get-Variable -Name dbgCmdQueue,dbgResults -Scope Script -ErrorAction Ignore).Count -ne 2) {22        $e.ResumeAction = [System.Management.Automation.DebuggerResumeAction]::Continue23        return24    }25    do {26        if ($script:dbgCmdQueue.Count -eq 0) {27            # If there are no more commands to process, continue execution28            $stringDbgCommand = 'c'29        } else {30            $stringDbgCommand = $script:dbgCmdQueue.Dequeue()31        }32        $dbgCmd = [System.Management.Automation.PSCommand]::new()33        $dbgCmd.AddScript($stringDbgCommand) > $null34        $output = [System.Management.Automation.PSDataCollection[PSObject]]::new()35        $result = $Host.Runspace.Debugger.ProcessCommand($dbgCmd, $output)36        if ($stringDbgCommand -eq '$?' -and $output.Count -eq 1) {37            $output[0] = $PSDebugContext.Trigger -isnot [System.Management.Automation.ErrorRecord]38        }39        $script:dbgResults += [pscustomobject]@{40            PSTypeName          = 'DebuggerCommandResult'41            Command             = $stringDbgCommand42            Context             = $PSDebugContext43            Output              = $output44            EvaluatedByDebugger = $result.EvaluatedByDebugger45            ResumeAction        = $result.ResumeAction46        }47    } while ($result -eq $null -or $result.ResumeAction -eq $null)48    $e.ResumeAction = $result.ResumeAction49}50 51# A flag to identify if the debugger handler has been added or not52$debuggerStopHandlerRegistered = $false53 54function Register-DebuggerHandler {55    [CmdletBinding()]56    [OutputType([System.Void])]57    param()58    try {59        $callerEAP = $ErrorActionPreference60        # We disable debugger interactivity so that all debugger events go through61        # the DebuggerStop event only (i.e. breakpoints don't actually generate a62        # prompt for user interaction)63        $Host.DebuggerEnabled = $false64        $Host.Runspace.Debugger.add_DebuggerStop($script:debuggerStopHandler)65        $script:debuggerStopHandlerRegistered = $true66    } catch {67        Write-Error -ErrorRecord $_ -ErrorAction $callerEAP68    }69}70Export-ModuleMember -Function Register-DebuggerHandler71 72function Unregister-DebuggerHandler {73    [CmdletBinding()]74    [OutputType([System.Void])]75    param()76    try {77        $callerEAP = $ErrorActionPreference78        $Host.Runspace.Debugger.remove_DebuggerStop($script:debuggerStopHandler)79        $Host.DebuggerEnabled = $true80        $script:debuggerStopHandlerRegistered = $false81    } catch {82        Write-Error -ErrorRecord $_ -ErrorAction $callerEAP83    }84}85Export-ModuleMember -Function Unregister-DebuggerHandler86 87function Test-Debugger {88    [CmdletBinding()]89    [OutputType('DebuggerCommandResult')]90    param(91        [Parameter(Position=0, Mandatory)]92        [ValidateNotNullOrEmpty()]93        [Alias('sb')]94        [ScriptBlock]95        $ScriptBlock,96 97        [Parameter()]98        [ValidateNotNullOrEmpty()]99        [string[]]100        $CommandQueue101    )102    try {103        $callerEAP = $ErrorActionPreference104        #  If the debugger is not set up properly, notify the user with an error message105        if (-not $script:debuggerStopHandlerRegistered -or $Host.DebuggerEnabled) {106            $message = 'You must invoke Register-DebuggerHandler before invoking Test-Debugger, and Unregister-DebuggerHandler after invoking Test-Debugger. As a best practice, invoke Register-DebuggerHandler in the BeforeAll block and Unregister-DebuggerHandler in the AfterAll block of your test script.'107            $exception = [System.InvalidOperationException]::new($message)108            $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, $exception.GetType().Name, 'InvalidOperation', $null)109            throw $errorRecord110        }111        $script:dbgResults = @()112        $script:dbgCmdQueue = [System.Collections.Queue]::new()113        foreach ($command in $CommandQueue) {114            $script:dbgCmdQueue.Enqueue($command)115        }116        # We re-create the script block before invoking it to ensure that it will117        # work regardless of where the script itself was defined in the test file.118        # We also silence any standard output because this invocation is about the119        # debugger output, not the output of the script itself.120        & {121            [System.Diagnostics.DebuggerStepThrough()]122            [CmdletBinding()]123            param()124            try {125                $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop126                [ScriptBlock]::Create($ScriptBlock).Invoke() > $null127            } catch {128                Write-Error -ErrorRecord $_ -ErrorAction Stop129            }130        }131        $script:dbgResults132    } catch {133        Write-Error -ErrorRecord $_ -ErrorAction $callerEAP134    } finally {135        Remove-Variable -Name dbgResults -Scope Script -ErrorAction Ignore136        Remove-Variable -Name dbgCmdQueue -Scope Script -ErrorAction Ignore137    }138}139Export-ModuleMember -Function Test-Debugger140 141function Get-DebuggerExtent {142    [CmdletBinding()]143    param(144        [Parameter(Position=0, Mandatory, ValueFromPipeline)]145        [ValidateNotNull()]146        [PSTypeName('DebuggerCommandResult')]147        $DebuggerCommandResult148    )149    process {150        try {151            $callerEAP = $ErrorActionPreference152            $script:internalExtentProperty.GetValue($DebuggerCommandResult.Context.InvocationInfo)153        } catch {154            Write-Error -ErrorRecord $_ -ErrorAction $callerEAP155        }156    }157}158 159function ShouldHaveExtent {160    [CmdletBinding(DefaultParameterSetName='SingleLineExtent')]161    param(162        [Parameter(Position=0, Mandatory, ValueFromPipeline)]163        [ValidateNotNull()]164        [PSTypeName('DebuggerCommandResult')]165        $DebuggerCommandResult,166 167        [Parameter(Mandatory, ParameterSetName='SingleLineExtent')]168        [ValidateRange(1, [int]::MaxValue)]169        [int]170        $Line,171 172        [Parameter(Mandatory, ParameterSetName='MultilineExtent')]173        [ValidateRange(1, [int]::MaxValue)]174        [int]175        $FromLine,176 177        [Parameter(Mandatory)]178        [ValidateRange(1, [int]::MaxValue)]179        [int]180        $FromColumn,181 182        [Parameter(Mandatory, ParameterSetName='MultilineExtent')]183        [ValidateRange(1, [int]::MaxValue)]184        [int]185        $ToLine,186 187        [Parameter(Mandatory)]188        [ValidateRange(1, [int]::MaxValue)]189        [int]190        $ToColumn191    )192    process {193        $extent = Get-DebuggerExtent -DebuggerCommandResult $DebuggerCommandResult194        $extent.StartLineNumber | Should -Be $(if ($PSCmdlet.ParameterSetName -eq 'SingleLineExtent') {$Line} else {$FromLine})195        $extent.StartColumnNumber | Should -Be $FromColumn196        $extent.EndLineNumber | Should -Be $(if ($PSCmdlet.ParameterSetName -eq 'SingleLineExtent') {$Line} else {$ToLine})197        $extent.EndColumnNumber | Should -Be $ToColumn198    }199}200Export-ModuleMember -Function ShouldHaveExtent201 202function ShouldHaveSameExtentAs {203    [CmdletBinding()]204    param(205        [Parameter(Position=0, Mandatory, ValueFromPipeline)]206        [ValidateNotNull()]207        [PSTypeName('DebuggerCommandResult')]208        $SourceDebuggerCommandResult,209 210        [Parameter(Position=1, Mandatory)]211        [ValidateNotNull()]212        [Alias('DebuggerCommandResult')]213        [PSTypeName('DebuggerCommandResult')]214        $TargetDebuggerCommandResult215    )216    begin {217        $targetExtent = Get-DebuggerExtent -DebuggerCommandResult $TargetDebuggerCommandResult218    }219    process {220        $sourceExtent = Get-DebuggerExtent -DebuggerCommandResult $SourceDebuggerCommandResult221        $sourceExtent | Should -Be $targetExtent222    }223}224Export-ModuleMember -Function ShouldHaveSameExtentAs225