PowerShell Logging v2 – Easily create log files

Sometime back in 2011 when I first started using PowerShell, I developed some standard functions to handle the creating and management of log files for my PowerShell scripts. These functions were stored in a file called Logging_Functions.ps1 and I would simply dot source them into my script to be able to use them.

I posted them on 9to5IT PowerShell: How to easily create log files for your scripts and since then, to my surprise, they have been well received by many people, and hence the post has become quite a popular one. Recently one of the users emailed me and made a suggestion to convert them into a PowerShell Module.

That got me thinking…. so I have made a number of improvements to the PowerShell logging functions and have now made them available as a PowerShell Logging module. Available right here, below….

Before I get into the details of the PowerShell Logging module (called PSLogging), let’s walk through a few administrative items, such as why should you even use log files and what are the improvements in the PowerShell Logging version 2.

Why create log files for your PowerShell scripts?

Why you would anyone want to create and use log files for their PowerShell scripts in the first place? Here are some of my thoughts around the subject…

#1 Create re-usable, clean solutions

I find that most admins see scripting as a quick fix for a manual or repetitive task. For this reason most scripts are developed with the mentality of a once off use, as opposed to developing a tool or solution that can be re-used in the future (even if its just in part).

A key component in developing a re-usable tool or solution is error handling and logging. This gives the user of the script a seamless experience, resulting in greater up-take and re-use of your scripts, especially within non-scripting admins.

For this reason, I believe that logging should be an mandatory component of any script that is going to be used on an ongoing or regular basis or if it is to be used by someone other than yourself.

Personally, most of the scripts I write are standardised using my script template (see PowerShell Script Template Version 2) and use the PSLogging module to handle logging (my previous use my Logging_Functions solution).

#2 Develop for end-users in mind

Having a log that people can follow to understand all of the key achievements of the script is very useful. In addition, handling warning and errors by redirecting them into the logs is a nice way to keep your users happy.

In my personal experience, I have found that by developing a nice error handled and logged solution, most people will respect your scripts \ tools and they will tend to be more likely to appreciate and use what you have developed, which to be honest is really rewarding.

#3 Troubleshooting becomes easier

Logging errors and warnings also assist in the troubleshooting of the script, not only by yourself but also by your users… particularly 6 – 12 months down the track when lets say you are running the script in a different environment than what it was originally developed for. Having a log and being able to write out the result of each step of your script allows you to easily pin-point where the problem lies, especially if you pipe out warning and error messages to the log (both custom or system errors).

#4 Future Improvements

Another great reason for pro-logging is having compassion on the guy the might be having to update or troubleshoot your script \ tool in the future (even if that guy is you). Its sort of like having well commented code (which I know everyone does… lol), it makes it easier for someone else to be able to understand what your script is doing and why it is doing it.

#5 Ease of Use

Finally, the reason why I personally like logging is because of the way I develop functionality in my scripts. Each separate function is a single task or component that achieves a specific result that contributes to the end solution. All I have to do then is call each function in the correct order and pass whatever parameters I have specified.

Because this is the way I develop, using my PowerShell logging module allows me to write my logs in the same way. Each function writes its own comments in the log, and once executed successfully, will write a success message. Doing this allows me to easily identify in exactly which function I have an issue and therefore make resolution much quicker and easier.

PSLogging Module – How does it work?

In order to be able to get the most of your PowerShell Logging using the PSLogging module, let’s have a look at what is included:

  • Start-Log – Creates a new .log file and initialises the log with execution date, time and script version
  • Stop-Log – Completes the PowerShell Logging and writes ending date and time. Optionally terminates the calling script
  • Send-Log – Sends an email with the contents of the log file to a specified set of email addresses
  • Write-LogInfo – Writes an informational message to the log file
  • Write-LogWarning – Writes a warning message to the log file (with the format of WARNING: )
  • Write-LogError – Writes an error message to the log file (with the format of ERROR: ). In addition, optionally calls Stop-Log to end logging and terminate the calling script on fatal error.

PowerShell Logging (Easily Create Log Files Version 2) – What is new?

The PSLogging module is based on my original Logging_Functions.ps1 solution (which has had much success), but with a number of improvements, streamlines and new features. Here is what is new:

  • My PowerShell Logging solution is now a PowerShell Module, which means it no longer needs to be dot-sourced. It can easily be installed (even automatically using PowerShell 5) and imported and then used as often as required.
  • Cmdlets use PowerShell approved verbs. I have re-written all of the cmdlet names so that they are in the standard PowerShell format of Verb-Noun. In addition, I have ensured that all logging cmdlets now use approved verbs only.
  • Improved Help. I have considerably improved the help information available for each of the cmdlets, which means on any of the PSLogging cmdlets you can call Get-Help to return detailed information and examples, exactly the same as you would for any other standard PowerShell cmdlet.
  • New Write-LogWarning cmdlet. You can now log not only informational and error messages but warning messages to. Warning messages have the prefix of WARNING: allowing you to easily identify potential issues within your log file. If you are using a log viewer (such as CMTrace.exe, all warnings will now auto highlight in yellow).
  • Improved Write-LogError cmdlet. Similarly, I have improved the error logging cmdlet so that all error messages are prefixed with ERROR:, again making it easier to identify within the log file. If you are using a log viewer (such as CMTrace.exe, all errors will now auto highlight in red).
  • Improved Send-Log cmdlet. In the previous version you would have to edit the Logging_Functions.ps1 file to include the FQDN of your SMTP server in order to be able to send logs via email. I have now improved that, so that the SMTP server is passed as a parameter, therefore eliminating the requirement of having to edit the PSLogging module at all.
  • Improved Parameters. All cmdlets now have standardised parameter names and have the ability to pass data by their positional order without the need to specify the parameter name.

Log File Format

Using the PSLogging module allows you to not only standardise the way you handle logging and errors in your PowerShell scripts, but also allows for the standardisation of the log files themselves, allowing your users to get the same experience across all of your scripts. This not only makes troubleshooting easier but also improves your script ‘rep’, resulting in a greater up-take of your scripts.

If you are wondering what a log file generated using the PSLogging module looks like, here is an example below:

PSLogging Log File Example

Download Links

Enough back info, let’s get to the good stuff – where to get the PSLogging Module from. Here are the download locations:

Install Instructions

Follow these steps to install and start using the my PowerShell Logging solution:

Any PowerShell Version:
  1. Download PSLogging from any of the links above
  2. Copy the PSLogging directory (and its contents) to your PSModulePath location. This can be either of the following locations:
    1. Install for Current User$Home\Documents\WindowsPowerShell\Modules (%UserProfile%\Documents\WindowsPowerShell\Modules)
    2. Install for All Users$Env:ProgramFiles\WindowsPowerShell\Modules (%ProgramFiles%\WindowsPowerShell\Modules)
    3. For more information see Microsoft TechNet – Installing PowerShell Modules
  3. To use PSLogging, in the script you want to use it (or in your current PowerShell environment) run Import-Module PSLogging.
  4. You will now be able to call all of the PSLogging cmdlets just like you would any other cmdlet. In addition you can run Get-Help -Full on any of the PSLogging cmdlets to get full detailed help and examples.
PowerShell v5 (Install PSLogging):
  1. From PowerShell, run Install-Module PSLogging -Scope CurrentUser
  2. To use PSLogging, in the script you want to use it (or in your current PowerShell environment) run Import-Module PSLogging.
  3. You will now be able to call all of the PSLogging cmdlets just like you would any other cmdlet. In addition you can run Get-Help -Full on any of the PSLogging cmdlets to get full detailed help and examples.
PowerShell v5 (Update PSLogging):
  1. From PowerShell, run Update-Module PSLogging -Force
  2. The latest version of PSLogging will automatically install

Note 1: To be able to use Install-Module and Update-Module in PowerShell 5, you need to run it on a machine that has an internet connection. If your machine cannot connect to the internet, then follow the Any PowerShell Version install section above.

Note 2: If you want to have the PSLogging module available in all of your PowerShell sessions, then once you have installed it you can add the Import-Module PSLogging command to your PowerShell Profile. For more information see – Understanding and Using PowerShell Profiles.

How To Create Log Files using PSLogging

Now that you have installed the PSLogging Module, you now want to be able to use it to create some log files for your PowerShell scripts. Here is some information on how to do that:

  1. First off, if you haven’t already you need to import the PSLogging module to be able to use it. To do this add the following code at the top of your script:
    
    Import-Module PSLogging
    
  2. Next you want to create the log file and start the initial logging. To do this use the following code:
    
    Start-Log -LogPath “C:\Windows\Temp” -LogName “Test_Script.log” -ScriptVersion “1.0”
    
  3. Here is how to write messages to the log file:
    
    # Write an informational message to the log file
    Write-LogInfo -LogPath “C:\Windows\Temp\Test_Script.log” -Message “This is a new line which I am appending to the end of the log file.”
    
    # Write a warning message to the log file
    Write-LogWarning -LogPath “C:\Windows\Temp\Test_Script.log” -Message “This is a warning message.”
    
    # Write an error message to the log file
    Write-LogError -LogPath “C:\Windows\Temp\Test_Script.log” -Message “This is an error message.” -ExitGracefully $False
    
  4. Finally, you want to close the logging, exit the script and write the final logging comments to the log file. To do this, use the following:
    
    Stop-Log -LogPath “C:\Windows\Temp\Test_Script.log”
    

You now know how to easily transform your existing (and new) scripts into PowerShell solutions by creating log files using the PSLogging module.

PowerShell Script Templates

If you are interested in creating log files for any of your new PowerShell scripts, then why not take a look at my PowerShell Script Templates. Not only will your scripts consistently and cleanly laid out, but the script templates I have developed already have all of the PSLogging functionality baked in, so it makes it even easier to create log files for your PowerShell scripts.

To coincide with my PowerShell Logging Version 2 (PSLogging Module) release, I have updated and improved all of my script templates as well. I have also added my script templates to the PSLogging GitHub repository, making it easier to get going with both logging and script creation in general.

If you are interested in more information about each of my script templates, then take a look at the following articles:

Updates – Version 2.5.1

As of, 12 September 2015, I have released version 2.5.1 of my PSLogging Module. Here are the improvements and changes that have been made:

  • -ExitGracefully parameter in the Write-LogError cmdlet: No longer needs to be specified using $True. All you need to do is call the parameter and it will automatically set itself to True. If you don’t specify the parameter, it set itself to False.
  • -NoExit parameter in the Stop-Log cmdlet: No longer needs to be specified using $True. All you need to do is call the parameter and it will automatically set itself to True. If you don’t specify the parameter, it set itself to False.
  • -ToScreen parameter: Applies to all of the cmdlets except Send-Log. When specified, will display the content that is being written to the log file to the screen as well as writing the content to the log file. This means you no longer need to set your scripts in debug mode if you want to display the content to screen. The content of the log file will still display to screen if your script is in debug mode, whether or not the -ToScreen parameter is set.
  • -TimeStamp parameter: Applies to all of the Write-Log cmdlets (i.e. Info, Warning, Error). When specified will append the current date and time as a timestamp to the message that is being written to the log file. This is useful if you want to document when something in your script commences and when it ends.
  • Minor improvements to consistency across all cmdlets.
  • Minor improvements to the help documentation.

If you have any issues with any of the new functionality, or you are unsure of how to use it, please let me know in the comments below or via an email.

Additional Help

If you have any problems using my PowerShell Logging solution (PSLogging) then please let me know in the comments below or send me an email.

Also, if you have any suggestions for improvements for future releases, then I really interested in hearing your ideas. Shoot me an email or use the comments below!

Hope this helps and happy scripting 🙂
Luca

Comments

  1. I downloaded the module and wrote a script yesterday and wanted to add the send-log cmdlet into the script but it seems that cmdlet doesn’t work if used after stop-log has been used. I had to use it prior to that command but then I don’t get the ending time in the log transcript that is sent to my email account. Is this by design or a bug?

  2. Anyway to add a time stamp to each line in the log? Would be nice to know when a process within a script begins and ends.

    1. Hi Brian,

      Good to hear you worked out the -NoExit switch. I might need to put some documentation around that to make it easier for people.

      In terms of time stamp, I might release an update that will include that as a switch on the Write-Logxxxx cmdlets. When I do I will let you know.

      Thanks for using my PowerShell Logging cmdlets.

      Luca

  3. Thanks for the response. It looks like thought using the -NoExit switch it isn’t posting an end time and closing out the log file like it was prior to using it.

    1. Hi Brian,

      The reason why you are having an issue is because in the version you are running you need to specify the -NoExit parameter like this: -NoExit $True.

      The good news is that I have updated the PSLogging Module to version 2.5.1 and have fixed that in this release. All you now need to do is specify the -NoExit parameter and it will automatically set it to $True for you. Same goes for the -ExitGracefully parameter. I have update my PowerShell and PowerCLI script templates to reflect these improvements.

      I have also added some new functionality in this release of the PSLogging Module. If you are interested in finding out what is new, check out the Updates – Version 2.5.1 section of the article. The most notable change is I have added the ability to write the log to screen as well as to log file (via the -ToScreen parameter). I have also added the ability to write a timestamp at the end of each line written to the log file. This is achieved through the -TimeStamp parameter.

      Hope these new updates help!
      Luca

      1. Is there a way for the script to keep running if a function fails? My experience has been that if a function fails the script closes and the rest of the functions in my scripts do not run. I noticed the -NoExit parameter you guys are mentioning would I just replace the -ExitGracefully with -NoExit? Another thing I had to do was break up my scripts based on Organizing its role so some of my scripts at the end use the Invoke command to run the next script this breaks the log being created and I dont get the end timestamp. Not a big deal as the new script starts a new log file just something that may be my inexperience with this type of thing.

        Thanks for your module btw I really enjoy it.
        Scott

        1. Hi Scott,

          Thanks very much, glad to hear you like it and it has helped you. Yeah you are right use the -NoExit parameter instead of -ExitGracefully in order to not exit on a function fail. To solve your problem of not getting the end timestamp, if you call Stop-Log with the -NoExit parameter, it will write the ending timestamp and then allow you to execute any other commands. I usually use it in combination with the Send-Log cmdlet but you can use it with anything including invoke.

          Hope that helps.

          P.S. Sorry about the super late reply.

          Luca

          1. Yes this solved my issue and no longer quits on a failed function but it doesn’t give any error information in the log. Not to big of a deal I was able to Write-LogInfo above the Write-LogError line in your template with the failed function so it writes to the log and continues.

  4. I’m having problems with PSLogging module using your Poweshell Template. It does not seem to create the log file – no errors displayed and the Copy-Item function that I am using in the script works OK.

    Also I can’t seem to be able to download v2.5.1 from https://www.powershellgallery.com/packages/PSLogging/. Save-Module -Name PSLogging -Path C:\Program Files\WindowsPowerShell\Modules\PSLogging and Install-Module -Name PSLogging -version 2.5.1 in Windows PowerShell ISE does not seem to do anything either.

    1. Hi Bruce,

      What exactly is happening when you try and use the PSLogging Module?

      Once you have downloaded it and copied to to the appropriate module install location (either for the system or the user), you then need to import the module into the PowerShell session before you can use it. You do this by using the Import-Module cmdlet.

      For more information on how it all works, take a look at my PowerShell Script Template which integrates the PSLogging module and makes it easier to use. If by any chance you use PowerCLI to manage your vSphere infrastructure, then I have a PowerCLI Script Template as well.

      Hope this helps
      Luca

  5. I have downloaded PSLogging.psd1 v2.5.2 today

    When I run Import-Module cmdlet I get:-
    PS C:\WINDOWS\system32> import-module pslogging
    import-module : The module manifest ‘C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1’ could not be
    processed because it is not a valid Windows PowerShell restricted language file. Remove the elements that are not
    permitted by the restricted language:
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:100 char:12
    + <!– –>

    <form accept-charset="UTF-8" action="/9to5 …
    + ~
    The '

    <input name="authenticity_token" type="hidden" value= …
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
    quotation marks ("&") to pass it as part of a string.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:469 char:11
    + 121 lines (80 sloc)
    + ~~~~~
    Unexpected token 'lines' in expression or statement.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:469 char:21
    + 121 lines (80 sloc)
    + ~~~~
    Unexpected token 'sloc' in expression or statement.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:469 char:20
    + 121 lines (80 sloc)
    + ~
    Missing closing ')' in expression.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:469 char:25
    + 121 lines (80 sloc)
    + ~
    Unexpected token ')' in expression or statement.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:471 char:10
    + 6.98 KB
    + ~~
    Unexpected token 'KB' in expression or statement.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:485 char:117
    + … est for module 'PSLogging'
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
    quotation marks (“&”) to pass it as part of a string.
    At C:\Program Files\WindowsPowerShell\Modules\pslogging\pslogging.psd1:527 char:81
    + … ne”>RootModule = 'PSLogging.psm …
    + ~
    The ‘<‘ operator is reserved for future use.
    Not all parse errors were reported. Correct the reported errors and try again.
    At line:1 char:1
    + import-module pslogging
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ResourceUnavailable: (C:\Program File…\pslogging.psd1:String) [Import-Module], Missing
    MemberException
    + FullyQualifiedErrorId : Modules_InvalidManifest,Microsoft.PowerShell.Commands.ImportModuleCommand

    ==================================================

    However, I can run the script and on screen I can see the Comments displayed as it goes through the script but does not do what the script says – in this case copying files from one location to another and also not creating a log file.

  6. I found the problem in my copy file script – syntax error in file path – but this error was not captured by PSLogging and seems to have prevent creation of a log file. Now syntax arror is correct I get a log file for a successful file copy.

    1. Hi Bruce,

      What version of PowerShell are you running this on and what OS is your machine?

      I will try and reproduce the same issue on the same version of OS and PowerShell and see what happens.

      Thanks

  7. Windows Server 2008 R2 Standard. Powershell v4.0 (upgraded from PowerShell v1.0). And I have been using my laptop which is Windows 8.1 Enterprise with Powershell 4.0.

  8. The logger and templates are working really well for me. Thanks for making them available.
    Let’s say that I want to write a few rows from a database table to the logfile. Something like this:
    $Reader = $SqlCmd.ExecuteReader()
    if ($Reader.HasRows)
    {
    while ($Reader.Read()) {
    $name=$Reader.GetValue(0)
    $Rows=$Reader.GetValue(1)
    $message=$name+’ ‘+$Rows
    Write-LogInfo -LogPath $sLogFile -Message $message
    }
    }
    else {
    Write-LogInfo -LogPath $sLogFile -Message “No Records”
    }
    Do you have a slick way to format this as a table in the log file?

    1. Hi Phil,

      Glad to hear that it has been helpful.

      At this stage I don’t have anything, however I could potentially add something in the future. The only thing I can think of is to have a seperate csv file that contains the data and you can use the Export-Csv cmdlet to create the csv file. Alternatively you could try formatting it manually using spaces or - or | if you know what I mean.

      Hope this helps
      Luca

  9. Hi guys, I adjusted the sample script to what i have here.

    ==========================================================

    “`
    <#
    .SYNOPSIS
    This script is to restart Message Queing and PieterBas Weegbrug Services

    .DESCRIPTION
    This script will restart the mentioned services at 00.00 hr.

    .PARAMETER

    .INPUTS

    .OUTPUTS
    Log File The script log file stored in C:\PBA\Restart\Restart_MSMQ_PBA.log

    .NOTES
    Version: 1.0
    Author: Roy van der Steen
    Creation Date: 18-12-2015 09:15
    Purpose/Change: Initial script development

    .EXAMPLE

    >

    ———————————————————[Initialisations]——————————————————–

    Set Error Action to Silently Continue

    $ErrorActionPreference = ‘SilentlyContinue’

    Import PSLogging Module

    Import-Module PSLogging

    ———————————————————-[Declarations]———————————————————-

    Script Version

    $sScriptVersion = ‘1.0’

    Log File Info

    $sLogPath = ‘C:\PBA\Restart’
    $sLogName = ‘Restart_MSMQ_PBA.log’
    $sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName

    ———————————————————–[Functions]————————————————————

    <#

    Function {
    Param ()

    Begin {
    Write-LogInfo -LogPath $sLogFile -Message ‘Begin to execute the restart of services’
    }

    Process {
    Try {

    }
    
    Catch {
      Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
      Break
    }
    

    }

    End {
    If ($?) {
    Write-LogInfo -LogPath $sLogFile -Message ‘Completed Successfully.’ Write-LogInfo -LogPath $sLogFile -Message ‘ ‘ }
    }
    }

    ———————————————————–[Execution]————————————————————

    Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersion -TimeStamp

    Script Execution goes here

    Param ( [Parameter(Mandatory=$true)] [String]$ServiceName )
    [System.Collections.ArrayList]$ServicesToRestart = @()

    function Custom-GetDependServices ($ServiceInput) {
    #Write-Output “Name of“$ServiceInput: $($ServiceInput.Name)”
    #Write-Output “Number of dependents: $($ServiceInput.DependentServices.Count)”

    If ($ServiceInput.DependentServices.Count -gt 0) {
    ForEach ($DepService in $ServiceInput.DependentServices) {
    #Write-Output “Dependent of $($ServiceInput.Name): $($Service.Name)”
    If ($DepService.Status -eq “Running”) {
    #Write-Output “$($DepService.Name) is running.”
    $CurrentService = Get-Service -Name $DepService.Name

        # get dependancies of running service
        Custom-GetDependServices $CurrentService                
      }
      Else
      {
        Write-LogInfo -TimeStamp "$($DepService.Name) is stopped. No Need to stop or start or check dependancies." 
      }
    }
    

    }

    Write-LogInfo -TimeStamp “Service to Stop $($ServiceInput.Name)”

    if ($ServicesToRestart.Contains($ServiceInput.Name) -eq $false) {
    Write-LogInfo -TimeStamp “Adding service to stop $($ServiceInput.Name)”
    $ServicesToRestart.Add($ServiceInput.Name)
    }
    }

    Get the main service

    $Service = Get-Service -Name $ServiceName

    Get dependancies and stop order

    Custom-GetDependServices -ServiceInput $Service

    Write-LogInfo -TimeStamp “Stopping Services…..”

    foreach($ServiceToStop in $ServicesToRestart) {
    Write-LogInfo -TimeStamp “Stop Service $ServiceToStop” Stop-Service $ServiceToStop -Verbose #-Force
    }

    Write-LogInfo -TimeStamp “Starting Services….”

    Reverse stop order to get start order

    $ServicesToRestart.Reverse()

    foreach($ServiceToRestart in $ServicesToRestart) {
    Write-LogInfo -TimeStamp “Start Service $ServiceToRestart”
    Start-Service $ServiceToRestart -Verbose
    }

    Write-LogInfo -TimeStamp “Restart of services completed”

    Stop-Log -LogPath $sLogFile
    “`

    The message that i get when executing this script is: “cmdlet Write-LogInfo at command pipeline position 1 Supply values for the following parameters: Message:”

    What am I missing..?

    Cheers..

    1. Hi Roy,

      The reason why this is happening is because you haven’t specified the LogPath parameter, such as in the example below:

      Write-LogInfo -LogPath $sLogFile -Message '<description of what is going on>...'

      The best thing if you are using the PSLogging Module is to use the PowerShell Script Template Version 2, as it has already been configured to work with the PSLogging Module. The Script Template is available here >>> PowerShell Script Template v2

      Hope this helps
      Luca

  10. Why does every call to Write-LogInfo() and Write-LogError() require me to specify the LogPath parameter? That doesn’t make any sense. You should initialize once at the start and from then on do easy logging, right?

    1. Hi Leon,

      Good point, I like that idea. I will add that to my future improvements list and work on that when I have a chance.

      Thanks
      Luca

    2. Hi Leon,
      I have a use case… I built a script that does many things and for clarity, i do have two scripts, so I can track what’s going on. On of the logs is for the script execution so I know if it fails somewhere, and also gives me an abstract of the executed actions. The other log, just give me what actions have been done, fully detailed.

      @Luca, thanks for this awesome module!

  11. A couple of things. First, thanks for putting this together. I did have a problem where the script goest to make the log file, the syantax for the New-item command is ?ItemType which throows an error. Changed it to -ItenmType and it worked..

    Suggestions:

    Would love to see the time stamp option as requested earlier
    Would like to be able to append a log
    Would like to see the script create the logfile path if it doesnt exist already.

      1. Hi Lee,

        Thanks for the comments and suggestions. I have already implemented the timestamp option and is available in the latest version of PSLogging (which is version 2.5.2). In regards to the other two suggestions, I like them and I am actually keeping a to-do list of all of the improvements and suggestions people make. Next time I get a chance to do an update on the PSLogging Module, I will include these updates.

        I also see the need for some better documentation of the PSLogging Module on 9to5IT, so that is another thing I want to focus on this year.

        I will let everyone know through 9to5IT when I release new versions.

        Thanks for your support and suggestions, it is good to have a community to help you think of improvements for new releases.

        Thanks
        Luca

  12. Luca,
    great Logging module!

    I just realized that I have posted this first on the page of the old Logging Functions. I apologize for this.
    I am using your new logging module (v2) and it works pretty well, although there is one thing I cannot understand.

    I am using them in one of my scripts to migrate a bunch of SharePoint site collections from one farm to another.
    I have a strange behavior that I cannot explain as I am reusing the same code for every site collection.

    Basically when I call the logging function to append a line, sometimes it gives me an error. The same code snippet works perfectly for other site collections.

    The code I use to add lines to the log is:

    function MountSiteCollectionWithContentDB ($DBserver, $dbname, $webapp, $site, $owner1, $owner2, $maxSite, $warningSite, $RestoreDB ) {

    Function to create/import site collection with dedicated DB

    ...
    Write-LogInfo -LogPath $Log -Message “PHASE 3 – CREATING new Site Collection $site” -ToScreen -TimeStamp
    Write-LogInfo -LogPath $Log -Message ” SITE COLLECTION: $site” -ToScreen
    Write-LogInfo -LogPath $Log -Message ” WEB APPLICATION: $webapp” -ToScreen
    Write-LogInfo -LogPath $Log -Message ” DATABASE: $dbname $OFS” -ToScreen
    ...

    The error that I get is shown below:

    Add-Content : Cannot use interface. The IContentCmdletProvider interface is not implemented by this provider.
    At C:\Program Files\WindowsPowerShell\Modules\PSLogging\PSLogging.psm1:210 char:5
    + Add-Content -Path $LogPath -Value $Message
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotImplemented: (:) [Add-Content], PSNotSupportedException
    + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.AddContentCommand

  13. Actually I think you can discard my comment.
    I have reviewed my script and I found a typo in a variable name when I was calling “Write-LogInfo”.

    After I corrected this mistake I did not experience anymore the problem mentioned in my previous post.

    1. Hi Oliviero,

      Glad you managed to work it out and it was an easy one!

      Thanks for letting me know
      Luca

  14. Here are some ideas for you…

    Send-Log
    – EmailSmtpPort (Need this for Gmail)
    – EmailBody (May not want the whole log inserted as text in an email)
    – SendAttachment

    This is just personal preference but I find that logs are easier to read when the Date/Time stamp is in front of ALL messages, in a different format as well.
    Get-Date -Format “yyyy.MM.dd – HH:mm:ss”

    1. Hi Robert,

      Thanks very much for the suggestions. I will add them to my list of improvements for future updates.

      Luca

  15. How do I send the log to multiple email addresses? What is the format between the email addresses that is required? I have implemented an generic email message (send-mailmessage) this way, but it is not working with the PSLogging script:

    $recipients = “Person One email1@email.org“, “Person Two email2@email.org
    Send-Log -SMTPServer “ourserver.org” -LogPath $sLogFile -EmailFrom “email1@email.org” -EmailTo $recipients -EmailSubject “TEST”

    1. Nevermind… I found the answer buried in one of your templates on a different page. I had quotes around each email address instead of around the entire email address list.

      -EmailTo “email1@email.org, email2@email.org

  16. Is it possible to authenticate to a SMTP server? Also, when I try Send-Log from directly in Powershell, it immediately quits my Powershell console.

    1. Hi Mark,

      At this stage I have not built in authentication, but have a look at this Stack Overflow post for more info >>> http://bit.ly/2dZDyI7.

      What version of PowerShell are you running? Have you tried on another machine?

      Thanks
      Luca

  17. Hi,
    I have a few issues, including problems and suggestions.

    I copy-pasted from the sample scripts, but added this line to create log folder if not exist:
    New-Item -ItemType Directory -Force -Path $sLogPath
    It would be good if inserted into Start-Log by default.
    IT OVERWRITES. It’s not a shouting but a shocked and worried expression of mine. I can have only one runtime log. It overwrites on old log file. I assumed it’s because of the forced folder creation but it didn’t solve when I removed the line. I can’t append, sadly.
    So much stars. It distracts me. I believe only before the Start-Log and after the Stop-Log. They may even be some dashes instead of stars.
    It’d be nice to format the message like:

    DATE TIME INFO Started processing at [11/13/2016 21:19:59].
    DATE TIME INFO Running script version [1.3].
    DATE TIME INFO ...
    DATE TIME WARNING ...
    DATE TIME INFO Finished processing at [11/13/2016 21:20:01].

    That would be a readable format.
    I wanted to change your module but I would lose them on further updates, so I feel the urge to tell these to you.

    Thanks in advance.

    1. Hi Zafer,

      The easiest way to keep your logs will would be to run Stop-Log with the -NoExit parameter and then after that copy your log somewhere else or rename it with the data and time.

      Hope that helps
      Luca

    1. Hi Bob,

      At this stage there is no functionality to append, but I will be bringing that out in a future release.

      Thanks
      Luca

  18. I must not understand GitHub all that well, but I created a fork and pull request with an updated version of your module. This version has time stamps at the beginning, directs ToScreen to verbose, and adds an Append option to the Start-Log function.

    The branch is PHactotum / PSLogging

    Perry Harris
    PHactotum

  19. I was trying to get the logging path to be relative to the folder the script is running in… but, it seems that only a absolute path will work. Is it possible to make something like this work?
    $loggingPath = “.\logs\”
    or
    $loggingPath = “\logs\”

    Great module – thanks!

    1. Hi Vinny, the easiest way is to use the $PSScriptRoot variable which is a default variable in PowerShell 3 and above. It essentially contains the path of the folder you are executing the script from. Here is some further information about relative file paths in PowerShell scripts that might be useful >>> Relative file paths in PowerShell.

      Hope that helps
      Luca

  20. Will be there any future version thats supports logging to the windows event log?
    This would allow to collect the log information very easy from all computers in an active directory domain.

  21. Ive been using PSLogging for some time, and it is awesome.mkeep up the good work. in a recent attempt to catch logs, i am getting an alternate data stream error when trying to write the log – the log file still appears to generate, but shouldnt be pulling errors to the screen. not sure what might cause that.

    derek

  22. Thanks for the script. A little annoying that LogPath has a different meaning for Start-Log than it does for the rest of the commands. At least in your examples, it’s the folder of the log file, whereas Write/Stop-Log both reference the full file path.

  23. You could use the standard powershell command Write-Eventlog.
    Something like this:
    Write-EventLog -LogName "Application" -Source "MyApp" -EventID 3001 -EntryType Information -Message "MyApp added a user-requested feature to the display." -Category 1 -RawData 10,20

  24. I know that I can use variables in the -Message like this:

    $Array = @()
    $Array = get-Item "C:\Temp"
    Write-LogInfo -LogPath $LogFile -Message "This is the contents of a variable $Array"

    Result: This is the contents of a variable C:\Temp

    But when I try the following I get unexpected results.

    $Array = @()
    $Array = get-Item "C:\Temp"
    Write-LogInfo -LogPath $LogFile -Message "This is the contents of a variable $Array[0].Name"

    Result: This is the contents of a variable C:\Temp[0].Name

    The “.Name” Property does not get resolved but gets inserted as littereal text. Only the default value of $Array gets resolved.

    A workaround would be to put $Array[0].Name into an other variable and then put that into -Message.

    I’ve tried severaql thins like using “$Array[0].Name”, ‘$Array[0].Name’ and ($Array[0].Name). No of which produced the wanted result.

    Is there another way to do this?

    On a side not….
    Just before this comment I put in a comment to Lukas’s comment from APRIL 20, 2017 AT 9:33 PM. Although it got accepted it never showed?

  25. Hi, Great code!
    I am seeing this error on calling
    Write-LogInfo -LogPath $logFilePath -Message “This is a new line which I am appending to the end of the log file.” -ToScreen -TimeStamp

    Write-LogInfo : A positional parameter cannot be found that accepts argument ‘is’.
    At C:\Kalyan\Citi\Citi\Functions\install.ps1:22 char:1
    + Write-LogInfo -LogPath $logFilePath -Message “This is a new line wh …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Write-LogInfo], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Write-LogInfo

    Any help would be great!

  26. I have a suggestion for improvement.
    I see that this allows for appending to the current log file, so long as you don’t stop the log.
    Is there any reason you didn’t provide a way to append to a pre-existing log file?

    For example
    Start-Log ….
    … Add ABC
    Stop-Log ….

    Example Output

    — Start Logging [timestamp] —
    ABC [timestamp]
    — Stop Logging [timestamp] —

    Start-Log ….
    … Add XYZ
    Stop-Log ….

    Example Output

    — Start Logging [timestamp] —
    ABC [timestamp]
    — Stop Logging [timestamp] —
    — Start Logging [timestamp] —
    XYZ [timestamp]
    — Stop Logging [timestamp] —

  27. Line 91 there’s a typo, looks like a random unicode character:
    New-Item -Path $sFullPath ?ItemType File

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.