Object/Table to LogFile with Write-Log Function

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:
CMTrace

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:

DesiredOutput

Bye