├── .gitignore ├── ScriptLogger ├── Resources │ ├── ScriptLogger.Types.ps1xml │ └── ScriptLogger.Formats.ps1xml ├── en-US │ └── about_ScriptLogger.help.txt ├── Tests │ └── Unit │ │ ├── Stop-ScriptLogger.Tests.ps1 │ │ ├── Get-ScriptLogger.Tests.ps1 │ │ ├── Write-WarningLog.Tests.ps1 │ │ ├── Write-VerboseLog.Tests.ps1 │ │ ├── Write-InformationLog.Tests.ps1 │ │ ├── Set-ScriptLogger.Tests.ps1 │ │ ├── Write-ErrorLog.Tests.ps1 │ │ └── Start-ScriptLogger.Tests.ps1 ├── Helpers │ ├── Show-VerboseMessage.ps1 │ ├── Show-WarningMessage.ps1 │ ├── Show-ErrorMessage.ps1 │ ├── Show-InformationMessage.ps1 │ └── Write-Log.ps1 ├── Functions │ ├── Stop-ScriptLogger.ps1 │ ├── Get-ScriptLogger.ps1 │ ├── Write-WarningLog.ps1 │ ├── Write-VerboseLog.ps1 │ ├── Write-InformationLog.ps1 │ ├── Write-ErrorLog.ps1 │ ├── Set-ScriptLogger.ps1 │ └── Start-ScriptLogger.ps1 ├── ScriptLogger.psm1 └── ScriptLogger.psd1 ├── .debug.ps1 ├── .build.ps1 ├── .vscode ├── launch.json ├── tasks.json └── settings.json ├── appveyor.yml ├── LICENSE ├── CHANGELOG.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /out/ 2 | -------------------------------------------------------------------------------- /ScriptLogger/Resources/ScriptLogger.Types.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.debug.ps1: -------------------------------------------------------------------------------- 1 | 2 | Get-ChildItem -Path $PSScriptRoot -Directory | 3 | ForEach-Object { '{0}\{1}.psd1'-f $_.FullName, $_.Name } | 4 | Where-Object { Test-Path -Path $_ } | 5 | Import-Module -Verbose -Force 6 | 7 | <# ------------------ PLACE DEBUG COMMANDS AFTER THIS LINE ------------------ #> 8 | -------------------------------------------------------------------------------- /.build.ps1: -------------------------------------------------------------------------------- 1 | 2 | # Import build tasks 3 | . InvokeBuildHelperTasks 4 | 5 | # Build configuration 6 | $IBHConfig.RepositoryTask.Token = Use-VaultSecureString -TargetName 'GitHub Token (claudiospizzi)' 7 | $IBHConfig.GalleryTask.Token = Use-VaultSecureString -TargetName 'PowerShell Gallery Key (claudiospizzi)' 8 | -------------------------------------------------------------------------------- /ScriptLogger/en-US/about_ScriptLogger.help.txt: -------------------------------------------------------------------------------- 1 | 2 | TOPIC 3 | about_ScriptLogger 4 | 5 | SHORT DESCRIPTION 6 | PowerShell Module to provide logging capabilities for PowerShell controller 7 | scripts. 8 | 9 | LONG DESCRIPTION 10 | To get more information about this module, check the open source GitHub 11 | repository readme or the cmdlet based help for the module functions: 12 | 13 | LINK 14 | https://github.com/claudiospizzi/ScriptLogger 15 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "PowerShell Interactive", 6 | "type": "PowerShell", 7 | "request": "launch", 8 | "cwd": "${workspaceFolder}", 9 | "createTemporaryIntegratedConsole": true 10 | }, 11 | { 12 | "name": "PowerShell Debug Script", 13 | "type": "PowerShell", 14 | "request": "launch", 15 | "script": "${workspaceFolder}\\.debug.ps1", 16 | "cwd": "${workspaceFolder}", 17 | "createTemporaryIntegratedConsole": true 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Stop-ScriptLogger.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | Describe 'Stop-ScriptLogger' { 9 | 10 | It 'should clean up the looger' { 11 | 12 | # Arrange 13 | Start-ScriptLogger -Path 'TestDrive:\test.log' 14 | 15 | # Act 16 | Stop-ScriptLogger 17 | 18 | # Assert 19 | Get-ScriptLogger | Should -BeNullOrEmpty 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | 2 | # PowerShell 5.0 build worker 3 | os: WMF 5 4 | 5 | # Install required Pester and PSScriptAnalyzer modules 6 | install: 7 | - ps: Install-PackageProvider NuGet -Force | Out-Null 8 | - ps: Install-Module posh-git -Force 9 | - ps: Install-Module SecurityFever -Force 10 | - ps: Install-Module InvokeBuild -Force 11 | - ps: Install-Module InvokeBuildHelper -Force 12 | - ps: Install-Module Pester -Force 13 | - ps: Install-Module PSScriptAnalyzer -Force 14 | 15 | # Set version to build number 16 | version: '{build}' 17 | 18 | # Build configuration 19 | configuration: Release 20 | platform: Any CPU 21 | 22 | # Execute psake build task 23 | build_script: 24 | - ps: >- 25 | Invoke-Build -Task 'Build' 26 | 27 | # Execute psake test and analyze task 28 | test_script: 29 | - ps: >- 30 | Invoke-Build -Task 'Test' 31 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | 4 | "command": "\"& { Invoke-Build -Task $args }\"", 5 | 6 | "type": "shell", 7 | "options": { 8 | "shell": { 9 | "executable": "powershell.exe", 10 | "args": [ "-NoProfile", "-Command" ] 11 | } 12 | }, 13 | "presentation": { 14 | "echo": false, 15 | "reveal": "always", 16 | "focus": false, 17 | "panel": "new" 18 | }, 19 | 20 | "tasks": [ 21 | { 22 | "label": "Test", 23 | "group": { 24 | "kind": "test", 25 | "isDefault": true 26 | } 27 | }, 28 | { 29 | "label": "Build", 30 | "group": { 31 | "kind": "build", 32 | "isDefault": true 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /ScriptLogger/Helpers/Show-VerboseMessage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Shows a verbose message on the PowerShell host. 4 | 5 | .DESCRIPTION 6 | Uses the internal .NET method WriteVerboseLine() of the host UI class to 7 | show the verbose message on the console. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | None. 14 | 15 | .EXAMPLE 16 | PS C:\> Show-VerboseMessage -Message 'My Verbose Message' 17 | Show the verbose message. 18 | 19 | .NOTES 20 | Author : Claudio Spizzi 21 | License : MIT License 22 | 23 | .LINK 24 | https://github.com/claudiospizzi/ScriptLogger 25 | #> 26 | 27 | function Show-VerboseMessage 28 | { 29 | param 30 | ( 31 | # The verbose message. 32 | [Parameter(Mandatory = $true)] 33 | [System.String] 34 | $Message 35 | ) 36 | 37 | $Host.UI.WriteVerboseLine($Message) 38 | } 39 | -------------------------------------------------------------------------------- /ScriptLogger/Helpers/Show-WarningMessage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Shows a warning message on the PowerShell host. 4 | 5 | .DESCRIPTION 6 | Uses the internal .NET method WriteWarningLine() of the host UI class to 7 | show the warning message on the console. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | None. 14 | 15 | .EXAMPLE 16 | PS C:\> Show-WarningMessage -Message 'My Warning Message' 17 | Show the warning message. 18 | 19 | .NOTES 20 | Author : Claudio Spizzi 21 | License : MIT License 22 | 23 | .LINK 24 | https://github.com/claudiospizzi/ScriptLogger 25 | #> 26 | 27 | function Show-WarningMessage 28 | { 29 | param 30 | ( 31 | # The warning message. 32 | [Parameter(Mandatory = $true)] 33 | [System.String] 34 | $Message 35 | ) 36 | 37 | $Host.UI.WriteWarningLine($Message) 38 | } 39 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Get-ScriptLogger.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | Describe 'Get-ScriptLogger' { 9 | 10 | It 'should be null if the script logger was not started before' { 11 | 12 | # Act 13 | $scriptLogger = Get-ScriptLogger 14 | 15 | # Assert 16 | $scriptLogger | Should -BeNullOrEmpty 17 | } 18 | 19 | It 'should return a valid object after starting' { 20 | 21 | # Act 22 | Start-ScriptLogger -Path 'TestDrive:\log.txt' 23 | $scriptLogger = Get-ScriptLogger 24 | 25 | # Assert 26 | $scriptLogger | Should -Not -BeNullOrEmpty 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ScriptLogger/Helpers/Show-ErrorMessage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Shows an error message on the PowerShell host. 4 | 5 | .DESCRIPTION 6 | Uses the internal .NET method WriteErrorLine() of the host UI class to 7 | show the error message on the console. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | None. 14 | 15 | .EXAMPLE 16 | PS C:\> Show-ErrorMessage -Message 'My Error Message' 17 | Show the error message. 18 | 19 | .NOTES 20 | Author : Claudio Spizzi 21 | License : MIT License 22 | 23 | .LINK 24 | https://github.com/claudiospizzi/ScriptLogger 25 | #> 26 | 27 | function Show-ErrorMessage 28 | { 29 | param 30 | ( 31 | # The error message. 32 | [Parameter(Mandatory = $true)] 33 | [System.String] 34 | $Message 35 | ) 36 | 37 | # Add the prefix ERROR: because WriteErrorLine() does not write it itself. 38 | $Host.UI.WriteErrorLine("ERROR: $Message") 39 | } 40 | -------------------------------------------------------------------------------- /ScriptLogger/Helpers/Show-InformationMessage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Shows an information message on the PowerShell host. 4 | 5 | .DESCRIPTION 6 | Uses the internal .NET method () of the host UI class to show the 7 | information message on the console. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | None. 14 | 15 | .EXAMPLE 16 | PS C:\> Show-InformationMessage -Message 'My Information Message' 17 | Show the information message. 18 | 19 | .NOTES 20 | Author : Claudio Spizzi 21 | License : MIT License 22 | 23 | .LINK 24 | https://github.com/claudiospizzi/ScriptLogger 25 | #> 26 | 27 | function Show-InformationMessage 28 | { 29 | param 30 | ( 31 | # The information message. 32 | [Parameter(Mandatory = $true)] 33 | [System.String] 34 | $Message 35 | ) 36 | 37 | # A method WriteErrorLine() is not available, so add the prefix INFORMATION: 38 | # and use the default method WriteLine(). 39 | $Host.UI.WriteLine("INFORMATION: $Message") 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Claudio Spizzi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.trimTrailingWhitespace": true, 3 | "[markdown]": { 4 | "files.trimTrailingWhitespace": false 5 | }, 6 | 7 | "files.exclude": { 8 | "**/.git": true, 9 | "out": true 10 | }, 11 | 12 | "search.exclude": { 13 | "out": true 14 | }, 15 | 16 | "powershell.debugging.createTemporaryIntegratedConsole": true, 17 | 18 | "powershell.codeFormatting.alignPropertyValuePairs": true, 19 | "powershell.codeFormatting.ignoreOneLineBlock": true, 20 | "powershell.codeFormatting.newLineAfterCloseBrace": true, 21 | "powershell.codeFormatting.newLineAfterOpenBrace": true, 22 | "powershell.codeFormatting.openBraceOnSameLine": false, 23 | "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationAfterEveryPipeline", 24 | "powershell.codeFormatting.useCorrectCasing": true, 25 | "powershell.codeFormatting.whitespaceAfterSeparator": true, 26 | "powershell.codeFormatting.whitespaceAroundOperator": true, 27 | "powershell.codeFormatting.WhitespaceAroundPipe": true, 28 | "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, 29 | "powershell.codeFormatting.whitespaceBeforeOpenParen": true, 30 | "powershell.codeFormatting.WhitespaceInsideBrace": true 31 | } 32 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Stop-ScriptLogger.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Stop the script logger in the current PowerShell session. 4 | 5 | .DESCRIPTION 6 | Stop the script logger in the current PowerShell session and clear all 7 | log configurations. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | None. 14 | 15 | .EXAMPLE 16 | PS C:\> Stop-ScriptLogger 17 | Stop the default logger. 18 | 19 | .EXAMPLE 20 | PS C:\> Stop-ScriptLogger -Name 'MyLogger' 21 | Stop the custom logger. 22 | 23 | .NOTES 24 | Author : Claudio Spizzi 25 | License : MIT License 26 | 27 | .LINK 28 | https://github.com/claudiospizzi/ScriptLogger 29 | #> 30 | 31 | function Stop-ScriptLogger 32 | { 33 | [CmdletBinding(SupportsShouldProcess = $true)] 34 | param 35 | ( 36 | # The logger name. 37 | [Parameter(Mandatory = $false)] 38 | [System.String] 39 | $Name = 'Default' 40 | ) 41 | 42 | if ($Script:Loggers.ContainsKey($Name)) 43 | { 44 | if ($PSCmdlet.ShouldProcess('ScriptLogger', 'Stop')) 45 | { 46 | Write-Verbose "Stop script logger '$Name'" 47 | 48 | $Script:Loggers.Remove($Name) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Get-ScriptLogger.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get the current script logger. 4 | 5 | .DESCRIPTION 6 | Returns an object with the current configuration of the script logger 7 | inside this PowerShell session. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | ScriptLogger.Configuration. Configuration of the script logger instance. 14 | 15 | .EXAMPLE 16 | PS C:\> Get-ScriptLogger 17 | Get all script loggers. 18 | 19 | .EXAMPLE 20 | PS C:\> Get-ScriptLogger -Name 'MyLogger' 21 | Get the custom script logger. 22 | 23 | .NOTES 24 | Author : Claudio Spizzi 25 | License : MIT License 26 | 27 | .LINK 28 | https://github.com/claudiospizzi/ScriptLogger 29 | #> 30 | 31 | function Get-ScriptLogger 32 | { 33 | [CmdletBinding()] 34 | param 35 | ( 36 | # The logger name filter. 37 | [Parameter(Mandatory = $false)] 38 | [System.String] 39 | $Name 40 | ) 41 | 42 | $selectedLoggers = $Script:Loggers.Values 43 | 44 | if ($PSBoundParameters.ContainsKey('Name')) 45 | { 46 | $selectedLoggers = $selectedLoggers | Where-Object { $_.Name -like $Name } 47 | } 48 | 49 | Write-Output $selectedLoggers 50 | } 51 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Write-WarningLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Log a warning message. 4 | 5 | .DESCRIPTION 6 | Log a warning message to the log file, the event log and show it on the 7 | current console. If the global log level is set to 'error', no warning 8 | message will be logged. 9 | 10 | .INPUTS 11 | None. 12 | 13 | .OUTPUTS 14 | None. 15 | 16 | .EXAMPLE 17 | PS C:\> Write-WarningLog -Message 'My Warning Message' 18 | Log the warning message. 19 | 20 | .EXAMPLE 21 | PS C:\> Write-WarningLog -Name 'MyLogger' -Message 'My Warning Message' 22 | Log the warning message in a custom logger. 23 | 24 | .NOTES 25 | Author : Claudio Spizzi 26 | License : MIT License 27 | 28 | .LINK 29 | https://github.com/claudiospizzi/ScriptLogger 30 | #> 31 | 32 | function Write-WarningLog 33 | { 34 | [CmdletBinding()] 35 | param 36 | ( 37 | # The logger name. 38 | [Parameter(Mandatory = $false)] 39 | [System.String] 40 | $Name = 'Default', 41 | 42 | # The warning message. 43 | [Parameter(Mandatory=$true, Position = 0, ValueFromPipeline = $true)] 44 | [System.String[]] 45 | $Message 46 | ) 47 | 48 | process 49 | { 50 | foreach ($currentMessage in $Message) 51 | { 52 | Write-Log -Name $Name -Message $currentMessage -Level 'Warning' 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Write-VerboseLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Log a verbose message. 4 | 5 | .DESCRIPTION 6 | Log a verbose message to the log file, the event log and show it on the 7 | current console. If the global log level is set to 'information', no 8 | verbose message will be logged. 9 | 10 | .INPUTS 11 | None. 12 | 13 | .OUTPUTS 14 | None. 15 | 16 | .EXAMPLE 17 | PS C:\> Write-VerboseLog -Message 'My Verbose Message' 18 | Log the verbose message. 19 | 20 | .EXAMPLE 21 | PS C:\> Write-VerboseLog -Name 'MyLogger' -Message 'My Verbose Message' 22 | Log the verbose message in a custom logger. 23 | 24 | .NOTES 25 | Author : Claudio Spizzi 26 | License : MIT License 27 | 28 | .LINK 29 | https://github.com/claudiospizzi/ScriptLogger 30 | #> 31 | 32 | function Write-VerboseLog 33 | { 34 | [CmdletBinding()] 35 | param 36 | ( 37 | # The logger name. 38 | [Parameter(Mandatory = $false)] 39 | [System.String] 40 | $Name = 'Default', 41 | 42 | # The verbose message. 43 | [Parameter(Mandatory=$true, Position = 0, ValueFromPipeline = $true)] 44 | [System.String[]] 45 | $Message 46 | ) 47 | 48 | process 49 | { 50 | foreach ($currentMessage in $Message) 51 | { 52 | Write-Log -Name $Name -Message $currentMessage -Level 'Verbose' 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Write-InformationLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Log an information message. 4 | 5 | .DESCRIPTION 6 | Log an information message to the log file, the event log and show it on 7 | the current console. If the global log level is set to 'warning', no 8 | information message will be logged. 9 | 10 | .INPUTS 11 | None. 12 | 13 | .OUTPUTS 14 | None. 15 | 16 | .EXAMPLE 17 | PS C:\> Write-InformationLog -Message 'My Information Message' 18 | Log the information message. 19 | 20 | .EXAMPLE 21 | PS C:\> Write-InformationLog -Name 'MyLogger' -Message 'My Information Message' 22 | Log the information message in a custom logger. 23 | 24 | .NOTES 25 | Author : Claudio Spizzi 26 | License : MIT License 27 | 28 | .LINK 29 | https://github.com/claudiospizzi/ScriptLogger 30 | #> 31 | 32 | function Write-InformationLog 33 | { 34 | [CmdletBinding()] 35 | param 36 | ( 37 | # The logger name. 38 | [Parameter(Mandatory = $false)] 39 | [System.String] 40 | $Name = 'Default', 41 | 42 | # The information message. 43 | [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] 44 | [System.String[]] 45 | $Message 46 | ) 47 | 48 | process 49 | { 50 | foreach ($currentMessage in $Message) 51 | { 52 | Write-Log -Name $Name -Message $currentMessage -Level 'Information' 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is mainly based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | ## 3.3.0 - 2019-11-05 9 | 10 | * Added: The parent folder will be created, if it does not exists 11 | 12 | ## 3.2.0 - 2019-08-29 13 | 14 | * Added: The Path parameter for Start-ScriptLogger can now be an empty string 15 | 16 | ## 3.1.0 - 2019-02-18 17 | 18 | * Added: Optional log rotation (hourly, daily, monthly, yearly) 19 | 20 | ## 3.0.1 - 2019-02-14 21 | 22 | * Changed: Format of the script logger object to show the logger name 23 | 24 | ## 3.0.0 - 2019-02-14 25 | 26 | * Added: Support multiple messages for log functions 27 | * Changed: Support multiple loggers distinguished by a logger name 28 | * Changed: Default log file is now next to the executed script 29 | 30 | ## 2.0.0 - 2016-12-10 31 | 32 | * Changed: Remove positional parameters (BREAKING CHANGE) 33 | * Changed: Convert module to new deployment model 34 | * Changed: Rework code against high quality module guidelines by Microsoft 35 | 36 | ## 1.2.0 - 2016-03-10 37 | 38 | * Added: Encoding option for the log file output 39 | * Added: Error handling for log file and event log output 40 | * Changed: Console output from cmdlets to $Host.UI methods 41 | * Fixed: Error record handling to log correct invocation information 42 | 43 | ## 1.1.1 - 2016-02-09 44 | 45 | * Added: Formats and types resources 46 | * Fixed: Tests for PowerShell 3.0 & 4.0 47 | 48 | ## 1.1.0 - 2016-02-04 49 | 50 | * Added: ErrorRecord parameter to Write-ErrorLog 51 | * Changed: Return logger object inside Start-ScriptLogger 52 | 53 | ## 1.0.0 - 2016-02-03 54 | 55 | * Added: Initial public release 56 | -------------------------------------------------------------------------------- /ScriptLogger/Resources/ScriptLogger.Formats.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ScriptLogger.Configuration 7 | 8 | ScriptLogger.Configuration 9 | 10 | 11 | 12 | 13 | 12 14 | 15 | 16 | 12 17 | 18 | 19 | 20 | 10 21 | 22 | 23 | 10 24 | 25 | 26 | 27 | 10 28 | 29 | 30 | 31 | 10 32 | 33 | 34 | 35 | 10 36 | 37 | 38 | 39 | 40 | 41 | 42 | Name 43 | 44 | 45 | Level 46 | 47 | 48 | Path 49 | 50 | 51 | Enabled 52 | 53 | 54 | Encoding 55 | 56 | 57 | LogFile 58 | 59 | 60 | EventLog 61 | 62 | 63 | ConsoleOutput 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /ScriptLogger/ScriptLogger.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Root module file. 4 | 5 | .DESCRIPTION 6 | The root module file loads all classes, helpers and functions into the 7 | module context. 8 | #> 9 | 10 | #region Namepsace Loader 11 | 12 | #endregion Namepsace Loader 13 | 14 | #region Module Loader 15 | 16 | # Get and dot source all classes (internal) 17 | Split-Path -Path $PSCommandPath | 18 | Get-ChildItem -Filter 'Classes' -Directory | 19 | Get-ChildItem -Include '*.ps1' -File -Recurse | 20 | ForEach-Object { . $_.FullName } 21 | 22 | # Get and dot source all helper functions (internal) 23 | Split-Path -Path $PSCommandPath | 24 | Get-ChildItem -Filter 'Helpers' -Directory | 25 | Get-ChildItem -Include '*.ps1' -File -Recurse | 26 | ForEach-Object { . $_.FullName } 27 | 28 | # Get and dot source all external functions (public) 29 | Split-Path -Path $PSCommandPath | 30 | Get-ChildItem -Filter 'Functions' -Directory | 31 | Get-ChildItem -Include '*.ps1' -File -Recurse | 32 | ForEach-Object { . $_.FullName } 33 | 34 | #endregion Module Loader 35 | 36 | #region Module Configuration 37 | 38 | #endregion Module Configuration 39 | 40 | 41 | 42 | 43 | <# 44 | .SYNOPSIS 45 | Root module file. 46 | 47 | .DESCRIPTION 48 | The root module file loads all classes, helpers and functions into the 49 | module context. 50 | #> 51 | 52 | #region Namepsace Loader 53 | 54 | #endregion Namepsace Loader 55 | 56 | #region Module Loader 57 | 58 | # Get and dot source all classes (internal) 59 | Split-Path -Path $PSCommandPath | 60 | Get-ChildItem -Filter 'Classes' -Directory | 61 | Get-ChildItem -Include '*.ps1' -File -Recurse | 62 | ForEach-Object { . $_.FullName } 63 | 64 | # Get and dot source all helper functions (internal) 65 | Split-Path -Path $PSCommandPath | 66 | Get-ChildItem -Filter 'Helpers' -Directory | 67 | Get-ChildItem -Include '*.ps1' -File -Recurse | 68 | ForEach-Object { . $_.FullName } 69 | 70 | # Get and dot source all external functions (public) 71 | Split-Path -Path $PSCommandPath | 72 | Get-ChildItem -Filter 'Functions' -Directory | 73 | Get-ChildItem -Include '*.ps1' -File -Recurse | 74 | ForEach-Object { . $_.FullName } 75 | 76 | #endregion Module Loader 77 | 78 | #region Module Configuration 79 | 80 | # Module path 81 | New-Variable -Name 'ModulePath' -Value $PSScriptRoot 82 | 83 | # Module wide array hosting all script loggers 84 | $Script:Loggers = @{} 85 | 86 | #endregion Module Configuration 87 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Write-ErrorLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Log an error message. 4 | 5 | .DESCRIPTION 6 | Log an error message to the log file, the event log and show it on the 7 | current console. It can also use an error record conataining an 8 | exception as input. The exception will be converted into a log message. 9 | 10 | .INPUTS 11 | None. 12 | 13 | .OUTPUTS 14 | None. 15 | 16 | .EXAMPLE 17 | PS C:\> Write-ErrorLog -Message 'My Error Message' 18 | Log the error message. 19 | 20 | .EXAMPLE 21 | PS C:\> Write-ErrorLog -Name 'MyLogger' -Message 'My Error Message' 22 | Log the error message in a custom logger. 23 | 24 | .NOTES 25 | Author : Claudio Spizzi 26 | License : MIT License 27 | 28 | .LINK 29 | https://github.com/claudiospizzi/ScriptLogger 30 | #> 31 | 32 | function Write-ErrorLog 33 | { 34 | [CmdletBinding(DefaultParameterSetName = 'Message')] 35 | param 36 | ( 37 | # The logger name. 38 | [Parameter(Mandatory = $false)] 39 | [System.String] 40 | $Name = 'Default', 41 | 42 | # The error message. 43 | [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'Message')] 44 | [System.String[]] 45 | $Message, 46 | 47 | # The error record containing an exception to log. 48 | [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'ErrorRecord')] 49 | [System.Management.Automation.ErrorRecord[]] 50 | $ErrorRecord 51 | ) 52 | 53 | process 54 | { 55 | if ($PSCmdlet.ParameterSetName -eq 'Message') 56 | { 57 | foreach ($currentMessage in $Message) 58 | { 59 | Write-Log -Name $Name -Message $currentMessage -Level 'Error' 60 | } 61 | } 62 | 63 | if ($PSCmdlet.ParameterSetName -eq 'ErrorRecord') 64 | { 65 | foreach ($currentErrorRecord in $ErrorRecord) 66 | { 67 | $currentMessage = '{0} ({1}: {2}:{3} char:{4})' -f $currentErrorRecord.Exception.Message, 68 | $currentErrorRecord.FullyQualifiedErrorId, 69 | $currentErrorRecord.InvocationInfo.ScriptName, 70 | $currentErrorRecord.InvocationInfo.ScriptLineNumber, 71 | $currentErrorRecord.InvocationInfo.OffsetInLine 72 | 73 | Write-Log -Name $Name -Message $currentMessage -Level 'Error' 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ScriptLogger/Helpers/Write-Log.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Log a message with the specified log level. 4 | 5 | .DESCRIPTION 6 | If the specified log level is higher as the configured log level, the 7 | message will be logged to the enabled destinations. These are the 8 | specified log file, the PowerShell event log and the current PowerShell 9 | console. 10 | 11 | .INPUTS 12 | None. 13 | 14 | .OUTPUTS 15 | None. 16 | 17 | .EXAMPLE 18 | PS C:\> Write-Log -Name 'Default' -Message 'My Warning Message' -Level Warning 19 | Log the warning message. 20 | 21 | .NOTES 22 | Author : Claudio Spizzi 23 | License : MIT License 24 | 25 | .LINK 26 | https://github.com/claudiospizzi/ScriptLogger 27 | #> 28 | 29 | function Write-Log 30 | { 31 | [CmdletBinding(SupportsShouldProcess = $true)] 32 | param 33 | ( 34 | # The logger name. 35 | [Parameter(Mandatory = $true)] 36 | [System.String] 37 | $Name, 38 | 39 | # The message to log. 40 | [Parameter(Mandatory = $true)] 41 | [System.String] 42 | $Message, 43 | 44 | # The log level to use. 45 | [Parameter(Mandatory = $true)] 46 | [ValidateSet('Verbose', 'Information', 'Warning', 'Error')] 47 | [System.String] 48 | $Level 49 | ) 50 | 51 | if ($Script:Loggers.ContainsKey($Name)) 52 | { 53 | $logger = $Script:Loggers[$Name] 54 | 55 | # Check if the logging enabled 56 | if ($logger.Enabled) 57 | { 58 | $levelMap = @{ 59 | 'Verbose' = 0 60 | 'Information' = 1 61 | 'Warning' = 2 62 | 'Error' = 3 63 | } 64 | 65 | # Check the logging level: The requested level needs to be equals or higher than the configured level 66 | if ($levelMap[$Level] -ge $levelMap[$logger.Level]) 67 | { 68 | if ($logger.LogFile -and $PSCmdlet.ShouldProcess('LogFile', 'Write Log')) 69 | { 70 | try 71 | { 72 | # Output to log file 73 | $line = $logger.Format -f (Get-Date), $env:ComputerName, $Env:Username, $Level, $Message 74 | $line | Out-File -FilePath $logger.Path -Encoding $logger.Encoding -Append -ErrorAction Stop 75 | } 76 | catch 77 | { 78 | Write-Warning "ScriptLogger '$Name' module error during write log file: $_" 79 | } 80 | } 81 | 82 | if ($logger.EventLog -and $PSCmdlet.ShouldProcess('EventLog', 'Write Log')) 83 | { 84 | $entryType = $Level.Replace('Verbose', 'Information') 85 | 86 | try 87 | { 88 | # Output to event log 89 | Write-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -EventId 0 -Category 0 -EntryType $entryType -Message $Message -ErrorAction Stop 90 | } 91 | catch 92 | { 93 | Write-Warning "ScriptLogger '$Name' module error during write event log: $_" 94 | } 95 | } 96 | 97 | if ($logger.ConsoleOutput -and $PSCmdlet.ShouldProcess('ConsoleOutput', 'Write Log')) 98 | { 99 | switch ($Level) 100 | { 101 | 'Verbose' { Show-VerboseMessage -Message $Message } 102 | 'Information' { Show-InformationMessage -Message $Message } 103 | 'Warning' { Show-WarningMessage -Message $Message } 104 | 'Error' { Show-ErrorMessage -Message $Message } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | else 111 | { 112 | Write-Warning "ScriptLogger '$Name' not found. No logs written." 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Write-WarningLog.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | InModuleScope $moduleName { 9 | 10 | Describe 'Write-WarningLog' { 11 | 12 | Context 'Ensure mocked Write-Log is invoked' { 13 | 14 | Mock Write-Log -ModuleName $moduleName -ParameterFilter { $Level -eq 'Warning' } -Verifiable 15 | 16 | It 'should invoke the mock one for a simple message' { 17 | 18 | # Act 19 | Write-WarningLog -Message 'My Warning' 20 | 21 | # Assert 22 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 1 -Exactly 23 | } 24 | 25 | It 'should invoke the mock twice for an array of 2 messages' { 26 | 27 | # Act 28 | Write-WarningLog -Message 'My Warning', 'My Warning' 29 | 30 | # Assert 31 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 2 -Exactly 32 | } 33 | 34 | It 'should invoke the mock three times for a pipeline input of 3 messages' { 35 | 36 | # Act 37 | 'My Warning', 'My Warning', 'My Warning' | Write-WarningLog 38 | 39 | # Assert 40 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 3 -Exactly 41 | } 42 | } 43 | 44 | Context 'Ensure valid output' { 45 | 46 | $logPath = 'TestDrive:\test.log' 47 | 48 | Mock Get-Date -ModuleName $moduleName { [DateTime] '2000-12-31 01:02:03' } 49 | 50 | It 'should write a valid message to the log file' { 51 | 52 | # Arrange 53 | Start-ScriptLogger -Path $logPath -NoEventLog -NoConsoleOutput 54 | 55 | # Act 56 | Write-WarningLog -Message 'My Warning' 57 | 58 | # Assert 59 | $logFile = Get-Content -Path $logPath 60 | $logFile | Should -Be "2000-12-31 01:02:03 $Env:ComputerName $Env:Username Warning My Warning" 61 | } 62 | 63 | It 'should write a valid message to the event log' { 64 | 65 | # Arrange 66 | Start-ScriptLogger -Path $logPath -NoLogFile -NoConsoleOutput 67 | $filterTimestamp = Get-Date 68 | 69 | # Act 70 | Write-WarningLog -Message 'My Warning' 71 | 72 | # Assert 73 | $eventLog = Get-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -InstanceId 0 -EntryType Warning -After $filterTimestamp -Newest 1 74 | $eventLog | Should -Not -BeNullOrEmpty 75 | $eventLog.EventID | Should -Be 0 76 | $eventLog.CategoryNumber | Should -Be 0 77 | $eventLog.EntryType | Should -Be 'Warning' 78 | $eventLog.Message | Should -Be "The description for Event ID '0' in Source 'PowerShell' cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event:'My Warning'" 79 | $eventLog.Source | Should -Be 'PowerShell' 80 | $eventLog.InstanceId | Should -Be 0 81 | } 82 | 83 | It 'should write a valid message to the console' { 84 | 85 | # Arrange 86 | Mock Show-WarningMessage -ModuleName $moduleName -ParameterFilter { $Message -eq 'My Warning' } 87 | Start-ScriptLogger -Path $logPath -NoLogFile -NoEventLog 88 | 89 | # Act 90 | Write-WarningLog -Message 'My Warning' 91 | 92 | # Assert 93 | Assert-MockCalled -Scope It -CommandName 'Show-WarningMessage' -Times 1 -Exactly 94 | } 95 | 96 | AfterEach { 97 | 98 | # Cleanup logger 99 | Get-ScriptLogger | Remove-Item -Force 100 | Stop-ScriptLogger 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Write-VerboseLog.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | InModuleScope $moduleName { 9 | 10 | Describe 'Write-VerboseLog' { 11 | 12 | Context 'Ensure mocked Write-Log is invoked' { 13 | 14 | Mock Write-Log -ModuleName $moduleName -ParameterFilter { $Level -eq 'Verbose' } -Verifiable 15 | 16 | It 'should invoke the mock one for a simple message' { 17 | 18 | # Act 19 | Write-VerboseLog -Message 'My Verbose' 20 | 21 | # Assert 22 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 1 -Exactly 23 | } 24 | 25 | It 'should invoke the mock twice for an array of 2 messages' { 26 | 27 | # Act 28 | Write-VerboseLog -Message 'My Verbose', 'My Verbose' 29 | 30 | # Assert 31 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 2 -Exactly 32 | } 33 | 34 | It 'should invoke the mock three times for a pipeline input of 3 messages' { 35 | 36 | # Act 37 | 'My Verbose', 'My Verbose', 'My Verbose' | Write-VerboseLog 38 | 39 | # Assert 40 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 3 -Exactly 41 | } 42 | } 43 | 44 | Context 'Ensure valid output' { 45 | 46 | $logPath = 'TestDrive:\test.log' 47 | 48 | Mock Get-Date -ModuleName $moduleName { [DateTime] '2000-12-31 01:02:03' } 49 | 50 | It 'should write a valid message to the log file' { 51 | 52 | # Arrange 53 | Start-ScriptLogger -Path $logPath -NoEventLog -NoConsoleOutput 54 | 55 | # Act 56 | Write-VerboseLog -Message 'My Verbose' 57 | 58 | # Assert 59 | $logFile = Get-Content -Path $logPath 60 | $logFile | Should -Be "2000-12-31 01:02:03 $Env:ComputerName $Env:Username Verbose My Verbose" 61 | } 62 | 63 | It 'should write a valid message to the event log' { 64 | 65 | # Arrange 66 | Start-ScriptLogger -Path $logPath -NoLogFile -NoConsoleOutput 67 | $filterTimestamp = Get-Date 68 | 69 | # Act 70 | Write-VerboseLog -Message 'My Verbose' 71 | 72 | # Assert 73 | $eventLog = Get-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -InstanceId 0 -EntryType Information -After $filterTimestamp -Newest 1 74 | $eventLog | Should -Not -BeNullOrEmpty 75 | $eventLog.EventID | Should -Be 0 76 | $eventLog.CategoryNumber | Should -Be 0 77 | $eventLog.EntryType | Should -Be 'Information' 78 | $eventLog.Message | Should -Be "The description for Event ID '0' in Source 'PowerShell' cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event:'My Verbose'" 79 | $eventLog.Source | Should -Be 'PowerShell' 80 | $eventLog.InstanceId | Should -Be 0 81 | } 82 | 83 | It 'should write a valid message to the console' { 84 | 85 | # Arrange 86 | Mock Show-VerboseMessage -ModuleName $moduleName -ParameterFilter { $Message -eq 'My Verbose' } 87 | Start-ScriptLogger -Path $logPath -NoLogFile -NoEventLog 88 | 89 | # Act 90 | Write-VerboseLog -Message 'My Verbose' 91 | 92 | # Assert 93 | Assert-MockCalled -Scope It -CommandName 'Show-VerboseMessage' -Times 1 -Exactly 94 | } 95 | 96 | AfterEach { 97 | 98 | # Cleanup logger 99 | Get-ScriptLogger | Remove-Item -Force 100 | Stop-ScriptLogger 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Write-InformationLog.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | InModuleScope $moduleName { 9 | 10 | Describe 'Write-InformationLog' { 11 | 12 | Context 'Ensure mocked Write-Log is invoked' { 13 | 14 | Mock Write-Log -ModuleName $moduleName -ParameterFilter { $Level -eq 'Information' } -Verifiable 15 | 16 | It 'should invoke the mock one for a simple message' { 17 | 18 | # Act 19 | Write-InformationLog -Message 'My Information' 20 | 21 | # Assert 22 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 1 -Exactly 23 | } 24 | 25 | It 'should invoke the mock twice for an array of 2 messages' { 26 | 27 | # Act 28 | Write-InformationLog -Message 'My Information', 'My Information' 29 | 30 | # Assert 31 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 2 -Exactly 32 | } 33 | 34 | It 'should invoke the mock three times for a pipeline input of 3 messages' { 35 | 36 | # Act 37 | 'My Information', 'My Information', 'My Information' | Write-InformationLog 38 | 39 | # Assert 40 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 3 -Exactly 41 | } 42 | } 43 | 44 | Context 'Ensure valid output' { 45 | 46 | $logPath = 'TestDrive:\test.log' 47 | 48 | Mock Get-Date -ModuleName $moduleName { [DateTime] '2000-12-31 01:02:03' } 49 | 50 | It 'should write a valid message to the log file' { 51 | 52 | # Arrange 53 | Start-ScriptLogger -Path $logPath -NoEventLog -NoConsoleOutput 54 | 55 | # Act 56 | Write-InformationLog -Message 'My Information' 57 | 58 | # Assert 59 | $logFile = Get-Content -Path $logPath 60 | $logFile | Should -Be "2000-12-31 01:02:03 $Env:ComputerName $Env:Username Information My Information" 61 | } 62 | 63 | It 'should write a valid message to the event log' { 64 | 65 | # Arrange 66 | Start-ScriptLogger -Path $logPath -NoLogFile -NoConsoleOutput 67 | $filterTimestamp = Get-Date 68 | 69 | # Act 70 | Write-InformationLog -Message 'My Information' 71 | 72 | # Assert 73 | $eventLog = Get-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -InstanceId 0 -EntryType Information -After $filterTimestamp -Newest 1 74 | $eventLog | Should -Not -BeNullOrEmpty 75 | $eventLog.EventID | Should -Be 0 76 | $eventLog.CategoryNumber | Should -Be 0 77 | $eventLog.EntryType | Should -Be 'Information' 78 | $eventLog.Message | Should -Be "The description for Event ID '0' in Source 'PowerShell' cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event:'My Information'" 79 | $eventLog.Source | Should -Be 'PowerShell' 80 | $eventLog.InstanceId | Should -Be 0 81 | } 82 | 83 | It 'should write a valid message to the console' { 84 | 85 | # Arrange 86 | Mock Show-InformationMessage -ModuleName $moduleName -ParameterFilter { $Message -eq 'My Information' } 87 | Start-ScriptLogger -Path $logPath -NoLogFile -NoEventLog 88 | 89 | # Act 90 | Write-InformationLog -Message 'My Information' 91 | 92 | # Assert 93 | Assert-MockCalled -Scope It -CommandName 'Show-InformationMessage' -Times 1 -Exactly 94 | } 95 | 96 | AfterEach { 97 | 98 | # Cleanup logger 99 | Get-ScriptLogger | Remove-Item -Force 100 | Stop-ScriptLogger 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Set-ScriptLogger.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Update the script logger log configuration. 4 | 5 | .DESCRIPTION 6 | The script logger inside the current PowerShell session can be updated 7 | with all parameters inside this cmdlet. 8 | 9 | .INPUTS 10 | None. 11 | 12 | .OUTPUTS 13 | None. 14 | 15 | .EXAMPLE 16 | PS C:\> Set-ScriptLogger -Level 'Warning' -EventLog $true 17 | Set the script logger level to warning and enable the event log output. 18 | 19 | .EXAMPLE 20 | PS C:\> Set-ScriptLogger -Path 'C:\Temp\test.log' -Format '{3}: {4}' 21 | Update the log file path and its format. 22 | 23 | .NOTES 24 | Author : Claudio Spizzi 25 | License : MIT License 26 | 27 | .LINK 28 | https://github.com/claudiospizzi/ScriptLogger 29 | #> 30 | 31 | function Set-ScriptLogger 32 | { 33 | [CmdletBinding(SupportsShouldProcess = $true)] 34 | param 35 | ( 36 | # The logger name. 37 | [Parameter(Mandatory = $false)] 38 | [System.String] 39 | $Name = 'Default', 40 | 41 | # Update the path to the log file. 42 | [Parameter(Mandatory = $false)] 43 | [ValidateScript({Test-Path -Path (Split-Path -Path $_ -Parent)})] 44 | [System.String] 45 | $Path, 46 | 47 | # Update the format for the log file. 48 | [Parameter(Mandatory = $false)] 49 | [ValidateScript({$_ -f (Get-Date), $Env:ComputerName, $Env:Username, 'Verbose', 'My Message'})] 50 | [System.String] 51 | $Format, 52 | 53 | # Update the logger level. 54 | [Parameter(Mandatory = $false)] 55 | [ValidateSet('Verbose', 'Information', 'Warning', 'Error')] 56 | [System.String] 57 | $Level, 58 | 59 | # Update the used log file encoding. 60 | [Parameter(Mandatory = $false)] 61 | [ValidateSet('Unicode', 'UTF7', 'UTF8', 'UTF32', 'ASCII', 'BigEndianUnicode', 'Default', 'OEM')] 62 | [System.String] 63 | $Encoding, 64 | 65 | # Enable or disable the log file output. 66 | [Parameter(Mandatory = $false)] 67 | [System.Boolean] 68 | $LogFile, 69 | 70 | # Enable or disable the event log output. 71 | [Parameter(Mandatory = $false)] 72 | [System.Boolean] 73 | $EventLog, 74 | 75 | # Enable or disable the console output. 76 | [Parameter(Mandatory = $false)] 77 | [System.Boolean] 78 | $ConsoleOutput 79 | ) 80 | 81 | if ($Script:Loggers.ContainsKey($Name)) 82 | { 83 | if ($PSBoundParameters.ContainsKey('Path')) 84 | { 85 | # Create an empty log file, if it does not exist 86 | if (-not (Test-Path -Path $Path)) 87 | { 88 | New-Item -Path $Path -ItemType File | Out-Null 89 | } 90 | 91 | # Only work with absolute path, makes error handling easier 92 | $Path = (Resolve-Path -Path $Path).Path 93 | 94 | if ($PSCmdlet.ShouldProcess('ScriptLogger.Path', 'Set')) 95 | { 96 | $Script:Loggers[$Name].Path = $Path 97 | } 98 | } 99 | 100 | if ($PSBoundParameters.ContainsKey('Format')) 101 | { 102 | if ($PSCmdlet.ShouldProcess('ScriptLogger.Format', 'Set')) 103 | { 104 | $Script:Loggers[$Name].Format = $Format 105 | } 106 | } 107 | 108 | if ($PSBoundParameters.ContainsKey('Level')) 109 | { 110 | if ($PSCmdlet.ShouldProcess('ScriptLogger.Level', 'Set')) 111 | { 112 | $Script:Loggers[$Name].Level = $Level 113 | } 114 | } 115 | 116 | if ($PSBoundParameters.ContainsKey('Encoding')) 117 | { 118 | if ($PSCmdlet.ShouldProcess('ScriptLogger.Encoding', 'Set')) 119 | { 120 | $Script:Loggers[$Name].Encoding = $Encoding 121 | } 122 | } 123 | 124 | if ($PSBoundParameters.ContainsKey('LogFile')) 125 | { 126 | if ($PSCmdlet.ShouldProcess('ScriptLogger.LogFile', 'Set')) 127 | { 128 | $Script:Loggers[$Name].LogFile = $LogFile 129 | } 130 | } 131 | 132 | if ($PSBoundParameters.ContainsKey('EventLog')) 133 | { 134 | if ($PSCmdlet.ShouldProcess('ScriptLogger.EventLog', 'Set')) 135 | { 136 | $Script:Loggers[$Name].EventLog = $EventLog 137 | } 138 | } 139 | 140 | if ($PSBoundParameters.ContainsKey('ConsoleOutput')) 141 | { 142 | if ($PSCmdlet.ShouldProcess('ScriptLogger.ConsoleOutput', 'Set')) 143 | { 144 | $Script:Loggers[$Name].ConsoleOutput = $ConsoleOutput 145 | } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /ScriptLogger/ScriptLogger.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest. 3 | RootModule = 'ScriptLogger.psm1' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '3.3.0' 7 | 8 | # Supported PSEditions 9 | # CompatiblePSEditions = @() 10 | 11 | # ID used to uniquely identify this module 12 | GUID = '0E1AF375-67C1-460A-A247-045C5D2B54AA' 13 | 14 | # Author of this module 15 | Author = 'Claudio Spizzi' 16 | 17 | # Company or vendor of this module 18 | # CompanyName = '' 19 | 20 | # Copyright statement for this module 21 | Copyright = 'Copyright (c) 2019 by Claudio Spizzi. Licensed under MIT license.' 22 | 23 | # Description of the functionality provided by this module 24 | Description = 'PowerShell Module to provide logging capabilities for PowerShell controller scripts.' 25 | 26 | # Minimum version of the Windows PowerShell engine required by this module 27 | PowerShellVersion = '3.0' 28 | 29 | # Name of the Windows PowerShell host required by this module 30 | # PowerShellHostName = '' 31 | 32 | # Minimum version of the Windows PowerShell host required by this module 33 | # PowerShellHostVersion = '' 34 | 35 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 36 | # DotNetFrameworkVersion = '' 37 | 38 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 39 | # CLRVersion = '' 40 | 41 | # Processor architecture (None, X86, Amd64) required by this module 42 | # ProcessorArchitecture = '' 43 | 44 | # Modules that must be imported into the global environment prior to importing this module 45 | # RequiredModules = @() 46 | 47 | # Assemblies that must be loaded prior to importing this module 48 | # RequiredAssemblies = @() 49 | 50 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 51 | # ScriptsToProcess = @() 52 | 53 | # Type files (.ps1xml) to be loaded when importing this module 54 | TypesToProcess = @( 55 | 'Resources\ScriptLogger.Types.ps1xml' 56 | ) 57 | 58 | # Format files (.ps1xml) to be loaded when importing this module 59 | FormatsToProcess = @( 60 | 'Resources\ScriptLogger.Formats.ps1xml' 61 | ) 62 | 63 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 64 | # NestedModules = @() 65 | 66 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 67 | FunctionsToExport = @( 68 | 'Start-ScriptLogger', 69 | 'Stop-ScriptLogger', 70 | 'Get-ScriptLogger', 71 | 'Set-ScriptLogger', 72 | 'Write-VerboseLog', 73 | 'Write-InformationLog', 74 | 'Write-WarningLog', 75 | 'Write-ErrorLog' 76 | ) 77 | 78 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 79 | # CmdletsToExport = @() 80 | 81 | # Variables to export from this module 82 | # VariablesToExport = @() 83 | 84 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 85 | # AliasesToExport = @() 86 | 87 | # DSC resources to export from this module 88 | # DscResourcesToExport = @() 89 | 90 | # List of all modules packaged with this module 91 | # ModuleList = @() 92 | 93 | # List of all files packaged with this module 94 | # FileList = @() 95 | 96 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 97 | PrivateData = @{ 98 | 99 | PSData = @{ 100 | 101 | # Tags applied to this module. These help with module discovery in online galleries. 102 | Tags = @('PSModule', 'Log', 'Logger', 'Script', 'Controller') 103 | 104 | # A URL to the license for this module. 105 | LicenseUri = 'https://raw.githubusercontent.com/claudiospizzi/ScriptLogger/master/LICENSE' 106 | 107 | # A URL to the main website for this project. 108 | ProjectUri = 'https://github.com/claudiospizzi/ScriptLogger' 109 | 110 | # A URL to an icon representing this module. 111 | # IconUri = '' 112 | 113 | # ReleaseNotes of this module 114 | ReleaseNotes = 'https://github.com/claudiospizzi/ScriptLogger/blob/master/CHANGELOG.md' 115 | 116 | } # End of PSData hashtable 117 | 118 | } # End of PrivateData hashtable 119 | 120 | # HelpInfo URI of this module 121 | # HelpInfoURI = '' 122 | 123 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 124 | # DefaultCommandPrefix = '' 125 | } 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![PowerShell Gallery - ScriptLogger](https://img.shields.io/badge/PowerShell_Gallery-ScriptLogger-0072C6.svg)](https://www.powershellgallery.com/packages/ScriptLogger) 2 | [![GitHub - Release](https://img.shields.io/github/release/claudiospizzi/ScriptLogger.svg)](https://github.com/claudiospizzi/ScriptLogger/releases) 3 | [![AppVeyor - master](https://img.shields.io/appveyor/ci/claudiospizzi/ScriptLogger/master.svg)](https://ci.appveyor.com/project/claudiospizzi/ScriptLogger/branch/master) 4 | 5 | # ScriptLogger PowerShell Module 6 | 7 | PowerShell Module to provide logging capabilities for PowerShell controller 8 | scripts. 9 | 10 | ## Introduction 11 | 12 | With the ScriptLogger module, you are able to log error, warning, informational 13 | and verbose messages into log files, the Windows event log and the current 14 | console host. You can start and stop the logger as required. Works great in 15 | cooperation with the [ScriptConfig] module to improve controller scripts. 16 | 17 | ## Features 18 | 19 | * **Start-ScriptLogger** 20 | Start the script logger in the active PowerShell session. 21 | 22 | * **Stop-ScriptLogger** 23 | Stop the script logger in the active PowerShell session. 24 | 25 | * **Set-ScriptLogger** 26 | Update the script logger log configuration. 27 | 28 | * **Get-ScriptLogger** 29 | Get the active script logger object. 30 | 31 | * **Write-VerboseLog** 32 | Log a verbose message. 33 | 34 | * **Write-InformationLog** 35 | Log an information message. 36 | 37 | * **Write-WarningLog** 38 | Log a warning message. 39 | 40 | * **Write-ErrorLog** 41 | Log an error message. 42 | 43 | ### Example 44 | 45 | The following example show two options how to start the script logger, the 46 | logger management and how to log the log messages. 47 | 48 | ```powershell 49 | # Initialize the logger with default values 50 | Start-ScriptLogger 51 | 52 | # Second options, specify multiple custom settings for the logger 53 | Start-ScriptLogger -Path 'C:\Temp\test.log' -Format '{0:yyyy-MM-dd} {0:HH:mm:ss} {1} {2} {3,-11} {4}' -Level Warning -Encoding 'UTF8' -NoEventLog -NoConsoleOutput 54 | 55 | # Start a second script logger with a dedicated name. The default script logger 56 | # is always named 'Default' 57 | Start-ScriptLogger -Name 'Logger2' -Path 'C:\Temp\test2.log' 58 | 59 | # Get the current script logger configuration object 60 | Get-ScriptLogger 61 | 62 | # Update the script logger configuration 63 | Set-ScriptLogger -Level Verbose 64 | 65 | # Log an error record 66 | try { 0 / 0 } catch { Write-ErrorLog -ErrorRecord $_ } 67 | 68 | # Log an error message 69 | Write-ErrorLog -Message 'My Error Message' 70 | 71 | # Log a warning massage 72 | Write-WarningLog -Message 'My Warning Message' 73 | 74 | # Log an information message 75 | Write-InformationLog -Message 'My Information Message' 76 | 77 | # Log a verbose message 78 | Write-VerboseLog -Message 'My Verbose Message' 79 | 80 | # Write a log message into the log 2 81 | Write-InformationLog -Name 'Logger2' -Message 'My Information Message in Log 2' 82 | 83 | # Disable the logger 84 | Stop-ScriptLogger 85 | ``` 86 | 87 | ## Versions 88 | 89 | Please find all versions in the [GitHub Releases] section and the release notes 90 | in the [CHANGELOG.md] file. 91 | 92 | ## Installation 93 | 94 | Use the following command to install the module from the [PowerShell Gallery], 95 | if the PackageManagement and PowerShellGet modules are available: 96 | 97 | ```powershell 98 | # Download and install the module 99 | Install-Module -Name 'ScriptLogger' 100 | ``` 101 | 102 | Alternatively, download the latest release from GitHub and install the module 103 | manually on your local system: 104 | 105 | 1. Download the latest release from GitHub as a ZIP file: [GitHub Releases] 106 | 2. Extract the module and install it: [Installing a PowerShell Module] 107 | 108 | ## Requirements 109 | 110 | The following minimum requirements are necessary to use this module, or in other 111 | words are used to test this module: 112 | 113 | * Windows PowerShell 3.0 114 | * Windows Server 2008 R2 / Windows 7 115 | 116 | ## Contribute 117 | 118 | Please feel free to contribute by opening new issues or providing pull requests. 119 | For the best development experience, open this project as a folder in Visual 120 | Studio Code and ensure that the PowerShell extension is installed. 121 | 122 | * [Visual Studio Code] with the [PowerShell Extension] 123 | * [Pester], [PSScriptAnalyzer] and [psake] PowerShell Modules 124 | 125 | [ScriptConfig]: https://github.com/claudiospizzi/ScriptConfig 126 | 127 | [PowerShell Gallery]: https://www.powershellgallery.com/packages/ScriptLogger 128 | [GitHub Releases]: https://github.com/claudiospizzi/ScriptLogger/releases 129 | [Installing a PowerShell Module]: https://msdn.microsoft.com/en-us/library/dd878350 130 | 131 | [CHANGELOG.md]: CHANGELOG.md 132 | 133 | [Visual Studio Code]: https://code.visualstudio.com/ 134 | [PowerShell Extension]: https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell 135 | [Pester]: https://www.powershellgallery.com/packages/Pester 136 | [PSScriptAnalyzer]: https://www.powershellgallery.com/packages/PSScriptAnalyzer 137 | [psake]: https://www.powershellgallery.com/packages/psake 138 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Set-ScriptLogger.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | Describe 'Set-ScriptLogger' { 9 | 10 | $defaultEnabled = $true 11 | $defaultPath = 'TestDrive:\test.log' 12 | $defaultFormat = '{0:yyyy-MM-dd HH:mm:ss} {1} {2} {3} {4}' 13 | $defaultLevel = 'Information' 14 | $defaultEncoding = 'UTF8' 15 | $defaultLogFile = $true 16 | $defaultEventLog = $true 17 | $defaultConsole = $true 18 | 19 | BeforeEach { 20 | 21 | Start-ScriptLogger -Path $defaultPath -Format $defaultFormat -Level $defaultLevel 22 | } 23 | 24 | It 'should update the logger path' { 25 | 26 | # Arrange 27 | $expectedPath = 'TestDrive:\testnew.log' 28 | 29 | # Act 30 | Set-ScriptLogger -Path $expectedPath 31 | 32 | # Assert 33 | $scriptLogger = Get-ScriptLogger 34 | 35 | $scriptLogger | Should -Not -BeNullOrEmpty 36 | $scriptLogger.Enabled | Should -Be $defaultEnabled 37 | $scriptLogger.Path | Should -Be $expectedPath 38 | $scriptLogger.Format | Should -Be $defaultFormat 39 | $scriptLogger.Level | Should -Be $defaultLevel 40 | $scriptLogger.Encoding | Should -Be $defaultEncoding 41 | $scriptLogger.LogFile | Should -Be $defaultLogFile 42 | $scriptLogger.EventLog | Should -Be $defaultEventLog 43 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 44 | } 45 | 46 | It 'should update the logger format' { 47 | 48 | # Arrange 49 | $expectedFormat = '{4} {3} {2} {1} {0}' 50 | 51 | # Act 52 | Set-ScriptLogger -Format $expectedFormat 53 | 54 | # Assert 55 | $scriptLogger = Get-ScriptLogger 56 | $scriptLogger | Should -Not -BeNullOrEmpty 57 | $scriptLogger.Enabled | Should -Be $defaultEnabled 58 | $scriptLogger.Path | Should -Be $defaultPath 59 | $scriptLogger.Format | Should -Be $expectedFormat 60 | $scriptLogger.Level | Should -Be $defaultLevel 61 | $scriptLogger.Encoding | Should -Be $defaultEncoding 62 | $scriptLogger.LogFile | Should -Be $defaultLogFile 63 | $scriptLogger.EventLog | Should -Be $defaultEventLog 64 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 65 | } 66 | 67 | It 'should update the logger log level' { 68 | 69 | # Arrange 70 | $expectedLevel = 'Error' 71 | 72 | # Act 73 | Set-ScriptLogger -Level $expectedLevel 74 | 75 | # Assert 76 | $scriptLogger = Get-ScriptLogger 77 | $scriptLogger | Should -Not -BeNullOrEmpty 78 | $scriptLogger.Enabled | Should -Be $defaultEnabled 79 | $scriptLogger.Path | Should -Be $defaultPath 80 | $scriptLogger.Format | Should -Be $defaultFormat 81 | $scriptLogger.Level | Should -Be $expectedLevel 82 | $scriptLogger.Encoding | Should -Be $defaultEncoding 83 | $scriptLogger.LogFile | Should -Be $defaultLogFile 84 | $scriptLogger.EventLog | Should -Be $defaultEventLog 85 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 86 | } 87 | 88 | It 'should update the logger encoding' { 89 | 90 | # Arrange 91 | $expectedEncoding = 'UTF8' 92 | 93 | # Act 94 | Set-ScriptLogger -Encoding $expectedEncoding 95 | 96 | # Assert 97 | $scriptLogger = Get-ScriptLogger 98 | $scriptLogger | Should -Not -BeNullOrEmpty 99 | $scriptLogger.Enabled | Should -Be $defaultEnabled 100 | $scriptLogger.Path | Should -Be $defaultPath 101 | $scriptLogger.Format | Should -Be $defaultFormat 102 | $scriptLogger.Level | Should -Be $defaultLevel 103 | $scriptLogger.Encoding | Should -Be $expectedEncoding 104 | $scriptLogger.LogFile | Should -Be $defaultLogFile 105 | $scriptLogger.EventLog | Should -Be $defaultEventLog 106 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 107 | } 108 | 109 | It 'should update the logger no log file option' { 110 | 111 | # Act 112 | Set-ScriptLogger -LogFile (-not $defaultLogFile) 113 | 114 | # Assert 115 | $scriptLogger = Get-ScriptLogger 116 | $scriptLogger | Should -Not -BeNullOrEmpty 117 | $scriptLogger.Enabled | Should -Be $defaultEnabled 118 | $scriptLogger.Path | Should -Be $defaultPath 119 | $scriptLogger.Format | Should -Be $defaultFormat 120 | $scriptLogger.Level | Should -Be $defaultLevel 121 | $scriptLogger.Encoding | Should -Be $defaultEncoding 122 | $scriptLogger.LogFile | Should -Not -Be $defaultLogFile 123 | $scriptLogger.EventLog | Should -Be $defaultEventLog 124 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 125 | } 126 | 127 | It 'should update the logger no event log option' { 128 | 129 | # Act 130 | Set-ScriptLogger -EventLog (-not $defaultEventLog) 131 | 132 | # Assert 133 | $scriptLogger = Get-ScriptLogger 134 | $scriptLogger | Should -Not -BeNullOrEmpty 135 | $scriptLogger.Enabled | Should -Be $defaultEnabled 136 | $scriptLogger.Path | Should -Be $defaultPath 137 | $scriptLogger.Format | Should -Be $defaultFormat 138 | $scriptLogger.Level | Should -Be $defaultLevel 139 | $scriptLogger.Encoding | Should -Be $defaultEncoding 140 | $scriptLogger.LogFile | Should -Be $defaultLogFile 141 | $scriptLogger.EventLog | Should -Not -Be $defaultEventLog 142 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 143 | } 144 | 145 | It 'should update the logger no console option' { 146 | 147 | # Act 148 | Set-ScriptLogger -ConsoleOutput (-not $defaultConsole) 149 | 150 | # Assert 151 | $scriptLogger = Get-ScriptLogger 152 | $scriptLogger | Should -Not -BeNullOrEmpty 153 | $scriptLogger.Enabled | Should -Be $defaultEnabled 154 | $scriptLogger.Path | Should -Be $defaultPath 155 | $scriptLogger.Format | Should -Be $defaultFormat 156 | $scriptLogger.Level | Should -Be $defaultLevel 157 | $scriptLogger.Encoding | Should -Be $defaultEncoding 158 | $scriptLogger.LogFile | Should -Be $defaultLogFile 159 | $scriptLogger.EventLog | Should -Be $defaultEventLog 160 | $scriptLogger.ConsoleOutput | Should -Not -Be $defaultConsole 161 | } 162 | 163 | AfterEach { 164 | 165 | Stop-ScriptLogger 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /ScriptLogger/Functions/Start-ScriptLogger.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Start the script logger in the current PowerShell session. 4 | 5 | .DESCRIPTION 6 | Start the script logger in the current PowerShell session. By starting 7 | the logger, a global log configuration for the current PowerShell 8 | session will be set. This configuration is customizable with the 9 | available paramters. 10 | With the format parameter, the logfile format can be defined. The format 11 | definition will be used to call the System.String.Format() method. The 12 | following values are used as arguments: 13 | - {0} Timestamp as datetime value. 14 | - {1} NetBIOS computer name. 15 | - {2} Current session username. 16 | - {3} Log entry level. 17 | - {4} Message. 18 | 19 | .INPUTS 20 | None. 21 | 22 | .OUTPUTS 23 | ScriptLogger.Configuration. Configuration of the script logger instance. 24 | 25 | .EXAMPLE 26 | PS C:\> Start-ScriptLogger 27 | Initialize the logger with default values. 28 | 29 | .EXAMPLE 30 | PS C:\> Start-ScriptLogger -Name 'MyLogger' -Path 'C:\my.log' 31 | Start a custom named logger instance. 32 | 33 | .EXAMPLE 34 | PS C:\> Start-ScriptLogger -Path 'C:\test.log' -Format '{3}: {4}' -Level 'Verbose' -SkipEventLog -HideConsoleOutput 35 | Log all message with verbose level or higher to the log file but skip 36 | the event log and the consule output. In addition, use a custom format 37 | for the log file content. 38 | 39 | .NOTES 40 | Author : Claudio Spizzi 41 | License : MIT License 42 | 43 | .LINK 44 | https://github.com/claudiospizzi/ScriptLogger 45 | #> 46 | function Start-ScriptLogger 47 | { 48 | [CmdletBinding(SupportsShouldProcess = $true)] 49 | param 50 | ( 51 | # The logger name. 52 | [Parameter(Mandatory = $false)] 53 | [System.String] 54 | $Name = 'Default', 55 | 56 | # The path to the log file. 57 | [Parameter(Mandatory = $false)] 58 | [AllowEmptyString()] 59 | [System.String] 60 | $Path, 61 | 62 | # This parameter defines, how the log output will be formated. 63 | [Parameter(Mandatory = $false)] 64 | [ValidateScript({$_ -f (Get-Date), $Env:ComputerName, $Env:Username, 'Verbose', 'Message'})] 65 | [System.String] 66 | $Format = '{0:yyyy-MM-dd} {0:HH:mm:ss} {1} {2} {3,-11} {4}', 67 | 68 | # The event log level. All log messages equal to or higher to the level 69 | # will be logged. This is the level order: Verbose, Information, Warning 70 | # and Error. 71 | [Parameter(Mandatory = $false)] 72 | [ValidateSet('Verbose', 'Information', 'Warning', 'Error')] 73 | [System.String] 74 | $Level = 'Verbose', 75 | 76 | # Define the encoding which is used to write the log file. The possible 77 | # options are the same as on the used Out-File cmdlet. 78 | [Parameter(Mandatory = $false)] 79 | [ValidateSet('Unicode', 'UTF7', 'UTF8', 'UTF32', 'ASCII', 'BigEndianUnicode', 'Default', 'OEM')] 80 | [System.String] 81 | $Encoding = 'UTF8', 82 | 83 | # Allow the auto log rotation. The period is attached to the log file. 84 | [Parameter(Mandatory = $false)] 85 | [ValidateSet('None', 'Hourly', 'Daily', 'Monthly', 'Yearly')] 86 | [System.String] 87 | $Rotation = 'None', 88 | 89 | # Do not write the log messages into the log file. By default, all 90 | # messages are written to the specified or default log file. 91 | [Parameter(Mandatory = $false)] 92 | [Switch] 93 | $NoLogFile, 94 | 95 | # Skip the event log output. By default, all log messages will be 96 | # written into the "Windows PowerShell" event log. 97 | [Parameter(Mandatory = $false)] 98 | [Switch] 99 | $NoEventLog, 100 | 101 | # Hide the PowerShell console output. By default, all log messages are 102 | # shown on the console. 103 | [Parameter(Mandatory = $false)] 104 | [Switch] 105 | $NoConsoleOutput, 106 | 107 | # If specified, the created script logger object will be returned. 108 | [Parameter(Mandatory = $false)] 109 | [Switch] 110 | $PassThru 111 | ) 112 | 113 | # If the Path parameter was not specified, add a default value. If possible, 114 | # use the last script called this function. Else use the temp path. 115 | if (-not $PSBoundParameters.ContainsKey('Path') -or [System.String]::IsNullOrEmpty($Path)) 116 | { 117 | $lastScriptPath = Get-PSCallStack | Select-Object -Skip 1 -First 1 -ExpandProperty 'ScriptName' 118 | 119 | if (-not [System.String]::IsNullOrEmpty($lastScriptPath)) 120 | { 121 | $Path = $lastScriptPath + '.log' 122 | } 123 | else 124 | { 125 | $Path = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'PowerShell.log' 126 | } 127 | } 128 | 129 | # If log rotation is enable, add the current period to the path 130 | switch ($Rotation) 131 | { 132 | 'Hourly' 133 | { 134 | $Path = $Path.Insert($Path.LastIndexOf('.'), [System.String]::Format('.{0:yyyyMMddHH}', (Get-Date))) 135 | } 136 | 'Daily' 137 | { 138 | $Path = $Path.Insert($Path.LastIndexOf('.'), [System.String]::Format('.{0:yyyyMMdd}', (Get-Date))) 139 | } 140 | 'Monthly' 141 | { 142 | $Path = $Path.Insert($Path.LastIndexOf('.'), [System.String]::Format('.{0:yyyyMM}', (Get-Date))) 143 | } 144 | 'Yearly' 145 | { 146 | $Path = $Path.Insert($Path.LastIndexOf('.'), [System.String]::Format('.{0:yyyy}', (Get-Date))) 147 | } 148 | } 149 | 150 | # Create the log file folder, if it does not exist 151 | $parent = Split-Path -Path $Path -Parent 152 | if (-not (Test-Path -Path $parent)) 153 | { 154 | try 155 | { 156 | New-Item -Path $parent -ItemType 'Directory' -ErrorAction 'Stop' | Out-Null 157 | } 158 | catch 159 | { 160 | throw "ScriptLogger failed to create the log folder: $parent" 161 | } 162 | } 163 | 164 | # Create an empty log file, if it does not exist 165 | if (-not (Test-Path -Path $Path)) 166 | { 167 | try 168 | { 169 | New-Item -Path $Path -ItemType 'File' -ErrorAction 'Stop' | Out-Null 170 | } 171 | catch 172 | { 173 | throw "ScriptLogger failed to create the log file: $Path" 174 | } 175 | } 176 | 177 | # Only work with absolute path, makes error handling easier 178 | $Path = (Resolve-Path -Path $Path).Path 179 | 180 | if ($PSCmdlet.ShouldProcess('ScriptLogger', 'Start')) 181 | { 182 | Write-Verbose "Start script logger '$Name'" 183 | 184 | $Script:Loggers[$Name] = [PSCustomObject] @{ 185 | PSTypeName = 'ScriptLogger.Configuration' 186 | Name = $Name 187 | Enabled = $true 188 | Path = $Path 189 | Format = $Format 190 | Level = $Level 191 | Encoding = $Encoding 192 | Rotation = $Rotation 193 | LogFile = -not $NoLogFile.IsPresent 194 | EventLog = -not $NoEventLog.IsPresent 195 | ConsoleOutput = -not $NoConsoleOutput.IsPresent 196 | } 197 | 198 | # Return logger object 199 | if ($PassThru.IsPresent) 200 | { 201 | Write-Output $Script:Loggers[$Name] 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Write-ErrorLog.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | InModuleScope $moduleName { 9 | 10 | Describe 'Write-ErrorLog' { 11 | 12 | Context 'Ensure mocked Write-Log is invoked' { 13 | 14 | $errorRecord = $(try { 0 / 0 } catch { $_ }) 15 | 16 | Mock Write-Log -ModuleName $moduleName -ParameterFilter { $Level -eq 'Error' } -Verifiable 17 | 18 | It 'should invoke the mock one for a simple message' { 19 | 20 | # Act 21 | Write-ErrorLog -Message 'My Error' 22 | 23 | # Assert 24 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 1 -Exactly 25 | } 26 | 27 | It 'should invoke the mock one for a simple error record' { 28 | 29 | # Act 30 | Write-ErrorLog -ErrorRecord $errorRecord 31 | 32 | # Assert 33 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 1 -Exactly 34 | } 35 | It 'should invoke the mock twice for an array of 2 messages' { 36 | 37 | # Act 38 | Write-ErrorLog -Message 'My Error', 'My Error' 39 | 40 | # Assert 41 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 2 -Exactly 42 | } 43 | 44 | It 'should invoke the mock twice for an array of 2 error records' { 45 | 46 | # Act 47 | Write-ErrorLog -Message $errorRecord, $errorRecord 48 | 49 | # Assert 50 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 2 -Exactly 51 | } 52 | 53 | It 'should invoke the mock three times for a pipeline input of 3 messages' { 54 | 55 | # Act 56 | 'My Error', 'My Error', 'My Error' | Write-ErrorLog 57 | 58 | # Assert 59 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 3 -Exactly 60 | } 61 | 62 | It 'should invoke the mock three times for a pipeline input of 3 error records' { 63 | 64 | # Act 65 | $errorRecord, $errorRecord, $errorRecord | Write-ErrorLog 66 | 67 | # Assert 68 | Assert-MockCalled -Scope It -CommandName 'Write-Log' -Times 3 -Exactly 69 | } 70 | } 71 | 72 | Context 'Ensure valid output' { 73 | 74 | $logPath = 'TestDrive:\test.log' 75 | 76 | $errorRecord = $(try { 0 / 0 } catch { $_ }) 77 | 78 | Mock Get-Date -ModuleName $moduleName { [DateTime] '2000-12-31 01:02:03' } 79 | 80 | It 'should write a valid message to the log file' { 81 | 82 | # Arrange 83 | Start-ScriptLogger -Path $logPath -NoEventLog -NoConsoleOutput 84 | 85 | # Act 86 | Write-ErrorLog -Message 'My Error' 87 | 88 | # Assert 89 | $logFile = Get-Content -Path $logPath 90 | $logFile | Should -Be "2000-12-31 01:02:03 $Env:ComputerName $Env:Username Error My Error" 91 | } 92 | 93 | It 'should write a valid error record to the log file' { 94 | 95 | # Arrange 96 | Start-ScriptLogger -Path $logPath -NoEventLog -NoConsoleOutput 97 | 98 | # Act 99 | Write-ErrorLog -ErrorRecord $errorRecord 100 | 101 | # Assert 102 | $logFile = Get-Content -Path $logPath 103 | $logFile | Should -BeLike "2000-12-31 01:02:03 $Env:ComputerName $Env:Username Error Attempted to divide by zero. (RuntimeException: *\Unit\Write-ErrorLog.Tests.ps1:* char:*)" 104 | } 105 | 106 | It 'should write a valid message to the event log' { 107 | 108 | # Arrange 109 | Start-ScriptLogger -Path $logPath -NoLogFile -NoConsoleOutput 110 | $filterTimestamp = Get-Date 111 | 112 | # Act 113 | Write-ErrorLog -Message 'My Error' 114 | 115 | # Assert 116 | $eventLog = Get-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -InstanceId 0 -EntryType Error -After $filterTimestamp -Newest 1 117 | $eventLog | Should -Not -BeNullOrEmpty 118 | $eventLog.EventID | Should -Be 0 119 | $eventLog.CategoryNumber | Should -Be 0 120 | $eventLog.EntryType | Should -Be 'Error' 121 | $eventLog.Message | Should -Be "The description for Event ID '0' in Source 'PowerShell' cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event:'My Error'" 122 | $eventLog.Source | Should -Be 'PowerShell' 123 | $eventLog.InstanceId | Should -Be 0 124 | } 125 | 126 | It 'should write a valid message to the event log' { 127 | 128 | # Arrange 129 | Start-ScriptLogger -Path $logPath -NoLogFile -NoConsoleOutput 130 | $filterTimestamp = Get-Date 131 | 132 | # Act 133 | Write-ErrorLog -ErrorRecord $errorRecord 134 | 135 | # Assert 136 | $eventLog = Get-EventLog -LogName 'Windows PowerShell' -Source 'PowerShell' -InstanceId 0 -EntryType Error -After $filterTimestamp -Newest 1 137 | $eventLog | Should -Not -BeNullOrEmpty 138 | $eventLog.EventID | Should -Be 0 139 | $eventLog.CategoryNumber | Should -Be 0 140 | $eventLog.EntryType | Should -Be 'Error' 141 | $eventLog.Message | Should -BeLike "The description for Event ID '0' in Source 'PowerShell' cannot be found. The local computer may not have the necessary registry information or message DLL files to display the message, or you may not have permission to access them. The following information is part of the event:'Attempted to divide by zero. (RuntimeException: *\Unit\Write-ErrorLog.Tests.ps1:* char:*)'" 142 | $eventLog.Source | Should -Be 'PowerShell' 143 | $eventLog.InstanceId | Should -Be 0 144 | } 145 | 146 | It 'should write a valid message to the console' { 147 | 148 | # Arrange 149 | Mock Show-ErrorMessage -ModuleName $moduleName -ParameterFilter { $Message -eq 'My Error' } 150 | Start-ScriptLogger -Path $logPath -NoLogFile -NoEventLog 151 | 152 | # Act 153 | Write-ErrorLog -Message 'My Error' 154 | 155 | # Assert 156 | Assert-MockCalled -Scope It -CommandName 'Show-ErrorMessage' -Times 1 -Exactly 157 | } 158 | 159 | It 'should write a valid message to the console' { 160 | 161 | # Arrange 162 | Mock Show-ErrorMessage -ModuleName $moduleName -ParameterFilter { $Message -like 'Attempted to divide by zero. (RuntimeException: *\Unit\Write-ErrorLog.Tests.ps1:* char:*)' } 163 | Start-ScriptLogger -Path $logPath -NoLogFile -NoEventLog 164 | 165 | # Act 166 | Write-ErrorLog -ErrorRecord $errorRecord 167 | 168 | # Assert 169 | Assert-MockCalled -Scope It -CommandName 'Show-ErrorMessage' -Times 1 -Exactly 170 | } 171 | 172 | AfterEach { 173 | 174 | # Cleanup logger 175 | Get-ScriptLogger | Remove-Item -Force 176 | Stop-ScriptLogger 177 | } 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /ScriptLogger/Tests/Unit/Start-ScriptLogger.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | $modulePath = Resolve-Path -Path "$PSScriptRoot\..\..\.." | Select-Object -ExpandProperty Path 3 | $moduleName = Resolve-Path -Path "$PSScriptRoot\..\.." | Get-Item | Select-Object -ExpandProperty BaseName 4 | 5 | Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue 6 | Import-Module -Name "$modulePath\$moduleName" -Force 7 | 8 | Describe 'Start-ScriptLogger' { 9 | 10 | Mock Get-Date { return [DateTime]::new(2010, 12, 06, 18, 20, 22) } -ModuleName $moduleName 11 | 12 | $defaultEnabled = $true 13 | $defaultPath = "$PSScriptRoot\Start-ScriptLogger.Tests.ps1.log" 14 | $defaultFormat = '{0:yyyy-MM-dd} {0:HH:mm:ss} {1} {2} {3,-11} {4}' 15 | $defaultLevel = 'Verbose' 16 | $defaultEncoding = 'UTF8' 17 | $defaultRotation = 'None' 18 | $defaultLogFile = $true 19 | $defaultEventLog = $true 20 | $defaultConsole = $true 21 | 22 | It 'should return default values without any specification' { 23 | 24 | # Act 25 | $scriptLogger = Start-ScriptLogger -PassThru 26 | 27 | # Assert 28 | $scriptLogger | Should -Not -BeNullOrEmpty 29 | $scriptLogger.Enabled | Should -Be $defaultEnabled 30 | $scriptLogger.Path | Should -Be $defaultPath 31 | $scriptLogger.Format | Should -Be $defaultFormat 32 | $scriptLogger.Level | Should -Be $defaultLevel 33 | $scriptLogger.Encoding | Should -Be $defaultEncoding 34 | $scriptLogger.Rotation | Should -Be $defaultRotation 35 | $scriptLogger.LogFile | Should -Be $defaultLogFile 36 | $scriptLogger.EventLog | Should -Be $defaultEventLog 37 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 38 | } 39 | 40 | It 'should return a valid value for the parameter path' { 41 | 42 | # Arrange 43 | $expectedPath = 'TestDrive:\test.log' 44 | 45 | # Act 46 | $scriptLogger = Start-ScriptLogger -Path $expectedPath -PassThru 47 | 48 | # Assert 49 | $scriptLogger | Should -Not -BeNullOrEmpty 50 | $scriptLogger.Enabled | Should -Be $defaultEnabled 51 | $scriptLogger.Path | Should -Be $expectedPath 52 | $scriptLogger.Format | Should -Be $defaultFormat 53 | $scriptLogger.Level | Should -Be $defaultLevel 54 | $scriptLogger.Encoding | Should -Be $defaultEncoding 55 | $scriptLogger.Rotation | Should -Be $defaultRotation 56 | $scriptLogger.LogFile | Should -Be $defaultLogFile 57 | $scriptLogger.EventLog | Should -Be $defaultEventLog 58 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 59 | } 60 | 61 | It 'should return a valid value for the parameter format' { 62 | 63 | # Arrange 64 | $expectedFormat = '{4} {3} {2} {1} {0}' 65 | 66 | # Act 67 | $scriptLogger = Start-ScriptLogger -Format $expectedFormat -PassThru 68 | 69 | # Assert 70 | $scriptLogger | Should -Not -BeNullOrEmpty 71 | $scriptLogger.Enabled | Should -Be $defaultEnabled 72 | $scriptLogger.Path | Should -Be $defaultPath 73 | $scriptLogger.Format | Should -Be $expectedFormat 74 | $scriptLogger.Level | Should -Be $defaultLevel 75 | $scriptLogger.Encoding | Should -Be $defaultEncoding 76 | $scriptLogger.Rotation | Should -Be $defaultRotation 77 | $scriptLogger.LogFile | Should -Be $defaultLogFile 78 | $scriptLogger.EventLog | Should -Be $defaultEventLog 79 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 80 | } 81 | 82 | It 'should return a valid value for the parameter log level' { 83 | 84 | # Arrange 85 | $expectedLevel = 'Error' 86 | 87 | # Act 88 | $scriptLogger = Start-ScriptLogger -Level $expectedLevel -PassThru 89 | 90 | # Assert 91 | $scriptLogger | Should -Not -BeNullOrEmpty 92 | $scriptLogger.Enabled | Should -Be $defaultEnabled 93 | $scriptLogger.Path | Should -Be $defaultPath 94 | $scriptLogger.Format | Should -Be $defaultFormat 95 | $scriptLogger.Level | Should -Be $expectedLevel 96 | $scriptLogger.Encoding | Should -Be $defaultEncoding 97 | $scriptLogger.Rotation | Should -Be $defaultRotation 98 | $scriptLogger.LogFile | Should -Be $defaultLogFile 99 | $scriptLogger.EventLog | Should -Be $defaultEventLog 100 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 101 | } 102 | 103 | It 'should return a valid value for the parameter encoding' { 104 | 105 | # Arrange 106 | $expectedEncoding = 'UTF8' 107 | 108 | # Act 109 | $scriptLogger = Start-ScriptLogger -Encoding $expectedEncoding -PassThru 110 | 111 | # Assert 112 | $scriptLogger | Should -Not -BeNullOrEmpty 113 | $scriptLogger.Enabled | Should -Be $defaultEnabled 114 | $scriptLogger.Path | Should -Be $defaultPath 115 | $scriptLogger.Format | Should -Be $defaultFormat 116 | $scriptLogger.Level | Should -Be $defaultLevel 117 | $scriptLogger.Encoding | Should -Be $expectedEncoding 118 | $scriptLogger.Rotation | Should -Be $defaultRotation 119 | $scriptLogger.LogFile | Should -Be $defaultLogFile 120 | $scriptLogger.EventLog | Should -Be $defaultEventLog 121 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 122 | } 123 | 124 | It 'should return a valid value for the parameter rotation hourly' { 125 | 126 | # Arrange 127 | $expectedRotation = 'Hourly' 128 | $expectedPath = "$PSScriptRoot\Start-ScriptLogger.Tests.ps1.2010120618.log" 129 | 130 | # Act 131 | $scriptLogger = Start-ScriptLogger -Rotation $expectedRotation -PassThru 132 | 133 | # Assert 134 | $scriptLogger | Should -Not -BeNullOrEmpty 135 | $scriptLogger.Enabled | Should -Be $defaultEnabled 136 | $scriptLogger.Path | Should -Be $expectedPath 137 | $scriptLogger.Format | Should -Be $defaultFormat 138 | $scriptLogger.Level | Should -Be $defaultLevel 139 | $scriptLogger.Encoding | Should -Be $defaultEncoding 140 | $scriptLogger.Rotation | Should -Be $expectedRotation 141 | $scriptLogger.LogFile | Should -Be $defaultLogFile 142 | $scriptLogger.EventLog | Should -Be $defaultEventLog 143 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 144 | } 145 | 146 | 147 | It 'should return a valid value for the parameter rotation daily' { 148 | 149 | # Arrange 150 | $expectedRotation = 'Daily' 151 | $expectedPath = "$PSScriptRoot\Start-ScriptLogger.Tests.ps1.20101206.log" 152 | 153 | # Act 154 | $scriptLogger = Start-ScriptLogger -Rotation $expectedRotation -PassThru 155 | 156 | # Assert 157 | $scriptLogger | Should -Not -BeNullOrEmpty 158 | $scriptLogger.Enabled | Should -Be $defaultEnabled 159 | $scriptLogger.Path | Should -Be $expectedPath 160 | $scriptLogger.Format | Should -Be $defaultFormat 161 | $scriptLogger.Level | Should -Be $defaultLevel 162 | $scriptLogger.Encoding | Should -Be $defaultEncoding 163 | $scriptLogger.Rotation | Should -Be $expectedRotation 164 | $scriptLogger.LogFile | Should -Be $defaultLogFile 165 | $scriptLogger.EventLog | Should -Be $defaultEventLog 166 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 167 | } 168 | 169 | It 'should return a valid value for the parameter rotation monthly' { 170 | 171 | # Arrange 172 | $expectedRotation = 'Monthly' 173 | $expectedPath = "$PSScriptRoot\Start-ScriptLogger.Tests.ps1.201012.log" 174 | 175 | # Act 176 | $scriptLogger = Start-ScriptLogger -Rotation $expectedRotation -PassThru 177 | 178 | # Assert 179 | $scriptLogger | Should -Not -BeNullOrEmpty 180 | $scriptLogger.Enabled | Should -Be $defaultEnabled 181 | $scriptLogger.Path | Should -Be $expectedPath 182 | $scriptLogger.Format | Should -Be $defaultFormat 183 | $scriptLogger.Level | Should -Be $defaultLevel 184 | $scriptLogger.Encoding | Should -Be $defaultEncoding 185 | $scriptLogger.Rotation | Should -Be $expectedRotation 186 | $scriptLogger.LogFile | Should -Be $defaultLogFile 187 | $scriptLogger.EventLog | Should -Be $defaultEventLog 188 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 189 | } 190 | 191 | It 'should return a valid value for the parameter rotation yearly' { 192 | 193 | # Arrange 194 | $expectedRotation = 'Yearly' 195 | $expectedPath = "$PSScriptRoot\Start-ScriptLogger.Tests.ps1.2010.log" 196 | 197 | # Act 198 | $scriptLogger = Start-ScriptLogger -Rotation $expectedRotation -PassThru 199 | 200 | # Assert 201 | $scriptLogger | Should -Not -BeNullOrEmpty 202 | $scriptLogger.Enabled | Should -Be $defaultEnabled 203 | $scriptLogger.Path | Should -Be $expectedPath 204 | $scriptLogger.Format | Should -Be $defaultFormat 205 | $scriptLogger.Level | Should -Be $defaultLevel 206 | $scriptLogger.Encoding | Should -Be $defaultEncoding 207 | $scriptLogger.Rotation | Should -Be $expectedRotation 208 | $scriptLogger.LogFile | Should -Be $defaultLogFile 209 | $scriptLogger.EventLog | Should -Be $defaultEventLog 210 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 211 | } 212 | 213 | It 'should return a valid value for the parameter no log file' { 214 | 215 | # Act 216 | $scriptLogger = Start-ScriptLogger -NoLogFile -PassThru 217 | 218 | # Assert 219 | $scriptLogger | Should -Not -BeNullOrEmpty 220 | $scriptLogger.Enabled | Should -Be $defaultEnabled 221 | $scriptLogger.Path | Should -Be $defaultPath 222 | $scriptLogger.Format | Should -Be $defaultFormat 223 | $scriptLogger.Level | Should -Be $defaultLevel 224 | $scriptLogger.Encoding | Should -Be $defaultEncoding 225 | $scriptLogger.Rotation | Should -Be $defaultRotation 226 | $scriptLogger.LogFile | Should -Be $false 227 | $scriptLogger.EventLog | Should -Be $defaultEventLog 228 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 229 | } 230 | 231 | It 'should return a valid value for the parameter no event log' { 232 | 233 | # Act 234 | $scriptLogger = Start-ScriptLogger -NoEventLog -PassThru 235 | 236 | # Assert 237 | $scriptLogger | Should -Not -BeNullOrEmpty 238 | $scriptLogger.Enabled | Should -Be $defaultEnabled 239 | $scriptLogger.Path | Should -Be $defaultPath 240 | $scriptLogger.Format | Should -Be $defaultFormat 241 | $scriptLogger.Level | Should -Be $defaultLevel 242 | $scriptLogger.Encoding | Should -Be $defaultEncoding 243 | $scriptLogger.Rotation | Should -Be $defaultRotation 244 | $scriptLogger.LogFile | Should -Be $defaultLogFile 245 | $scriptLogger.EventLog | Should -Be $false 246 | $scriptLogger.ConsoleOutput | Should -Be $defaultConsole 247 | } 248 | 249 | It 'should return a valid value for the parameter no console output' { 250 | 251 | # Act 252 | $scriptLogger = Start-ScriptLogger -NoConsoleOutput -PassThru 253 | 254 | # Assert 255 | $scriptLogger | Should -Not -BeNullOrEmpty 256 | $scriptLogger.Enabled | Should -Be $defaultEnabled 257 | $scriptLogger.Path | Should -Be $defaultPath 258 | $scriptLogger.Format | Should -Be $defaultFormat 259 | $scriptLogger.Level | Should -Be $defaultLevel 260 | $scriptLogger.Encoding | Should -Be $defaultEncoding 261 | $scriptLogger.Rotation | Should -Be $defaultRotation 262 | $scriptLogger.LogFile | Should -Be $defaultLogFile 263 | $scriptLogger.EventLog | Should -Be $defaultEventLog 264 | $scriptLogger.ConsoleOutput | Should -Be $false 265 | } 266 | 267 | AfterEach { 268 | 269 | Get-ScriptLogger | Remove-Item -Force 270 | Stop-ScriptLogger 271 | } 272 | } 273 | --------------------------------------------------------------------------------