首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重载诸如写-详细的内置函数

重载诸如写-详细的内置函数
EN

Stack Overflow用户
提问于 2016-02-25 06:50:32
回答 2查看 844关注 0票数 2

我刚刚了解了在我自己的Write-Verbose函数之上使用Write-Debug &Write-Debug的好处,您可以在下面找到它:

代码语言:javascript
复制
Function Write-Log 
{
    param($logType, $logString, $logFile, [switch]$newLine)

    $time = get-date -Format "HH:mm:ss"
    $date = get-date -Format "yyyy-MM-dd"
    $line = "[${date}][${time}][$logType] ${logString}"

    if ($logFile) 
    {
        $retryDelay = 0.5; 
        $maxRetries = 10; 
        $retries = 0;

        while($retries -lt $maxRetries) 
        {
            try 
            {
                $line | out-file -Encoding utf8 -Append $logFile
                break; 
            } 
            catch 
            {
                ++$retries;
                Sleep $retryDelay; 
            }
        }
    }

    if ($logType -eq 'INFO') 
    {
        write-host -ForegroundColor Green $line 
    } 
    elseif ($logType -eq 'WARN') 
    {
        write-host -ForegroundColor Yellow $line
    } 
    elseif ($logType -eq 'ERROR') 
    {
        write-host -ForegroundColor Red $line
    }

    if ($newLine -eq $true)
    {
        write-host 
    }
}

这有助于我尽可能少地将脚本输出弄得乱七八糟,并包括一个时间戳,在调试时非常方便。

问题

是否有一种方法来重载Write-Verbose,使其以下列方式运行?

代码语言:javascript
复制
PS > Write-Verbose -Message 'I am a verbose message!' 

[2016-02-25][07:44:36] VERBOSE: I am a verbose message! 

编辑

我发现了以下内容,不幸的是,它不符合$VerbosePreference变量的要求:

代码语言:javascript
复制
$VerbosePreference = "SilentlyContinue"

Function Private:Write-Verbose ($Message) 
{
    $time = get-date -Format "HH:mm:ss"
    $date = get-date -Format "yyyy-MM-dd"
    $line = "[${date}][${time}] "

    Write-Host $line -NoNewline 

    &{Write-Verbose -Message $Message}

}

Write-Verbose -Message "Test"

上面的内容只是输出日期和时间戳,而不需要消息。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-25 07:10:55

写-详细驻留在Microsoft.PowerShell.Utility中,因此这是不可能的;如果不操作和更改Powershell中的内置行为(这应该避免)。

您可以在脚本/会话范围内创建自己的“写-详细”函数;该函数将输出所需的结果(使用cmdletbinding());或者使用输出消息,如“详细的: 2016-02-25您的日志消息”(依赖于写-详细的默认行为)。

我推荐后者,除非您对主机有一些奇怪的输出要求。

如果继续创建自己的写-详细函数,则应该在params之前使用cmdletbinding();因为这样可以将默认参数/开关传递给函数(如-verbose / -information、-debug等)。有关binding绑定和参数绑定的详细信息,请参阅:

https://blogs.technet.microsoft.com/heyscriptingguy/2012/07/07/weekend-scripter-cmdletbinding-attribute-simplifies-powershell-functions/

https://posh2scripting.wordpress.com/2013/06/05/what-is-cmdletbinding/

最后一件事;不建议在脚本中直接使用写主机,因为这会导致默认的流重定向(等等)。如果要将信息打印到流中,我强烈建议使用写-详细、写-调试、写-信息、写-输出cmdlet。

有关不使用写主机的更多信息,请参见:

http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/

http://powershell.com/cs/blogs/donjones/archive/2012/04/06/2012-scripting-games-commentary-stop-using-write-host.aspx

希望这能回答你的问题。

票数 2
EN

Stack Overflow用户

发布于 2016-04-06 09:57:48

同意@CmdrTchort关于这个问题的答案。

提供这个答案是为了给出一个Write-Verbose自定义实现的实现,这个实现可以被使用(即调用Write-CustomVerbose而不是Write-Verbose )。显然,这不会影响仍然使用Write-Verbose的引用库中的任何现有代码或代码。

代码语言:javascript
复制
function Write-CustomVerbose {
    [CmdletBinding(DefaultParameterSetName='UseTimestamp')]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [AllowEmptyString()]
        [string]$Message
        ,
        [Parameter(Mandatory = $false, ParameterSetName='UseTimestamp')]
        [string]$TimestampFormat = ((Get-Culture).DateTimeFormat.UniversalSortableDateTimePattern)
        ,
        [Parameter(Mandatory = $false, ParameterSetName='UseTimestamp')]
        [switch]$UseLocalTime #defaults to UTC
        ,
        [Parameter(Mandatory = $false, ParameterSetName='DoNotUseTimestamp')]
        [switch]$ExcludeTimestamp #defaults to include the timestamp (as that's why we're using this function over the standard write-verbose

    )
    begin {
        [string]$FormattedMessage = '{0}'
        if(-not $ExcludeTimestamp.IsPresent) {
            $FormattedMessage = "{1:$TimestampFormat}: $FormattedMessage"
        }
    }
    process {
        #get the time here rather than in begin as we want it to be accurate per message from pipeline
        [DateTime]$Now = Get-Date
        if(-not $UseLocalTime.IsPresent){$Now = $Now.ToUniversalTime()}
        #output the results
        write-verbose ($FormattedMessage -f $Message, $Now)
    }
}

示例用法:1..1000 | Write-CustomVerbose -Verbose -UseLocalTime -TimestampFormat 'HH:mm'

更新

这里有一个稍微高级一些的版本,允许您一次劫持所有流:

代码语言:javascript
复制
function Write-Custom {
    [CmdletBinding(DefaultParameterSetName='UseTimestamp')]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [PSCustomObject]$InputObject
        ,
        [Parameter(Mandatory = $false, ParameterSetName='UseTimestamp')]
        [string]$TimestampFormat = ((Get-Culture).DateTimeFormat.UniversalSortableDateTimePattern)
        ,
        [Parameter(Mandatory = $false, ParameterSetName='UseTimestamp')]
        [switch]$UseLocalTime #defaults to UTC
        ,
        [Parameter(Mandatory = $false, ParameterSetName='DoNotUseTimestamp')]
        [switch]$ExcludeTimestamp #defaults to include the timestamp (as that's why we're using this function over the standard write-verbose

    )
    begin {
        [string]$FormattedMessage = '{0}'
        if(-not $ExcludeTimestamp.IsPresent) {
            $FormattedMessage = "{1:$TimestampFormat}: $FormattedMessage"
        }
    }
    process {
        #get the time here rather than in begin as we want it to be accurate per message from pipeline
        [DateTime]$Now = Get-Date
        if(-not $UseLocalTime.IsPresent){$Now = $Now.ToUniversalTime()}
        #determine output back to original stream
        [bool]$outputStream = $true
        if($InputObject.WriteErrorStream)  {$outputStream=$false;write-error   ($FormattedMessage -f $InputObject, $Now)}
        if($InputObject.WriteWarningStream){$outputStream=$false;write-warning ($FormattedMessage -f $InputObject, $Now)}
        if($InputObject.WriteVerboseStream){$outputStream=$false;write-verbose ($FormattedMessage -f $InputObject, $Now) -Verbose}
        if($InputObject.WriteDebugStream)  {$outputStream=$false;write-debug   ($FormattedMessage -f $InputObject, $Now) -Debug}
        if($outputStream){$InputObject}
    }
}

#demo
1..20 | %{
    if($_ % 2 -eq 0) {Write-Output  $_}
    if($_ -eq 11)    {Write-Error   $_ -ErrorAction Continue 2>&1} #bit of a hack required to get error output to flow further along the pipeline.
    if($_ -eq 13)    {Write-Warning $_}
    if($_ -eq 15)    {Write-Verbose $_ -Verbose}
    if($_ -eq 17)    {Write-Debug   $_ -Debug}
} *>&1 | Write-Custom
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35620301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档