Possible Write-log bug

Hi,

I am running a function returning an array of values then I convert it to string and using write-log to pipe it in my log in CMTrace format. But instead, I see the value in the log with Notepad but not with CMTrace. And, worst, after that if I run the script again the log is no more recognise as CMTrace.

<code>
Function Get-MonitorInfo
{
    [CmdletBinding()]
    Param
    (
        [Parameter(
        Position=0,
        ValueFromPipeLine=$true,
        ValueFromPipeLineByPropertyName=$true)]
        [string]$name = &#039;.&#039;
    )
    Begin { 

		## Get the name of this function and write header
		#[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
		Set-StrictMode -off
			#Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -CmdletBoundParameters $PSBoundParameters -Header
		Set-StrictMode -Version Latest

	 }## End Begin Script Block 
 
    Process
    {
 
        $ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID -ComputerName $name
        $monitorInfo = @()
 
        foreach ($monitor in $ActiveMonitors)
        {
            $mon = New-Object PSObject
            $manufacturer = $null
            $product = $null
            $serial = $null
            $name = $null
            $week = $null
            $year = $null
 
            $monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
            $monitor.ProductCodeID | foreach {$product += [char]$_}
            $monitor.SerialNumberID | foreach {$serial += [char]$_}
            $monitor.UserFriendlyName | foreach {$name += [char]$_}
 
            $mon | Add-Member NoteProperty Manufacturer $manufacturer
            $mon | Add-Member NoteProperty ProductCode $product
            $mon | Add-Member NoteProperty SerialNumber $serial
            $mon | Add-Member NoteProperty Name $name
            $mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
            $mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
 
            $monitorInfo += $mon
        }
        #$monitorInfo
        [string]$StrMonitorData=$monitorInfo | Out-String
        
        #$StrMonitorData
		#Write-Log $StrMonitorData
		Write-Output $StrMonitorData
    }
    End { 

		Set-StrictMode -off
			#Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -Footer
		Set-StrictMode -Version Latest

	}## End End 
}
</code>
<code>
$StrMonitorData=Get-MonitorInfo
[string]$StrMonitorDataTexte=&quot;Informations d écrans: $($StrMonitorData)&quot;
$StrMonitorDataTexte

Set-StrictMode -off
	Write-Log $StrMonitorDataTexte 
Set-StrictMode -Version Latest
</code>

Thanks,

Francois

I think the problem is that you’re not using the Write-Log function as it’s designed to be used. Model your Write-Log call like the other calls in the toolkit.

Write-Log -Message $StrMonitorDataTexte -Source ${CmdletName}

Hi,

:frowning: Seems not.

<code>
Function Get-MonitorInfo
{
    [CmdletBinding()]
    Param
    (
        [Parameter(
        Position=0,
        ValueFromPipeLine=$true,
        ValueFromPipeLineByPropertyName=$true)]
        [string]$name = &#039;.&#039;
    )
    Begin { 

		## Get the name of this function and write header
		[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
		Set-StrictMode -off
			#Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -CmdletBoundParameters $PSBoundParameters -Header
		Set-StrictMode -Version Latest

	 }## End Begin Script Block 
 
    Process
    {
 
        $ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID -ComputerName $name
        $monitorInfo = @()
 
        foreach ($monitor in $ActiveMonitors)
        {
            $mon = New-Object PSObject
            $manufacturer = $null
            $product = $null
            $serial = $null
            $name = $null
            $week = $null
            $year = $null
 
            $monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
            $monitor.ProductCodeID | foreach {$product += [char]$_}
            $monitor.SerialNumberID | foreach {$serial += [char]$_}
            $monitor.UserFriendlyName | foreach {$name += [char]$_}
 
            $mon | Add-Member NoteProperty Manufacturer $manufacturer
            $mon | Add-Member NoteProperty ProductCode $product
            $mon | Add-Member NoteProperty SerialNumber $serial
            $mon | Add-Member NoteProperty Name $name
            $mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
            $mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
 
            $monitorInfo += $mon
        }
        #$monitorInfo
        [string]$StrMonitorData=$monitorInfo | Out-String
        Write-Log -Message $StrMonitorData -Source ${CmdletName}
		Write-Output $StrMonitorData
    }
    End { 

		Set-StrictMode -off
			#Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -Footer
		Set-StrictMode -Version Latest

	}## End End 
}
</code>
<code>
$StrMonitorData=Get-MonitorInfo

Write-Log &#039;************************************************************************************************************&#039;
	Write-Log &#039;Fin du traitement&#039;
	Write-Log &#039;************************************************************************************************************&#039;
	Write-Log &#039;============================================ Fin Script====================================&#039; -LogFilename $VarJournalisation
	Exit-Script -ExitCode 0
</code>

In CMTRace, I get nothing but with Notepad, I will get:

<![LOG[[Installation] ::

Manufacturer : DEL
ProductCode : A07E
SerialNumber : xxx
Name : DELL P2212H
Week : 47
Year : 2013

Manufacturer : DEL
ProductCode : A098
SerialNumber : xxx
Name : DELL P2214H
Week : 28
Year : 2015

]LOG]!><time=“11:09:13.958-300” date=“11-13-2015” component=“Get-MonitorInfo” context=“xxx” type=“1” thread=“7044” file="">
<![LOG[[Installation] :: ************************************************************************************************************]LOG]!><time=“11:09:13.974-300” date=“11-13-2015” component="" context=“xxx” type=“1” thread=“7044” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: Fin du traitement]LOG]!><time=“11:09:13.974-300” date=“11-13-2015” component="" context=“xxx” type=“1” thread=“7044” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: ************************************************************************************************************]LOG]!><time=“11:09:13.989-300” date=“11-13-2015” component="" context=“xxx” type=“1” thread=“7044” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: ============================================ Fin Script====================================]LOG]!><time=“11:09:13.989-300” date=“11-13-2015” component="" context=“xxx” type=“1” thread=“7044” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: xxx_Info_Depannage_1.0_Fr_v1 Installation completed with exit code [0].]LOG]!><time=“11:09:14.005-300” date=“11-13-2015” component=“Exit-Script” context=“xxx” type=“1” thread=“7044” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: -------------------------------------------------------------------------------]LOG]!><time=“11:09:14.020-300” date=“11-13-2015” component=“Exit-Script” context=“xxx” type=“1” thread=“7044” file=“Info_Depannage1.0_Frv1.ps1”>

Possibly the array cannot be directly pipe (even with | out-string) to the log. Any idea?

Seems Write-log does love the empty line between monitors.

Manufacturer : DEL
ProductCode : A07E
SerialNumber : xxx
Name : DELL P2212H
Week : 47
Year : 2013

Manufacturer : DEL
ProductCode : A098
SerialNumber : xxx
Name : DELL P2214H
Week : 28
Year : 2015

If I remove it manually or put === then everything is fine. Any idea how making write-log accepting it or replacing the empty line with === ?

Are you sure you’re using the new version of CMTrace that came with SCCM 2012? The older version of the utility does not work with the new CMTrace log format.

Well I guess you do have the latest version of CMTrace if it works when you get rid of the empty line. There must be some character code of some sort that messes up the log file when you turn that array into a string using Out-String.

Do this instead to join the array into a string:
[string]$StrMonitorData=$monitorInfo | Format-List | Out-String

I am running CMTrace 5.0.7804-1000 (32-bit). No the problem is still there.

<code>
[string]$StrMonitorData=$monitorInfo | Format-List | Out-String
Write-Log -Message &amp;quot;Ecran: </code>

n$($StrMonitorData)" -Source ${CmdletName}

`

In CMTrace it did not show up.
With Notepad, I get:

]LOG]!><time="14:39:30.046-300" date="11-13-2015" component="Get-PendingReboot" context="xxx\xxx" type="1" thread="3000" file="Info_Depannage1.0_Frv1.ps1"> <![LOG[[Installation] :: Période d'allumage: 0 jours 6 heures 16 minutes]LOG]!><time="14:39:30.093-300" date="11-13-2015" component="" context="xxx\xxx" type="1" thread="3000" file=""> <![LOG[[Installation] :: Ecran:

Manufacturer : DEL
ProductCode : A07E
SerialNumber : xxx
Name : DELL P2212H
Week : 47
Year : 2013

Manufacturer : DEL
ProductCode : A098
SerialNumber : xxx
Name : DELL P2214H
Week : 28
Year : 2015

]LOG]!><time=“14:39:30.155-300” date=“11-13-2015” component=“Get-MonitorInfo” context=“xxx\xxx” type=“1” thread=“3000” file="">
<![LOG[[Installation] :: ************************************************************************************************************]LOG]!><time=“14:39:30.155-300” date=“11-13-2015” component="" context=“xxx\xxx” type=“1” thread=“3000” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: Fin du traitement]LOG]!><time=“14:39:30.155-300” date=“11-13-2015” component="" context=“xxx\xxx” type=“1” thread=“3000” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: ************************************************************************************************************]LOG]!><time=“14:39:30.171-300” date=“11-13-2015” component="" context=“xxx\xxx” type=“1” thread=“3000” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: ============================================ Fin Script====================================]LOG]!><time=“14:39:30.171-300” date=“11-13-2015” component="" context=“xxx\xxx” type=“1” thread=“3000” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: CARRA_Info_Depannage_1.0_Fr_v1 Installation completed with exit code [0].]LOG]!><time=“14:39:30.186-300” date=“11-13-2015” component=“Exit-Script” context=“xxx\xxx” type=“1” thread=“3000” file=“Info_Depannage1.0_Frv1.ps1”>
<![LOG[[Installation] :: -------------------------------------------------------------------------------]LOG]!><time=“14:39:30.202-300” date=“11-13-2015” component=“Exit-Script” context=“xxx\xxx” type=“1” thread=“3000” file=“Info_Depannage1.0_Frv1.ps1”>

If manually I am removing a line at the end of that list or between both monitor then I will be correct in CMTrace.

Hi,

I just made a test script with lesser script line and the problem is still appearing.
Easy to reproduce:

<code>
#Region 5.0 Get-MonitorInfo
Function Get-MonitorInfo
{
    [CmdletBinding()]
    Param
    (
        [Parameter(
        Position=0,
        ValueFromPipeLine=$true,
        ValueFromPipeLineByPropertyName=$true)]
        [string]$name = &#039;.&#039;
    )
    Begin { 

		## Get the name of this function and write header
		[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
		Set-StrictMode -off
			#Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -CmdletBoundParameters $PSBoundParameters -Header
		Set-StrictMode -Version Latest

	 }## End Begin Script Block 
 
    Process
    {
 
        $ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID -ComputerName $name
        $monitorInfo = @()
 
        foreach ($monitor in $ActiveMonitors)
        {
            $mon = New-Object PSObject
            $manufacturer = $null
            $product = $null
            $serial = $null
            $name = $null
            $week = $null
            $year = $null
 
            $monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
            $monitor.ProductCodeID | foreach {$product += [char]$_}
            $monitor.SerialNumberID | foreach {$serial += [char]$_}
            $monitor.UserFriendlyName | foreach {$name += [char]$_}
 
            $mon | Add-Member NoteProperty Manufacturer $manufacturer
            $mon | Add-Member NoteProperty ProductCode $product
            $mon | Add-Member NoteProperty SerialNumber $serial
            $mon | Add-Member NoteProperty Name $name
            $mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
            $mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
 
            $monitorInfo += $mon
        }
                
		[string]$StrMonitorData=$monitorInfo | Format-List | Out-String
		Set-StrictMode -off
        	Write-Log -Message &amp;quot;Ecran: </code>

n$($StrMonitorData)" -Source ${CmdletName}
Set-StrictMode -Version Latest

    #Write-Log -Message $StrMonitorData -Source ${CmdletName}
	#Write-Output $StrMonitorData
}
End { 

	Set-StrictMode -off
		#Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -Footer
	Set-StrictMode -Version Latest

}## End End 

}

#************************************************************************************************************
#EndRegion 5.0 Get-MonitorInfo
#************************************************************************************************************
[string]$scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
[string]$moduleAppDeployToolkitMain = “$scriptDirectory_Include\AppDeployToolkit\AppDeployToolkitMain.ps1”
If (-not (Test-Path -Path $moduleAppDeployToolkitMain -PathType Leaf)) { Throw ‘Le module n existe pas à l’‘endroit spécifié: [$moduleAppDeployToolkitMain].’ }
. $moduleAppDeployToolkitMain

Get-MonitorInfo

`

Hi,

Seems this is working with write-log.

&lt;code&gt;
#Region 5.0 Get-MonitorInfo
Function Get-MonitorInfo
{
    [CmdletBinding()]
    Param
    (
        [Parameter(
        Position=0,
        ValueFromPipeLine=$true,
        ValueFromPipeLineByPropertyName=$true)]
        [string]$name = &amp;#039;.&amp;#039;
    )
    Begin { 

		## Get the name of this function and write header
		[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
		Set-StrictMode -off
			Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -CmdletBoundParameters $PSBoundParameters -Header
		Set-StrictMode -Version Latest

	 }## End Begin Script Block 
 
    Process
    {
 
        [PSObject]$MonitorData= gwmi WmiMonitorID -Namespace root\wmi | &lt&gt;
			Select @{n="Model";e={[System.Text.Encoding]::ASCII.GetString($_.UserFriendlyName -ne 00)}}, `
			@{n="Serial Number";e={[System.Text.Encoding]::ASCII.GetString($_.SerialNumberID -ne 00)}}
          
	
	$StrMonitorData = $MonitorData | Out-String
	
	
	Set-StrictMode -off
    	Write-Log -Message "Information sur les écrans: $($StrMonitorData)" -Source ${CmdletName}
    Set-StrictMode -Version Latest

    Write-Output $StrMonitorData
}
End { 

	Set-StrictMode -off
		Write-FunctionHeaderOrFooter -CmdletName ${CmdletName} -Footer
	Set-StrictMode -Version Latest

}## End End 

}

#************************************************************************************************************
#EndRegion 5.0 Get-MonitorInfo
#************************************************************************************************************
$insttrousses=“c:\temp”
[string]$scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
[string]$moduleAppDeployToolkitMain = “$scriptDirectory_Include\AppDeployToolkit\AppDeployToolkitMain.ps1”
If (-not (Test-Path -Path $moduleAppDeployToolkitMain -PathType Leaf)) { Throw ‘Le module n existe pas à l’‘endroit spécifié: [$moduleAppDeployToolkitMain].’ }
Set-StrictMode -off
#Ce module n’a pas été conçu pour fonctionner avec set-strictmode, il doit être exécuté avec des privilège élevé.
#https://psappdeploytoolkit.codeplex.com/
. $moduleAppDeployToolkitMain
Set-StrictMode -Version Latest

Get-MonitorInfo
`
;/code