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:

  1. Takes a couple strings as input, one as the path to store the log in, one as the name of the log file
  2. Checks if a file with that name already exists, renaming it with .bak if it does.  If a .bak exists, it will overwrite it.
  3. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *