这是我最近用于我的脚本的更专业的日志记录功能的通用版本。
这种情况是,当我需要将某事作为计划任务执行时,我通常会创建一个通用脚本,或在一个模块中创建一个执行“繁重工作”的函数,然后是一个处理特定细节的调用脚本工作,例如从 XML 配置中获取参数、日志记录、通知等。
内部脚本使用 Write-Error、Write-Warning 和 Write-Verbose,调用脚本将所有输出流重定向到到此函数的管道,该函数将消息记录在 csv 文件中,其中包含时间戳、级别和消息。
在这种情况下,它针对的是 PoSh v.4,所以我基本上使用 Write-Verbose 作为 Write-Information 的替代,但想法相同。如果我在 Some-Script.ps1(参见示例)中使用 Write-Host 而不是 Write-Verbose 或 Write-Information,则 Add-LogEntry 函数不会捕获和记录消息。如果您想使用它来适当地捕获更多流,请在 switch 语句中添加条目以满足您的需求。
在这种情况下,-PassThru 开关基本上是一种解决您提到的关于写入日志文件以及输出到控制台(或另一个变量,或向下管道)。在这个实现中,我为对象添加了一个“Level”属性,但希望你能明白这一点。我的用例是将日志条目传递给一个变量,以便检查它们是否有错误,并在发生错误时用于 SMTP 通知。
function Add-LogEntry {
[CmdletBinding()]
param (
# Path to logfile
[Parameter(ParameterSetName = 'InformationObject', Mandatory = $true, Position = 0)]
[Parameter(ParameterSetName = 'Normal', Mandatory = $true, Position = 0)]
[String]$Path,
# Can set a message manually if not capturing an alternate output stream via the InformationObject parameter set.
[Parameter(ParameterSetName = 'Normal', Mandatory = $true)]
[String]$Message,
# Captures objects redirected to the output channel from Verbose, Warning, and Error channels
[ValidateScript({ @("VerboseRecord", "WarningRecord", "ErrorRecord") -Contains $_.GetType().name })]
[Parameter(ParameterSetName = 'InformationObject', Mandatory = $true, ValueFromPipeline = $true)]
$InformationObject,
# If using the message parameter, must specify a level, InformationObject derives level from the object.
[ValidateSet("Information", "Warning", "Error")]
[Parameter(ParameterSetName = 'Normal', Mandatory = $true, Position = 2)]
[String]$Level,
# Forward the InformationObject down the pipeline with additional level property.
[Parameter(ParameterSetName = 'InformationObject', Mandatory = $false)]
[Switch]$PassThru
)
Process {
# If using an information object, set log entry level according to object type.
if ($PSCmdlet.ParameterSetName -eq "InformationObject") {
$Message = $InformationObject.ToString()
# Depending on the object type, set the error level,
# add entry to cover "Write-Information" output here if needed
switch -exact ($InformationObject.GetType().name) {
"VerboseRecord" { $Level = "Information" }
"WarningRecord" { $Level = "Warning" }
"ErrorRecord" { $Level = "Error" }
}
}
# Generate timestamp for log entry
$Timestamp = (get-date).Tostring("yyyy\-MM\-dd\_HH\:mm\:ss.ff")
$LogEntryProps = @{
"Timestamp" = $Timestamp;
"Level" = $Level;
"Message" = $Message
}
$LogEntry = New-Object -TypeName System.Management.Automation.PSObject -Property $LogEntryProps
$LogEntry | Select-Object Timestamp, Level, Message | Export-Csv -Path $Path -NoTypeInformation -Append
if ($PassThru) { Write-Output ($InformationObject | Add-Member @{Level = $Level } -PassThru) }
}
}
示例用法是
& $PSScriptRoot\Some-Script.ps1 -Param $Param -Verbose *>&1 | Add-LogEntry -Path $LogPath -PassThru
-PassThru 开关本质上应该将信息对象写入控制台,如果您不捕获变量中的输出或将其通过管道传递给其他东西。