Hello,
I sometimes have the demand to log the output of an object/(hash-)table to the logfile.
For example I have the following code:
$Parameters = @{
"Source" = "C:\MySource";
"Destination" = "C:\MyDestination";
"CopyType" = "Mirror";
}
$Parameters.GetEnumerator() | Sort-Object Name | Write-Log -Severity 1 -Source $MyInvocation.MyCommand.Name -LogType CMTrace -LogFile $LogFile
This does not work:
System.Collections.DictionaryEntry
I was trying with something like this:
"`n`n" + ( $Parameters.GetEnumerator() | Sort-Object Name | Out-String ).Trim() + "`n" | Write-Log …
The output to host is OK. The CMTrace does not look that good:
Does anybody have an tips on this?
Thank you
Function Write-PSObjectToLog
{
<#
.SYNOPSIS
.DESCRIPTION
.PARAMETER
.EXAMPLE
.NOTES
.LINK
#>
[CmdletBinding(ConfirmImpact = 'Medium', DefaultParameterSetName = 'ByInputObject', HelpURI = '', SupportsPaging = $True, SupportsShouldProcess = $True, PositionalBinding = $True)]
Param
(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[Object[]]$InputObject,
[Parameter(Mandatory=$False)]
[Switch]$LogParameters = $False,
[Parameter(Mandatory=$False)]
[Switch]$PassThru,
[Parameter(Mandatory=$False)]
[Switch]$ContinueOnError
)
Begin
{
Try
{
[String]$CmdletName = $MyInvocation.MyCommand.Name
Write-FunctionHeaderOrFooter -CmdletName "$($CmdletName)" -CmdletBoundParameters $PSBoundParameters -Header
Write-Log -Message "Function `'$($CmdletName)`' is beginning. Please Wait..." -Severity 2 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
#Define Default Action Preferences
$ErrorActionPreference = 'Stop'
If ($LogParameters.IsPresent -eq $True)
{
$LogMessage = "The following parameters and values were provided to the `'$($CmdletName)`' function."
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
$FunctionProperties = Get-Command -Name $CmdletName
ForEach ($Parameter In $FunctionProperties.Parameters.Keys)
{
If (!([String]::IsNullOrEmpty($Parameter)))
{
$ParameterProperties = Get-Variable -Name $Parameter -ErrorAction SilentlyContinue
$ParameterValueCount = $ParameterProperties.Value | Measure-Object | Select-Object -ExpandProperty Count
If ($ParameterValueCount -gt 1)
{
$ParameterValueStringFormat = ($ParameterProperties.Value | ForEach-Object {"`"$($_)`""}) -Join "`r`n"
$LogMessage = "$($ParameterProperties.Name):`r`n`r`n$($ParameterValueStringFormat)"
}
Else
{
$ParameterValueStringFormat = ($ParameterProperties.Value | ForEach-Object {"`"$($_)`""}) -Join ', '
$LogMessage = "$($ParameterProperties.Name): $($ParameterValueStringFormat)"
}
If (!([String]::IsNullOrEmpty($ParameterProperties.Name)))
{
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
}
}
}
}
}
Catch
{
$ErrorMessage = "$($CmdletName): $($_.Exception.Message)`r`n`r`n[ScriptName: $($_.InvocationInfo.ScriptName)]`r`n[Line Number: $($_.InvocationInfo.ScriptLineNumber)]`r`n[Line Position: $($_.InvocationInfo.OffsetInLine)]`r`n[Code: $($_.InvocationInfo.Line.Trim())]"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
If ($ContinueOnError.IsPresent -eq $False) {Throw "$($ErrorMessage)"}
}
}
Process
{
Try
{
$LogMessage = "Attempting to write the provided object to the following location `'$($configToolkitLogDir)\$($LogName)`'. Please Wait..."
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
If ($PassThru.IsPresent -eq $True)
{
$ResultantPropertiesFinal = @()
}
ForEach ($Item In $InputObject)
{
$ResultantPropertiesTemporary = New-Object -TypeName 'PSObject'
#Create a string builder object and add all properties and values from the specified powershell object to the log
[System.Text.StringBuilder]$StringBuilder = [System.Text.StringBuilder]::New()
[Void]$StringBuilder.Append("`r`n`r`n")
$ResultantPropertiesTemporaryMembers = $Item | Get-Member -MemberType Property, NoteProperty
ForEach ($Member in $ResultantPropertiesTemporaryMembers)
{
$MemberName = "$($Member.Name)"
$MemberValue = ($Item.$($Member.Name))
$MemberNameAndValue = "`r`n$($MemberName): $($MemberValue)"
[Void]$StringBuilder.Append($MemberNameAndValue)
}
$StringBuilderResult = [String]::New("`r`n$($StringBuilder.ToString().TrimStart().TrimEnd())")
$LogMessage = "$($StringBuilderResult)"
Write-Log -Message $LogMessage -Severity 1 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
If ($PassThru.IsPresent -eq $True)
{
Write-Output -InputObject $ResultantPropertiesFinal
}
}
}
Catch
{
$ErrorMessage = "$($CmdletName): $($_.Exception.Message)`r`n`r`n[ScriptName: $($_.InvocationInfo.ScriptName)]`r`n[Line Number: $($_.InvocationInfo.ScriptLineNumber)]`r`n[Line Position: $($_.InvocationInfo.OffsetInLine)]`r`n[Code: $($_.InvocationInfo.Line.Trim())]"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
If ($ContinueOnError.IsPresent -eq $False) {Throw "$($ErrorMessage)"}
}
}
End
{
Try
{
Write-Log -Message "Function `'$($CmdletName)`' is completed." -Severity 2 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
Write-FunctionHeaderOrFooter -CmdletName "$($CmdletName)" -Footer
}
Catch
{
$ErrorMessage = "$($CmdletName): $($_.Exception.Message)`r`n`r`n[ScriptName: $($_.InvocationInfo.ScriptName)]`r`n[Line Number: $($_.InvocationInfo.ScriptLineNumber)]`r`n[Line Position: $($_.InvocationInfo.OffsetInLine)]`r`n[Code: $($_.InvocationInfo.Line.Trim())]"
Write-Log -Message $ErrorMessage -Severity 3 -LogType CMTrace -Source "$($CmdletName)" -ContinueOnError:$True
If ($ContinueOnError.IsPresent -eq $False) {Throw "$($ErrorMessage)"}
}
}
}
#Run the function using the line below
Write-PSObjectToLog -InputObject (Get-Process | Select-Object -First 1)
I have been using this for some time now as I usually like to know what data is contained in a given object. I hope this helps you!
Note: By using a string builder object and adding to it using built-in methods, you can write a single log entry with tons of data formatted exactly the way you want. Your logs will grow in size depending on how much data is contained within your object(s).
God Bless!
Hello alphaeus,
sorry for the delay. I did not think, that I would get an answer here and did not check anymore.
Thank you for your function. I did some short testing right now.
I really like it, but it does not output the object in a way I want to. From my example above the Output would look like this:
Ideally I would want the output to look like this:
Bye