From 8e2667df44d42351614bd4468fe46ccfe7939eb3 Mon Sep 17 00:00:00 2001 From: blue Date: Sun, 18 Aug 2019 17:21:22 +0100 Subject: [PATCH 1/7] Add proxy for Write-Host to also write log files --- ConfigMgrClientHealth.ps1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index 947540f..750652c 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -64,6 +64,12 @@ Begin { Write-Verbose "Script version: $Version" Write-Verbose "PowerShell version: $PowerShellVersion" +#Region proxy functions +$WriteHostMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Host) +$WriteHostBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteHostMetadata) +$WriteHostParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteHostMetadata) +$WriteHostWrapped = {Microsoft.Powershell.Utility\Write-Host @PSBoundParameters; Out-LogFile -Text $Object} +${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostParams, $WriteHostWrapped Function Test-XML { <# .SYNOPSIS From d63d4d01b97890925fa19fffeb7167edf4b9c220 Mon Sep 17 00:00:00 2001 From: blue Date: Sun, 18 Aug 2019 17:58:21 +0100 Subject: [PATCH 2/7] Replace Write-Outputs putting text with Write-Host Script is mostly using Write-Host, so stick with that. --- ConfigMgrClientHealth.ps1 | 100 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index 750652c..896320a 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -664,7 +664,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ($ok -eq $true) { $text = 'ConfigMgr Client Certificate: OK' - Write-Output $text + Write-Host $text $log.ClientCertificate = 'OK' } } @@ -1003,7 +1003,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } $true { $text = 'DNS Check: OK' - Write-Output $text + Write-Host $text $log.DNS = 'OK' } } @@ -1062,7 +1062,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if (($count -eq 0) -or ($count -eq $null)) { $text = 'Updates: No mandatory updates to install.' - Write-Output $text + Write-Host $text $log.Updates = 'OK' } else { @@ -1073,7 +1073,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar $kb = $hotfix -replace $regex -replace "\." -replace "-" if ($installedUpdates -contains $kb) { $text = "Update $hotfix" + ": OK" - Write-Output $text + Write-Host $text } else { if ($null -eq $logEntry) { $logEntry = $kb } @@ -1159,7 +1159,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar Write-Host "ConfigMgr Agent not running. Attempting to start it." if ($CCMService.StartType -ne "Automatic") { $text = "Configuring service CcmExec StartupType to: Automatic (Delayed Start)..." - Write-Output $text + Write-Host $text Set-Service -Name CcmExec -StartupType Automatic } Start-Service -Name CcmExec @@ -1269,7 +1269,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ($installedVersion -ge $ClientVersion) { $text = 'ConfigMgr Client version is: ' +$installedVersion + ': OK' - Write-Output $text + Write-Host $text $obj = $false } elseif ($ClientAutoUpgrade -like 'true') { @@ -1279,7 +1279,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } else { $text = 'ConfigMgr Client version is: ' +$installedVersion +': Required version: '+$ClientVersion +' AutoUpgrade: false. Skipping upgrade' - Write-Output $text + Write-Host $text $obj = $false } Write-Output $obj @@ -1357,7 +1357,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } else { $text = 'Pending Reboot: OK' - Write-Output $text + Write-Host $text $log.PendingReboot = 'OK' } #Out-LogFile -Xml $xml -Text $text @@ -1381,7 +1381,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } else { $text = 'ConfigMgr Client Provisioning Mode: OK' - Write-Output $text + Write-Host $text $log.ProvisioningMode = 'OK' } } @@ -1403,7 +1403,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ($StateMessage -match 'Successfully forwarded State Messages to the MP') { $text = 'StateMessage: OK' $log.StateMessages = 'OK' - Write-Output $text + Write-Host $text } else { $text = 'StateMessage: ERROR. Remediating...' @@ -1454,7 +1454,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar #If we need to repart the policy files then do so. if ($RepairReason -ne ""){ $log.WUAHandler = "Broken ($RepairReason)" - Write-Output "GPO Cache: Broken ($RepairReason)" + Write-Host "GPO Cache: Broken ($RepairReason)" Write-Verbose 'Deleting registry.pol and running gpupdate...' try { if (Test-Path -Path $MachineRegistryFile) {Remove-Item $MachineRegistryFile -Force } } @@ -1469,11 +1469,11 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar Get-SCCMPolicySourceUpdateMessage $log.WUAHandler = "Repaired ($RepairReason)" - Write-Output "GPO Cache: $($log.WUAHandler)" + Write-Host "GPO Cache: $($log.WUAHandler)" } else { $log.WUAHandler = 'OK' - Write-Output "GPO Cache: OK" + Write-Host "GPO Cache: OK" } } @@ -1575,7 +1575,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ((Test-Path $ClientShare -ErrorAction SilentlyContinue) -eq $true) { if ($FirstInstall -eq $true) { $text = 'Installing Configuration Manager Client.' } else { $text = 'Client tagged for reinstall. Reinstalling client...' } - Write-Output $text + Write-Host $text Write-Verbose "Perform a test on a specific registry key required for ccmsetup to succeed." Test-CCMSetup1 @@ -1690,7 +1690,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar Function Repair-WMI { $text ='Repairing WMI' - Write-Output $text + Write-Host $text # Check PATH if((! (@(($ENV:PATH).Split(";")) -contains "$env:SystemDrive\WINDOWS\System32\Wbem")) -and (! (@(($ENV:PATH).Split(";")) -contains "%systemroot%\System32\Wbem"))){ @@ -1754,7 +1754,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar Write-Verbose "Resending compliance states." (New-Object -ComObject Microsoft.CCM.UpdatesStore).RefreshServerComplianceState() $LastSent=Get-Date - Write-Output "Compliance States: Refreshed." + Write-Host "Compliance States: Refreshed." } Catch{ Write-Error "Failed to resend the compliance states." @@ -1762,7 +1762,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } } Else{ - Write-Output "Compliance States: OK." + Write-Host "Compliance States: OK." } Set-RegistryValue -Path $RegistryKey -Name $RegValueName -Value $LastSent @@ -1912,7 +1912,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ($serviceStartType -eq $StartupType) { $text = "Service $Name startup: OK" - Write-Output $text + Write-Host $text } elseif ($StartupType -like "Automatic (Delayed Start)") { # Handle Automatic Trigger Start the dirty way for these two services. Implement in a nice way in future version. @@ -1928,7 +1928,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar # Automatic delayed requires the use of sc.exe & sc.exe config $service start= delayed-auto | Out-Null $text = "Configuring service $Name StartupType to: $StartupType..." - Write-Output $text + Write-Host $text $log.Services = 'Started' } } @@ -1936,7 +1936,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar else { try { $text = "Configuring service $Name StartupType to: $StartupType..." - Write-Output $text + Write-Host $text Set-Service -Name $service.Name -StartupType $StartupType $log.Services = 'Started' } @@ -1949,7 +1949,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar Write-Verbose 'Verify service is running' if ($service.Status -eq "Running") { $text = 'Service ' +$Name+' running: OK' - Write-Output $text + Write-Host $text #If we are checking uptime. If ($Uptime){ @@ -1977,9 +1977,9 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar #If the processes are not running the restart the service. If ($ProcessesStopped){ - Write-Output "Restarting service: $($Name)..." + Write-Host "Restarting service: $($Name)..." Restart-Service -Name $service.Name -Force - Write-Output "Restarted service: $($Name)..." + Write-Host "Restarted service: $($Name)..." $log.Services = 'Restarted' } } catch { @@ -1988,7 +1988,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } } else { - Write-Output "Service $($Name) uptime: OK" + Write-Host "Service $($Name) uptime: OK" } } } @@ -2007,14 +2007,14 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar try { $RetryService= $False $text = 'Starting service: ' + $Name + '...' - Write-Output $text + Write-Host $text Start-Service -Name $service.Name -ErrorAction Stop $log.Services = 'Started' } catch { #Error 1290 (-2146233087) indicates that the service is sharing a thread with another service that is protected and cannot share its thread. #This is resolved by configuring the service to run on its own thread. If ($_.Exception.Hresult -eq '-2146233087'){ - Write-Output "Failed to start service $Name because it's sharing a thread with another process. Changing to use its own thread." + Write-Host "Failed to start service $Name because it's sharing a thread with another process. Changing to use its own thread." & cmd /c sc config $Name type= own $RetryService= $True } @@ -2046,7 +2046,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ($share.Name -contains 'ADMIN$') { $text = 'Adminshare Admin$: OK' - Write-Output $text + Write-Host $text } else { $fix = $true } @@ -2056,7 +2056,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar if ($share.Name -contains "C$") { $text = 'Adminshare C$: OK' - Write-Output $text + Write-Host $text } else { $fix = $true } @@ -2082,7 +2082,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } else { $text ="Free space $env:SystemDrive OK" - Write-Output $text + Write-Host $text } } @@ -2119,7 +2119,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar $uptime = (Get-Date) - ($wmi.ConvertToDateTime($wmi.lastbootuptime)) if ($uptime.TotalDays -lt $maxRebootDays) { $text = 'Last boot time: ' +$lastBootTime + ': OK' - Write-Output $text + Write-Host $text } elseif (($uptime.TotalDays -ge $maxRebootDays) -and (Get-XMLConfigRebootApplicationEnable -eq $true)) { $text = 'Last boot time: ' +$lastBootTime + ': More than '+$maxRebootDays +' days since last reboot. Starting reboot application.' @@ -2201,7 +2201,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } else { $text = "Drivers: OK" - Write-Output $text + Write-Host $text $log.Drivers = 'OK' } } @@ -2258,7 +2258,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar } else { $text = "ConfigMgr Hardware Inventory scan: OK" - Write-Output $text + Write-Host $text } $log.HWInventory = $HWScanDate Write-Verbose "End Test-SCCMHardwareInventoryScan" @@ -2390,7 +2390,7 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar Function Get-Version { $text = 'ConfigMgr Client Health Version ' +$Version - Write-Output $text + Write-Host $text Out-LogFile -Xml $xml -Text $text -Severity 1 } @@ -3197,28 +3197,28 @@ ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostPar $info = Get-Info | Select-Object HostName, OperatingSystem, Architecture, Build, InstallDate, Manufacturer, Model, LastLoggedOnUser #$text = 'Computer info'+ "`n" $text = 'Hostname: ' +$info.HostName - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'Operatingsystem: ' +$info.OperatingSystem - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'Architecture: ' + $info.Architecture - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'Build: ' + $info.Build - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'Manufacturer: ' + $info.Manufacturer - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'Model: ' + $info.Model - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'InstallDate: ' + $info.InstallDate - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text $text = 'LastLoggedOnUser: ' + $info.LastLoggedOnUser - Write-Output $text + Write-Host $text #Out-LogFile -Xml $xml $text } @@ -3632,11 +3632,11 @@ Process { #Get the last run from the registry, defaulting to the minimum date value if the script has never ran. try{[datetime]$LastRun = Get-RegistryValue -Path $RegistryKey -Name $LastRunRegistryValueName} catch{$LastRun=[datetime]::MinValue} - Write-Output "Script last ran: $($LastRun)" + Write-Host "Script last ran: $($LastRun)" Write-Verbose "Testing if log files are bigger than max history for logfiles." Test-ConfigMgrHealthLogging - + # Create the log object containing the result of health check $Log = New-LogObject @@ -3785,7 +3785,7 @@ Process { # Restart ConfigMgr client if tagged for restart and no reinstall tag if (($restartCCMExec -eq $true) -and ($Reinstall -eq $false)) { - Write-Output "Restarting service CcmExec..." + Write-Host "Restarting service CcmExec..." if ($SCCMLogJobs.Rows.Count -ge 1) { Stop-Service -Name CcmExec @@ -3855,25 +3855,25 @@ End { #Set the last run. $Date = Get-Date Set-RegistryValue -Path $RegistryKey -Name $LastRunRegistryValueName -Value $Date - Write-Output "Setting last ran to $($Date)" + Write-Host "Setting last ran to $($Date)" if ($LocalLogging -like 'true') { - Write-Output 'Updating local logfile with results' + Write-Host 'Updating local logfile with results' Update-LogFile -Log $log -Mode 'Local' } if (($FileLogging -like 'true') -and ($FileLogLevel -like 'full')) { - Write-Output 'Updating fileshare logfile with results' + Write-Host 'Updating fileshare logfile with results' Update-LogFile -Log $log } - if (($SQLLogging -eq 'true') -and -not $PSBoundParameters.ContainsKey('Webservice')) { - Write-Output 'Updating SQL database with results' + if (($SQLLogging -like 'true') -and -not $PSBoundParameters.ContainsKey('Webservice')) { + Write-Host 'Updating SQL database with results' Update-SQL -Log $log } if ($PSBoundParameters.ContainsKey('Webservice')) { - Write-Output 'Updating SQL database with results using webservice' + Write-Host 'Updating SQL database with results using webservice' Update-Webservice -URI $Webservice -Log $Log } Write-Verbose "Client Health script finished" From e59d989ddbf0abf4420936895abd314296b3b39b Mon Sep 17 00:00:00 2001 From: blue Date: Sun, 18 Aug 2019 20:27:23 +0100 Subject: [PATCH 3/7] Add proxy functions for Write-Warning, and -Error Also `Write-Information`, but that's not used in the script and is commented out, to avoid PowerShell version support issues. A proxy is also crated for `Write-Verbose`, but this should probably be behind some sort of log level flag. --- ConfigMgrClientHealth.ps1 | 44 +++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index 896320a..e55be61 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -64,12 +64,44 @@ Begin { Write-Verbose "Script version: $Version" Write-Verbose "PowerShell version: $PowerShellVersion" -#Region proxy functions -$WriteHostMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Host) -$WriteHostBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteHostMetadata) -$WriteHostParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteHostMetadata) -$WriteHostWrapped = {Microsoft.Powershell.Utility\Write-Host @PSBoundParameters; Out-LogFile -Text $Object} -${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostParams, $WriteHostWrapped + #region proxy functions for logging + # #Write-Verbose + # $WriteVerboseMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Verbose) + # $WriteVerboseBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteVerboseMetadata) + # $WriteVerboseParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteVerboseMetadata) + # $WriteVerboseWrapped = {Microsoft.Powershell.Utility\Write-Verbose @PSBoundParameters; Out-LogFile -Text $Message} + # ${Function:Write-Verbose} = '{0}param({1}) {2}' -f $WriteVerboseBinding, $WriteVerboseParams, $WriteVerboseWrapped + + #Write-Host + $WriteHostMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Host) + $WriteHostBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteHostMetadata) + $WriteHostParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteHostMetadata) + $WriteHostWrapped = {Microsoft.Powershell.Utility\Write-Host @PSBoundParameters; Out-LogFile -Text $Object} + ${Function:Write-Host} = '{0}param({1}) {2}' -f $WriteHostBinding, $WriteHostParams, $WriteHostWrapped + + # #Write-Information + # $WriteInformationMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Information) + # $WriteInformationBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteInformationMetadata) + # $WriteInformationParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteInformationMetadata) + # $WriteInformationWrapped = {Microsoft.Powershell.Utility\Write-Information @PSBoundParameters; Out-LogFile -Text $MessageData} + # ${Function:Write-Information} = '{0}param({1}) {2}' -f $WriteInformationBinding, $WriteInformationParams, $WriteInformationWrapped + + #Write-Warning + $WriteWarningMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Warning) + $WriteWarningBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteWarningMetadata) + $WriteWarningParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteWarningMetadata) + $WriteWarningWrapped = {Microsoft.Powershell.Utility\Write-Warning @PSBoundParameters; Out-LogFile -Text "WARNING: $Message"} + ${Function:Write-Warning} = '{0}param({1}) {2}' -f $WriteWarningBinding, $WriteWarningParams, $WriteWarningWrapped + + #Write-Error + $WriteErrorMetadata = New-Object System.Management.Automation.CommandMetadata (Get-Command Write-Error) + $WriteErrorBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($WriteErrorMetadata) + $WriteErrorParams = [System.Management.Automation.ProxyCommand]::GetParamBlock($WriteErrorMetadata) + $WriteErrorWrapped = {Microsoft.Powershell.Utility\Write-Error @PSBoundParameters; Out-LogFile -Text "ERROR: $Message"} + ${Function:Write-Error} = '{0}param({1}) {2}' -f $WriteErrorBinding, $WriteErrorParams, $WriteErrorWrapped + + #endregion proxy functions for logging + Function Test-XML { <# .SYNOPSIS From b382468ba3eca7ff92fd37efb7aeb7743d825496 Mon Sep 17 00:00:00 2001 From: blue Date: Mon, 19 Aug 2019 17:15:31 +0100 Subject: [PATCH 4/7] Remove redundant line from Update-Logfile The dump of `$Log` is no longer the first thing written to the logs, so saying 'Client Health Check starting' doesn't make much sense. Also simplifies some redundant logic. --- ConfigMgrClientHealth.ps1 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index e55be61..5f1aa8e 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -3509,16 +3509,13 @@ Begin { Test-ValuesBeforeLogUpdate $logfile = $logfile = Get-LogFileName Test-LogFileHistory -Logfile $logfile - $text = "<--- ConfigMgr Client Health Check starting --->" - $text += $log | Select-Object Hostname, Operatingsystem, Architecture, Build, Model, InstallDate, OSUpdates, LastLoggedOnUser, ClientVersion, PSVersion, PSBuild, SiteCode, Domain, MaxLogSize, MaxLogHistory, CacheSize, Certificate, ProvisioningMode, DNS, PendingReboot, LastBootTime, OSDiskFreeSpace, Services, AdminShare, StateMessages, WUAHandler, WMI, RefreshComplianceState, ClientInstalled, Version, Timestamp, HWInventory, SWMetering, BITS, ClientSettings, PatchLevel, ClientInstalledReason | Out-String + $text = $log | Select-Object Hostname, Operatingsystem, Architecture, Build, Model, InstallDate, OSUpdates, LastLoggedOnUser, ClientVersion, PSVersion, PSBuild, SiteCode, Domain, MaxLogSize, MaxLogHistory, CacheSize, Certificate, ProvisioningMode, DNS, PendingReboot, LastBootTime, OSDiskFreeSpace, Services, AdminShare, StateMessages, WUAHandler, WMI, RefreshComplianceState, ClientInstalled, Version, Timestamp, HWInventory, SWMetering, BITS, ClientSettings, PatchLevel, ClientInstalledReason | Out-String $text = $text.replace("`t","") $text = $text.replace(" ","") $text = $text.replace(" :",":") $text = $text -creplace '(?m)^\s*\r?\n','' - if ($Mode -eq 'Local') { Out-LogFile -Xml $xml -Text $text -Mode $Mode -Severity 1} - elseif ($Mode -eq 'ClientInstalledFailed') { Out-LogFile -Xml $xml -Text $text -Mode $Mode -Severity 1} - else { Out-LogFile -Xml $xml -Text $text -Severity 1} + Out-LogFile -Xml $xml -Text $text -Mode $Mode -Severity 1 Write-Verbose "End Update-LogFile" } From 67b46954301d300d159605ceb874e9d768e382f3 Mon Sep 17 00:00:00 2001 From: blue Date: Mon, 19 Aug 2019 17:27:15 +0100 Subject: [PATCH 5/7] Log script completion --- ConfigMgrClientHealth.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index 5f1aa8e..d4b1944 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -3905,5 +3905,5 @@ End { Write-Host 'Updating SQL database with results using webservice' Update-Webservice -URI $Webservice -Log $Log } - Write-Verbose "Client Health script finished" + Write-Host "Client Health script finished" } From 07a3f7e740d86452a361f1ac8e51fc5bd6001a02 Mon Sep 17 00:00:00 2001 From: blue Date: Tue, 20 Aug 2019 18:48:38 +0100 Subject: [PATCH 6/7] Move logging config to with other config From Process block to Begin block --- ConfigMgrClientHealth.ps1 | 45 +++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index d4b1944..87e4933 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -3547,6 +3547,11 @@ Begin { $ClientStateMessages = Get-XMLConfigRemediationClientStateMessages $ClientWUAHandler = Get-XMLConfigRemediationClientWUAHandler $LogShare = Get-XMLConfigLoggingShare + + $LocalLogging = ((Get-XMLConfigLoggingLocalFile).ToString()).ToLower() + $FileLogging = ((Get-XMLConfigLoggingEnable).ToString()).ToLower() + $FileLogLevel = ((Get-XMLConfigLoggingLevel).ToString()).ToLower() + $SQLLogging = ((Get-XMLConfigSQLLoggingEnable).ToString()).ToLower() } @@ -3587,6 +3592,20 @@ Begin { } $LogShare = $Configuration.logFileShare + + $LocalLogging = "true" + #$LocalLogging = $Configuration.localFiles.ToString().ToLower() + $FileLogging = $Configuration.logFileShareEnable.ToString().ToLower() + $FLL = $Configuration.logLevel.ToString().ToLower() + switch ($FLL) { + 0 { $FileLogLevel = "Full"} + 1 { $FileLogLevel = "ClientInstall"} + } + $SQLLogging = "true" + + Write-Host "LocalLogging: $LocalLogging" -ForegroundColor Yellow + Write-Host "FileLogging: $FileLogging" -ForegroundColor Yellow + Write-Host "FileLogLevel: $FileLogLevel" -ForegroundColor Yellow } @@ -3629,32 +3648,6 @@ Process { } } - - # If config.xml is used - if ($Config) { - $LocalLogging = ((Get-XMLConfigLoggingLocalFile).ToString()).ToLower() - $FileLogging = ((Get-XMLConfigLoggingEnable).ToString()).ToLower() - $FileLogLevel = ((Get-XMLConfigLoggingLevel).ToString()).ToLower() - $SQLLogging = ((Get-XMLConfigSQLLoggingEnable).ToString()).ToLower() - - } - - if ($Webservice) { - $LocalLogging = "true" - #$LocalLogging = $Configuration.localFiles.ToString().ToLower() - $FileLogging = $Configuration.logFileShareEnable.ToString().ToLower() - $FLL = $Configuration.logLevel.ToString().ToLower() - switch ($FLL) { - 0 { $FileLogLevel = "Full"} - 1 { $FileLogLevel = "ClientInstall"} - } - $SQLLogging = "true" - - Write-Host "LocalLogging: $LocalLogging" -ForegroundColor Yellow - Write-Host "FileLogging: $FileLogging" -ForegroundColor Yellow - Write-Host "FileLogLevel: $FileLogLevel" -ForegroundColor Yellow - } - $RegistryKey = "HKLM:\Software\ConfigMgrClientHealth" $LastRunRegistryValueName = "LastRun" From 38512069ec9e2091f537932b9adc515d69e2d58e Mon Sep 17 00:00:00 2001 From: blue Date: Tue, 20 Aug 2019 19:00:09 +0100 Subject: [PATCH 7/7] Remove `-Xml` param from `Out-Logfile` The parameter's not used anywhere so just causes `$Xml` to be shadowed, and since `$Xml` did not have a default, it's shadowed by `$null`, resulting in strange behaviour from anything within `Out-Logfile`'s scope that expects `$Xml` to be defined and populated with a config file if `Out-Logfile` is called without `-Xml $xml`. Decided to remove the parameter rather than default to `$script:xml` as this seemed the clearer option. --- ConfigMgrClientHealth.ps1 | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ConfigMgrClientHealth.ps1 b/ConfigMgrClientHealth.ps1 index 87e4933..aac1a55 100644 --- a/ConfigMgrClientHealth.ps1 +++ b/ConfigMgrClientHealth.ps1 @@ -380,7 +380,7 @@ Begin { } Function Out-LogFile { - Param([Parameter(Mandatory = $false)][xml]$Xml, $Text, $Mode, + Param($Text, $Mode, [Parameter(Mandatory = $false)][ValidateSet(1, 2, 3, 'Information', 'Warning', 'Error')]$Severity = 1) switch ($Severity) { @@ -389,7 +389,7 @@ Begin { 'Error' {$Severity = 3} } - if ($Mode -like "Local") { + if ($LocalLogging -or ($Mode -like "Local")) { Test-LocalLogging $clientpath = Get-LocalFilesPath $Logfile = "$clientpath\ClientHealth.log" @@ -1020,15 +1020,15 @@ Begin { Write-Host $text $log.DNS = $logFail if (-NOT($FileLogLevel -like "clientlocal")) { - Out-LogFile -Xml $xml -Text $text -Severity 2 - Out-LogFile -Xml $xml -Text $dnsFail -Severity 2 + Out-Logfile -Text $text -Severity 2 + Out-Logfile -Text $dnsFail -Severity 2 } } else { $text = 'DNS Check: FAILED. IP address published in DNS do not match IP address on local machine. Monitor mode only, no remediation' $log.DNS = $logFail - if (-NOT($FileLogLevel -like "clientlocal")) { Out-LogFile -Xml $xml -Text $text -Severity 2} + if (-NOT($FileLogLevel -like "clientlocal")) { Out-Logfile -Text $text -Severity 2 } Write-Host $text } @@ -1392,7 +1392,7 @@ Begin { Write-Host $text $log.PendingReboot = 'OK' } - #Out-LogFile -Xml $xml -Text $text + #Out-Logfile -Text $text } } @@ -1715,7 +1715,7 @@ Begin { Write-Verbose "returning true to tag client for reinstall" $obj = $true } - #Out-LogFile -Xml $xml -Text $text + #Out-Logfile -Text $text Write-Output $obj } } @@ -2228,7 +2228,7 @@ Begin { foreach ($device in $devices) { $text = 'Missing or faulty driver: ' +$device.Name + '. Device ID: ' + $device.DeviceID Write-Warning $text - if (-NOT($FileLogLevel -like "clientlocal")) { Out-LogFile -Xml $xml -Text $text -Severity 2} + if (-NOT($FileLogLevel -like "clientlocal")) { Out-Logfile -Text $text -Severity 2 } } } else { @@ -2423,7 +2423,7 @@ Begin { Function Get-Version { $text = 'ConfigMgr Client Health Version ' +$Version Write-Host $text - Out-LogFile -Xml $xml -Text $text -Severity 1 + Out-Logfile -Text $text -Severity 1 } <# Trigger codes @@ -2497,7 +2497,7 @@ Begin { catch { $text = "Error connecting to SQLDatabase $Database on SQL Server $SQLServer" Write-Error -Message $text - if (-NOT($FileLogLevel -like "clientinstall")) { Out-LogFile -Xml $xml -Text $text -Severity 3} + if (-NOT($FileLogLevel -like "clientinstall")) { Out-Logfile -Text $text -Severity 3 } $obj = $false; Write-Verbose "SQL connection test failed" } @@ -3230,28 +3230,28 @@ Begin { #$text = 'Computer info'+ "`n" $text = 'Hostname: ' +$info.HostName Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'Operatingsystem: ' +$info.OperatingSystem Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'Architecture: ' + $info.Architecture Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'Build: ' + $info.Build Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'Manufacturer: ' + $info.Manufacturer Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'Model: ' + $info.Model Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'InstallDate: ' + $info.InstallDate Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text $text = 'LastLoggedOnUser: ' + $info.LastLoggedOnUser Write-Host $text - #Out-LogFile -Xml $xml $text + #Out-Logfile $text } Function Test-ConfigMgrHealthLogging { @@ -3492,7 +3492,7 @@ Begin { $ErrorMessage = $_.Exception.Message $text = "Error updating SQL with the following query: $query. Error: $ErrorMessage" Write-Error $text - Out-LogFile -Xml $Xml -Text "ERROR Insert/Update SQL. SQL Query: $query `nSQL Error: $ErrorMessage" -Severity 3 + Out-Logfile -Text "ERROR Insert/Update SQL. SQL Query: $query `nSQL Error: $ErrorMessage" -Severity 3 } Write-Verbose "End Update-SQL" } @@ -3515,7 +3515,7 @@ Begin { $text = $text.replace(" :",":") $text = $text -creplace '(?m)^\s*\r?\n','' - Out-LogFile -Xml $xml -Text $text -Mode $Mode -Severity 1 + Out-Logfile -Text $text -Mode $Mode -Severity 1 Write-Verbose "End Update-LogFile" } @@ -3622,7 +3622,7 @@ Process { If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { $text = 'ERROR: Powershell not running as Administrator! Client Health aborting.' - Out-LogFile -Xml $Xml -Text $text -Severity 3 + Out-Logfile -Text $text -Severity 3 Write-Error $text Exit 1 }