是否可以拦截输入到交互式shell中的每个命令?

时间:2018-01-02 08:43:27

标签: powershell

我希望能够将我手动输入的每个命令包装到具有我自己功能的交互式Powershell控制台中,有没有办法以理智的方式拦截它?我想要完成的是为每个命令计时,如果超过30秒,则在完成时自动弹出BurntToast通知。

2 个答案:

答案 0 :(得分:2)

我将工作用于类似的事情:

function Invoke-CommandWithTimeout {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [Management.Automation.ScriptBlock]$ScriptBlock,
        [Parameter(Mandatory=$false)]
        [array]$ArgumentList = @(),
        [Parameter(Mandatory=$false)]
        [int]$Timeout = 30
    )

    $job = Start-Job -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList
    Wait-Job -Job $job -Timeout $Timeout
    if ($job.State -ne 'Stopped') {
        $job.StopJob()
        Write-Warning 'Command timed out.'
    }
    Receive-Job -Job $job
    Remove-Job -Job $job
}

Invoke-CommandWithTimeout {Test-Connection 'server.example.org'}

我不知道如何自动和透明地拦截在PowerShell控制台中输入的任何命令并以不同的方式运行它。

答案 1 :(得分:2)

如果您只想测量交互式命令的执行时间,而不是更改或中断它们,那么您可以覆盖Out-Default命令:

function Out-Default {
    begin {
        $StartTime = Get-Date
        $OutDefault = { Microsoft.PowerShell.Core\Out-Default @args }.GetSteppablePipeline($MyInvocation.CommandOrigin)
        $OutDefault.Begin($MyInvocation.ExpectingInput, $ExecutionContext)
    }
    process {
        if($MyInvocation.ExpectingInput) {
            $OutDefault.Process($_)
        } else {
            $OutDefault.Process()
        }
    }
    end {
        $OutDefault.End()
        $OutDefault.Dispose()
        $ExecutionTime = New-TimeSpan -Start $StartTime
        if($ExecutionTime -gt (New-TimeSpan -Seconds 30)) {
            Write-Host -ForegroundColor Red -Object $ExecutionTime
            # popup toast notification
        } else {
            Write-Host -ForegroundColor Green -Object $ExecutionTime
        }
    }
}

PowerShell隐式注入Out-Default命令,以便在PowerShell控制台中显示结果。