我刚学会了使用Write-Verbose
& Write-Debug
超过我自己的Write-Log
功能,您可以在下面找到:
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
所以它的行为方式如下?
PS > Write-Verbose -Message 'I am a verbose message!'
[2016-02-25][07:44:36] VERBOSE: I am a verbose message!
修改
我发现了以下内容,但遗憾的是,$VerbosePreference
变量并未兑现:
$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"
上面只输出日期和时间戳,没有消息。
答案 0 :(得分:2)
Write-Verbose驻留在Microsoft.PowerShell.Utility中,所以这不可能是afaik;没有操纵和改变Powershell中的内置行为(应该避免)。
您可以在脚本/会话范围中创建自己的“Write-Verbose”函数;这将输出所需的结果(使用cmdletbinding());或者使用输出消息,例如“VERBOSE:[2016-02-25] [07:44:36]您的日志消息”(依赖于write-verbose的默认行为)。
我建议使用后者,除非你的主机有一些时髦的输出要求。
如果你继续创建自己的Write-Verbose函数,你应该在params之前使用[cmdletbinding()];因为这可以将默认参数/开关传递给您的函数(例如-verbose / -information,-debug等)。 有关cmdletbinding和参数绑定的详细信息,请参阅:
https://posh2scripting.wordpress.com/2013/06/05/what-is-cmdletbinding/
最后一件事;不推荐在脚本中直接使用Write-host,因为这会混淆默认的流重定向(等)。如果您要向流打印信息,我强烈建议使用Write-Verbose,Write-Debug,Write-information,Write-Output cmdlet。
有关不使用Write-host的更多信息,请访问:
http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/
希望这能回答你的问题。
答案 1 :(得分:0)
同意@CmdrTchort对这个问题的回答。
提供此答案是为了实现Write-Verbose
的自定义实现,可以代之以使用(即拨打Write-CustomVerbose
而不是Write-Verbose
。显然这不会影响引用库中仍使用Write-Verbose
的任何现有代码或代码。
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'
<强>更新强>
这是一个稍微高级的版本,允许您一次劫持所有流:
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