I have a logging function in my script however when I call the function it seems to work properly except for the actual logging portion. It echos to the screen just fine, but when I go to check the log file it doesn't update. Below is the code.
Function Get-Logger {
param(
[Parameter(Mandatory=$true)]
[String]$message,
[Parameter(Mandatory=$false)]
[validatescript({[enum]::getvalues([system.consolecolor]) -contains $_})][string]$Color
)
### Function Variables ###
$Log = $MyInvocation.MyCommand.ToString().Replace(".ps1",".log")
$LogPath = "C:\Source\Scripts\ScriptLog"
$LogFile = "$LogPath\$Log"
$TimeStamp = Get-Date -Format "MM-dd-yyy hh:mm:ss"
#Creates the ScriptLog folder in C:\Source\Scripts if it doesn't exist
IF(-not(Test-Path $LogPath)) {
New-Item -ItemType Directory -Path $LogPath
Get-Logger "Created ScriptLog Directory"
}
Write-Host $TimeStamp -NoNewline
IF ($Color) {
Write-Host `t $message -ForegroundColor $($color)
} Else {
Write-Host `t $message -ForegroundColor Cyan
}
$logMessage = "[$TimeStamp] $message"
$logMessage | Out-File -Append -LiteralPath $LogFile
}
The variables are only used within the function, if I place the variables outside of the function it works, but I want to try and keep the variables within the function itself.
I've tried adding scopes as well $global:
, $script:
, $local:
, etc.. and none of that seems to work. Is it possible to actually have the variables stay within the function, or do I have to place them outside the function?
Local variables are always visible in the same scope (and all descendant scopes, unless created with the $private:
scope specifier), so they aren't the problem.
However, it looks like your intent is to base the $Log
variable value on the script-level definition of $MyInvocation
, not the function's (which reflects how the function was invoked).
To refer to the script's definition of $MyInvocation
- from which you can derive the script file name as intended - use the $script:
scope specifier:
$Log = $script:MyInvocation.MyCommand.ToString().Replace(".ps1",".log")
More simply, however, you can use the automatic $PSCommandPath
variable, which contains the script's full file path, even inside functions:
$Log = [IO.Path]::GetFileNameWithoutExtension($PSCommandPath) + '.log'
In PowerShell (Core) 7, you can alternatively use Split-Path -LeafBase
(not supported in Windows PowerShell):
$Log = (Split-Path -LeafBase $PSCommandPath) + '.log'