Private/Export-CMHealthCheck.ps1
function Export-CMHealthCheck { <# .SYNOPSIS Convert extracted ConfigMgr site information to Word Document .DESCRIPTION Converts the data output from Get-CMHealthCheck to generate a report document using Microsoft Word (2010, 2013, 2016). Intended to be invoked on a desktop computer which has Office installed. .PARAMETER ReportFolder Path to output data folder (e.g. "My Documents\2019-03-06\cm01.contoso.local") .PARAMETER AutoConfig Use an auto configuration file, cmhealthconfig.txt in "My Documents" folder to fill-in AuthorName, CopyrightName, Theme, CssFilename, TableRowStyle .PARAMETER Detailed Collect more granular data for final reporting, or use AutoConfig file .PARAMETER CoverPage Word theme cover page (default = "Slice (Light)"), or use AutoConfig file .PARAMETER Template Word document file to use as a template. Should have a cover page already in place. If Template is specified, CoverPage and Copyright are ignored. .PARAMETER CustomerName Name of customer (default = "Customer Name"), or use AutoConfig file .PARAMETER AuthorName Report Author name (default = "Your Name"), or use AutoConfig file .PARAMETER CopyrightName Text to use for copyright footer string (default = "Your Company Name") .PARAMETER Overwrite Overwrite existing report file if found, or use AutoConfig file .PARAMETER Healthcheckfilename Healthcheck configuration XML file name (default = ".\assets\cmhealthcheck.xml") The file can be local, UNC or URI sourced as well .PARAMETER MessagesFilename Status and error message lookup table (default = ".\assets\messages.xml") The file can be local, UNC or URI sourced as well .PARAMETER Healthcheckdebug Enable verbose output (or use -Verbose) .EXAMPLE Export-CMHealthCheck -ReportFolder "2019-03-06\cm01.contoso.local" -Detailed -CustomerName "Contoso" -AuthorName "David Stein" -CopyrightName "ACME Consulting" -Overwrite -Verbose .EXAMPLE Export-CMHealthCheck -ReportFolder "2019-03-06\cm01.contoso.local" -Detailed -Template ".\contoso.docx" -CustomerName "Contoso" -AuthorName "David Stein" -CopyrightName "ACME Consulting" -Overwrite -Verbose .EXAMPLE Export-CMHealthCheck -ReportFolder "2019-03-06\cm01.contoso.local" -AutoConfig -CustomerName "Contoso" .NOTES Sample AutoConfig file cmhealthconfig.txt... AuthorName=John Wick CopyrightName=Retirement Specialists Theme=Ocean Detailed=True TableRowStyle=Solid CssFilename=c:\docs\wickrocks.css ImageFile=c:\docs\bodybags.png CoverPage= Template= HealthcheckFilename= MessagesFilename= HealthcheckDebug=False Overwrite=True #> [CmdletBinding()] param ( [parameter (Mandatory, HelpMessage = "Collected data folder")] [ValidateNotNullOrEmpty()][string] $ReportFolder, [parameter(HelpMessage="Log folder path")][ValidateNotNullOrEmpty()][string] $OutputFolder = ".\$(($env:COMPUTERNAME, $env:USERDNSDOMAIN) -join '.')", [parameter (HelpMessage = "Customer company name")][string] $CustomerName = "Customer Name", [parameter (HelpMessage = "Use Auto Config File")][switch] $AutoConfig, [parameter (HelpMessage = "Export full data, not only summary")] [switch] $Detailed, [parameter (HelpMessage = "Word Template cover page name")] [string] $CoverPage = "Slice (Light)", [parameter (HelpMessage = "Word document source file")][string] $Template = "", [parameter (HelpMessage = "Author's full name")] [string] $AuthorName = "Your Name", [parameter (HelpMessage = "Footer text")][string] $CopyrightName = "Your Company Name", [parameter (HelpMessage = "Overwrite existing report file")][switch] $Overwrite, [parameter (HelpMessage = "HealthCheck query file name")] [string] $Healthcheckfilename = "", [parameter (HelpMessage = "HealthCheck messages file name")][string] $MessagesFilename = "", [parameter (HelpMessage = "Debug more?")] $Healthcheckdebug = $False ) Write-Verbose "Export-CMHealthCheck: Word Format" $time1 = Get-Date -Format "hh:mm:ss" $ModuleData = Get-Module CMHealthCheck $ModuleVer = $ModuleData.Version -join '.' $ModulePath = $ModuleData.Path -replace 'CMHealthCheck.psm1', '' $logfile = Join-Path -Path $OutputFolder -ChildPath "Export-CMHealthCheck.log" $Script:TempFilename = "cmhealthreport.docx" $Script:DefaultTableStyle = "Grid Table 4 - Accent 1" $Script:TableStyle = "Grid Table 4 - Accent 1" $Script:TableSimpleStyle = "Grid Table 4 - Accent 1" $Script:ReviewTableStyle = "Grid Table 4 - Accent 6" $Script:RecTableStyle = "Grid Table 4 - Accent 3" $Script:ReviewTableCols = ("No.", "Severity", "Comment") $bLogValidation = $False $Script:bAutoProps = $True $Script:NormalFontSize = 10 $poshversion = $PSVersionTable.PSVersion.Major $Script:osversion = (Get-CimInstance -ClassName Win32_OperatingSystem).Caption $autoconfigfile = Join-Path -Path "$(($env:COMPUTERNAME, $env:USERDNSDOMAIN) -join '.')" -ChildPath "cmhealthconfig.txt" if ($AutoConfig -and (Test-Path $autoconfigfile)) { Write-Verbose "importing settings from config file: $autoconfigfile" $cfgdata = Get-Content -Path $autoconfigfile $cfgdata | ForEach-Object { $rowset = $_ -split '=' if (![string]::IsNullOrEmpty($rowset[1])) { switch($rowset[1]) { 'True' { Set-Variable -Name $rowset[0] -Value $True Write-Verbose "...$($rowset[0]) == $($rowset[1])" } 'False' { Set-Variable -Name $rowset[0] -Value $False Write-Verbose "...$($rowset[0]) == $($rowset[1])" } default { Set-Variable -Name $rowset[0] -Value $rowset[1] Write-Verbose "...$($rowset[0]) == $($rowset[1])" } } } } } if ([string]::IsNullOrEmpty($Healthcheckfilename)) { $Healthcheckfilename = Join-Path -Path $ModulePath -ChildPath "assets\cmhealthcheck.xml" } if ([string]::IsNullOrEmpty($MessagesFilename)) { $MessagesFilename = Join-Path -Path $ModulePath -ChildPath "assets\messages.xml" } if ($healthcheckdebug -eq $true) { $PSDefaultParameterValues = @{"*:Verbose"=$True} } $logFolder = Join-Path -Path $PWD.Path -ChildPath "_Logs\" if (!(Test-Path $logFolder)) { mkdir $logFolder -Force | Out-Null } if ($reportFolder.Substring($reportFolder.length-1) -ne '\') { $reportFolder+= '\' } $Error.Clear() $poshversion = $PSVersionTable.PSVersion.Major Show-CMHCInfo [xml]$HealthCheckXML = Get-CmHealthCheckFile -XmlSource $HealthcheckFilename [xml]$MessagesXML = Get-CmHealthCheckFile -XmlSource $MessagesFilename Write-Log -Message "Connecting to Microsoft Word..." -LogFile $logfile try { $Word = New-Object -ComObject "Word.Application" -ErrorAction Stop } catch { Invoke-Error -Message "Microsoft Word could not be opened!" break } if ($HealthCheckXML -and $MessagesXML) { $bLogValidation = $true Write-Log -Message "Provisioning config table" -LogFile $logfile $ConfigTable = New-Object System.Data.DataTable 'ConfigTable' $ConfigTable = Get-CmXMLFile -Path $reportFolder -FileName "config.xml" if ([string]::IsNullOrEmpty($ConfigTable)) { Invoke-Error -Message "File $configfile does not exist, no futher action taken"; break } Write-Log -Message "Provisioning report table" -LogFile $logfile $ReportTable = New-Object System.Data.DataTable 'ReportTable' $ReportTable = Get-CmXMLFile -Path $reportFolder -FileName "report.xml" if ([string]::IsNullOrEmpty($ReportTable)) { Invoke-Error -Message "File $repfile does not exist, no futher action taken"; break } Write-Log -Message "Assigning number of days from config data..." -LogFile $logfile if ($poshversion -eq 3) { $NumberOfDays = $ConfigTable.Rows[0].NumberOfDays } else { $NumberOfDays = $ConfigTable.NumberOfDays } Write-Log -Message "number of days = $NumberOfDays" Write-Log -Message "checking powershell platform type" if (!(Test-Powershell64bit)) { Invoke-Error -Message "Powershell is not 64bit, no futher action taken"; break } $wordVersion = $Word.Version Write-Log -Message "Microsoft Word version: $WordVersion" -LogFile $logfile if ($wordVersion -lt '15.0') { Invoke-Error -Message "This module requires Word 2013 or newer"; break } if (![string]::IsNullOrEmpty($Template)) { $newFile = Get-WordTempSource -SourceFile $Template Write-Log -Message "Opening temp file [$newFile]..." -LogFile $logfile try { $Doc = $Word.Documents.Open($newFile) } catch { Invoke-Error -Message "Failed to open temp document file: $newFile" break } } else { Write-Log -Message "Creating new (blank) document..." -LogFile $logfile $Doc = $Word.Documents.Add() } if ($null -eq $doc) { Invoke-Error -Message "Failed to obtain handle to Word document"; break } $Word.Visible = $True $Selection = $Word.Selection Set-WordOptions Set-DocProperties Write-Log -Message "Loading default building blocks " -LogFile $logfile $Word.Templates.LoadBuildingBlocks() | Out-Null $BuildingBlocks = $Word.Templates | Where-Object {$_.name -eq "Built-In Building Blocks.dotx"} if ([string]::IsNullOrEmpty($Template)) { Write-Log -Message "Inserting cover page: $CoverPage" -LogFile $logfile $part = $BuildingBlocks.BuildingBlockEntries.Item($CoverPage) $part.Insert($selection.Range,$True) | Out-Null } else { Write-Log -Message "Cover page option ignored when using custom template" -LogFile $logfile $Selection.EndKey(6, 0) | Out-Null } $selection.InsertNewPage() Set-WordTOC $selection.InsertNewPage() $currentview = $doc.ActiveWindow.ActivePane.view.SeekView $doc.ActiveWindow.ActivePane.view.SeekView = 4 Set-WordFooter $doc.ActiveWindow.ActivePane.view.SeekView = $currentview $selection.EndKey(6,0) | Out-Null Set-WordAbstract Write-WordTableGrid -Caption "Revision History" -Rows 4 -ColumnHeadings ("Version","Date","Description","Author") $selection.InsertNewPage() Write-WordTableGrid -Caption "Summary of Findings" -Rows 4 -ColumnHeadings ("Item", "Severity", "Explanation") -StyleName $ReviewTableStyle Write-WordTableGrid -Caption "Summary of Recommendations" -Rows 4 -ColumnHeadings ("Item", "Severity", "Explanation") -StyleName $RecTableStyle $selection.InsertNewPage() Write-DocReportSections $selection.InsertNewPage() Set-DocAppendix } else { Write-Log -Message "Unable to load Healthcheck or Messages XML data" -Severity 3 -LogFile $logfile -ShowMsg $error.Clear() } if ($null -ne $toc) { $Doc.TablesOfContents.Item(1).Update() if ($bLogValidation -eq $False) { Write-Host "Finishing up healthcheck report" } else { Write-Log -Message "Finishing up HealthCheck Export" -LogFile $logfile } } $Difference = Get-TimeOffset -StartTime $time1 Write-Log -Message "Completed in: $Difference (hh:mm:ss)" -LogFile $logfile -ShowMsg } |