PowerShell Logging Functions
I have been working on automating my organizations Active Directory/Exchange user provisioning, and needed a method to easily log what actions are taken. To accomplish this, I decided to write a couple PowerShell logging functions that I could integrate into my other functions for creating the user, creating the mailbox, generating approval emails, and assigning groups. The functions I came up with are Start-Log, Write-Log, and Stop Log.
My goal was to create a log file with some basic information (time, username, and machine calling the function) with Start-Log. Then, Write-Log will write a line to the file with a timestamp, username, and specified log message. Finally, Stop-Log will right a tail line with the same information as Start-Log. Here are the functions:
Start-Log:
FUNCTION Start-Log{
<#
.SYNOPSIS
Creates log file
.DESCRIPTION
Creates log file based on specified name and path, backs up existing log if exists
.PARAMETER Path
Requires a valid path
.PARAMETER Name
Requires a valid filename
.EXAMPLE
PS C:\> Start-Log -Path "C:\Temp" -Name "NewLog.log"
.NOTES
Author : Ryan DeVries
Last Updated: 2015/05/19
Version : 1
#>
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter the path for the log directory",ValueFromPipeline)]
[ValidateNotNullorEmpty()]
[String]$Path,
[Parameter(Position=1,Mandatory,HelpMessage="Enter the name of the log",ValueFromPipeline)]
[ValidateNotNullorEmpty()]
[String]$Name
)
begin {
Write-Verbose "Starting $($MyInvocation.Mycommand)"
Write-Verbose "Detected parameter set $($PSCmdlet.ParameterSetName)"
Write-Verbose ($PSBoundParameters | out-string)
}
process {
try {
$fullpath = $path + "\" + $name
$bakpath = $fullpath + '.bak'
Write-Verbose "Checking for existing log at $fullpath"
if(Test-Path -Path $fullpath){
Move-Item -Path $fullpath -Destination $bakpath -Force -ErrorAction Stop
Write-Verbose "Backed up existing log to $bakpath"
}
New-Item -Path $path -Name $name -ItemType file -ErrorAction Stop | Out-Null
Write-Verbose "Created log at $fullpath"
Add-Content -Path $fullpath -Value "Log started: at [$([DateTime]::Now)] by $env:USERNAME on $env:COMPUTERNAME"
Add-Content -Path $fullpath -Value "--------------------------------------------------------------------`n"
Write-Verbose "Started Log at $fullpath"
}
catch { Write-Error $_ }
}
end { Write-Verbose "Ending $($MyInvocation.Mycommand)" }
}
Nothing super complex going on here. Here is the basic flow:
- Takes a couple strings as input, one as the path to store the log in, one as the name of the log file
- Checks if a file with that name already exists, renaming it with .bak if it does. If a .bak exists, it will overwrite it.
- Creates the log file and adds a header to it using environment variables
Write-Log:
FUNCTION Write-Log{
<#
.SYNOPSIS
Writes a line to a log file
.DESCRIPTION
Writes a line to the end of the specified log file, prepended with a timestamp
.PARAMETER Path
Specifies a valid log path
.PARAMETER Line
Specifies a line to add to the log
.EXAMPLE
PS C:\> Log-Write -Path "C:\Temp\NewLog.log" -Line "Test message please ignore."
.NOTES
Author : Ryan DeVries
Last Updated: 2015/05/19
Version : 1
#>
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter the path of the log file",ValueFromPipeline)]
[ValidateNotNullorEmpty()]
[String]$Path,
[Parameter(Position=1,Mandatory,HelpMessage="Enter the line to add to the log",ValueFromPipeline)]
[ValidateNotNullorEmpty()]
[String]$Line
)
begin {
Write-Verbose "Starting $($MyInvocation.Mycommand)"
Write-Verbose "Detected parameter set $($PSCmdlet.ParameterSetName)"
Write-Verbose ($PSBoundParameters | out-string)
}
process{
if(Test-Path -Path $path){
$timeline = "$([DateTime]::Now)" + "`t" + $env:USERNAME + "`t" + $line
Write-Verbose "Writing $timeline to $path"
Add-Content -Path $path -Value $timeline
}
else{ Write-Error "Log does not exist at $path " -Category ResourceUnavailable }
}
}
This one is even simpler, just takes a path and a message and writes a line, including a timestamp and username, if the file exists.
Stop-Log:
FUNCTION Stop-Log{
<#
.SYNOPSIS
Ends log file
.DESCRIPTION
Adds a closing line to a log file
.PARAMETER Path
Requires a valid log path
.EXAMPLE
PS C:\> Stop-Log -Path "C:\Temp\NewLog.log"
.NOTES
Author : Ryan DeVries
Last Updated: 2015/05/19
Version : 1
#>
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter the path of the log file",ValueFromPipeline)]
[ValidateNotNullorEmpty()]
[String]$Path
)
begin {
Write-Verbose "Starting $($MyInvocation.Mycommand)"
Write-Verbose "Detected parameter set $($PSCmdlet.ParameterSetName)"
Write-Verbose ($PSBoundParameters | out-string)
}
process {
if(Test-Path -Path $path){
Write-Verbose "Finalizing Log at $path"
Add-Content -Path $Path -Value "`n--------------------------------------------------------------------"
Add-Content -Path $Path -Value "Log ended: at [$([DateTime]::Now)] by $env:USERNAME on $env:COMPUTERNAME"
}
else{ Write-Error "Log does not exist at $path " -Category ResourceUnavailable }
}
end { Write-Verbose "Ending $($MyInvocation.Mycommand)" }
}
This one is the same as Write-Log, except it only needs a path and writes a couple tail lines if the file exists.
Here is an example of what the output looks like:
Log started: at [05/21/2015 13:15:06] by rdevries on FNY-WS-XXXXXXXX -------------------------------------------------------------------- 05/21/2015 13:15:21 rdevries test message 1 05/21/2015 13:15:26 rdevries test message 2 -------------------------------------------------------------------- Log ended: at [05/21/2015 13:15:32] by rdevries on FNY-WS-XXXXXXXX
As usual, latest versions can be found on GitHub.