在Powershell中适当登录

时间:2014-08-28 15:25:47

标签: powershell logging

如果我有一个名为 caller.ps1 的PowerShell脚本,看起来像这样

.\Lib\library.ps1

$output = SomeLibraryFunction

其中 library.ps1 如下所示

function SomeLibraryFunction()
{
   Write-Output "Some meaningful function logging text"
   Write-Output "return value"
}

我想要实现的是库函数可以返回其值的方式,但也添加一些日志消息,允许调用者按照自己的意愿处理这些内部消息。我能想到的最好的方法是将两者写入管道,然后调用者将有一个数组,其中包含实际返回值以及可能对调用脚本具有的记录器有用的内部消息。

我是否正确地解决了这个问题?有没有更好的方法来实现这一目标?

3 个答案:

答案 0 :(得分:5)

将记录消息与实际输出混合通常不是一个好主意。然后,您的函数的消费者必须进行大量过滤才能找到他们真正想要的对象。

您的函数应将日志消息写入详细输出流。如果呼叫者想要查看这些消息,可以通过指定-Verbose切换到您的功能。

function SomeLibraryFunction()
{
    [CmdletBinding()]
    param(
    )

    Write-Verbose "Some meaningful function logging text"
    Write-Output "return value"
}

在PowerShell 3+中,消费者可以redirect your verbose messages to the output stream or a file

# Show verbose logging messages on the console
SomeLibraryFunction -Verbose 

# Send verbose logging messages to a file
SomeLibraryFunction -Verbose 4> verbose.txt

# redirect verbose message to the output stream
SomeLibraryFunction -Verbose 4>&1 

其他选项包括:

  • 写一个知名文件
  • 写入事件日志
  • 使用Start-Transcript创建会话日志。

答案 1 :(得分:1)

像Tee-Object这样的东西可能会对你有所帮助

function SomeLibraryFunction()
{
    $filepath = "C:\temp\log.txt"
    write-output "Some meaningful function logging text" |  Tee-Object -FilePath $filepath -Append
    write-output "return value" |  Tee-Object -FilePath $filepath -Append
}

有关Tee-Object外观here

的更多信息

您可以使用基于If之类的变量的$logging=$true语句,但我可以看到变得混乱。

另一种方法

如果您正在寻找更多可选解决方案,那么您可以使用类似Start-TranscriptStop-Transcript之类的内容,在文本文件中创建全部或部分Windows PowerShell会话的记录。

function SomeLibraryFunction()
{
    write-output "Some meaningful function logging text"
    write-output "return value"
}


$logging = $True
If ($logging){
    Start-Transcript -Path C:\temp\log.txt -Append
}

SomeLibraryFunction

If ($logging){
    Stop-Transcript
}

这只会显示您可以切换开始和停止。如果选择的话,甚至可以使用传递给脚本的参数来设置开关。

注意输出可能比您正在寻找的更多,但至少要试一试。此外,这在Powershell ISE中不起作用,因为您将收到错误Start-Transcript : This host does not support transcription.

答案 2 :(得分:1)

另一种方法是返回包含结果和日志信息的复合对象。这很容易分开。

function MyFunc
{

    # initialize
    $result = $null
    $log = @()

    # write to the log
    $log += "This will be written to the log"
    $log += "So will this"

    # record the result
    $result = $true

    # return result and log combined into object
    return New-Object -TypeName PSObject -Property @{ result = $result; log = $log -join "`r`n" }

}

# Call the function and get the results
$MyFuncResult = MyFunc

# Display the returned result value
Write-Host ( "MyFunc Result = {0}" -f $MyFuncResult.Result )

# Display the log
write-host ( "MyFunc Log = {0}" -f $MyFuncResult.Log )

或者,如果要避免该对象,请通过引用传入日志变量。该函数可以写入日志变量,并且更改将在调用范围中可见。为此,您需要将[ref]前缀添加到函数定义和函数调用中。当您在函数中写入变量时,需要引用.value属性。

function MyFunc2 ([ref]$log)
{

    # initialize
    $result = $null

    # write to the log
    $log.value += "`r`nThis will be written to the log"
    $log.value += "`r`nSo will this"

    # record the result
    $result = $true

    # return result and log combined into object
    return $result

}

# Call the function and get the results
$log = "before MyFunc2"
$MyFuncResult = MyFunc2([ref]$log)
$log += "`nafter MyFunc2"

# Display the returned result value
write-host ( "MyFunc2 result = {0}" -f $MyFuncResult )

# Display the log
write-host ( "MyFunc2 Log = {0}" -f $Log )