Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
David O'Brien Fixed WMI query b789090 Apr 7, 2015
0 contributors

Users who have contributed to this file

5049 lines (4524 sloc) 214 KB
#Requires -Version 3.0
#This File is in Unicode format. Do not edit in an ASCII editor.
#region help text
<#
.SYNOPSIS
Demonstrates script functionality using Microsoft Word, PDF, formatted text or HTML.
.DESCRIPTION
Creates a sample report of various Word functionality using Microsoft Word, PDF, formatted text, HTML and PowerShell.
Creates a document named Script_Template.docx (or .PDF or .TXT or .HTML).
Word and PDF documents include a Cover Page, Table of Contents and Footer.
Includes support for the following language versions of Microsoft Word:
Catalan
Danish
Dutch
English
Finnish
French
German
Norwegian
Portuguese
Spanish
Swedish
Look for the sections starting with ### to find the lines to either be replaced with your
script code or that need changing for your script needs
.PARAMETER CompanyName
Company Name to use for the Cover Page.
Default value is contained in HKCU:\Software\Microsoft\Office\Common\UserInfo\CompanyName or
HKCU:\Software\Microsoft\Office\Common\UserInfo\Company, whichever is populated on the
computer running the script.
This parameter has an alias of CN.
If either registry key does not exist and this parameter is not specified, the report will
not contain a Company Name on the cover page.
.PARAMETER CoverPage
What Microsoft Word Cover Page to use.
Only Word 2010 and 2013 are supported.
(default cover pages in Word en-US)
Valid input is:
Alphabet (Word 2010. Works)
Annual (Word 2010. Doesn't work well for this report)
Austere (Word 2010. Works)
Austin (Word 2010/2013. Doesn't work in 2013, mostly works in 2010 but Subtitle/Subject & Author fields need to be moved after title box is moved up)
Banded (Word 2013. Works)
Conservative (Word 2010. Works)
Contrast (Word 2010. Works)
Cubicles (Word 2010. Works)
Exposure (Word 2010. Works if you like looking sideways)
Facet (Word 2013. Works)
Filigree (Word 2013. Works)
Grid (Word 2010/2013.Works in 2010)
Integral (Word 2013. Works)
Ion (Dark) (Word 2013. Top date doesn't fit, box needs to be manually resized or font changed to 8 point)
Ion (Light) (Word 2013. Top date doesn't fit, box needs to be manually resized or font changed to 8 point)
Mod (Word 2010. Works)
Motion (Word 2010/2013. Works if top date is manually changed to 36 point)
Newsprint (Word 2010. Works but date is not populated)
Perspective (Word 2010. Works)
Pinstripes (Word 2010. Works)
Puzzle (Word 2010. Top date doesn't fit, box needs to be manually resized or font changed to 14 point)
Retrospect (Word 2013. Works)
Semaphore (Word 2013. Works)
Sideline (Word 2010/2013. Doesn't work in 2013, works in 2010)
Slice (Dark) (Word 2013. Doesn't work)
Slice (Light) (Word 2013. Doesn't work)
Stacks (Word 2010. Works)
Tiles (Word 2010. Date doesn't fit unless changed to 26 point)
Transcend (Word 2010. Works)
ViewMaster (Word 2013. Works)
Whisp (Word 2013. Works)
Default value is Sideline.
This parameter has an alias of CP.
.PARAMETER UserName
User name to use for the Cover Page and Footer.
Default value is contained in $env:username
This parameter has an alias of UN.
.PARAMETER PDF
SaveAs PDF file instead of DOCX file.
This parameter is disabled by default.
The PDF file is roughly 5X to 10X larger than the DOCX file.
.PARAMETER MSWord
SaveAs DOCX file
This parameter is set True if no other output format is selected.
.PARAMETER AddDateTime
Adds a date time stamp to the end of the file name.
Time stamp is in the format of yyyy-MM-dd_HHmm.
June 1, 2014 at 6PM is 2014-06-01_1800.
Output filename will be ReportName_2014-06-01_1800.docx (or .pdf).
This parameter is disabled by default.
.PARAMETER Hardware
Use WMI to gather hardware information on: Computer System, Disks, Processor and Network Interface Cards
This parameter may require the script be run from an elevated PowerShell session
using an account with permission to retrieve hardware information (i.e. Domain Admin or Local Administrator).
Selecting this parameter will add to both the time it takes to run the script and size of the report.
This parameter is disabled by default.
.PARAMETER ComputerName
Specifies a computer to use to run the script against.
ComputerName can be entered as the NetBIOS name, FQDN, localhost or IP Address.
If entered as localhost, the actual computer name is determined and used.
If entered as an IP address, an attempt is made to determine and use the actual computer name.
Default is localhost.
.PARAMETER Software
Specifies whether the script should run an inventory of Applications, Packages and OSD related objects.
.PARAMETER ListAllInformation
Specifies whether the script should only output an overview of what is configured (like count of collections) or
a full output with verbose information.
.PARAMETER SMSProvider
Some information rely on WMI queries that need to be executed against the SMS Provider directly.
Please specify as FQDN.
If not specified, it assumes localhost.
.EXAMPLE
PS C:\PSScript > .\ScriptTemplate.ps1 -PDF
Will use all default values and save the document as a PDF file.
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\CompanyName="Carl Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl Webster"
$env:username = Administrator
Carl Webster for the Company Name.
Sideline for the Cover Page format.
Administrator for the User Name.
.EXAMPLE
PS C:\PSScript .\ScriptTemplate.ps1 -CompanyName "Carl Webster Consulting" -CoverPage "Mod" -UserName "Carl Webster"
Will use:
Carl Webster Consulting for the Company Name.
Mod for the Cover Page format.
Carl Webster for the User Name.
.EXAMPLE
PS C:\PSScript .\ScriptTemplate.ps1 -CN "Carl Webster Consulting" -CP "Mod" -UN "Carl Webster"
Will use:
Carl Webster Consulting for the Company Name (alias CN).
Mod for the Cover Page format (alias CP).
Carl Webster for the User Name (alias UN).
.EXAMPLE
PS C:\PSScript > .\ScriptTemplate.ps1 -AddDateTime
Will use all default values.
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\CompanyName="Carl Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl Webster"
$env:username = Administrator
Carl Webster for the Company Name.
Sideline for the Cover Page format.
Administrator for the User Name.
Adds a date time stamp to the end of the file name.
Time stamp is in the format of yyyy-MM-dd_HHmm.
June 1, 2014 at 6PM is 2014-06-01_1800.
Output filename will be Script_Template_2014-06-01_1800.docx
.EXAMPLE
PS C:\PSScript > .\ScriptTemplate.ps1 -PDF -AddDateTime
Will use all default values and save the document as a PDF file.
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\CompanyName="Carl Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl Webster"
$env:username = Administrator
Carl Webster for the Company Name.
Sideline for the Cover Page format.
Administrator for the User Name.
Adds a date time stamp to the end of the file name.
Time stamp is in the format of yyyy-MM-dd_HHmm.
June 1, 2014 at 6PM is 2014-06-01_1800.
Output filename will be Script_Template_2014-06-01_1800.PDF
.EXAMPLE
PS C:\PSScript > .\ScriptTemplate.ps1 -Hardware
Will use all default values.
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\CompanyName="Carl Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl Webster"
$env:username = Administrator
Carl Webster for the Company Name.
Sideline for the Cover Page format.
Administrator for the User Name.
localhost for running hardware inventory.
localhost will be replaced by the actual computer name.
.EXAMPLE
PS C:\PSScript > .\ScriptTemplate.ps1 -Hardware -ComputerName 192.168.1.51
Will use all default values.
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\CompanyName="Carl Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl Webster"
$env:username = Administrator
Carl Webster for the Company Name.
Sideline for the Cover Page format.
Administrator for the User Name.
192.168.1.51 for running hardware inventory.
192.168.1.51 will be replaced by the actual computer name, if possible.
.INPUTS
None. You cannot pipe objects to this script.
.OUTPUTS
No objects are output from this script.
This script creates a Word, PDF, Formatted Text or HTML document.
.NOTES
NAME: DocumentCM12R2v2.ps1
VERSION: 1.00
AUTHOR: Carl Webster, Michael B. Smith, Iain Brighton, Jeff Wouters, Barry Schiffer, David O'Brien
LASTEDIT: April 06, 2015
#>
#endregion
#region script parameters
#thanks to @jeffwouters and Michael B. Smith for helping me with these parameters
[CmdletBinding(SupportsShouldProcess = $False, ConfirmImpact = "None", DefaultParameterSetName = "Word") ]
Param(
[parameter(ParameterSetName="Word",Mandatory=$False)]
[Switch]$MSWord=$False,
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[Switch]$PDF=$False,
[parameter(Mandatory=$False)]
[Switch]$AddDateTime=$False,
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[Alias("CN")]
[ValidateNotNullOrEmpty()]
[string]$CompanyName="",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[Alias("CP")]
[ValidateNotNullOrEmpty()]
[string]$CoverPage="Sideline",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[Alias("UN")]
[ValidateNotNullOrEmpty()]
[string]$UserName=$env:username,
[parameter(Mandatory=$False)]
[Switch]$Software,
[parameter(Mandatory=$False)]
[Switch]$ListAllInformation,
[parameter(Mandatory=$False)]
[string]$SMSProvider='localhost'
)
#endregion
#region script change log
#webster@carlwebster.com
#@carlwebster on Twitter
#http://www.CarlWebster.com
#Created on June 1, 2014
#HTML functions and sample text contributed by Ken Avram October 2014
#Organized functions into logical units 16-Oct-2014
#Added regions 16-Oct-2014
#endregion
#region initial variable testing and setup
Set-StrictMode -Version 2
#force on
$PSDefaultParameterValues = @{"*:Verbose"=$True}
$SaveEAPreference = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
If($PDF -eq $Null)
{
$PDF = $False
}
If($Text -eq $Null)
{
$Text = $False
}
If($MSWord -eq $Null)
{
$MSWord = $False
}
If($HTML -eq $Null)
{
$HTML = $False
}
If($AddDateTime -eq $Null)
{
$AddDateTime = $False
}
If($Hardware -eq $Null)
{
$Hardware = $False
}
If($ComputerName -eq $Null)
{
$ComputerName = "LocalHost"
}
If(!(Test-Path Variable:PDF))
{
$PDF = $False
}
If(!(Test-Path Variable:Text))
{
$Text = $False
}
If(!(Test-Path Variable:MSWord))
{
$MSWord = $False
}
If(!(Test-Path Variable:HTML))
{
$HTML = $False
}
If(!(Test-Path Variable:AddDateTime))
{
$AddDateTime = $False
}
If(!(Test-Path Variable:Hardware))
{
$Hardware = $False
}
If(!(Test-Path Variable:ComputerName))
{
$ComputerName = "LocalHost"
}
If($MSWord -eq $Null)
{
If($Text -or $HTML -or $PDF)
{
$MSWord = $False
}
Else
{
$MSWord = $True
}
}
If($MSWord -eq $False -and $PDF -eq $False -and $Text -eq $False -and $HTML -eq $False)
{
$MSWord = $True
}
Write-Verbose "$(Get-Date): Testing output parameters"
If($MSWord)
{
Write-Verbose "$(Get-Date): MSWord is set"
}
ElseIf($PDF)
{
Write-Verbose "$(Get-Date): PDF is set"
}
ElseIf($Text)
{
Write-Verbose "$(Get-Date): Text is set"
}
ElseIf($HTML)
{
Write-Verbose "$(Get-Date): HTML is set"
}
Else
{
$ErrorActionPreference = $SaveEAPreference
Write-Verbose "$(Get-Date): Unable to determine output parameter"
If($MSWord -eq $Null)
{
Write-Verbose "$(Get-Date): MSWord is Null"
}
ElseIf($PDF -eq $Null)
{
Write-Verbose "$(Get-Date): PDF is Null"
}
ElseIf($Text -eq $Null)
{
Write-Verbose "$(Get-Date): Text is Null"
}
ElseIf($HTML -eq $Null)
{
Write-Verbose "$(Get-Date): HTML is Null"
}
Else
{
Write-Verbose "$(Get-Date): MSWord is $($MSWord)"
Write-Verbose "$(Get-Date): PDF is $($PDF)"
Write-Verbose "$(Get-Date): Text is $($Text)"
Write-Verbose "$(Get-Date): HTML is $($HTML)"
}
Write-Error "Unable to determine output parameter. Script cannot continue"
Exit
}
#endregion
#region initialize variables for word html and text
If($MSWord -or $PDF)
{
#try and fix the issue with the $CompanyName variable
$Script:CoName = $CompanyName
Write-Verbose "$(Get-Date): CoName is $($Script:CoName)"
#the following values were attained from
#http://groovy.codehaus.org/modules/scriptom/1.6.0/scriptom-office-2K3-tlb/apidocs/
#http://msdn.microsoft.com/en-us/library/office/aa211923(v=office.11).aspx
[int]$wdAlignPageNumberRight = 2
[long]$wdColorGray15 = 14277081
[long]$wdColorGray05 = 15987699
[int]$wdMove = 0
[int]$wdSeekMainDocument = 0
[int]$wdSeekPrimaryFooter = 4
[int]$wdStory = 6
[int]$wdColorRed = 255
[int]$wdColorBlack = 0
[int]$wdWord2007 = 12
[int]$wdWord2010 = 14
[int]$wdWord2013 = 15
[int]$wdFormatDocumentDefault = 16
[int]$wdFormatPDF = 17
#http://blogs.technet.com/b/heyscriptingguy/archive/2006/03/01/how-can-i-right-align-a-single-column-in-a-word-table.aspx
#http://msdn.microsoft.com/en-us/library/office/ff835817%28v=office.15%29.aspx
[int]$wdAlignParagraphLeft = 0
[int]$wdAlignParagraphCenter = 1
[int]$wdAlignParagraphRight = 2
#http://msdn.microsoft.com/en-us/library/office/ff193345%28v=office.15%29.aspx
[int]$wdCellAlignVerticalTop = 0
[int]$wdCellAlignVerticalCenter = 1
[int]$wdCellAlignVerticalBottom = 2
#http://msdn.microsoft.com/en-us/library/office/ff844856%28v=office.15%29.aspx
[int]$wdAutoFitFixed = 0
[int]$wdAutoFitContent = 1
[int]$wdAutoFitWindow = 2
#http://msdn.microsoft.com/en-us/library/office/ff821928%28v=office.15%29.aspx
[int]$wdAdjustNone = 0
[int]$wdAdjustProportional = 1
[int]$wdAdjustFirstColumn = 2
[int]$wdAdjustSameWidth = 3
[int]$PointsPerTabStop = 36
[int]$Indent0TabStops = 0 * $PointsPerTabStop
[int]$Indent1TabStops = 1 * $PointsPerTabStop
[int]$Indent2TabStops = 2 * $PointsPerTabStop
[int]$Indent3TabStops = 3 * $PointsPerTabStop
[int]$Indent4TabStops = 4 * $PointsPerTabStop
# http://www.thedoctools.com/index.php?show=wt_style_names_english_danish_german_french
[int]$wdStyleHeading1 = -2
[int]$wdStyleHeading2 = -3
[int]$wdStyleHeading3 = -4
[int]$wdStyleHeading4 = -5
[int]$wdStyleNoSpacing = -158
[int]$wdTableGrid = -155
#http://groovy.codehaus.org/modules/scriptom/1.6.0/scriptom-office-2K3-tlb/apidocs/org/codehaus/groovy/scriptom/tlb/office/word/WdLineStyle.html
[int]$wdLineStyleNone = 0
[int]$wdLineStyleSingle = 1
[int]$wdHeadingFormatTrue = -1
[int]$wdHeadingFormatFalse = 0
[string]$RunningOS = (Get-WmiObject -class Win32_OperatingSystem -EA 0).Caption
}
If($HTML)
{
Set htmlredmask -Option AllScope -Value "#FF0000" 4>$Null
Set htmlcyanmask -Option AllScope -Value "#00FFFF" 4>$Null
Set htmlbluemask -Option AllScope -Value "#0000FF" 4>$Null
Set htmldarkbluemask -Option AllScope -Value "#0000A0" 4>$Null
Set htmllightbluemask -Option AllScope -Value "#ADD8E6" 4>$Null
Set htmlpurplemask -Option AllScope -Value "#800080" 4>$Null
Set htmlyellowmask -Option AllScope -Value "#FFFF00" 4>$Null
Set htmllimemask -Option AllScope -Value "#00FF00" 4>$Null
Set htmlmagentamask -Option AllScope -Value "#FF00FF" 4>$Null
Set htmlwhitemask -Option AllScope -Value "#FFFFFF" 4>$Null
Set htmlsilvermask -Option AllScope -Value "#C0C0C0" 4>$Null
Set htmlgraymask -Option AllScope -Value "#808080" 4>$Null
Set htmlblackmask -Option AllScope -Value "#000000" 4>$Null
Set htmlorangemask -Option AllScope -Value "#FFA500" 4>$Null
Set htmlmaroonmask -Option AllScope -Value "#800000" 4>$Null
Set htmlgreenmask -Option AllScope -Value "#008000" 4>$Null
Set htmlolivemask -Option AllScope -Value "#808000" 4>$Null
Set htmlbold -Option AllScope -Value 1 4>$Null
Set htmlitalics -Option AllScope -Value 2 4>$Null
Set htmlred -Option AllScope -Value 4 4>$Null
Set htmlcyan -Option AllScope -Value 8 4>$Null
Set htmlblue -Option AllScope -Value 16 4>$Null
Set htmldarkblue -Option AllScope -Value 32 4>$Null
Set htmllightblue -Option AllScope -Value 64 4>$Null
Set htmlpurple -Option AllScope -Value 128 4>$Null
Set htmlyellow -Option AllScope -Value 256 4>$Null
Set htmllime -Option AllScope -Value 512 4>$Null
Set htmlmagenta -Option AllScope -Value 1024 4>$Null
Set htmlwhite -Option AllScope -Value 2048 4>$Null
Set htmlsilver -Option AllScope -Value 4096 4>$Null
Set htmlgray -Option AllScope -Value 8192 4>$Null
Set htmlolive -Option AllScope -Value 16384 4>$Null
Set htmlorange -Option AllScope -Value 32768 4>$Null
Set htmlmaroon -Option AllScope -Value 65536 4>$Null
Set htmlgreen -Option AllScope -Value 131072 4>$Null
Set htmlblack -Option AllScope -Value 262144 4>$Null
}
If($TEXT)
{
$global:output = ""
}
#endregion
#region word specific functions
Function SetWordHashTable
{
Param([string]$CultureCode)
#optimized by Michael B. SMith
# DE and FR translations for Word 2010 by Vladimir Radojevic
# Vladimir.Radojevic@Commerzreal.com
# DA translations for Word 2010 by Thomas Daugaard
# Citrix Infrastructure Specialist at edgemo A/S
# CA translations by Javier Sanchez
# CEO & Founder 101 Consulting
#ca - Catalan
#da - Danish
#de - German
#en - English
#es - Spanish
#fi - Finnish
#fr - French
#nb - Norwegian
#nl - Dutch
#pt - Portuguese
#sv - Swedish
[string]$toc = $(
Switch ($CultureCode)
{
'ca-' { 'Taula automática 2' }
'da-' { 'Automatisk tabel 2' }
'de-' { 'Automatische Tabelle 2' }
'en-' { 'Automatic Table 2' }
'es-' { 'Tabla automática 2' }
'fi-' { 'Automaattinen taulukko 2' }
'fr-' { 'Sommaire Automatique 2' }
'nb-' { 'Automatisk tabell 2' }
'nl-' { 'Automatische inhoudsopgave 2' }
'pt-' { 'Sumário Automático 2' }
'sv-' { 'Automatisk innehållsförteckning2' }
}
)
$Script:myHash = @{}
$Script:myHash.Word_TableOfContents = $toc
$Script:myHash.Word_NoSpacing = $wdStyleNoSpacing
$Script:myHash.Word_Heading1 = $wdStyleheading1
$Script:myHash.Word_Heading2 = $wdStyleheading2
$Script:myHash.Word_Heading3 = $wdStyleheading3
$Script:myHash.Word_Heading4 = $wdStyleheading4
$Script:myHash.Word_TableGrid = $wdTableGrid
}
Function GetCulture
{
Param([int]$WordValue)
#codes obtained from http://support.microsoft.com/kb/221435
#http://msdn.microsoft.com/en-us/library/bb213877(v=office.12).aspx
$CatalanArray = 1027
$DanishArray = 1030
$DutchArray = 2067, 1043
$EnglishArray = 3081, 10249, 4105, 9225, 6153, 8201, 5129, 13321, 7177, 11273, 2057, 1033, 12297
$FinnishArray = 1035
$FrenchArray = 2060, 1036, 11276, 3084, 12300, 5132, 13324, 6156, 8204, 10252, 7180, 9228, 4108
$GermanArray = 1031, 3079, 5127, 4103, 2055
$NorwegianArray = 1044, 2068
$PortugueseArray = 1046, 2070
$SpanishArray = 1034, 11274, 16394, 13322, 9226, 5130, 7178, 12298, 17418, 4106, 18442, 19466, 6154, 15370, 10250, 20490, 3082, 14346, 8202
$SwedishArray = 1053, 2077
#ca - Catalan
#da - Danish
#de - German
#en - English
#es - Spanish
#fi - Finnish
#fr - French
#nb - Norwegian
#nl - Dutch
#pt - Portuguese
#sv - Swedish
Switch ($WordValue)
{
{$CatalanArray -contains $_} {$CultureCode = "ca-"}
{$DanishArray -contains $_} {$CultureCode = "da-"}
{$DutchArray -contains $_} {$CultureCode = "nl-"}
{$EnglishArray -contains $_} {$CultureCode = "en-"}
{$FinnishArray -contains $_} {$CultureCode = "fi-"}
{$FrenchArray -contains $_} {$CultureCode = "fr-"}
{$GermanArray -contains $_} {$CultureCode = "de-"}
{$NorwegianArray -contains $_} {$CultureCode = "nb-"}
{$PortugueseArray -contains $_} {$CultureCode = "pt-"}
{$SpanishArray -contains $_} {$CultureCode = "es-"}
{$SwedishArray -contains $_} {$CultureCode = "sv-"}
Default {$CultureCode = "en-"}
}
Return $CultureCode
}
Function ValidateCoverPage
{
Param([int]$xWordVersion, [string]$xCP, [string]$CultureCode)
$xArray = ""
Switch ($CultureCode)
{
'ca-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "En bandes", "Faceta", "Filigrana",
"Integral", "Ió (clar)", "Ió (fosc)", "Línia lateral",
"Moviment", "Quadrícula", "Retrospectiu", "Sector (clar)",
"Sector (fosc)", "Semàfor", "Visualització", "Whisp")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabet", "Anual", "Austin", "Conservador",
"Contrast", "Cubicles", "Diplomàtic", "Exposició",
"Línia lateral", "Mod", "Mosiac", "Moviment", "Paper de diari",
"Perspectiva", "Piles", "Quadrícula", "Sobri",
"Transcendir", "Trencaclosques")
}
}
'da-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("BevægElse", "Brusen", "Ion (lys)", "Filigran",
"Retro", "Semafor", "Visningsmaster", "Integral",
"Facet", "Gitter", "Stribet", "Sidelinje", "Udsnit (lys)",
"Udsnit (mørk)", "Ion (mørk)", "Austin")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("BevægElse", "Moderat", "Perspektiv", "Firkanter",
"Overskrid", "Alfabet", "Kontrast", "Stakke", "Fliser", "Gåde",
"Gitter", "Austin", "Eksponering", "Sidelinje", "Enkel",
"Nålestribet", "Årlig", "Avispapir", "Tradionel")
}
}
'de-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Semaphor", "Segment (hell)", "Ion (hell)",
"Raster", "Ion (dunkel)", "Filigran", "Rückblick", "Pfiff",
"ViewMaster", "Segment (dunkel)", "Verbunden", "Bewegung",
"Randlinie", "Austin", "Integral", "Facette")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alphabet", "Austin", "Bewegung", "Durchscheinend",
"Herausgestellt", "Jährlich", "Kacheln", "Kontrast", "Kubistisch",
"Modern", "Nadelstreifen", "Perspektive", "Puzzle", "Randlinie",
"Raster", "Schlicht", "Stapel", "Traditionell", "Zeitungspapier")
}
}
'en-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "Banded", "Facet", "Filigree", "Grid",
"Integral", "Ion (Dark)", "Ion (Light)", "Motion", "Retrospect",
"Semaphore", "Sideline", "Slice (Dark)", "Slice (Light)", "ViewMaster",
"Whisp")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alphabet", "Annual", "Austere", "Austin", "Conservative",
"Contrast", "Cubicles", "Exposure", "Grid", "Mod", "Motion", "Newsprint",
"Perspective", "Pinstripes", "Puzzle", "Sideline", "Stacks", "Tiles", "Transcend")
}
}
'es-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Whisp", "Vista principal", "Filigrana", "Austin",
"Slice (luz)", "Faceta", "Semáforo", "Retrospectiva", "Cuadrícula",
"Movimiento", "Cortar (oscuro)", "Línea lateral", "Ion (oscuro)",
"Ion (claro)", "Integral", "Con bandas")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabeto", "Anual", "Austero", "Austin", "Conservador",
"Contraste", "Cuadrícula", "Cubículos", "Exposición", "Línea lateral",
"Moderno", "Mosaicos", "Movimiento", "Papel periódico",
"Perspectiva", "Pilas", "Puzzle", "Rayas", "Sobrepasar")
}
}
'fi-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Filigraani", "Integraali", "Ioni (tumma)",
"Ioni (vaalea)", "Opastin", "Pinta", "Retro", "Sektori (tumma)",
"Sektori (vaalea)", "Vaihtuvavärinen", "ViewMaster", "Austin",
"Kiehkura", "Liike", "Ruudukko", "Sivussa")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Aakkoset", "Askeettinen", "Austin", "Kontrasti",
"Laatikot", "Liike", "Liituraita", "Mod", "Osittain peitossa",
"Palapeli", "Perinteinen", "Perspektiivi", "Pinot", "Ruudukko",
"Ruudut", "Sanomalehtipaperi", "Sivussa", "Vuotuinen", "Ylitys")
}
}
'fr-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("ViewMaster", "Secteur (foncé)", "Sémaphore",
"Rétrospective", "Ion (foncé)", "Ion (clair)", "Intégrale",
"Filigrane", "Facette", "Secteur (clair)", "À bandes", "Austin",
"Guide", "Whisp", "Lignes latérales", "Quadrillage")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Mosaïques", "Ligne latérale", "Annuel", "Perspective",
"Contraste", "Emplacements de bureau", "Moderne", "Blocs empilés",
"Rayures fines", "Austère", "Transcendant", "Classique", "Quadrillage",
"Exposition", "Alphabet", "Mots croisés", "Papier journal", "Austin", "Guide")
}
}
'nb-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "BevegElse", "Dempet", "Fasett", "Filigran",
"Integral", "Ion (lys)", "Ion (mørk)", "Retrospekt", "Rutenett",
"Sektor (lys)", "Sektor (mørk)", "Semafor", "Sidelinje", "Stripet",
"ViewMaster")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabet", "Årlig", "Avistrykk", "Austin", "Avlukker",
"BevegElse", "Engasjement", "Enkel", "Fliser", "Konservativ",
"Kontrast", "Mod", "Perspektiv", "Puslespill", "Rutenett", "Sidelinje",
"Smale striper", "Stabler", "Transcenderende")
}
}
'nl-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "Beweging", "Facet", "Filigraan", "Gestreept",
"Integraal", "Ion (donker)", "Ion (licht)", "Raster",
"Segment (Light)", "Semafoor", "Slice (donker)", "Spriet",
"Terugblik", "Terzijde", "ViewMaster")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Aantrekkelijk", "Alfabet", "Austin", "Bescheiden",
"Beweging", "Blikvanger", "Contrast", "Eenvoudig", "Jaarlijks",
"Krantenpapier", "Krijtstreep", "Kubussen", "Mod", "Perspectief",
"Puzzel", "Raster", "Stapels",
"Tegels", "Terzijde")
}
}
'pt-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Animação", "Austin", "Em Tiras", "Exibição Mestra",
"Faceta", "Fatia (Clara)", "Fatia (Escura)", "Filete", "Filigrana",
"Grade", "Integral", "Íon (Claro)", "Íon (Escuro)", "Linha Lateral",
"Retrospectiva", "Semáforo")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabeto", "Animação", "Anual", "Austero", "Austin", "Baias",
"Conservador", "Contraste", "Exposição", "Grade", "Ladrilhos",
"Linha Lateral", "Listras", "Mod", "Papel Jornal", "Perspectiva", "Pilhas",
"Quebra-cabeça", "Transcend")
}
}
'sv-' {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "Band", "Fasett", "Filigran", "Integrerad", "Jon (ljust)",
"Jon (mörkt)", "Knippe", "Rutnät", "RörElse", "Sektor (ljus)", "Sektor (mörk)",
"Semafor", "Sidlinje", "VisaHuvudsida", "Återblick")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabetmönster", "Austin", "Enkelt", "Exponering", "Konservativt",
"Kontrast", "Kritstreck", "Kuber", "Perspektiv", "Plattor", "Pussel", "Rutnät",
"RörElse", "Sidlinje", "Sobert", "Staplat", "Tidningspapper", "Årligt",
"Övergående")
}
}
Default {
If($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "Banded", "Facet", "Filigree", "Grid", "Integral",
"Ion (Dark)", "Ion (Light)", "Motion", "Retrospect", "Semaphore",
"Sideline", "Slice (Dark)", "Slice (Light)", "ViewMaster", "Whisp")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alphabet", "Annual", "Austere", "Austin", "Conservative",
"Contrast", "Cubicles", "Exposure", "Grid", "Mod", "Motion", "Newsprint",
"Perspective", "Pinstripes", "Puzzle", "Sideline", "Stacks", "Tiles", "Transcend")
}
}
}
If($xArray -contains $xCP)
{
$xArray = $Null
Return $True
}
Else
{
$xArray = $Null
Return $False
}
}
Function CheckWordPrereq
{
If((Test-Path REGISTRY::HKEY_CLASSES_ROOT\Word.Application) -eq $False)
{
$ErrorActionPreference = $SaveEAPreference
Write-Host "`n`n`t`tThis script directly outputs to Microsoft Word, please install Microsoft Word`n`n"
Exit
}
#find out our session (usually "1" except on TS/RDC or Citrix)
$SessionID = (Get-Process -PID $PID).SessionId
#Find out if winword is running in our session
[bool]$wordrunning = ((Get-Process 'WinWord' -ea 0)|?{$_.SessionId -eq $SessionID}) -ne $Null
If($wordrunning)
{
$ErrorActionPreference = $SaveEAPreference
Write-Host "`n`n`tPlease close all instances of Microsoft Word before running this report.`n`n"
Exit
}
}
Function ValidateCompanyName
{
[bool]$xResult = Test-RegistryValue "HKCU:\Software\Microsoft\Office\Common\UserInfo" "CompanyName"
If($xResult)
{
Return Get-RegistryValue "HKCU:\Software\Microsoft\Office\Common\UserInfo" "CompanyName"
}
Else
{
$xResult = Test-RegistryValue "HKCU:\Software\Microsoft\Office\Common\UserInfo" "Company"
If($xResult)
{
Return Get-RegistryValue "HKCU:\Software\Microsoft\Office\Common\UserInfo" "Company"
}
Else
{
Return ""
}
}
}
Function _SetDocumentProperty
{
#jeff hicks
Param([object]$Properties,[string]$Name,[string]$Value)
#get the property object
$prop = $properties | ForEach {
$propname=$_.GetType().InvokeMember("Name","GetProperty",$Null,$_,$Null)
If($propname -eq $Name)
{
Return $_
}
} #ForEach
#set the value
$Prop.GetType().InvokeMember("Value","SetProperty",$Null,$prop,$Value)
}
Function FindWordDocumentEnd
{
#return focus to main document
$Script:Doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument
#move to the end of the current document
$Script:Selection.EndKey($wdStory,$wdMove) | Out-Null
}
Function SetupWord
{
Write-Verbose "$(Get-Date): Setting up Word"
# Setup word for output
Write-Verbose "$(Get-Date): Create Word comObject."
$Script:Word = New-Object -comobject "Word.Application" -EA 0 4>$Null
If(!$? -or $Script:Word -eq $Null)
{
Write-Warning "The Word object could not be created. You may need to repair your Word installation."
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tThe Word object could not be created. You may need to repair your Word installation.`n`n`t`tScript cannot continue.`n`n"
Exit
}
Write-Verbose "$(Get-Date): Determine Word language value"
If( ( validStateProp $Script:Word Language Value__ ) )
{
[int]$Script:WordLanguageValue = [int]$Script:Word.Language.Value__
}
Else
{
[int]$Script:WordLanguageValue = [int]$Script:Word.Language
}
If(!($Script:WordLanguageValue -gt -1))
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tUnable to determine the Word language value.`n`n`t`tScript cannot continue.`n`n"
AbortScript
}
Write-Verbose "$(Get-Date): Word language value is $($Script:WordLanguageValue)"
$Script:WordCultureCode = GetCulture $Script:WordLanguageValue
SetWordHashTable $Script:WordCultureCode
[int]$Script:WordVersion = [int]$Script:Word.Version
If($Script:WordVersion -eq $wdWord2013)
{
$Script:WordProduct = "Word 2013"
}
ElseIf($Script:WordVersion -eq $wdWord2010)
{
$Script:WordProduct = "Word 2010"
}
ElseIf($Script:WordVersion -eq $wdWord2007)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tMicrosoft Word 2007 is no longer supported.`n`n`t`tScript will end.`n`n"
AbortScript
}
Else
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tYou are running an untested or unsupported version of Microsoft Word.`n`n`t`tScript will end.`n`n`t`tPlease send info on your version of Word to webster@carlwebster.com`n`n"
AbortScript
}
#only validate CompanyName if the field is blank
If([String]::IsNullOrEmpty($Script:CoName))
{
Write-Verbose "$(Get-Date): Company name is blank. Retrieve company name from registry."
$TmpName = ValidateCompanyName
If([String]::IsNullOrEmpty($TmpName))
{
Write-Warning "`n`n`t`tCompany Name is blank so Cover Page will not show a Company Name."
Write-Warning "`n`t`tCheck HKCU:\Software\Microsoft\Office\Common\UserInfo for Company or CompanyName value."
Write-Warning "`n`t`tYou may want to use the -CompanyName parameter if you need a Company Name on the cover page.`n`n"
}
Else
{
$Script:CoName = $TmpName
Write-Verbose "$(Get-Date): Updated company name to $($Script:CoName)"
}
}
If($Script:WordCultureCode -ne "en-")
{
Write-Verbose "$(Get-Date): Check Default Cover Page for $($WordCultureCode)"
[bool]$CPChanged = $False
Switch ($Script:WordCultureCode)
{
'ca-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Línia lateral"
$CPChanged = $True
}
}
'da-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Sidelinje"
$CPChanged = $True
}
}
'de-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Randlinie"
$CPChanged = $True
}
}
'es-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Línea lateral"
$CPChanged = $True
}
}
'fi-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Sivussa"
$CPChanged = $True
}
}
'fr-' {
If($CoverPage -eq "Sideline")
{
If($Script:WordVersion -eq $wdWord2013)
{
$CoverPage = "Lignes latérales"
$CPChanged = $True
}
Else
{
$CoverPage = "Ligne latérale"
$CPChanged = $True
}
}
}
'nb-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Sidelinje"
$CPChanged = $True
}
}
'nl-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Terzijde"
$CPChanged = $True
}
}
'pt-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Linha Lateral"
$CPChanged = $True
}
}
'sv-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Sidlinje"
$CPChanged = $True
}
}
}
If($CPChanged)
{
Write-Verbose "$(Get-Date): Changed Default Cover Page from Sideline to $($CoverPage)"
}
}
Write-Verbose "$(Get-Date): Validate cover page $($CoverPage) for culture code $($Script:WordCultureCode)"
[bool]$ValidCP = $False
$ValidCP = ValidateCoverPage $Script:WordVersion $CoverPage $Script:WordCultureCode
If(!$ValidCP)
{
$ErrorActionPreference = $SaveEAPreference
Write-Verbose "$(Get-Date): Word language value $($Script:WordLanguageValue)"
Write-Verbose "$(Get-Date): Culture code $($Script:WordCultureCode)"
Write-Error "`n`n`t`tFor $($Script:WordProduct), $($CoverPage) is not a valid Cover Page option.`n`n`t`tScript cannot continue.`n`n"
AbortScript
}
ShowScriptOptions
$Script:Word.Visible = $False
#http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/
#using Jeff's Demo-WordReport.ps1 file for examples
Write-Verbose "$(Get-Date): Load Word Templates"
[bool]$Script:CoverPagesExist = $False
[bool]$BuildingBlocksExist = $False
$Script:Word.Templates.LoadBuildingBlocks()
#word 2010/2013
$BuildingBlocksCollection = $Script:Word.Templates | Where {$_.name -eq "Built-In Building Blocks.dotx"}
Write-Verbose "$(Get-Date): Attempt to load cover page $($CoverPage)"
$part = $Null
$BuildingBlocksCollection |
ForEach{
If ($_.BuildingBlockEntries.Item($CoverPage).Name -eq $CoverPage)
{
$BuildingBlocks = $_
}
}
If($BuildingBlocks -ne $Null)
{
$BuildingBlocksExist = $True
Try
{
$part = $BuildingBlocks.BuildingBlockEntries.Item($CoverPage)
}
Catch
{
$part = $Null
}
If($part -ne $Null)
{
$Script:CoverPagesExist = $True
}
}
If(!$Script:CoverPagesExist)
{
Write-Verbose "$(Get-Date): Cover Pages are not installed or the Cover Page $($CoverPage) does not exist."
Write-Warning "Cover Pages are not installed or the Cover Page $($CoverPage) does not exist."
Write-Warning "This report will not have a Cover Page."
}
Write-Verbose "$(Get-Date): Create empty word doc"
$Script:Doc = $Script:Word.Documents.Add()
If($Script:Doc -eq $Null)
{
Write-Verbose "$(Get-Date): "
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tAn empty Word document could not be created.`n`n`t`tScript cannot continue.`n`n"
AbortScript
}
$Script:Selection = $Script:Word.Selection
If($Script:Selection -eq $Null)
{
Write-Verbose "$(Get-Date): "
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tAn unknown error happened selecting the entire Word document for default formatting options.`n`n`t`tScript cannot continue.`n`n"
AbortScript
}
#set Default tab stops to 1/2 inch (this line is not from Jeff Hicks)
#36 = .50"
$Script:Word.ActiveDocument.DefaultTabStop = 36
#Disable Spell and Grammar Check to resolve issue and improve performance (from Pat Coughlin)
Write-Verbose "$(Get-Date): Disable grammar and spell checking"
#bug reported 1-Apr-2014 by Tim Mangan
#save current options first before turning them off
$Script:CurrentGrammarOption = $Script:Word.Options.CheckGrammarAsYouType
$Script:CurrentSpellingOption = $Script:Word.Options.CheckSpellingAsYouType
$Script:Word.Options.CheckGrammarAsYouType = $False
$Script:Word.Options.CheckSpellingAsYouType = $False
If($BuildingBlocksExist)
{
#insert new page, getting ready for table of contents
Write-Verbose "$(Get-Date): Insert new page, getting ready for table of contents"
$part.Insert($Script:Selection.Range,$True) | Out-Null
$Script:Selection.InsertNewPage()
#table of contents
Write-Verbose "$(Get-Date): Table of Contents - $($Script:MyHash.Word_TableOfContents)"
$toc = $BuildingBlocks.BuildingBlockEntries.Item($Script:MyHash.Word_TableOfContents)
If($toc -eq $Null)
{
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): Table of Content - $($Script:MyHash.Word_TableOfContents) could not be retrieved."
Write-Warning "This report will not have a Table of Contents."
}
Else
{
$toc.insert($Script:Selection.Range,$True) | Out-Null
}
}
Else
{
Write-Verbose "$(Get-Date): Table of Contents are not installed."
Write-Warning "Table of Contents are not installed so this report will not have a Table of Contents."
}
#set the footer
Write-Verbose "$(Get-Date): Set the footer"
[string]$footertext = "Report created by $username"
#get the footer
Write-Verbose "$(Get-Date): Get the footer and format font"
$Script:Doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekPrimaryFooter
#get the footer and format font
$footers = $Script:Doc.Sections.Last.Footers
ForEach ($footer in $footers)
{
If($footer.exists)
{
$footer.range.Font.name = "Calibri"
$footer.range.Font.size = 8
$footer.range.Font.Italic = $True
$footer.range.Font.Bold = $True
}
} #end ForEach
Write-Verbose "$(Get-Date): Footer text"
$Script:Selection.HeaderFooter.Range.Text = $footerText
#add page numbering
Write-Verbose "$(Get-Date): Add page numbering"
$Script:Selection.HeaderFooter.PageNumbers.Add($wdAlignPageNumberRight) | Out-Null
FindWordDocumentEnd
Write-Verbose "$(Get-Date):"
#end of Jeff Hicks
}
Function UpdateDocumentProperties
{
Param([string]$AbstractTitle, [string]$SubjectTitle)
#Update document properties
If($MSWORD -or $PDF)
{
If($Script:CoverPagesExist)
{
Write-Verbose "$(Get-Date): Set Cover Page Properties"
_SetDocumentProperty $Script:Doc.BuiltInDocumentProperties "Company" $Script:CoName
_SetDocumentProperty $Script:Doc.BuiltInDocumentProperties "Title" $Script:title
_SetDocumentProperty $Script:Doc.BuiltInDocumentProperties "Author" $username
_SetDocumentProperty $Script:Doc.BuiltInDocumentProperties "Subject" $SubjectTitle
#Get the Coverpage XML part
$cp = $Script:Doc.CustomXMLParts | Where {$_.NamespaceURI -match "coverPageProps$"}
#get the abstract XML part
$ab = $cp.documentelement.ChildNodes | Where {$_.basename -eq "Abstract"}
#set the text
If([String]::IsNullOrEmpty($Script:CoName))
{
[string]$abstract = $AbstractTitle
}
Else
{
[string]$abstract = "$($AbstractTitle) for $($Script:CoName)"
}
$ab.Text = $abstract
$ab = $cp.documentelement.ChildNodes | Where {$_.basename -eq "PublishDate"}
#set the text
[string]$abstract = (Get-Date -Format d).ToString()
$ab.Text = $abstract
Write-Verbose "$(Get-Date): Update the Table of Contents"
#update the Table of Contents
$Script:Doc.TablesOfContents.item(1).Update()
$cp = $Null
$ab = $Null
$abstract = $Null
}
}
}
#endregion
#region registry functions
#http://stackoverflow.com/questions/5648931/test-if-registry-value-exists
# This Function just gets $True or $False
Function Test-RegistryValue($path, $name)
{
$key = Get-Item -LiteralPath $path -EA 0
$key -and $Null -ne $key.GetValue($name, $Null)
}
# Gets the specified registry value or $Null if it is missing
Function Get-RegistryValue($path, $name)
{
$key = Get-Item -LiteralPath $path -EA 0
If($key)
{
$key.GetValue($name, $Null)
}
Else
{
$Null
}
}
#endregion
#region word, text and html line output functions
Function line
#function created by Michael B. Smith, Exchange MVP
#@essentialexchange on Twitter
#http://TheEssentialExchange.com
#for creating the formatted text report
#created March 2011
#updated March 2014
{
Param( [int]$tabs = 0, [string]$name = '', [string]$value = '', [string]$newline = "`r`n", [switch]$nonewline )
While( $tabs -gt 0 ) { $Global:Output += "`t"; $tabs--; }
If( $nonewline )
{
$Global:Output += $name + $value
}
Else
{
$Global:Output += $name + $value + $newline
}
}
Function WriteWordLine
#Function created by Ryan Revord
#@rsrevord on Twitter
#Function created to make output to Word easy in this script
#updated 27-Mar-2014 to include font name, font size, italics and bold options
{
Param([int]$style=0,
[int]$tabs = 0,
[string]$name = '',
[string]$value = '',
[string]$fontName=$Null,
[int]$fontSize=0,
[bool]$italics=$False,
[bool]$boldface=$False,
[Switch]$nonewline)
#Build output style
[string]$output = ""
Switch ($style)
{
0 {$Script:Selection.Style = $Script:MyHash.Word_NoSpacing}
1 {$Script:Selection.Style = $Script:MyHash.Word_Heading1}
2 {$Script:Selection.Style = $Script:MyHash.Word_Heading2}
3 {$Script:Selection.Style = $Script:MyHash.Word_Heading3}
4 {$Script:Selection.Style = $Script:MyHash.Word_Heading4}
Default {$Script:Selection.Style = $Script:MyHash.Word_NoSpacing}
}
#build # of tabs
While($tabs -gt 0)
{
$output += "`t"; $tabs--;
}
If(![String]::IsNullOrEmpty($fontName))
{
$Script:Selection.Font.name = $fontName
}
If($fontSize -ne 0)
{
$Script:Selection.Font.size = $fontSize
}
If($italics -eq $True)
{
$Script:Selection.Font.Italic = $True
}
If($boldface -eq $True)
{
$Script:Selection.Font.Bold = $True
}
#output the rest of the parameters.
$output += $name + $value
$Script:Selection.TypeText($output)
#test for new WriteWordLine 0.
If($nonewline)
{
# Do nothing.
}
Else
{
$Script:Selection.TypeParagraph()
}
}
#***********************************************************************************************************
# WriteHTMLLine
#***********************************************************************************************************
<#
.Synopsis
Writes a line of output for HTML output
.DESCRIPTION
This function formats an HTML line
.USAGE
WriteHTMLLine <Style> <Tabs> <Name> <Value> <Font Name> <Font Size> <Options>
0 for Font Size denotes using the default font size of 2 or 10 point
.EXAMPLE
WriteHTMLLine 0 0 ""
Writes a blank line with no style or tab stops, obviously none needed.
.EXAMPLE
WriteHTMLLine 0 1 "This is a regular line of text indented 1 tab stops"
Writes a line with 1 tab stop.
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in italics" "" $null 0 $htmlitalics
Writes a line omitting font and font size and setting the italics attribute
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in bold" "" $null 0 $htmlbold
Writes a line omitting font and font size and setting the bold attribute
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in bold italics" "" $null 0 ($htmlbold -bor $htmlitalics)
Writes a line omitting font and font size and setting both italics and bold options
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in 10 point" "" $null 2 # 10 point font
Writes a line using 10 point font
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in Courier New font" "" "Courier New" 0
Writes a line using Courier New Font and 0 font point size (default = 2 if set to 0)
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of RED text indented 0 tab stops with the computer name as data in 10 point Courier New bold italics: " $env:computername "Courier New" 2 ($htmlbold -bor $htmlred -bor $htmlitalics)
Writes a line using Courier New Font with first and second string values to be used, also uses 10 point font with bold, italics and red color options set.
.NOTES
Font Size - Unlike word, there is a limited set of font sizes that can be used in HTML. They are:
0 - default which actually gives it a 2 or 10 point.
1 - 7.5 point font size
2 - 10 point
3 - 13.5 point
4 - 15 point
5 - 18 point
6 - 24 point
7 - 36 point
Any number larger than 7 defaults to 7
Style - Refers to the headers that are used with output and resemble the headers in word, HTML supports headers h1-h6 and h1-h4 are more commonly used. Unlike word, H1 will not give you
a blue colored font, you will have to set that yourself.
Colors and Bold/Italics Flags are:
htmlbold
htmlitalics
htmlred
htmlcyan
htmlblue
htmldarkblue
htmllightblue
htmlpurple
htmlyellow
htmllime
htmlmagenta
htmlwhite
htmlsilver
htmlgray
htmlolive
htmlorange
htmlmaroon
htmlgreen
htmlblack
#>
Function WriteHTMLLine
#Function created by Ken Avram
#Function created to make output to HTML easy in this script
{
Param([int]$style=0,
[int]$tabs = 0,
[string]$name = '',
[string]$value = '',
[string]$fontName="Calibri",
[int]$fontSize=1,
[int]$options=$htmlblack)
#Build output style
[string]$output = ""
If([String]::IsNullOrEmpty($Name))
{
$HTMLBody = "<p></p>"
}
Else
{
$color = CheckHTMLColor $options
#build # of tabs
While($tabs -gt 0)
{
$output += "&nbsp;&nbsp;&nbsp;&nbsp;"; $tabs--;
}
$HTMLFontName = $fontName
$HTMLBody = ""
If($options -band $htmlitalics)
{
$HTMLBody += "<i>"
}
If($options -band $htmlbold)
{
$HTMLBody += "<b>"
}
#output the rest of the parameters.
$output += $name + $value
$HTMLBody += "<font face='" + $HTMLFontName + "' " + "color='" + $color + "' size='" + $fontsize + "'>"
Switch ($style)
{
1 {$HTMLStyle = "<h1>"}
2 {$HTMLStyle = "<h2>"}
3 {$HTMLStyle = "<h3>"}
4 {$HTMLStyle = "<h4>"}
Default {$HTMLStyle = ""}
}
$HTMLBody += $HTMLStyle + $output
Switch ($style)
{
1 {$HTMLStyle = "</h1>"}
2 {$HTMLStyle = "</h2>"}
3 {$HTMLStyle = "</h3>"}
4 {$HTMLStyle = "</h4>"}
Default {$HTMLStyle = ""}
}
$HTMLBody += $HTMLStyle + "</font>"
If($options -band $htmlitalics)
{
$HTMLBody += "</i>"
}
If($options -band $htmlbold)
{
$HTMLBody += "</b>"
}
}
#echo $HTMLBody >> $FileName1
out-file -FilePath $Script:FileName1 -Append -InputObject $HTMLBody 4>$Null
}
#endregion
#region Iain's Word table functions
<#
.Synopsis
Add a table to a Microsoft Word document
.DESCRIPTION
This function adds a table to a Microsoft Word document from either an array of
Hashtables or an array of PSCustomObjects.
Using this function is quicker than setting each table cell individually but can
only utilise the built-in MS Word table autoformats. Individual tables cells can
be altered after the table has been appended to the document (a table reference
is returned).
.EXAMPLE
AddWordTable -Hashtable $HashtableArray
This example adds table to the MS Word document, utilising all key/value pairs in
the array of hashtables. Column headers will display the key names as defined.
Note: the columns might not be displayed in the order that they were defined. To
ensure columns are displayed in the required order utilise the -Columns parameter.
.EXAMPLE
AddWordTable -Hashtable $HashtableArray -List
This example adds table to the MS Word document, utilising all key/value pairs in
the array of hashtables. No column headers will be added, in a ListView format.
Note: the columns might not be displayed in the order that they were defined. To
ensure columns are displayed in the required order utilise the -Columns parameter.
.EXAMPLE
AddWordTable -CustomObject $PSCustomObjectArray
This example adds table to the MS Word document, utilising all note property names
the array of PSCustomObjects. Column headers will display the note property names.
Note: the columns might not be displayed in the order that they were defined. To
ensure columns are displayed in the required order utilise the -Columns parameter.
.EXAMPLE
AddWordTable -Hashtable $HashtableArray -Columns FirstName,LastName,EmailAddress
This example adds a table to the MS Word document, but only using the specified
key names: FirstName, LastName and EmailAddress. If other keys are present in the
array of Hashtables they will be ignored.
.EXAMPLE
AddWordTable -CustomObject $PSCustomObjectArray -Columns FirstName,LastName,EmailAddress -Headers "First Name","Last Name","Email Address"
This example adds a table to the MS Word document, but only using the specified
PSCustomObject note properties: FirstName, LastName and EmailAddress. If other note
properties are present in the array of PSCustomObjects they will be ignored. The
display names for each specified column header has been overridden to display a
custom header. Note: the order of the header names must match the specified columns.
#>
Function AddWordTable
{
[CmdletBinding()]
Param
(
# Array of Hashtable (including table headers)
[Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True, ParameterSetName='Hashtable', Position=0)]
[ValidateNotNullOrEmpty()] [System.Collections.Hashtable[]] $Hashtable,
# Array of PSCustomObjects
[Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True, ParameterSetName='CustomObject', Position=0)]
[ValidateNotNullOrEmpty()] [PSCustomObject[]] $CustomObject,
# Array of Hashtable key names or PSCustomObject property names to include, in display order.
# If not supplied then all Hashtable keys or all PSCustomObject properties will be displayed.
[Parameter(ValueFromPipelineByPropertyName=$True)] [AllowNull()] [string[]] $Columns = $Null,
# Array of custom table header strings in display order.
[Parameter(ValueFromPipelineByPropertyName=$True)] [AllowNull()] [string[]] $Headers = $Null,
# AutoFit table behavior.
[Parameter(ValueFromPipelineByPropertyName=$True)] [AllowNull()] [int] $AutoFit = -1,
# List view (no headers)
[Switch] $List,
# Grid lines
[Switch] $NoGridLines,
[Switch] $NoInternalGridLines,
# Built-in Word table formatting style constant
# Would recommend only $wdTableFormatContempory for normal usage (possibly $wdTableFormatList5 for List view)
[Parameter(ValueFromPipelineByPropertyName=$True)] [int] $Format = 0
)
Begin
{
Write-Debug ("Using parameter set '{0}'" -f $PSCmdlet.ParameterSetName);
## Check if -Columns wasn't specified but -Headers were (saves some additional parameter sets!)
If(($Columns -eq $Null) -and ($Headers -ne $Null))
{
Write-Warning "No columns specified and therefore, specified headers will be ignored.";
$Columns = $Null;
}
ElseIf(($Columns -ne $Null) -and ($Headers -ne $Null))
{
## Check if number of specified -Columns matches number of specified -Headers
If($Columns.Length -ne $Headers.Length)
{
Write-Error "The specified number of columns does not match the specified number of headers.";
}
} ## end elseif
} ## end Begin
Process
{
## Build the Word table data string to be converted to a range and then a table later.
[System.Text.StringBuilder] $WordRangeString = New-Object System.Text.StringBuilder;
Switch ($PSCmdlet.ParameterSetName)
{
'CustomObject'
{
If($Columns -eq $Null)
{
## Build the available columns from all availble PSCustomObject note properties
[string[]] $Columns = @();
## Add each NoteProperty name to the array
ForEach($Property in ($CustomObject | Get-Member -MemberType NoteProperty))
{
$Columns += $Property.Name;
}
}
## Add the table headers from -Headers or -Columns (except when in -List(view)
If(-not $List)
{
Write-Debug ("$(Get-Date): `t`tBuilding table headers");
If($Headers -ne $Null)
{
[ref] $Null = $WordRangeString.AppendFormat("{0}`n", [string]::Join("`t", $Headers));
}
Else
{
[ref] $Null = $WordRangeString.AppendFormat("{0}`n", [string]::Join("`t", $Columns));
}
}
## Iterate through each PSCustomObject
Write-Debug ("$(Get-Date): `t`tBuilding table rows");
ForEach($Object in $CustomObject)
{
$OrderedValues = @();
## Add each row item in the specified order
ForEach($Column in $Columns)
{
$OrderedValues += $Object.$Column;
}
## Use the ordered list to add each column in specified order
[ref] $Null = $WordRangeString.AppendFormat("{0}`n", [string]::Join("`t", $OrderedValues));
} ## end foreach
Write-Debug ("$(Get-Date): `t`t`tAdded '{0}' table rows" -f ($CustomObject.Count));
} ## end CustomObject
Default
{ ## Hashtable
If($Columns -eq $Null)
{
## Build the available columns from all available hashtable keys. Hopefully
## all Hashtables have the same keys (they should for a table).
$Columns = $Hashtable[0].Keys;
}
## Add the table headers from -Headers or -Columns (except when in -List(view)
If(-not $List)
{
Write-Debug ("$(Get-Date): `t`tBuilding table headers");
If($Headers -ne $Null)
{
[ref] $Null = $WordRangeString.AppendFormat("{0}`n", [string]::Join("`t", $Headers));
}
Else
{
[ref] $Null = $WordRangeString.AppendFormat("{0}`n", [string]::Join("`t", $Columns));
}
}
## Iterate through each Hashtable
Write-Debug ("$(Get-Date): `t`tBuilding table rows");
ForEach($Hash in $Hashtable)
{
$OrderedValues = @();
## Add each row item in the specified order
ForEach($Column in $Columns)
{
$OrderedValues += $Hash.$Column;
}
## Use the ordered list to add each column in specified order
[ref] $Null = $WordRangeString.AppendFormat("{0}`n", [string]::Join("`t", $OrderedValues));
} ## end foreach
Write-Debug ("$(Get-Date): `t`t`tAdded '{0}' table rows" -f $Hashtable.Count);
} ## end default
} ## end switch
## Create a MS Word range and set its text to our tab-delimited, concatenated string
Write-Debug ("$(Get-Date): `t`tBuilding table range");
$WordRange = $Script:Doc.Application.Selection.Range;
$WordRange.Text = $WordRangeString.ToString();
## Create hash table of named arguments to pass to the ConvertToTable method
$ConvertToTableArguments = @{ Separator = [Microsoft.Office.Interop.Word.WdTableFieldSeparator]::wdSeparateByTabs; }
## Negative built-in styles are not supported by the ConvertToTable method
If($Format -ge 0)
{
$ConvertToTableArguments.Add("Format", $Format);
$ConvertToTableArguments.Add("ApplyBorders", $True);
$ConvertToTableArguments.Add("ApplyShading", $True);
$ConvertToTableArguments.Add("ApplyFont", $True);
$ConvertToTableArguments.Add("ApplyColor", $True);
If(!$List)
{
$ConvertToTableArguments.Add("ApplyHeadingRows", $True);
}
$ConvertToTableArguments.Add("ApplyLastRow", $True);
$ConvertToTableArguments.Add("ApplyFirstColumn", $True);
$ConvertToTableArguments.Add("ApplyLastColumn", $True);
}
## Invoke ConvertToTable method - with named arguments - to convert Word range to a table
## See http://msdn.microsoft.com/en-us/library/office/aa171893(v=office.11).aspx
Write-Debug ("$(Get-Date): `t`tConverting range to table");
## Store the table reference just in case we need to set alternate row coloring
$WordTable = $WordRange.GetType().InvokeMember(
"ConvertToTable", # Method name
[System.Reflection.BindingFlags]::InvokeMethod, # Flags
$Null, # Binder
$WordRange, # Target (self!)
([Object[]]($ConvertToTableArguments.Values)), ## Named argument values
$Null, # Modifiers
$Null, # Culture
([String[]]($ConvertToTableArguments.Keys)) ## Named argument names
);
## Implement grid lines (will wipe out any existing formatting
If($Format -lt 0)
{
Write-Debug ("$(Get-Date): `t`tSetting table format");
$WordTable.Style = $Format;
}
## Set the table autofit behavior
If($AutoFit -ne -1)
{
$WordTable.AutoFitBehavior($AutoFit);
}
If(!$List)
{
#the next line causes the heading row to flow across page breaks
$WordTable.Rows.First.Headingformat = $wdHeadingFormatTrue;
}
If(!$NoGridLines)
{
$WordTable.Borders.InsideLineStyle = $wdLineStyleSingle;
$WordTable.Borders.OutsideLineStyle = $wdLineStyleSingle;
}
If($NoGridLines)
{
$WordTable.Borders.InsideLineStyle = $wdLineStyleNone;
$WordTable.Borders.OutsideLineStyle = $wdLineStyleNone;
}
If($NoInternalGridLines)
{
$WordTable.Borders.InsideLineStyle = $wdLineStyleNone;
$WordTable.Borders.OutsideLineStyle = $wdLineStyleSingle;
}
Return $WordTable;
} ## end Process
}
<#
.Synopsis
Sets the format of one or more Word table cells
.DESCRIPTION
This function sets the format of one or more table cells, either from a collection
of Word COM object cell references, an individual Word COM object cell reference or
a hashtable containing Row and Column information.
The font name, font size, bold, italic , underline and shading values can be used.
.EXAMPLE
SetWordCellFormat -Hashtable $Coordinates -Table $TableReference -Bold
This example sets all text to bold that is contained within the $TableReference
Word table, using an array of hashtables. Each hashtable contain a pair of co-
ordinates that is used to select the required cells. Note: the hashtable must
contain the .Row and .Column key names. For example:
@ { Row = 7; Column = 3 } to set the cell at row 7 and column 3 to bold.
.EXAMPLE
$RowCollection = $Table.Rows.First.Cells
SetWordCellFormat -Collection $RowCollection -Bold -Size 10
This example sets all text to size 8 and bold for all cells that are contained
within the first row of the table.
Note: the $Table.Rows.First.Cells returns a collection of Word COM cells objects
that are in the first table row.
.EXAMPLE
$ColumnCollection = $Table.Columns.Item(2).Cells
SetWordCellFormat -Collection $ColumnCollection -BackgroundColor 255
This example sets the background (shading) of all cells in the table's second
column to red.
Note: the $Table.Columns.Item(2).Cells returns a collection of Word COM cells objects
that are in the table's second column.
.EXAMPLE
SetWordCellFormat -Cell $Table.Cell(17,3) -Font "Tahoma" -Color 16711680
This example sets the font to Tahoma and the text color to blue for the cell located
in the table's 17th row and 3rd column.
Note: the $Table.Cell(17,3) returns a single Word COM cells object.
#>
Function SetWordCellFormat
{
[CmdletBinding(DefaultParameterSetName='Collection')]
Param (
# Word COM object cell collection reference
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName='Collection', Position=0)] [ValidateNotNullOrEmpty()] $Collection,
# Word COM object individual cell reference
[Parameter(Mandatory=$true, ParameterSetName='Cell', Position=0)] [ValidateNotNullOrEmpty()] $Cell,
# Hashtable of cell co-ordinates
[Parameter(Mandatory=$true, ParameterSetName='Hashtable', Position=0)] [ValidateNotNullOrEmpty()] [System.Collections.Hashtable[]] $Coordinates,
# Word COM object table reference
[Parameter(Mandatory=$true, ParameterSetName='Hashtable', Position=1)] [ValidateNotNullOrEmpty()] $Table,
# Font name
[Parameter()] [AllowNull()] [string] $Font = $null,
# Font color
[Parameter()] [AllowNull()] $Color = $null,
# Font size
[Parameter()] [ValidateNotNullOrEmpty()] [int] $Size = 0,
# Cell background color
[Parameter()] [AllowNull()] $BackgroundColor = $null,
# Force solid background color
[Switch] $Solid,
[Switch] $Bold,
[Switch] $Italic,
[Switch] $Underline
)
Begin
{
Write-Debug ("Using parameter set '{0}'." -f $PSCmdlet.ParameterSetName);
}
Process
{
Switch ($PSCmdlet.ParameterSetName)
{
'Collection' {
ForEach($Cell in $Collection)
{
If($BackgroundColor -ne $null) { $Cell.Shading.BackgroundPatternColor = $BackgroundColor; }
If($Bold) { $Cell.Range.Font.Bold = $true; }
If($Italic) { $Cell.Range.Font.Italic = $true; }
If($Underline) { $Cell.Range.Font.Underline = 1; }
If($Font -ne $null) { $Cell.Range.Font.Name = $Font; }
If($Color -ne $null) { $Cell.Range.Font.Color = $Color; }
If($Size -ne 0) { $Cell.Range.Font.Size = $Size; }
If($Solid) { $Cell.Shading.Texture = 0; } ## wdTextureNone
} # end foreach
} # end Collection
'Cell'
{
If($Bold) { $Cell.Range.Font.Bold = $true; }
If($Italic) { $Cell.Range.Font.Italic = $true; }
If($Underline) { $Cell.Range.Font.Underline = 1; }
If($Font -ne $null) { $Cell.Range.Font.Name = $Font; }
If($Color -ne $null) { $Cell.Range.Font.Color = $Color; }
If($Size -ne 0) { $Cell.Range.Font.Size = $Size; }
If($BackgroundColor -ne $null) { $Cell.Shading.BackgroundPatternColor = $BackgroundColor; }
If($Solid) { $Cell.Shading.Texture = 0; } ## wdTextureNone
} # end Cell
'Hashtable'
{
ForEach($Coordinate in $Coordinates)
{
$Cell = $Table.Cell($Coordinate.Row, $Coordinate.Column);
If($Bold) { $Cell.Range.Font.Bold = $true; }
If($Italic) { $Cell.Range.Font.Italic = $true; }
If($Underline) { $Cell.Range.Font.Underline = 1; }
If($Font -ne $null) { $Cell.Range.Font.Name = $Font; }
If($Color -ne $null) { $Cell.Range.Font.Color = $Color; }
If($Size -ne 0) { $Cell.Range.Font.Size = $Size; }
If($BackgroundColor -ne $null) { $Cell.Shading.BackgroundPatternColor = $BackgroundColor; }
If($Solid) { $Cell.Shading.Texture = 0; } ## wdTextureNone
}
} # end Hashtable
} # end switch
} # end process
}
<#
.Synopsis
Sets alternate row colors in a Word table
.DESCRIPTION
This function sets the format of alternate rows within a Word table using the
specified $BackgroundColor. This function is expensive (in performance terms) as
it recursively sets the format on alternate rows. It would be better to pick one
of the predefined table formats (if one exists)? Obviously the more rows, the
longer it takes :'(
Note: this function is called by the AddWordTable function if an alternate row
format is specified.
.EXAMPLE
SetWordTableAlternateRowColor -Table $TableReference -BackgroundColor 255
This example sets every-other table (starting with the first) row and sets the
background color to red (wdColorRed).
.EXAMPLE
SetWordTableAlternateRowColor -Table $TableReference -BackgroundColor 39423 -Seed Second
This example sets every other table (starting with the second) row and sets the
background color to light orange (weColorLightOrange).
#>
Function SetWordTableAlternateRowColor
{
[CmdletBinding()]
Param (
# Word COM object table reference
[Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)] [ValidateNotNullOrEmpty()] $Table,
# Alternate row background color
[Parameter(Mandatory=$true, Position=1)] [ValidateNotNull()] [int] $BackgroundColor,
# Alternate row starting seed
[Parameter(ValueFromPipelineByPropertyName=$true, Position=2)] [ValidateSet('First','Second')] [string] $Seed = 'First'
)
Process
{
$StartDateTime = Get-Date;
Write-Debug ("{0}: `t`tSetting alternate table row colors.." -f $StartDateTime);
## Determine the row seed (only really need to check for 'Second' and default to 'First' otherwise
If($Seed.ToLower() -eq 'second')
{
$StartRowIndex = 2;
}
Else
{
$StartRowIndex = 1;
}
For($AlternateRowIndex = $StartRowIndex; $AlternateRowIndex -lt $Table.Rows.Count; $AlternateRowIndex += 2)
{
$Table.Rows.Item($AlternateRowIndex).Shading.BackgroundPatternColor = $BackgroundColor;
}
## I've put verbose calls in here we can see how expensive this functionality actually is.
$EndDateTime = Get-Date;
$ExecutionTime = New-TimeSpan -Start $StartDateTime -End $EndDateTime;
Write-Debug ("{0}: `t`tDone setting alternate row style color in '{1}' seconds" -f $EndDateTime, $ExecutionTime.TotalSeconds);
}
}
#endregion
#region general script functions
Function ShowScriptOptions
{
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): Company Name : $($Script:CoName)"
Write-Verbose "$(Get-Date): Cover Page : $($CoverPage)"
Write-Verbose "$(Get-Date): User Name : $($UserName)"
Write-Verbose "$(Get-Date): Save As PDF : $($PDF)"
Write-Verbose "$(Get-Date): Save As TEXT : $($TEXT)"
Write-Verbose "$(Get-Date): Save As WORD : $($MSWORD)"
Write-Verbose "$(Get-Date): Save As HTML : $($HTML)"
Write-Verbose "$(Get-Date): Add DateTime : $($AddDateTime)"
Write-Verbose "$(Get-Date): HW Inventory : $($Hardware)"
Write-Verbose "$(Get-Date): Filename1 : $($Script:FileName1)"
If($PDF)
{
Write-Verbose "$(Get-Date): Filename2 : $($Script:FileName2)"
}
Write-Verbose "$(Get-Date): OS Detected : $($RunningOS)"
Write-Verbose "$(Get-Date): PSUICulture : $($PSUICulture)"
Write-Verbose "$(Get-Date): PSCulture : $($PSCulture)"
Write-Verbose "$(Get-Date): Word version : $($Script:WordProduct)"
Write-Verbose "$(Get-Date): Word language: $($Script:WordLanguageValue)"
Write-Verbose "$(Get-Date): PoSH version : $($Host.Version)"
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): Script start : $($Script:StartTime)"
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): "
}
Function validStateProp( [object] $object, [string] $topLevel, [string] $secondLevel )
{
#function created 8-jan-2014 by Michael B. Smith
if( $object )
{
If( ( gm -Name $topLevel -InputObject $object ) )
{
If( ( gm -Name $secondLevel -InputObject $object.$topLevel ) )
{
Return $True
}
}
}
Return $False
}
Function SaveandCloseDocumentandShutdownWord
{
#bug fix 1-Apr-2014
#reset Grammar and Spelling options back to their original settings
$Script:Word.Options.CheckGrammarAsYouType = $Script:CurrentGrammarOption
$Script:Word.Options.CheckSpellingAsYouType = $Script:CurrentSpellingOption
Write-Verbose "$(Get-Date): Save and Close document and Shutdown Word"
If($Script:WordVersion -eq $wdWord2010)
{
#the $saveFormat below passes StrictMode 2
#I found this at the following two links
#http://blogs.technet.com/b/bshukla/archive/2011/09/27/3347395.aspx
#http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.wdsaveformat(v=office.14).aspx
If($PDF)
{
Write-Verbose "$(Get-Date): Saving as DOCX file first before saving to PDF"
}
Else
{
Write-Verbose "$(Get-Date): Saving DOCX file"
}
If($AddDateTime)
{
$Script:FileName1 += "_$(Get-Date -f yyyy-MM-dd_HHmm).docx"
If($PDF)
{
$Script:FileName2 += "_$(Get-Date -f yyyy-MM-dd_HHmm).pdf"
}
}
Write-Verbose "$(Get-Date): Running Word 2010 and detected operating system $($RunningOS)"
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatDocumentDefault")
$Script:Doc.SaveAs([REF]$Script:FileName1, [ref]$SaveFormat)
If($PDF)
{
Write-Verbose "$(Get-Date): Now saving as PDF"
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatPDF")
$Script:Doc.SaveAs([REF]$Script:FileName2, [ref]$saveFormat)
}
}
ElseIf($Script:WordVersion -eq $wdWord2013)
{
If($PDF)
{
Write-Verbose "$(Get-Date): Saving as DOCX file first before saving to PDF"
}
Else
{
Write-Verbose "$(Get-Date): Saving DOCX file"
}
If($AddDateTime)
{
$Script:FileName1 += "_$(Get-Date -f yyyy-MM-dd_HHmm).docx"
If($PDF)
{
$Script:FileName2 += "_$(Get-Date -f yyyy-MM-dd_HHmm).pdf"
}
}
Write-Verbose "$(Get-Date): Running Word 2013 and detected operating system $($RunningOS)"
$Script:Doc.SaveAs2([REF]$Script:FileName1, [ref]$wdFormatDocumentDefault)
If($PDF)
{
Write-Verbose "$(Get-Date): Now saving as PDF"
$Script:Doc.SaveAs([REF]$Script:FileName2, [ref]$wdFormatPDF)
}
}
Write-Verbose "$(Get-Date): Closing Word"
$Script:Doc.Close()
$Script:Word.Quit()
If($PDF)
{
Write-Verbose "$(Get-Date): Deleting $($Script:FileName1) since only $($Script:FileName2) is needed"
Remove-Item $Script:FileName1 4>$Null
}
Write-Verbose "$(Get-Date): System Cleanup"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Script:Word) | Out-Null
If(Test-Path variable:global:word)
{
Remove-Variable -Name word -Scope Global 4>$Null
}
$SaveFormat = $Null
[gc]::collect()
[gc]::WaitForPendingFinalizers()
}
Function SaveandCloseTextDocument
{
If($AddDateTime)
{
$Script:FileName1 += "_$(Get-Date -f yyyy-MM-dd_HHmm).txt"
}
Write-Output $Global:Output | Out-File $Script:Filename1 4>$Null
}
Function SaveandCloseHTMLDocument
{
#echo "<p></p></body></html>" >> $FileName1
out-file -FilePath $Script:FileName1 -Append -InputObject "<p></p></body></html>" 4>$Null
}
Function SetFileName1andFileName2
{
Param([string]$OutputFileName)
$pwdpath = $pwd.Path
If($pwdpath.EndsWith("\"))
{
#remove the trailing \
$pwdpath = $pwdpath.SubString(0, ($pwdpath.Length - 1))
}
#set $filename1 and $filename2 with no file extension
If($AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName)"
If($PDF)
{
[string]$Script:FileName2 = "$($pwdpath)\$($OutputFileName)"
}
}
If($MSWord -or $PDF)
{
CheckWordPreReq
If(!$AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName).docx"
If($PDF)
{
[string]$Script:FileName2 = "$($pwdpath)\$($OutputFileName).pdf"
}
}
SetupWord
}
ElseIf($Text)
{
If(!$AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName).txt"
}
}
ElseIf($HTML)
{
If(!$AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName).html"
}
SetupHTML
}
}
Function TestComputerName
{
Param([string]$Cname)
If(![String]::IsNullOrEmpty($CName))
{
#get computer name
#first test to make sure the computer is reachable
Write-Verbose "$(Get-Date): Testing to see if $($CName) is online and reachable"
If(Test-Connection -ComputerName $CName -quiet)
{
Write-Verbose "$(Get-Date): Server $($CName) is online."
}
Else
{
Write-Verbose "$(Get-Date): Computer $($CName) is offline"
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tComputer $($CName) is offline.`nScript cannot continue.`n`n"
Exit
}
}
#if computer name is localhost, get actual computer name
If($CName -eq "localhost")
{
$CName = $env:ComputerName
Write-Verbose "$(Get-Date): Computer name has been renamed from localhost to $($CName)"
Return $CName
}
#if computer name is an IP address, get host name from DNS
#http://blogs.technet.com/b/gary/archive/2009/08/29/resolve-ip-addresses-to-hostname-using-powershell.aspx
#help from Michael B. Smith
$ip = $CName -as [System.Net.IpAddress]
If($ip)
{
$Result = [System.Net.Dns]::gethostentry($ip)
If($? -and $Result -ne $Null)
{
$CName = $Result.HostName
Write-Verbose "$(Get-Date): Computer name has been renamed from $($ip) to $($CName)"
Return $CName
}
Else
{
Write-Warning "Unable to resolve $($CName) to a hostname"
}
}
Else
{
#computer is online but for some reason $ComputerName cannot be converted to a System.Net.IpAddress
}
Return $CName
}
Function ProcessDocumentOutput
{
If($MSWORD -or $PDF)
{
SaveandCloseDocumentandShutdownWord
}
ElseIf($Text)
{
SaveandCloseTextDocument
}
ElseIf($HTML)
{
SaveandCloseHTMLDocument
}
If($PDF)
{
If(Test-Path "$($Script:FileName2)")
{
Write-Verbose "$(Get-Date): $($Script:FileName2) is ready for use"
}
Else
{
Write-Warning "$(Get-Date): Unable to save the output file, $($Script:FileName2)"
Write-Error "Unable to save the output file, $($Script:FileName2)"
}
}
Else
{
If(Test-Path "$($Script:FileName1)")
{
Write-Verbose "$(Get-Date): $($Script:FileName1) is ready for use"
}
Else
{
Write-Warning "$(Get-Date): Unable to save the output file, $($Script:FileName1)"
Write-Error "Unable to save the output file, $($Script:FileName1)"
}
}
}
Function AbortScript
{
If($MSWord -or $PDF)
{
$Script:Word.quit()
Write-Verbose "$(Get-Date): System Cleanup"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Script:Word) | Out-Null
If(Test-Path variable:global:word)
{
Remove-Variable -Name word -Scope Global
}
}
[gc]::collect()
[gc]::WaitForPendingFinalizers()
Write-Verbose "$(Get-Date): Script has been aborted"
$ErrorActionPreference = $SaveEAPreference
Exit
}
#endregion
#region script setup function
Function ProcessScriptSetup
{
$script:startTime = Get-Date
$ComputerName = TestComputerName $ComputerName
}
#endregion
#region script core
#Script begins
ProcessScriptSetup
###REPLACE AFTER THIS SECTION WITH YOUR SCRIPT###
###The function SetFileName1andFileName2 needs your script output filename###
SetFileName1andFileName2 'InventoryScript'
###change title for your report###
[string]$Script:Title = 'System Center 2012 R2 Configuration Manager Documentation Script for {0}' -f $CompanyName;
###REPLACE AFTER THIS SECTION WITH YOUR SCRIPT###
Function Read-ScheduleToken {
$SMS_ScheduleMethods = 'SMS_ScheduleMethods'
$class_SMS_ScheduleMethods = [wmiclass]''
$class_SMS_ScheduleMethods.psbase.Path ="ROOT\SMS\Site_$($SiteCode):$($SMS_ScheduleMethods)"
$script:ScheduleString = $class_SMS_ScheduleMethods.ReadFromString($ServiceWindow.ServiceWindowSchedules)
return $ScheduleString
}
Function Convert-WeekDay {
[CmdletBinding()]
param (
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$Day
)
### day of week
switch ($Day)
{
1 {$weekday = 'Sunday'}
2 {$weekday = 'Monday'}
3 {$weekday = 'Tuesday'}
4 {$weekday = 'Wednesday'}
5 {$weekday = 'Thursday'}
6 {$weekday = 'Friday'}
7 {$weekday = 'Saturday'}
}
return $weekday
}
Function Convert-Time {
param (
[int]$time
)
$min = $time % 60
if ($min -le 9) {$min = "0$($min)" }
$hrs = [Math]::Truncate($time/60)
$NewTime = "$($hrs):$($min)"
return $NewTime
}
Function Get-SiteCode
{
$wqlQuery = 'SELECT * FROM SMS_ProviderLocation'
$a = Get-WmiObject -Query $wqlQuery -Namespace 'root\sms' -ComputerName $SMSProvider
$a | ForEach-Object {
if($_.ProviderForLocalSite)
{
$script:SiteCode = $_.SiteCode
}
}
return $SiteCode
}
function Get-ExecuteWqlQuery
{
param
(
[System.Object]
$siteServerName,
[System.Object]
$query
)
$returnValue = $null
$connectionManager = New-Object Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine.WqlConnectionManager
if($connectionManager.Connect($siteServerName))
{
$result = $connectionManager.QueryProcessor.ExecuteQuery($query)
foreach($i in $result.GetEnumerator())
{
$returnValue = $i
break
}
$connectionManager.Dispose()
}
$returnValue
}
function Get-ApplicationObjectFromServer
{
param
(
[System.Object]
$appName,
[System.Object]
$siteServerName
)
$resultObject = Get-ExecuteWqlQuery $siteServerName 'select thissitecode from sms_identification'
$siteCode = $resultObject['thissitecode'].StringValue
$path = [string]::Format('\\{0}\ROOT\sms\site_{1}', $siteServerName, $siteCode)
$scope = New-Object System.Management.ManagementScope -ArgumentList $path
$query = [string]::Format("select * from sms_application where LocalizedDisplayName='{0}' AND ISLatest='true'", $appName.Trim())
$oQuery = New-Object System.Management.ObjectQuery -ArgumentList $query
$obectSearcher = New-Object System.Management.ManagementObjectSearcher -ArgumentList $scope,$oQuery
$applicationFoundInCollection = $obectSearcher.Get()
$applicationFoundInCollectionEnumerator = $applicationFoundInCollection.GetEnumerator()
if($applicationFoundInCollectionEnumerator.MoveNext())
{
$returnValue = $applicationFoundInCollectionEnumerator.Current
$getResult = $returnValue.Get()
$sdmPackageXml = $returnValue.Properties['SDMPackageXML'].Value.ToString()
[Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($sdmPackageXml)
}
}
function Load-ConfigMgrAssemblies()
{
$AdminConsoleDirectory = Split-Path $env:SMS_ADMIN_UI_PATH -Parent
$filesToLoad = 'Microsoft.ConfigurationManagement.ApplicationManagement.dll','AdminUI.WqlQueryEngine.dll', 'AdminUI.DcmObjectWrapper.dll'
Set-Location $AdminConsoleDirectory
[System.IO.Directory]::SetCurrentDirectory($AdminConsoleDirectory)
foreach($fileName in $filesToLoad)
{
$fullAssemblyName = [System.IO.Path]::Combine($AdminConsoleDirectory, $fileName)
if([System.IO.File]::Exists($fullAssemblyName ))
{
$FileLoaded = [Reflection.Assembly]::LoadFrom($fullAssemblyName )
}
else
{
Write-Output ([System.String]::Format('File not found {0}',$fileName )) -backgroundcolor 'red'
}
}
}
$SiteCode = Get-SiteCode
Write-Verbose "$(Get-Date): Start writing report data"
$LocationBeforeExecution = Get-Location
$Script:selection.InsertNewPage() | Out-Null
#Import the CM12 Powershell cmdlets
if (-not (Test-Path -Path $SiteCode))
{
Write-Verbose "$(Get-Date): CM12 module has not been imported yet, will import it now."
Import-Module ($env:SMS_ADMIN_UI_PATH.Substring(0,$env:SMS_ADMIN_UI_PATH.Length5) + '\ConfigurationManager.psd1') | Out-Null
}
#CM12 cmdlets need to be run from the CM12 drive
Set-Location "$($SiteCode):" | Out-Null
if (-not (Get-PSDrive -Name $SiteCode))
{
Write-Error "There was a problem loading the Configuration Manager powershell module and accessing the site's PSDrive."
exit 1
}
#### Administration
#### Site Configuration
WriteWordLine 1 0 'Summary of all Sites in this Hierarchy'
Write-Verbose "$(Get-Date): Getting Site Information"
$CMSites = Get-CMSite
$CAS = $CMSites | Where-Object {$_.Type -eq 4}
$ChildPrimarySites = $CMSites | Where-Object {$_.Type -eq 3}
$StandAlonePrimarySite = $CMSites | Where-Object {$_.Type -eq 2}
$SecondarySites = $CMSites | Where-Object {$_.Type -eq 1}
#region CAS
if (-not [string]::IsNullOrEmpty($CAS))
{
WriteWordLine 0 1 'The following Central Administration Site is installed:'
$CAS = @{'Site Name' = $CAS.SiteName; 'Site Code' = $CAS.SiteCode; Version = $CAS.Version };
$Table = AddWordTable -Hashtable $CAS -Format -155 -AutoFit $wdAutoFitFixed;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
## IB - set column widths without recursion
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 170;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
$Table.AutoFitBehavior($wdAutoFitFixed)
FindWordDocumentEnd
$Table = $Null
}
else {
WriteWordLine 0 1 'No' -nonewline
WriteWordLine 0 0 ' CAS' -boldface $true -nonewline
WriteWordLine 0 1 ' detected. Continue with Primary Sites.'
}
#endregion CAS
#region Child Primary Sites
if (-not [string]::IsNullOrEmpty($ChildPrimarySites))
{
Write-Verbose "$(Get-Date): Enumerating all child Primary Site."
WriteWordLine 0 1 'The following child Primary Sites are installed:'
$StandAlonePrimarySite = @{'Site Name' = $ChildPrimarySites.SiteName; 'Site Code' = $ChildPrimarySites.SiteCode; Version = $ChildPrimarySites.Version };
$Table = AddWordTable -Hashtable $ChildPrimarySites -Format -155 -AutoFit $wdAutoFitFixed;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
## IB - set column widths without recursion
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 170;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
$Table.AutoFitBehavior($wdAutoFitFixed)
FindWordDocumentEnd
$Table = $Null
}
#endregion Child Primary Sites
#region Standalone Primary
if (-not [string]::IsNullOrEmpty($StandAlonePrimarySite))
{
Write-Verbose "$(Get-Date): Enumerating a standalone Primary Site."
WriteWordLine 0 1 'The following Primary Site is installed:'
$SiteCULevel = (Invoke-Command -ComputerName $(Get-CMSiteRole -RoleName 'SMS Site Server').NALPath.tostring().split('\\')[2] -ScriptBlock {Get-ItemProperty -Path registry::hklm\software\microsoft\sms\setup | Select-Object CULevel} -ErrorAction SilentlyContinue ).CULevel
$StandAlonePrimarySite = @{'Site Name' = $StandAlonePrimarySite.SiteName; 'Site Code' = $StandAlonePrimarySite.SiteCode; Version = $StandAlonePrimarySite.Version; 'CU Installed' = $SiteCULevel };
$Table = AddWordTable -Hashtable $StandAlonePrimarySite -Format -155 -AutoFit $wdAutoFitFixed;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
## IB - set column widths without recursion
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 170;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
$Table.AutoFitBehavior($wdAutoFitFixed)
FindWordDocumentEnd
$Table = $Null
}
#endregion Standalone Primary
#region Secondary Sites
if (-not [string]::IsNullOrEmpty($SecondarySites))
{
Write-Verbose "$(Get-Date): Enumerating all secondary sites."
WriteWordLine 0 1 'The following Secondary Sites are installed:'
$SecondarySites = @{'Site Name' = $SecondarySites.SiteName; 'Site Code' = $SecondarySites.SiteCode; Version = $SecondarySites.Version };
$Table = AddWordTable -Hashtable $SecondarySites -Format -155 -AutoFit $wdAutoFitFixed;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
## IB - set column widths without recursion
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 170;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
$Table.AutoFitBehavior($wdAutoFitFixed)
FindWordDocumentEnd
$Table = $Null
}
#endregion Secondary Sites
#region Site Configuration report
foreach ($CMSite in $CMSites)
{
Write-Verbose "$(Get-Date): Checking each site's configuration."
WriteWordLine 1 0 "Configuration Summary for Site $($CMSite.SiteCode)"
WriteWordLine 0 0 ''
$SiteRoleWordTable = @()
$SiteRoles = Get-CMSiteRole -SiteCode $CMSite.SiteCode | Select-Object -Property NALPath, rolename
WriteWordLine 2 0 'Site Roles'
WriteWordLine 0 1 'The following Site Roles are installed in this site:'
foreach ($SiteRole in $SiteRoles) {
if (-not (($SiteRole.rolename -eq 'SMS Component Server') -or ($SiteRole.rolename -eq 'SMS Site System'))) {
$SiteRoleRowHash = @{'Server Name' = ($SiteRole.NALPath).ToString().Split('\\')[2]; 'Role' = $SiteRole.RoleName}
$SiteRoleWordTable += $SiteRoleRowHash
}
}
$Table = AddWordTable -Hashtable $SiteRoleWordTable -Format -155 -AutoFit $wdAutoFitContent
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray1 -Underline -Italic
FindWordDocumentEnd
$Table = $Null
$SiteMaintenanceTaskWordTable = @()
$SiteMaintenanceTasks = Get-CMSiteMaintenanceTask -SiteCode $CMSite.SiteCode
WriteWordLine 2 0 "Site Maintenance Tasks for Site $($CMSite.SiteCode)"
foreach ($SiteMaintenanceTask in $SiteMaintenanceTasks) {
$SiteMaintenanceTaskRowHash = @{'Task Name' = $SiteMaintenanceTask.TaskName; Enabled = $SiteMaintenanceTask.Enabled};
$SiteMaintenanceTaskWordTable += $SiteMaintenanceTaskRowHash;
}
$Table = AddWordTable -Hashtable $SiteMaintenanceTaskWordTable -Format -155 -AutoFit $wdAutoFitContent;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
<#
## IB - set column widths without recursion
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 170;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
$Table.AutoFitBehavior($wdAutoFitFixed)
#>
FindWordDocumentEnd
$Table = $Null
$CMManagementPoints = Get-CMManagementPoint -SiteCode $CMSite.SiteCode
WriteWordLine 2 1 "Summary of Management Points for Site $($CMSite.SiteCode)"
foreach ($CMManagementPoint in $CMManagementPoints)
{
Write-Verbose "$(Get-Date): Management Point: $($CMManagementPoint)"
$CMMPServerName = $CMManagementPoint.NetworkOSPath.Split('\\')[2]
WriteWordLine 0 1 "$($CMMPServerName)"
}
WriteWordLine 2 1 "Summary of Distribution Points for Site $($CMSite.SiteCode)"
$CMDistributionPoints = Get-CMDistributionPoint -SiteCode $CMSite.SiteCode
foreach ($CMDistributionPoint in $CMDistributionPoints)
{
$CMDPServerName = $CMDistributionPoint.NetworkOSPath.Split('\\')[2]
Write-Verbose "$(Get-Date): Found DP: $($CMDPServerName)"
WriteWordLine 0 1 "$($CMDPServerName)" -boldface $true
Write-Verbose "Trying to ping $($CMDPServerName)"
$PingResult = Test-NetConnection -ComputerName $CMDPServerName
if (-not ($PingResult.PingSucceeded))
{
WriteWordLine 0 2 "The Distribution Point $($CMDPServerName) is not reachable. Check connectivity."
}
else
{
WriteWordLine 0 2 'Disk information:'
$CMDPDrives = (Get-WmiObject -Class SMS_DistributionPointDriveInfo -Namespace root\sms\site_$SiteCode -ComputerName $SMSProvider).Where({$PSItem.NALPath -like "*$CMDPServerName*"})
foreach ($CMDPDrive in $CMDPDrives)
{
WriteWordLine 0 2 "Partition $($CMDPDrive.Drive):" -boldface $true
$Size = ''
$Size = $CMDPDrive.BytesTotal / 1024 / 1024
$Freesize = ''
$Freesize = $CMDPDrive.BytesFree / 1024 / 1024
WriteWordLine 0 3 "$([MATH]::Round($Size,2)) GB Size in total"
WriteWordLine 0 3 "$([MATH]::Round($Freesize,2)) GB Free Space"
WriteWordLine 0 3 "Still $($CMDPDrive.PercentFree) percent free."
WriteWordLine 0 0 ''
}
WriteWordLine -style 0 -tabs 2 -value 'Hardware Info:' -boldface $true
try {
$Capacity = 0
Get-WmiObject -Class win32_physicalmemory -ComputerName $CMDPServerName | ForEach-Object {[int64]$Capacity = $Capacity + [int64]$_.Capacity}
$TotalMemory = $Capacity / 1024 / 1024 / 1024
WriteWordLine 0 3 "This server has a total of $($TotalMemory) GB RAM."
}
catch {
WriteWordLine 0 3 "Failed to access server $CMDPServerName."
}
}
$DPInfo = $CMDistributionPoint.Props
$IsPXE = ($DPInfo.Where({$_.PropertyName -eq 'IsPXE'})).Value
$UnknownMachines = ($DPInfo.Where({$_.PropertyName -eq 'SupportUnknownMachines'})).Value
switch ($IsPXE)
{
1
{
WriteWordLine 0 2 'PXE Enabled'
switch ($UnknownMachines)
{
1 { WriteWordLine 0 2 'Supports unknown machines: true' }
0 { WriteWordLine 0 2 'Supports unknown machines: false' }
}
}
0
{
WriteWordLine 0 2 'PXE disabled'
}
}
$DPGroupMembers = $Null
$DPGroupIDs = $Null
$DPGroupMembers = (Get-WmiObject -class SMS_DPGroupMembers -Namespace root\sms\site_$SiteCode -ComputerName $SMSProvider).Where({$_.DPNALPath -ilike "*$($CMDPServerName)*"});
if (-not [string]::IsNullOrEmpty($DPGroupMembers))
{
$DPGroupIDs = $DPGroupMembers.GroupID
}
#enumerating DP Group Membership
if (-not [string]::IsNullOrEmpty($DPGroupIDs))
{
WriteWordLine 0 1 'This Distribution Point is a member of the following DP Groups:'
foreach ($DPGroupID in $DPGroupIDs)
{
$DPGroupName = (Get-CMDistributionPointGroup -Id "$($DPGroupID)").Name
WriteWordLine 0 2 "$($DPGroupName)"
}
}
else
{
WriteWordLine 0 1 'This Distribution Point is not a member of any DP Group.'
}
}
#enumerating Software Update Points
Write-Verbose "$(Get-Date): Enumerating all Software Update Points"
WriteWordLine 2 1 "Summary of Software Update Point Servers for Site $($CMSite.SiteCode)"
$CMSUPs = Get-WmiObject -Class sms_sci_sysresuse -Namespace root\sms\site_$($CMSite.SiteCode) -ComputerName $CMMPServerName | Where-Object {$_.rolename -eq 'SMS Software Update Point'}
#$CMSUPs = (Get-CMSoftwareUpdatePoint).Where({$_.SiteCode -eq "$($CMSite.SiteCode)"})
if (-not [string]::IsNullOrEmpty($CMSUPs))
{
foreach ($CMSUP in $CMSUPs) {
$SUPHashTable = @();
$CMSUPServerName = $CMSUP.NetworkOSPath.split('\\')[2]
Write-Verbose "$(Get-Date): Found SUP: $($CMSUPServerName)"
WriteWordLine 0 1 "$($CMSUPServerName)"
foreach ($SUPProp in $CMSUP.Props) {
$SUPHash = @{Value2 = $SUPProp.Value2; Value1 = $SUPProp.Value1; Value = $SUPProp.Value; 'Property Name' = $SUPProp.PropertyName};
$SUPHashTable += $SUPHash;
}
$Table = AddWordTable -Hashtable $SUPHashTable -Format -155 -AutoFit $wdAutoFitFixed;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
## IB - set column widths without recursion
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 170;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
$Table.AutoFitBehavior($wdAutoFitFixed)
FindWordDocumentEnd
$Table = $Null
}
}
else
{
WriteWordLine 0 1 'This site has no Software Update Points installed.'
}
}
##### Hierarchy wide configuration
WriteWordLine 1 0 'Summary of Hierarchy Wide Configuration'
#region enumerating Boundaries
Write-Verbose "$(Get-Date): Enumerating all Site Boundaries"
WriteWordLine 2 0 'Summary of Site Boundaries'
$Boundaries = Get-CMBoundary
if (-not [string]::IsNullOrEmpty($Boundaries))
{
$SubnetHashTable = @();
$ADHashTable = @();
$IPv6HashTable = @();
$IPRangeHashTable = @();
foreach ($Boundary in $Boundaries) {
if ($Boundary.BoundaryType -eq 0) {
$BoundaryType = 'IP Subnet';
$NamesOfBoundarySiteSystems = $Null
if (-not [string]::IsNullOrEmpty($Boundary.SiteSystems))
{
ForEach-Object -Begin {$BoundarySiteSystems= $Boundary.SiteSystems} -Process {$NamesOfBoundarySiteSystems += $BoundarySiteSystems.split(',')} -End {$NamesOfBoundarySiteSystems} | Out-Null
}
else
{
$NamesOfBoundarySiteSystems = 'n/a'
}
$SubnetHash = @{'Boundary Type' = $BoundaryType;
'Default Site Code' = "$($Boundary.DefaultSiteCode)"
'Associated Site Systems' = "$NamesOfBoundarySiteSystems"
Description = $Boundary.DisplayName;
Value = $Boundary.Value;
}
$SubnetHashTable += $SubnetHash;
}
elseif ($Boundary.BoundaryType -eq 1) {
$BoundaryType = 'Active Directory Site';
$NamesOfBoundarySiteSystems = $Null
if (-not [string]::IsNullOrEmpty($Boundary.SiteSystems))
{
ForEach-Object -Begin {$BoundarySiteSystems= $Boundary.SiteSystems} -Process {$NamesOfBoundarySiteSystems += $BoundarySiteSystems.split(',')} -End {$NamesOfBoundarySiteSystems} | Out-Null
}
else
{
$NamesOfBoundarySiteSystems = 'n/a'
}
$ADHash = @{'Boundary Type' = $BoundaryType;
'Default Site Code' = "$($Boundary.DefaultSiteCode)"
'Associated Site Systems' = "$NamesOfBoundarySiteSystems";
Description = $Boundary.DisplayName;
Value = $Boundary.Value;
}
$ADHashTable += $ADHash;
}
elseif ($Boundary.BoundaryType -eq 2) {
$BoundaryType = 'IPv6 Prefix';
$NamesOfBoundarySiteSystems = $Null
if (-not [string]::IsNullOrEmpty($Boundary.SiteSystems))
{
ForEach-Object -Begin {$BoundarySiteSystems= $Boundary.SiteSystems} -Process {$NamesOfBoundarySiteSystems += $BoundarySiteSystems.split(',')} -End {$NamesOfBoundarySiteSystems} | Out-Null
}
else
{
$NamesOfBoundarySiteSystems = 'n/a'
}
$IPv6Hash = @{'Boundary Type' = $BoundaryType;
'Default Site Code' = "$($Boundary.DefaultSiteCode)"
'Associated Site Systems' = "$NamesOfBoundarySiteSystems";
Description = $Boundary.DisplayName;
Value = $Boundary.Value;
}
$IPv6HashTable += $IPv6Hash;
}
elseif ($Boundary.BoundaryType -eq 3)
{
$BoundaryType = 'IP Range';
$NamesOfBoundarySiteSystems = $Null
if (-not [string]::IsNullOrEmpty($Boundary.SiteSystems))
{
ForEach-Object -Begin {$BoundarySiteSystems= $Boundary.SiteSystems} -Process {$NamesOfBoundarySiteSystems += $BoundarySiteSystems.split(',')} -End {$NamesOfBoundarySiteSystems} | Out-Null
}
else
{
$NamesOfBoundarySiteSystems = 'n/a'
}
$IPRangeHash = @{'Boundary Type' = $BoundaryType
'Default Site Code' = "$($Boundary.DefaultSiteCode)"
'Associated Site Systems' = "$NamesOfBoundarySiteSystems"
Description = $Boundary.DisplayName
Value = $Boundary.Value
}
$IPRangeHashTable += $IPRangeHash
}
}
}
#region IPv6 Boundaries Table
$Table = AddWordTable -Hashtable $IPv6HashTable -Format -155 -AutoFit $wdAutoFitContent;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray1
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
#endregion IPv6 Boundaries Table
WriteWordLine 0 0 ''
WriteWordLine 0 0 ''
#region IP Subnet Boundaries Table
$Table = AddWordTable -Hashtable $SubnetHashTable -Format -155 -AutoFit $wdAutoFitContent
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
#endregion IP Subnet Boundaries Table
WriteWordLine 0 0 ''
WriteWordLine 0 0 ''
#region IP Range Boundaries Table
$Table = AddWordTable -Hashtable $IPRangeHashTable -Format -155 -AutoFit $wdAutoFitContent ;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
#endregion IP Range Boundaries Table
WriteWordLine 0 0 ''
WriteWordLine 0 0 ''
#region AD Site Boundaries Table
$Table = AddWordTable -Hashtable $ADHashTable -Format -155 -AutoFit $wdAutoFitContent;
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
#endregion AD Site Boundaries Table
WriteWordLine 0 0 ''
WriteWordLine 0 0 ''
#endregion enumerating Boundaries
#region enumerating all Boundary Groups and their members
Write-Verbose "$(Get-Date): Enumerating all Boundary Groups and their members"
$BoundaryGroups = Get-CMBoundaryGroup
WriteWordLine 2 0 'Summary of Site Boundary Groups'
$BoundaryGroupHashTable = @();
if (-not [string]::IsNullOrEmpty($BoundaryGroups))
{
foreach ($BoundaryGroup in $BoundaryGroups) {
$MemberNames = @();
if ($BoundaryGroup.SiteSystemCount -gt 0)
{
$MemberIDs = (Get-WmiObject -Class SMS_BoundaryGroupMembers -Namespace root\sms\site_$SiteCode -ComputerName $SMSProvider | Where-Object -FilterScript {$_.GroupID -eq "$($BoundaryGroup.GroupID)"}).BoundaryID
foreach ($MemberID in $MemberIDs)
{
$MemberName = (Get-CMBoundary -Id $MemberID).DisplayName
$MemberNames += "$MemberName (ID: $MemberID); "
Write-Verbose "Member names: $($MemberName)"
}
}
else
{
$MemberNames += 'There are no Site Systems associated to this Boundary Group.'
Write-Verbose 'There are no Site Systems associated to this Boundary Group.'
}
$BoundaryGroupRow = @{Name = $BoundaryGroup.Name; Description = $BoundaryGroup.Description; 'Boundary members' = "$MemberNames"};
$BoundaryGroupHashTable += $BoundaryGroupRow;
}
$Table = AddWordTable -Hashtable $BoundaryGroupHashTable -Format -155 -AutoFit $wdAutoFitContent
#-Columns Name, Description, 'Boundary Members' -Headers Name, Description, 'Boundary Members'
## Set first column format
SetWordCellFormat -Collection $Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15
FindWordDocumentEnd
$Table = $Null
}
else
{
WriteWordLine 0 1 'There are no Boundary Groups configured. It is mandatory to configure a Boundary Group in order for CM12 to work properly.'
}
#endregion enumerating all Boundary Groups and their members
#region enumerating Client Policies
Write-Verbose "$(Get-Date): Enumerating all Client/Device Settings"
WriteWordLine 2 0 'Summary of Custom Client Device Settings'
$AllClientSettings = Get-CMClientSetting | Where-Object -FilterScript {$_.SettingsID -ne '0'}
foreach ($ClientSetting in $AllClientSettings)
{
WriteWordLine 0 1 "Client Settings Name: $($ClientSetting.Name)" -bold
WriteWordLine 0 2 "Client Settings Description: $($ClientSetting.Description)"
WriteWordLine 0 2 "Client Settings ID: $($ClientSetting.SettingsID)"
WriteWordLine 0 2 "Client Settings Priority: $($ClientSetting.Priority)"
if ($ClientSetting.Type -eq '1')
{
WriteWordLine 0 2 'This is a custom client Device Setting.'
}
else
{
WriteWordLine 0 2 'This is a custom client User Setting.'
}
WriteWordLine 0 1 'Configurations'
foreach ($AgentConfig in $ClientSetting.AgentConfigurations)
{
try
{
switch ($AgentConfig.AgentID)
{
1
{
WriteWordLine 0 2 'Compliance Settings'
WriteWordLine 0 2 "Enable compliance evaluation on clients: $($AgentConfig.Enabled)"
WriteWordLine 0 2 "Enable user data and profiles: $($AgentConfig.EnableUserStateManagement)"
WriteWordLine 0 0 ''
WriteWordLine 0 0 '---------------------'
}
2
{
WriteWordLine 0 2 'Software Inventory'
WriteWordLine 0 2 "Enable software inventory on clients: $($AgentConfig.Enabled)"
WriteWordLine 0 2 'Schedule software inventory and file collection: ' -nonewline
$Schedule = Convert-CMSchedule -ScheduleString $AgentConfig.Schedule
if ($Schedule.DaySpan -gt 0)
{
WriteWordLine 0 0 " Occurs every $($Schedule.DaySpan) days effective $($Schedule.StartTime)"
}
elseif ($Schedule.HourSpan -gt 0)
{
WriteWordLine 0 0 " Occurs every $($Schedule.HourSpan) hours effective $($Schedule.StartTime)"
}
elseif ($Schedule.MinuteSpan -gt 0)
{
WriteWordLine 0 0 " Occurs every $($Schedule.MinuteSpan) minutes effective $($Schedule.StartTime)"
}
elseif ($Schedule.ForNumberOfWeeks)
{
WriteWordLine 0 0 " Occurs every $($Schedule.ForNumberOfWeeks) weeks on $(Convert-WeekDay $Schedule.Day) effective $($Schedule.StartTime)"
}
elseif ($Schedule.ForNumberOfMonths)
{
if ($Schedule.MonthDay -gt 0)
{
WriteWordLine 0 0 " Occurs on day $($Schedule.MonthDay) of every $($Schedule.ForNumberOfMonths) months effective $($Schedule.StartTime)"
}
elseif ($Schedule.MonthDay -eq 0)
{
WriteWordLine 0 0 " Occurs the last day of every $($Schedule.ForNumberOfMonths) months effective $($Schedule.StartTime)"
}
elseif ($Schedule.WeekOrder -gt 0)
{
switch ($Schedule.WeekOrder)
{
0 {$order = 'last'}
1 {$order = 'first'}
2 {$order = 'second'}
3 {$order = 'third'}
4 {$order = 'fourth'}
}
WriteWordLine 0 0 " Occurs the $($order) $(Convert-WeekDay $Schedule.Day) of every $($Schedule.ForNumberOfMonths) months effective $($Schedule.StartTime)"
}
}
WriteWordLine 0 2 'Inventory reporting detail: ' -nonewline
switch ($AgentConfig.ReportOptions)
{
1 { WriteWordLine 0 0 'Product only' }
2 { WriteWordLine 0 0 'File only' }
7 { WriteWordLine 0 0 'Full details' }
}
WriteWordLine 0 2 'Inventory these file types: '
if ($AgentConfig.InventoriableTypes)
{
WriteWordLine 0 3 "$($AgentConfig.InventoriableTypes)"
}
if ($AgentConfig.Path)
{
WriteWordLine 0 3 "$($AgentConfig.Path)"
}
if (($AgentConfig.InventoriableTypes) -and ($AgentConfig.ExcludeWindirAndSubfolders -eq 'true'))
{
WriteWordLine 0 3 'Exclude WinDir and Subfolders'
}
else
{
WriteWordLine 0 3 'Do not exclude WinDir and Subfolders'
}
WriteWordLine 0 0 ''
WriteWordLine 0 0 '---------------------'
}
3
{
WriteWordLine 0 2 'Remote Tools'
WriteWordLine 0 2 'Enable Remote Control on clients: ' -nonewline
switch ($AgentConfig.FirewallExceptionProfiles)
{
0 { WriteWordLine 0 0 'Disabled' }
8 { WriteWordLine 0 0 'Enabled: No Firewall Profile.' }
9 { WriteWordLine 0 2 'Enabled: Public.' }
10 { WriteWordLine 0 2 'Enabled: Private.' }
11 { WriteWordLine 0 2 'Enabled: Private, Public.' }
12 { WriteWordLine 0 2 'Enabled: Domain.' }
13 { WriteWordLine 0 2 'Enabled: Domain, Public.' }
14 { WriteWordLine 0 2 'Enabled: Domain, Private.' }
15 { WriteWordLine 0 2 'Enabled: Domain, Private, Public.' }
}
WriteWordLine 0 2 "Users can change policy or notification settings in Software Center: $($AgentConfig.AllowClientChange)"
WriteWordLine 0 2 "Allow Remote Control of an unattended computer: $($AgentConfig.AllowRemCtrlToUnattended)"
WriteWordLine 0 2 "Prompt user for Remote Control permission: $($AgentConfig.PermissionRequired)"
WriteWordLine 0 2 "Grant Remote Control permission to local Administrators group: $($AgentConfig.AllowLocalAdminToDoRemoteControl)"
WriteWordLine 0 2 'Access level allowed: ' -nonewline
switch ($AgentConfig.AccessLevel)
{
0 { WriteWordLine 0 0 'No access' }
1 { WriteWordLine 0 0 'View only' }
2 { WriteWordLine 0 0 'Full Control' }
}
WriteWordLine 0 2 'Permitted viewers of Remote Control and Remote Assistance:'
foreach ($Viewer in $AgentConfig.PermittedViewers)
{
WriteWordLine 0 3 "$($Viewer)"
}
WriteWordLine 0 2 "Show session notification icon on taskbar: $($AgentConfig.RemCtrlTaskbarIcon)"
WriteWordLine 0 2 "Show session connection bar: $($AgentConfig.RemCtrlConnectionBar)"
WriteWordLine 0 2 'Play a sound on client: ' -nonewline
Switch ($AgentConfig.AudibleSignal)
{
0 { WriteWordLine 0 0 'None.' }
1 { WriteWordLine 0 0 'Beginning and end of session.' }
2 { WriteWordLine 0 0 'Repeatedly during session.' }
}
WriteWordLine 0 2 "Manage unsolicited Remote Assistance settings: $($AgentConfig.ManageRA)"
WriteWordLine 0 2 "Manage solicited Remote Assistance settings: $($AgentConfig.EnforceRAandTSSettings)"
WriteWordLine 0 2 'Level of access for Remote Assistance: ' -nonewline
if (($AgentConfig.AllowRAUnsolicitedView -ne 'True') -and ($AgentConfig.AllowRAUnsolicitedControl -ne 'True'))
{
WriteWordLine 0 0 'None.'
}
elseif (($AgentConfig.AllowRAUnsolicitedView -eq 'True') -and ($AgentConfig.AllowRAUnsolicitedControl -ne 'True'))
{
WriteWordLine 0 0 'Remote viewing.'
}
elseif (($AgentConfig.AllowRAUnsolicitedView -eq 'True') -and ($AgentConfig.AllowRAUnsolicitedControl -eq 'True'))
{
WriteWordLine 0 0 'Full Control.'
}
WriteWordLine 0 2 "Manage Remote Desktop settings: $($AgentConfig.ManageTS)"
if ($AgentConfig.ManageTS -eq 'True')
{
WriteWordLine 0 2 "Allow permitted viewers to connect by using Remote Desktop connection: $($AgentConfig.EnableTS)"
WriteWordLine 0 2 "Require network level authentication on computers that run Windows Vista operating system and later versions: $($AgentConfig.TSUserAuthentication)"
}
WriteWordLine 0 0 ''
WriteWordLine 0 0 '---------------------'
}
4
{
WriteWordLine 0 2 'Computer Agent'
WriteWordLine 0 2 "Deployment deadline greater than 24 hours, remind user every (hours): $([string]($AgentConfig.ReminderInterval) / 60 / 60)"
WriteWordLine 0 2 "Deployment deadline less than 24 hours, remind user every (hours): $([string]($AgentConfig.DayReminderInterval) / 60 / 60)"
WriteWordLine 0 2 "Deployment deadline less than 1 hour, remind user every (minutes): $([string]($AgentConfig.HourReminderInterval) / 60)"
WriteWordLine 0 2 "Default application catalog website point: $($AgentConfig.PortalUrl)"
WriteWordLine 0 2 "Add default Application Catalog website to Internet Explorer trusted sites zone: $($AgentConfig.AddPortalToTrustedSiteList)"
WriteWordLine 0 2 "Allow Silverlight applicatio