PoshCode Logo PowerShell Code Repository

Write-Log by Pat Richard 29 months ago (modification of post by Andy Arismendi view diff)
View followups from Vidrine | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/3270"></script>download | new post

Logging function for Powershell v2. Needed to address current Powershell logging limitations. See a discussion about said limitations here: http://jdhitsolutions.com/blog/2011/03/powershell-automatic-logging/#comment-2899 .

Logs to file and prints messages to the console and optionally logs to the system event logs. Note – admin rights are required when specifying the EventLogName parameter because the SourceExists method requires admin rights because it checks rights on the Security log. This limitation seems silly to me and if you think so as well get Microsoft to fix it by voting here: https://connect.microsoft.com/VisualStudio/feedback/details/293617/eventlog-sourceexists-always-fails-for-non-administrators#tabs .

Feel free to add features as necessary.

Will Steele: I suggest adding the Encoding switch to the Out-File calls (lines 58 and 60) to ensure the file didn’t clog up the output file. I also added a parameter, $LogEncoding, (lines 37-38) to allow for Encoding selection. The default is ASCII.

It might be worth adding a few lines that allow for folder creation using the input file parameter. For instance, if the folder path referenced in the -Path parameter is invalid it doesn’t handle this. Example:

dir | Write-Log -Path C:\test\test\test.txt
Contacts
Failed to create log entry in: ‘C:\test\test\test.txt’. The error was: ‘Could not find a part of the path ‘C:\test\test\test.txt’.’.
At line:86 char:9
+ throw <<<< “Failed to create log entry in: ‘$Path’. The error was: ‘$_’.” + CategoryInfo : OperationStopped: (Failed to creat…st\test.txt’.’.:String) [], RuntimeException + FullyQualifiedErrorId : Failed to create log entry in: ‘C:\test\test\test.txt’. The error was: ‘Could not find a part of the path ‘C:\test\test\test.txt’.’.

Andy Arismendi: Added support for creating directories that do not exist in the log file path.

Future ideas – make system event log optional so that the function doesn’t always require admin privs. Maybe organizing the parameters into sets…

  1. function Write-Log {
  2.  
  3.         #region Parameters
  4.        
  5.                 [cmdletbinding()]
  6.                 Param(
  7.                         [Parameter(ValueFromPipeline=$true,Mandatory=$true)] [ValidateNotNullOrEmpty()]
  8.                         [string] $Message,
  9.  
  10.                         [Parameter()] [ValidateSet(“Error”, “Warn”, “Info”)]
  11.                         [string] $Level = “Info”,
  12.                        
  13.                         [Parameter()]
  14.                         [Switch] $NoConsoleOut,
  15.                        
  16.                         [Parameter()]
  17.                         [ValidateSet("Black", "DarkMagenta", "DarkRed", "DarkBlue", "DarkGreen", "DarkCyan", "DarkYellow", "Red", "Blue", "Green", "Cyan", "Magenta", "Yellow", "DarkGray", "Gray", "White")]
  18.                         [String] $ConsoleForeground = 'White',
  19.                        
  20.                         [Parameter()] [ValidateRange(1,30)]
  21.                         [Int16] $Indent = 0,
  22.  
  23.                         [Parameter()]
  24.                         [IO.FileInfo] $Path =$env:temp\PowerShellLog.txt”,
  25.                        
  26.                         [Parameter()]
  27.                         [Switch] $Clobber,
  28.                        
  29.                         [Parameter()]
  30.                         [ValidateSet("Application","System","Security")]
  31.                         [String] $EventLogName,
  32.                        
  33.                         [Parameter()]
  34.                         [String] $EventSource,
  35.                        
  36.                         [Parameter()]
  37.                         [Int32] $EventID = 1,
  38.  
  39.                         [Parameter()]
  40.                         [String] $LogEncoding = "ASCII"
  41.                 )
  42.                
  43.         #endregion
  44.  
  45.         Begin {}
  46.  
  47.         Process {
  48.                 try {                  
  49.                         $msg = '{0} : {1} : {2}{3}' -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), (" " * $Indent), $Message                   
  50.                         if ($NoConsoleOut -eq $false) {
  51.                                 switch ($Level) {
  52.                                         'Error' { Write-Error $Message }
  53.                                         'Warn' { Write-Warning $Message }
  54.                                         'Info' { Write-Host ('{0}{1}' -f (" " * $Indent), $Message) -ForegroundColor $ConsoleForeground}
  55.                                 }
  56.                         }
  57.  
  58.                         if (-not $Path.Exists) {
  59.                                 New-Item -Path $Path.FullName -ItemType File -Force | Out-Null
  60.                         }
  61.                        
  62.                         if ($Clobber) {
  63.                                 $msg | Out-File -FilePath $Path -Encoding $LogEncoding -Force
  64.                         } else {
  65.                                 $msg | Out-File -FilePath $Path -Encoding $LogEncoding -Append
  66.                         }
  67.                        
  68.                         if ($EventLogName) {
  69.                        
  70.                                 if (-not $EventSource) {
  71.                                         $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name
  72.                                 }
  73.                        
  74.                                 if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) {
  75.                                         [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName)
  76.                         }
  77.  
  78.                                 $log = New-Object System.Diagnostics.EventLog  
  79.                             $log.set_log($EventLogName)  
  80.                             $log.set_source($EventSource)
  81.                                
  82.                                 switch ($Level) {
  83.                                         “Error” { $log.WriteEntry($Message, 'Error', $EventID) }
  84.                                         “Warn”  { $log.WriteEntry($Message, 'Warning', $EventID) }
  85.                                         “Info”  { $log.WriteEntry($Message, 'Information', $EventID) }
  86.                                 }
  87.                         }
  88.  
  89.                 } catch {
  90.                         throw “Failed to create log entry in: ‘$Path’. The error was: ‘$_’.”
  91.                 }
  92.         }
  93.  
  94.         End {}
  95.  
  96.         <#
  97.                 .SYNOPSIS
  98.                         Writes logging information to screen and log file simultaneously.
  99.  
  100.                 .DESCRIPTION
  101.                         Writes logging information to screen and log file simultaneously. Supports multiple log levels.
  102.  
  103.                 .PARAMETER Message
  104.                         The message to be logged.
  105.  
  106.                 .PARAMETER Level
  107.                         The type of message to be logged.
  108.                        
  109.                 .PARAMETER NoConsoleOut
  110.                         Specifies to not display the message to the console.
  111.                        
  112.                 .PARAMETER ConsoleForeground
  113.                         Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified.
  114.                
  115.                 .PARAMETER Indent
  116.                         The number of spaces to indent the line in the log file.
  117.  
  118.                 .PARAMETER Path
  119.                         The log file path.
  120.                
  121.                 .PARAMETER Clobber
  122.                         Existing log file is deleted when this is specified.
  123.                
  124.                 .PARAMETER EventLogName
  125.                         The name of the system event log, e.g. 'Application'.
  126.                
  127.                 .PARAMETER EventSource
  128.                         The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified.
  129.                
  130.                 .PARAMETER EventID
  131.                         The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified.
  132.  
  133.                 .PARAMETER LogEncoding
  134.                         The text encoding for the log file. Default is ASCII.
  135.                
  136.                 .EXAMPLE
  137.                         PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application'
  138.  
  139.                 .EXAMPLE
  140.                         PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script"
  141.  
  142.                 .INPUTS
  143.                         System.String
  144.  
  145.                 .OUTPUTS
  146.                         No output.
  147.                        
  148.                 .NOTES
  149.                         Revision History:
  150.                                 2011-03-10 : Andy Arismendi - Created.
  151.                                 2011-07-23 : Will Steele - Updated.
  152.                                 2011-07-23 : Andy Arismendi
  153.                                         - Added missing comma in param block.
  154.                                         - Added support for creating missing directories in log file path.
  155.                                 2012-03-10 : Pat Richard
  156.                                         - Added validation sets to $ConsoleForeground and $EventLogName
  157.                                         - Changed formatting of $msg so that only $message is indented instead of entire line (looks cleaner)
  158.                                         - suppressed output when creating path/file
  159.         #>
  160. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me