Solved

Help with exporting the results of the script into csv instead of word

Posted on 2014-11-21
6
426 Views
Last Modified: 2014-12-10
Hello,
I need assistance with this AD script. It exports results into formatted word document, but I need to export the results into csv so I can do filtering.
 I am new to powershell and vbscript, so if you can add the line to the script to export the results to csv into different tabs or tables, etc. Thank you so much.

http://carlwebster.com/active-directory-documentation-script-updated-5-jun-2014/
#This File is in Unicode format.  Do not edit in an ASCII editor.

<#
.SYNOPSIS
	Creates a complete inventory of a Microsoft Active Directory Forest using Microsoft Word.
.DESCRIPTION
	Creates a complete inventory of a Microsoft Active Directory Forest using Microsoft Word and PowerShell.
	Creates a Word document named after the Active Directory Forest.
	Document includes 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

	While most of the script can be run with a non admin account, there are some features 
	that will not or may not work without domain admin rights.  The Hardware and Services 
	parameters require domain admin privileges.  The count of all users may not be accurate
	if the user running the script doesn't have the necessary permissions on all user
	objects.  In that case, there may be user accounts classified as "unknown".
.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.
	(default cover pages in Word en-US)
	Valid input is:
		Alphabet (Word 2007/2010. Works)
		Annual (Word 2007/2010. Doesn't really work well for this report)
		Austere (Word 2007/2010. Works)
		Austin (Word 2010/2013. Doesn't work in 2013, mostly works in 2007/2010 but Subtitle/Subject &amp; Author fields need to me moved after title box is moved up)
		Banded (Word 2013. Works)
		Conservative (Word 2007/2010. Works)
		Contrast (Word 2007/2010. Works)
		Cubicles (Word 2007/2010. Works)
		Exposure (Word 2007/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 2007/2010. Works)
		Motion (Word 2007/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 2007/2010. Works)
		Puzzle (Word 2007/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 2007/2010/2013. Doesn't work in 2013, works in 2007/2010)
		Slice (Dark) (Word 2013. Doesn't work)
		Slice (Light) (Word 2013. Doesn't work)
		Stacks (Word 2007/2010. Works)
		Tiles (Word 2007/2010. Date doesn't fit unless changed to 26 point)
		Transcend (Word 2007/2010. Works)
		ViewMaster (Word 2013. Works)
		Whisp (Word 2013. Works)
	Default value is Motion.
	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.
	For Word 2007, the Microsoft add-in for saving as a PDF muct be installed.
	For Word 2007, please see http://www.microsoft.com/en-us/download/details.aspx?id=9943
	The PDF file is roughly 5X to 10X larger than the DOCX file.
.PARAMETER Hardware
	Use WMI to gather hardware information on: Computer System, Disks, Processor and Network Interface Cards
	Will be used on Domain Controllers only.
	This parameters requires the script be run from an elevated PowerShell session 
	using an account with permission to retrieve hardware information (i.e. Domain Admin).
	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 ADForest
	Specifies an Active Directory forest object by providing one of the following attribute values. 
	The identifier in parentheses is the LDAP display name for the attribute.

	Fully qualified domain name
		Example: corp.contoso.com
	GUID (objectGUID)
		Example: 599c3d2e-f72d-4d20-8a88-030d99495f20
	DNS host name
		Example: dnsServer.corp.contoso.com
	NetBIOS name
		Example: corp
		
	This parameter is required.
.PARAMETER ComputerName
	Specifies which domain controller to use to run the script against.
	If ADForest is a trusted forest then ComputerName is required to detect the existence of ADForest.
	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.
.PARAMETER Services
	Gather information on all services running on domain controllers.
	Servers that are configured to automatically start but are not running will be colored in red.
	Will be used on Domain Controllers only.
	This parameters requires the script be run from an elevated PowerShell session
	using an account with permission to retrieve service information (i.e. Domain Admin).
	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 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.
.EXAMPLE
	PS C:\PSScript > .\ADDS_Inventory.ps1 -ADForest company.tld
	
	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.
	Motion for the Cover Page format.
	Administrator for the User Name.
	company.tld for the AD Forest
.EXAMPLE
	PS C:\PSScript > .\ADDS_Inventory.ps1 -PDF -ADForest corp.carlwebster.com
	
	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.
	Motion for the Cover Page format.
	Administrator for the User Name.
	corp.carlwebster.com for the AD Forest
.EXAMPLE
	PS C:\PSScript > .\ADDS_Inventory.ps1 -hardware
	
	Will use all default values and add additional information for each domain controller about its hardware.
	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.
	Motion for the Cover Page format.
	Administrator for the User Name.
	The user will be prompted for ADForest.
.EXAMPLE
	PS C:\PSScript .\ADDS_Inventory.ps1 -CompanyName "Carl Webster Consulting" -CoverPage "Mod" -UserName "Carl Webster" -ComputerName ADDC01

	Will use:
		Carl Webster Consulting for the Company Name.
		Mod for the Cover Page format.
		Carl Webster for the User Name.
		The user will be prompted for ADForest.
		Domain Controller named ADDC01 for the ComputerName.
.EXAMPLE
	PS C:\PSScript .\ADDS_Inventory.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).
		The user will be prompted for ADForest.
		The computer running the script for the ComputerName.
.INPUTS
	None.  You cannot pipe objects to this script.
.OUTPUTS
	No objects are output from this script.  This script creates a Word or PDF document.
.NOTES
	NAME: ADDS_Inventory.ps1
	VERSION: 1.02
	AUTHOR: Carl Webster
	LASTEDIT: June 5, 2014
#>


#thanks to @jeffwouters and Michael B. Smith for helping me with these parameters
[CmdletBinding( SupportsShouldProcess = $False, ConfirmImpact = "None", DefaultParameterSetName = "" ) ]

Param(
	[parameter(
	Position = 0, 
	Mandatory=$False )
	] 
	[Alias("CN")]
	[ValidateNotNullOrEmpty()]
	[string]$CompanyName="",
    
	[parameter(
	Position = 1, 
	Mandatory=$False )
	] 
	[Alias("CP")]
	[ValidateNotNullOrEmpty()]
	[string]$CoverPage="Sideline", 

	[parameter(
	Position = 2, 
	Mandatory=$False )
	] 
	[Alias("UN")]
	[ValidateNotNullOrEmpty()]
	[string]$UserName=$env:username,

	[parameter(
	Position = 3, 
	Mandatory=$False )
	] 
	[Switch]$PDF=$False,

	[parameter(
	Position = 4, 
	Mandatory=$False )
	] 
	[Switch]$Hardware=$False,

	[parameter(
	Position = 5, 
	Mandatory=$True )
	] 
	[string]$ADForest="", 

	[parameter(
	Position = 6, 
	Mandatory=$False )
	] 
	[string]$ComputerName="",
	
	[parameter(
	Position = 7, 
	Mandatory=$False )
	] 
	[Switch]$Services=$False,
	
	[parameter(
	Position = 8, 
	Mandatory=$False )
	] 
	[Switch]$AddDateTime=$False
	
	)
	

#force -verbose on
$PSDefaultParameterValues = @{"*:Verbose"=$True}
#since the Microsoft AD cmdlets do not honor -EA 0, set $ErrorActionPreference
$SaveEAPreference = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'

If($PDF -eq $Null)
{
	$PDF = $False
}
If($Hardware -eq $Null)
{
	$Hardware = $False
}
If($Services -eq $Null)
{
	$Services = $False
}
If($AddDateTime -eq $Null)
{
	$AddDateTime = $False
}

#webster@carlwebster.com
#@carlwebster on Twitter
#http://www.CarlWebster.com
#Created on April 10, 2014

#Version 1.0 released to the community on May 31, 2014
#
#Version 1.01
#	Added an AddDateTime parameter
#Version 1.02
#	Fixed the Enterprise Admins and Schema Admins privileged groups tables

Set-StrictMode -Version 2

#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]$wdSaveFormatPDF = 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

$hash = @{}

# 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 &amp; 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

Switch ($PSCulture.Substring(0,3))
{
	'ca-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Taula automática 2';
			}
		}

	'da-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Automatisk tabel 2';
			}
		}

	'de-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Automatische Tabelle 2';
			}
		}

	'en-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents'  = 'Automatic Table 2';
			}
		}

	'es-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Tabla automática 2';
			}
		}

	'fi-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Automaattinen taulukko 2';
			}
		}

	'fr-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Sommaire Automatique 2';
			}
		}

	'nb-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Automatisk tabell 2';
			}
		}

	'nl-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Automatische inhoudsopgave 2';
			}
		}

	'pt-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Sumário Automático 2';
			}
		}

	'sv-'	{
			$hash.($($PSCulture)) = @{
				'Word_TableOfContents' = 'Automatisk innehållsförteckning2';
			}
		}

	Default	{$hash.('en-US') = @{
				'Word_TableOfContents'  = 'Automatic Table 2';
			}
		}
}

$myHash = $hash.$PSCulture

If($myHash -eq $Null)
{
	$myHash = $hash.('en-US')
}

$myHash.Word_NoSpacing = $wdStyleNoSpacing
$myHash.Word_Heading1 = $wdStyleheading1
$myHash.Word_Heading2 = $wdStyleheading2
$myHash.Word_Heading3 = $wdStyleheading3
$myHash.Word_Heading4 = $wdStyleheading4
$myHash.Word_TableGrid = $wdTableGrid

Function ValidateCoverPage
{
	Param([int]$xWordVersion, [string]$xCP)
	
	$xArray = ""
	
	Switch ($PSCulture.Substring(0,3))
	{
		'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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alfabet", "Anual", "Conservador", "Contrast",
					"Cubicles", "Diplomàtic", "En mosaic", "Exposició", "Línia lateral",
					"Mod", "Moviment", "Piles", "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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alfabet", "Årlig", "BevægElse", "Eksponering",
					"Enkel", "Firkanter", "Fliser", "Gåde", "Kontrast",
					"Mod", "Nålestribet", "Overskrid", "Sidelinje", "Stakke",
					"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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alphabet", "Bewegung", "Durchscheinend", "Herausgestellt",
					"Jährlich", "Kacheln", "Kontrast", "Kubistisch", "Modern",
					"Nadelstreifen", "Puzzle", "Randlinie", "Raster", "Schlicht", "Stapel",
					"Traditionell")
				}
			}

		'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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alphabet", "Annual", "Austere", "Conservative", "Contrast",
					"Cubicles", "Exposure", "Mod", "Motion", "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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alfabeto", "Anual", "Austero", "Conservador",
					"Contraste", "Cubículos", "Exposición", "Línea lateral",
					"Moderno", "Mosaicos", "Movimiento", "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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Aakkoset", "Alttius", "Kontrasti", "Kuvakkeet ja tiedot",
					"Liike" , "Liituraita" , "Mod" , "Palapeli", "Perinteinen", "Pinot",
					"Sivussa", "Työpisteet", "Vuosittainen", "Yksinkertainen", "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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alphabet", "Annuel", "Austère", "Blocs empilés", "Blocs superposés",
					"Classique", "Contraste", "Exposition", "Guide", "Ligne latérale", "Moderne",
					"Mosaïques", "Mots croisés", "Rayures fines", "Transcendant")
				}
			}

		'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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alfabet", "Årlig", "Avlukker", "BevegElse", "Engasjement",
					"Enkel", "Fliser", "Konservativ", "Kontrast", "Mod", "Puslespill",
					"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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Aantrekkelijk", "Alfabet", "Bescheiden", "Beweging",
					"Blikvanger", "Contrast", "Eenvoudig", "Jaarlijks", "Krijtstreep",
					"Mod", "Puzzel", "Stapels", "Tegels", "Terzijde", "Werkplekken")
				}
			}

		'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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alfabeto", "Animação", "Anual", "Austero", "Baias", "Conservador",
					"Contraste", "Exposição", "Ladrilhos", "Linha Lateral", "Listras", "Mod",
					"Pilhas", "Quebra-cabeça", "Transcendente")
				}
			}

		'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")
				}
				ElseIf($xWordVersion -eq $wdWord2007)
				{
					$xArray = ("Alfabetmönster", "Årligt", "Enkelt", "Exponering", "Konservativt",
					"Kontrast", "Kritstreck", "Kuber", "Övergående", "Plattor", "Pussel", "RörElse",
					"Sidlinje", "Sobert", "Staplat")
				}
			}

		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")
					}
					ElseIf($xWordVersion -eq $wdWord2007)
					{
						$xArray = ("Alphabet", "Annual", "Austere", "Conservative", "Contrast",
						"Cubicles", "Exposure", "Mod", "Motion", "Pinstripes", "Puzzle",
						"Sideline", "Stacks", "Tiles", "Transcend")
					}
				}
	}
	
	If($xArray -contains $xCP)
	{
		$xArray = $Null
		Return $True
	}
	Else
	{
		$xArray = $Null
		Return $False
	}
}

Function GetComputerWMIInfo
{
	Param([string]$RemoteComputerName)
	
	# original work by Kees Baggerman, 
	# Senior Technical Consultant @ Inter Access
	# k.baggerman@myvirtualvision.com
	# @kbaggerman on Twitter
	# http://blog.myvirtualvision.com
	# modified 1-May-2014 to work in trusted AD Forests and using different domain admin credentials	

	#Get Computer info
	Write-Verbose "$(Get-Date): `t`tProcessing WMI Computer information"
	Write-Verbose "$(Get-Date): `t`t`tHardware information"
	WriteWordLine 3 0 "Computer Information"
	WriteWordLine 0 1 "General Computer"
	[bool]$GotComputerItems = $True
	
	Try
	{
		$Results = Get-WmiObject -computername $RemoteComputerName win32_computersystem
	}
	
	Catch
	{
		$Results = $Null
	}
	
	If($? -and $Results -ne $Null)
	{
		$ComputerItems = $Results | Select Manufacturer, Model, Domain, @{N="TotalPhysicalRam"; E={[math]::round(($_.TotalPhysicalMemory / 1GB),0)}}
		$Results = $Null

		ForEach($Item in $ComputerItems)
		{
			WriteWordLine 0 2 "Manufacturer`t: " $Item.manufacturer
			WriteWordLine 0 2 "Model`t`t: " $Item.model
			WriteWordLine 0 2 "Domain`t`t: " $Item.domain
			WriteWordLine 0 2 "Total Ram`t: $($Item.totalphysicalram) GB"
			WriteWordLine 0 2 ""
		}
	}
	ElseIf(!$?)
	{
		Write-Verbose "$(Get-Date): Get-WmiObject win32_computersystem failed for $($RemoteComputerName)"
		Write-Warning "Get-WmiObject win32_computersystem failed for $($RemoteComputerName)"
		WriteWordLine 0 2 "Get-WmiObject win32_computersystem failed for $($RemoteComputerName)" "" $Null 0 $False $True
		WriteWordLine 0 2 "On $($RemoteComputerName) you may need to run winmgmt /verifyrepository" "" $Null 0 $False $True
		WriteWordLine 0 2 "and winmgmt /salvagerepository.  If this is a trusted Forest, you may" "" $Null 0 $False $True
		WriteWordLine 0 2 "need to rerun the script with Domain Admin credentials from the trusted Forest." "" $Null 0 $False $True
	}
	Else
	{
		Write-Verbose "$(Get-Date): No results returned for Computer information"
		WriteWordLine 0 2 "No results returned for Computer information" "" $Null 0 $False $True
	}
	
	#Get Disk info
	Write-Verbose "$(Get-Date): `t`t`tDrive information"
	WriteWordLine 0 1 "Drive(s)"
	[bool]$GotDrives = $True
	
	Try
	{
		$Results = Get-WmiObject -computername $RemoteComputerName Win32_LogicalDisk
	}
	
	Catch
	{
		$Results = $Null
	}

	If($? -and $Results -ne $Null)
	{
		$drives = $Results | Select caption, @{N="drivesize"; E={[math]::round(($_.size / 1GB),0)}}, 
		filesystem, @{N="drivefreespace"; E={[math]::round(($_.freespace / 1GB),0)}}, 
		volumename, drivetype, volumedirty, volumeserialnumber
		$Results = $Null
		ForEach($drive in $drives)
		{
			If($drive.caption -ne "A:" -and $drive.caption -ne "B:")
			{
				WriteWordLine 0 2 "Caption`t`t: " $drive.caption
				WriteWordLine 0 2 "Size`t`t: $($drive.drivesize) GB"
				If(![String]::IsNullOrEmpty($drive.filesystem))
				{
					WriteWordLine 0 2 "File System`t: " $drive.filesystem
				}
				WriteWordLine 0 2 "Free Space`t: $($drive.drivefreespace) GB"
				If(![String]::IsNullOrEmpty($drive.volumename))
				{
					WriteWordLine 0 2 "Volume Name`t: " $drive.volumename
				}
				If(![String]::IsNullOrEmpty($drive.volumedirty))
				{
					WriteWordLine 0 2 "Volume is Dirty`t: " -nonewline
					If($drive.volumedirty)
					{
						WriteWordLine 0 0 "Yes"
					}
					Else
					{
						WriteWordLine 0 0 "No"
					}
				}
				If(![String]::IsNullOrEmpty($drive.volumeserialnumber))
				{
					WriteWordLine 0 2 "Volume Serial #`t: " $drive.volumeserialnumber
				}
				WriteWordLine 0 2 "Drive Type`t: " -nonewline
				Switch ($drive.drivetype)
				{
					0	{WriteWordLine 0 0 "Unknown"}
					1	{WriteWordLine 0 0 "No Root Directory"}
					2	{WriteWordLine 0 0 "Removable Disk"}
					3	{WriteWordLine 0 0 "Local Disk"}
					4	{WriteWordLine 0 0 "Network Drive"}
					5	{WriteWordLine 0 0 "Compact Disc"}
					6	{WriteWordLine 0 0 "RAM Disk"}
					Default {WriteWordLine 0 0 "Unknown"}
				}
				WriteWordLine 0 2 ""
			}
		}
	}
	ElseIf(!$?)
	{
		Write-Verbose "$(Get-Date): Get-WmiObject Win32_LogicalDisk failed for $($RemoteComputerName)"
		Write-Warning "Get-WmiObject Win32_LogicalDisk failed for $($RemoteComputerName)"
		WriteWordLine 0 2 "Get-WmiObject Win32_LogicalDisk failed for $($RemoteComputerName)" "" $Null 0 $False $True
		WriteWordLine 0 2 "On $($RemoteComputerName) you may need to run winmgmt /verifyrepository" "" $Null 0 $False $True
		WriteWordLine 0 2 "and winmgmt /salvagerepository.  If this is a trusted Forest, you may" "" $Null 0 $False $True
		WriteWordLine 0 2 "need to rerun the script with Domain Admin credentials from the trusted Forest." "" $Null 0 $False $True
	}
	Else
	{
		Write-Verbose "$(Get-Date): No results returned for Drive information"
		WriteWordLine 0 2 "No results returned for Drive information" "" $Null 0 $False $True
	}
	

	#Get CPU's and stepping
	Write-Verbose "$(Get-Date): `t`t`tProcessor information"
	WriteWordLine 0 1 "Processor(s)"
	[bool]$GotProcessors = $True
	
	Try
	{
		$Results = Get-WmiObject -computername $RemoteComputerName win32_Processor
	}
	
	Catch
	{
		$Results = $Null
	}

	If($? -and $Results -ne $Null)
	{
		$Processors = $Results | Select availability, name, description, maxclockspeed, 
		l2cachesize, l3cachesize, numberofcores, numberoflogicalprocessors
		$Results = $Null
		ForEach($processor in $processors)
		{
			WriteWordLine 0 2 "Name`t`t`t: " $processor.name
			WriteWordLine 0 2 "Description`t`t: " $processor.description
			WriteWordLine 0 2 "Max Clock Speed`t: $($processor.maxclockspeed) MHz"
			If($processor.l2cachesize -gt 0)
			{
				WriteWordLine 0 2 "L2 Cache Size`t`t: $($processor.l2cachesize) KB"
			}
			If($processor.l3cachesize -gt 0)
			{
				WriteWordLine 0 2 "L3 Cache Size`t`t: $($processor.l3cachesize) KB"
			}
			If($processor.numberofcores -gt 0)
			{
				WriteWordLine 0 2 "# of Cores`t`t: " $processor.numberofcores
			}
			If($processor.numberoflogicalprocessors -gt 0)
			{
				WriteWordLine 0 2 "# of Logical Procs`t: " $processor.numberoflogicalprocessors
			}
			WriteWordLine 0 2 "Availability`t`t: " -nonewline
			Switch ($processor.availability)
			{
				1	{WriteWordLine 0 0 "Other"}
				2	{WriteWordLine 0 0 "Unknown"}
				3	{WriteWordLine 0 0 "Running or Full Power"}
				4	{WriteWordLine 0 0 "Warning"}
				5	{WriteWordLine 0 0 "In Test"}
				6	{WriteWordLine 0 0 "Not Applicable"}
				7	{WriteWordLine 0 0 "Power Off"}
				8	{WriteWordLine 0 0 "Off Line"}
				9	{WriteWordLine 0 0 "Off Duty"}
				10	{WriteWordLine 0 0 "Degraded"}
				11	{WriteWordLine 0 0 "Not Installed"}
				12	{WriteWordLine 0 0 "Install Error"}
				13	{WriteWordLine 0 0 "Power Save - Unknown"}
				14	{WriteWordLine 0 0 "Power Save - Low Power Mode"}
				15	{WriteWordLine 0 0 "Power Save - Standby"}
				16	{WriteWordLine 0 0 "Power Cycle"}
				17	{WriteWordLine 0 0 "Power Save - Warning"}
				Default	{WriteWordLine 0 0 "Unknown"}
			}
			WriteWordLine 0 2 ""
		}
	}
	ElseIf(!$?)
	{
		Write-Verbose "$(Get-Date): Get-WmiObject win32_Processor failed for $($RemoteComputerName)"
		Write-Warning "Get-WmiObject win32_Processor failed for $($RemoteComputerName)"
		WriteWordLine 0 2 "Get-WmiObject win32_Processor failed for $($RemoteComputerName)" "" $Null 0 $False $True
		WriteWordLine 0 2 "On $($RemoteComputerName) you may need to run winmgmt /verifyrepository" "" $Null 0 $False $True
		WriteWordLine 0 2 "and winmgmt /salvagerepository.  If this is a trusted Forest, you may" "" $Null 0 $False $True
		WriteWordLine 0 2 "need to rerun the script with Domain Admin credentials from the trusted Forest." "" $Null 0 $False $True
	}
	Else
	{
		Write-Verbose "$(Get-Date): No results returned for Processor information"
		WriteWordLine 0 2 "No results returned for Processor information" "" $Null 0 $False $True
	}

	#Get Nics
	Write-Verbose "$(Get-Date): `t`t`tNIC information"
	WriteWordLine 0 1 "Network Interface(s)"
	[bool]$GotNics = $True
	
	Try
	{
		$Results = Get-WmiObject -computername $RemoteComputerName win32_networkadapterconfiguration
	}
	
	Catch
	{
		$Results
	}

	If($? -and $Results -ne $Null)
	{
		$Nics = $Results | Where {$_.ipaddress -ne $Null}
		$Results = $Null

		If($Nics -eq $Null ) 
		{ 
			$GotNics = $False 
		} 
		Else 
		{ 
			$GotNics = !($Nics.__PROPERTY_COUNT -eq 0) 
		} 
	
		If($GotNics)
		{
			ForEach($nic in $nics)
			{
				Try
				{
					$ThisNic = Get-WmiObject -computername $RemoteComputerName win32_networkadapter | Where {$_.index -eq $nic.index}
				}
				
				Catch 
				{
					$ThisNic = $Null
				}
				
				If($? -and $ThisNic -ne $Null)
				{
					If($ThisNic.Name -eq $nic.description)
					{
						WriteWordLine 0 2 "Name`t`t`t: " $ThisNic.Name
					}
					Else
					{
						WriteWordLine 0 2 "Name`t`t`t: " $ThisNic.Name
						WriteWordLine 0 2 "Description`t`t: " $nic.description
					}
					WriteWordLine 0 2 "Connection ID`t`t: " $ThisNic.NetConnectionID
					WriteWordLine 0 2 "Manufacturer`t`t: " $ThisNic.manufacturer
					WriteWordLine 0 2 "Availability`t`t: " -nonewline
					Switch ($ThisNic.availability)
					{
						1	{WriteWordLine 0 0 "Other"}
						2	{WriteWordLine 0 0 "Unknown"}
						3	{WriteWordLine 0 0 "Running or Full Power"}
						4	{WriteWordLine 0 0 "Warning"}
						5	{WriteWordLine 0 0 "In Test"}
						6	{WriteWordLine 0 0 "Not Applicable"}
						7	{WriteWordLine 0 0 "Power Off"}
						8	{WriteWordLine 0 0 "Off Line"}
						9	{WriteWordLine 0 0 "Off Duty"}
						10	{WriteWordLine 0 0 "Degraded"}
						11	{WriteWordLine 0 0 "Not Installed"}
						12	{WriteWordLine 0 0 "Install Error"}
						13	{WriteWordLine 0 0 "Power Save - Unknown"}
						14	{WriteWordLine 0 0 "Power Save - Low Power Mode"}
						15	{WriteWordLine 0 0 "Power Save - Standby"}
						16	{WriteWordLine 0 0 "Power Cycle"}
						17	{WriteWordLine 0 0 "Power Save - Warning"}
						Default	{WriteWordLine 0 0 "Unknown"}
					}
					WriteWordLine 0 2 "Physical Address`t: " $nic.macaddress
					WriteWordLine 0 2 "IP Address`t`t: " $nic.ipaddress
					WriteWordLine 0 2 "Default Gateway`t: " $nic.Defaultipgateway
					WriteWordLine 0 2 "Subnet Mask`t`t: " $nic.ipsubnet
					If($nic.dhcpenabled)
					{
						$DHCPLeaseObtainedDate = $nic.ConvertToDateTime($nic.dhcpleaseobtained)
						$DHCPLeaseExpiresDate = $nic.ConvertToDateTime($nic.dhcpleaseexpires)
						WriteWordLine 0 2 "DHCP Enabled`t`t: " $nic.dhcpenabled
						WriteWordLine 0 2 "DHCP Lease Obtained`t: " $dhcpleaseobtaineddate
						WriteWordLine 0 2 "DHCP Lease Expires`t: " $dhcpleaseexpiresdate
						WriteWordLine 0 2 "DHCP Server`t`t:" $nic.dhcpserver
					}
					If(![String]::IsNullOrEmpty($nic.dnsdomain))
					{
						WriteWordLine 0 2 "DNS Domain`t`t: " $nic.dnsdomain
					}
					If($nic.dnsdomainsuffixsearchorder -ne $Null -and $nic.dnsdomainsuffixsearchorder.length -gt 0)
					{
						[int]$x = 1
						WriteWordLine 0 2 "DNS Search Suffixes`t:" -nonewline
						$nicdnsdomainsuffixsearchorder = $nic.dnsdomainsuffixsearchorder
						ForEach($DNSDomain in $nicdnsdomainsuffixsearchorder)
						{
							If($x -eq 1)
							{
								$x = 2
								WriteWordLine 0 0 " $($DNSDomain)"
							}
							Else
							{
								WriteWordLine 0 5 " $($DNSDomain)"
							}
						}
					}
					WriteWordLine 0 2 "DNS WINS Enabled`t: " -nonewline
					If($nic.dnsenabledforwinsresolution)
					{
						WriteWordLine 0 0 "Yes"
					}
					Else
					{
						WriteWordLine 0 0 "No"
					}
					If($nic.dnsserversearchorder -ne $Null -and $nic.dnsserversearchorder.length -gt 0)
					{
						[int]$x = 1
						WriteWordLine 0 2 "DNS Servers`t`t:" -nonewline
						$nicdnsserversearchorder = $nic.dnsserversearchorder
						ForEach($DNSServer in $nicdnsserversearchorder)
						{
							If($x -eq 1)
							{
								$x = 2
								WriteWordLine 0 0 " $($DNSServer)"
							}
							Else
							{
								WriteWordLine 0 5 " $($DNSServer)"
							}
						}
					}
					WriteWordLine 0 2 "NetBIOS Setting`t`t: " -nonewline
					Switch ($nic.TcpipNetbiosOptions)
					{
						0	{WriteWordLine 0 0 "Use NetBIOS setting from DHCP Server"}
						1	{WriteWordLine 0 0 "Enable NetBIOS"}
						2	{WriteWordLine 0 0 "Disable NetBIOS"}
						Default	{WriteWordLine 0 0 "Unknown"}
					}
					WriteWordLine 0 2 "WINS:"
					WriteWordLine 0 3 "Enabled LMHosts`t: " -nonewline
					If($nic.winsenablelmhostslookup)
					{
						WriteWordLine 0 0 "Yes"
					}
					Else
					{
						WriteWordLine 0 0 "No"
					}
					If(![String]::IsNullOrEmpty($nic.winshostlookupfile))
					{
						WriteWordLine 0 3 "Host Lookup File`t: " $nic.winshostlookupfile
					}
					If(![String]::IsNullOrEmpty($nic.winsprimaryserver))
					{
						WriteWordLine 0 3 "Primary Server`t`t: " $nic.winsprimaryserver
					}
					If(![String]::IsNullOrEmpty($nic.winssecondaryserver))
					{
						WriteWordLine 0 3 "Secondary Server`t: " $nic.winssecondaryserver
					}
					If(![String]::IsNullOrEmpty($nic.winsscopeid))
					{
						WriteWordLine 0 3 "Scope ID`t`t: " $nic.winsscopeid
					}
				}
				ElseIf(!$?)
				{
					Write-Warning "$(Get-Date): Error retrieving NIC information"
					Write-Verbose "$(Get-Date): Get-WmiObject win32_networkadapterconfiguration failed for $($RemoteComputerName)"
					Write-Warning "Get-WmiObject win32_networkadapterconfiguration failed for $($RemoteComputerName)"
					WriteWordLine 0 2 "Error retrieving NIC information" "" $Null 0 $False $True
					WriteWordLine 0 2 "Get-WmiObject win32_networkadapterconfiguration failed for $($RemoteComputerName)" "" $Null 0 $False $True
					WriteWordLine 0 2 "On $($RemoteComputerName) you may need to run winmgmt /verifyrepository" "" $Null 0 $False $True
					WriteWordLine 0 2 "and winmgmt /salvagerepository.  If this is a trusted Forest, you may" "" $Null 0 $False $True
					WriteWordLine 0 2 "need to rerun the script with Domain Admin credentials from the trusted Forest." "" $Null 0 $False $True
				}
				Else
				{
					Write-Verbose "$(Get-Date): No results returned for NIC information"
					WriteWordLine 0 2 "No results returned for NIC information" "" $Null 0 $False $True
				}
			}
		}	
	}
	ElseIf(!$?)
	{
		Write-Warning "$(Get-Date): Error retrieving NIC configuration information"
		Write-Verbose "$(Get-Date): Get-WmiObject win32_networkadapterconfiguration failed for $($RemoteComputerName)"
		Write-Warning "Get-WmiObject win32_networkadapterconfiguration failed for $($RemoteComputerName)"
		WriteWordLine 0 2 "Error retrieving NIC configuration information" "" $Null 0 $False $True
		WriteWordLine 0 2 "Get-WmiObject win32_networkadapterconfiguration failed for $($RemoteComputerName)" "" $Null 0 $False $True
		WriteWordLine 0 2 "On $($RemoteComputerName) you may need to run winmgmt /verifyrepository" "" $Null 0 $False $True
		WriteWordLine 0 2 "and winmgmt /salvagerepository.  If this is a trusted Forest, you may" "" $Null 0 $False $True
		WriteWordLine 0 2 "need to rerun the script with Domain Admin credentials from the trusted Forest." "" $Null 0 $False $True
	}
	Else
	{
		Write-Verbose "$(Get-Date): No results returned for NIC configuration information"
		WriteWordLine 0 2 "No results returned for NIC configuration information" "" $Null 0 $False $True
	}
	
	WriteWordLine 0 0 ""
	$Results = $Null
	$ComputerItems = $Null
	$Drives = $Null
	$Processors = $Null
	$Nics = $Null
}

Function GetComputerServices 
{
	Param([string]$RemoteComputerName)
	
	#Get Computer services info
	Write-Verbose "$(Get-Date): `t`tProcessing Computer services information"
	WriteWordLine 3 0 "Services"

	Try
	{
		$DCServices = Get-Service -ComputerName $RemoteComputerName | Sort DisplayName
	}
	
	Catch
	{
		$DCServices = $Null
	}
	
	If($? -and $DCServices -ne $Null)
	{
		[int]$Columns = 3
		If($DCServices -is [array])
		{
			[int]$Rows = $DCServices.count + 1
			[int]$NumServices = $DCServices.count
		}
		Else
		{
			[int]$Rows = 2
			[int]$NumServices = 1
		}
		Write-Verbose "$(Get-Date): `t`t $NumServices Services found"
		WriteWordLine 0 1 "Services ($NumServices Services found)"
		$TableRange = $doc.Application.Selection.Range
		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.Style = $myHash.Word_TableGrid
		$Table.rows.first.headingformat = $wdHeadingFormatTrue
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
		[int]$xRow = 1
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Display Name"
		$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,2).Range.Font.Bold = $True
		$Table.Cell($xRow,2).Range.Text = "Status"
		$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,3).Range.Font.Bold = $True
		$Table.Cell($xRow,3).Range.Text = "Startup Type"
		ForEach($Service in $DCServices)
		{
			$xRow++
			$Table.Cell($xRow,1).Range.Text = $Service.DisplayName
			
			Try
			{
				$StartupType = (Get-WMIObject Win32_Service -Filter "Name='$($Service.Name)'" -ComputerName $RemoteComputerName).StartMode
			}
			
			Catch
			{
				$StartupType = "Not Found"
			}
			
			If($Service.Status -eq "Stopped" -and $StartupType -eq "Auto")
			{
				$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorRed
				$Table.Cell($xRow,2).Range.Font.Bold  = $True
				$Table.Cell($xRow,2).Range.Font.Color = $WDColorBlack
			}
			$Table.Cell($xRow,2).Range.Text = $Service.Status
			$Table.Cell($xRow,3).Range.Text = $StartupType
		}

		$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustProportional)
		$Table.AutoFitBehavior($wdAutoFitContent)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null
	}
	ElseIf(!$?)
	{
		Write-Warning "No services were retrieved."
		WriteWordLine 0 0 "Warning: No Services were retrieved" "" $Null 0 $False $True
		WriteWordLine 0 1 "If this is a trusted Forest, you may need to rerun the" "" $Null 0 $False $True
		WriteWordLine 0 1 "script with Domain Admin credentials from the trusted Forest." "" $Null 0 $False $True
	}
	Else
	{
		Write-Warning "Services retrieval was successful but no services were returned."
		WriteWordLine 0 0 "Services retrieval was successful but no services were returned." "" $Null 0 $False $True
	}
	$DCServices = $Null
}

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 CheckWord2007SaveAsPDFInstalled
{
	If((Test-Path  REGISTRY::HKEY_CLASSES_ROOT\Installer\Products\000021090B0090400000000000F01FEC) -eq $False)
	{
		Write-Host "`n`n`t`tWord 2007 is detected and the option to SaveAs PDF was selected but the Word 2007 SaveAs PDF add-in is not installed."
		Write-Host "`n`n`t`tThe add-in can be downloaded from http://www.microsoft.com/en-us/download/details.aspx?id=9943"
		Write-Host "`n`n`t`tInstall the SaveAs PDF add-in and rerun the script."
		Return $False
	}
	Return $True
}

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 ""
		}
	}
}

#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
	}
}
	
Function Check-LoadedModule
#Function created by Jeff Wouters
#@JeffWouters on Twitter
#modified by Michael B. Smith to handle when the module doesn't exist on server
#modified by @andyjmorgan
#bug fixed by @schose
#This Function handles all three scenarios:
#
# 1. Module is already imported into current session
# 2. Module is not already imported into current session, it does exists on the server and is imported
# 3. Module does not exist on the server

{
	Param([parameter(Mandatory = $True)][alias("Module")][string]$ModuleName)
	#$LoadedModules = Get-Module | Select Name
	#following line changed at the recommendation of @andyjmorgan
	$LoadedModules = Get-Module | % { $_.Name.ToString() }
	#bug reported on 21-JAN-2013 by @schose 
	#the following line did not work if the citrix.grouppolicy.commands.psm1 module
	#was manually loaded from a non Default folder
	#$ModuleFound = (!$LoadedModules -like "*$ModuleName*")
	$ModuleFound = ($LoadedModules -like "*$ModuleName*")
	If(!$ModuleFound) 
	{
		$module = Import-Module -Name $ModuleName -PassThru -EA 0
		If($module -and $?)
		{
			# module imported properly
			Return $True
		}
		Else
		{
			# module import failed
			Return $False
		}
	}
	Else
	{
		#module already imported into current session
		Return $True
	}
}

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 {$Selection.Style = $myHash.Word_NoSpacing}
		1 {$Selection.Style = $myHash.Word_Heading1}
		2 {$Selection.Style = $myHash.Word_Heading2}
		3 {$Selection.Style = $myHash.Word_Heading3}
		4 {$Selection.Style = $myHash.Word_Heading4}
		Default {$Selection.Style = $myHash.Word_NoSpacing}
	}
	
	#build # of tabs
	While($tabs -gt 0)
	{ 
		$output += "`t"; $tabs--; 
	}
 
	If(![String]::IsNullOrEmpty($fontName)) 
	{
		$Selection.Font.name = $fontName
	} 

	If($fontSize -ne 0) 
	{
		$Selection.Font.size = $fontSize
	} 
 
	If($italics -eq $True) 
	{
		$Selection.Font.Italic = $True
	} 
 
	If($boldface -eq $True) 
	{
		$Selection.Font.Bold = $True
	} 

	#output the rest of the parameters.
	$output += $name + $value
	$Selection.TypeText($output)
 
	#test for new WriteWordLine 0.
	If($nonewline)
	{
		# Do nothing.
	} 
	Else 
	{
		$Selection.TypeParagraph()
	}
}

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 AbortScript
{
	$Word.quit()
	Write-Verbose "$(Get-Date): System Cleanup"
	[System.Runtime.Interopservices.Marshal]::ReleaseComObject($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
}

Function BuildMultiColumnTable
{
	Param([Array]$xArray, [String]$xType)
	
	#divide by 0 bug reported 9-Apr-2014 by Lee Dehmer 
	#if security group name or OU name was longer than 60 characters it caused a divide by 0 error
	
	#added a second parameter to the function so the verbose message would say whether 
	#the function is processing servers, security groups or OUs.
	
	If(-not ($xArray -is [Array]))
	{
		$xArray = (,$xArray)
	}
	[int]$MaxLength = 0
	[int]$TmpLength = 0
	#remove 60 as a hard-coded value
	#60 is the max width the table can be when indented 36 points
	[int]$MaxTableWidth = 60
	ForEach($xName in $xArray)
	{
		$TmpLength = $xName.Length
		If($TmpLength -gt $MaxLength)
		{
			$MaxLength = $TmpLength
		}
	}
	$TableRange = $doc.Application.Selection.Range
	#removed hard-coded value of 60 and replace with MaxTableWidth variable
	[int]$Columns = [Math]::Floor($MaxTableWidth / $MaxLength)
	If($xArray.count -lt $Columns)
	{
		[int]$Rows = 1
		#not enough array items to fill columns so use array count
		$MaxCells  = $xArray.Count
		#reset column count so there are no empty columns
		$Columns   = $xArray.Count 
	}
	ElseIf($Columns -eq 0)
	{
		#divide by 0 bug if this condition is not handled
		#number was larger than $MaxTableWidth so there can only be one column
		#with one cell per row
		[int]$Rows = $xArray.count
		$Columns   = 1
		$MaxCells  = 1
	}
	Else
	{
		[int]$Rows = [Math]::Floor( ( $xArray.count + $Columns - 1 ) / $Columns)
		#more array items than columns so don't go past last column
		$MaxCells  = $Columns
	}
	$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
	$Table.Style = $myHash.Word_TableGrid
	$Table.Borders.InsideLineStyle = $wdLineStyleSingle
	$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
	[int]$xRow = 1
	[int]$ArrayItem = 0
	While($xRow -le $Rows)
	{
		For($xCell=1; $xCell -le $MaxCells; $xCell++)
		{
			$Table.Cell($xRow,$xCell).Range.Text = $xArray[$ArrayItem]
			$ArrayItem++
		}
		$xRow++
	}
	$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
	$Table.AutoFitBehavior($wdAutoFitContent)

	#return focus back to document
	$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

	#move to the end of the current document
	$selection.EndKey($wdStory,$wdMove) | Out-Null
	$TableRange = $Null
	$Table = $Null
	$xArray = $Null
}

Function UserIsaDomainAdmin
{
	#function adapted from sample code provided by Thomas Vuylsteke
	$IsDA = $False
	$name = $env:username
	Write-Verbose "$(Get-Date): TokenGroups - Checking groups for $name"

	$root = [ADSI]""
	$filter = "(sAMAccountName=$name)"
	$props = @("distinguishedName")
	$Searcher = new-Object System.DirectoryServices.DirectorySearcher($root,$filter,$props)
	$account = $Searcher.FindOne().properties.distinguishedname

	$user = [ADSI]"LDAP://$Account"
	$user.GetInfoEx(@("tokengroups"),0)
	$groups = $user.Get("tokengroups")

	$domainAdminsSID = New-Object System.Security.Principal.SecurityIdentifier (((Get-ADDomain -Server $ADForest).DomainSid).Value+"-512") 

	ForEach($group in $groups)
	{     
		$ID = New-Object System.Security.Principal.SecurityIdentifier($group,0)       
		If($ID.CompareTo($domainAdminsSID) -eq 0)
		{
			$IsDA = $True
		}     
	}

	$root = $Null
	$filter = $Null
	$props = $Null
	$Searcher = $Null
	$account = $Null
	$user = $Null
	$groups = $Null
	$domainAdminsSID = $Null
	Return $IsDA
}

Function GetComputerCountByOS
{
	Param([string]$xDomain)

	<#
	  This function will count the number of Windows workstations, Windows servers and
	  non-Windows computers and list them by Operating System.

	  Note that for servers we filter out Cluster Name Objects (CNOs) and
	  Virtual Computer Objects (VCOs) by checking the objects serviceprincipalname
	  property for a value of MSClusterVirtualServer. The CNO is the cluster
	  name, whereas a VCO is the client access point for the clustered role.
	  These are not actual computers, so we exlude them to assist with
	  accuracy.

	  Function Name: GetComputerCountByOS
	  Release: 1.0
	  Written by Jeremy@jhouseconsulting.com 20th May 2012
	#>

	#function optimized by Michael B. Smith
	
	Write-Verbose "$(Get-Date): `t`tGathering computer misc data"
	$Computers = @()
	$UnknownComputers = @()
	
	$Results = Get-ADComputer -Filter * -Properties Name,Operatingsystem,servicePrincipalName,DistinguishedName -Server $Domain
	
	If($? -and $Results -ne $Null)
	{
	
		Write-Verbose "$(Get-Date): `t`t`tGetting server OS counts"
		$Computers += $Results | `
			Where-Object {($_.Operatingsystem -like '*server*') -AND !($_.serviceprincipalname -like '*MSClusterVirtualServer*')} | `
			Sort-Object Name
		
		Write-Verbose "$(Get-Date): `t`t`tGetting workstation OS counts"
		$Computers += $Results | `
			Where-Object {($_.Operatingsystem -like '*windows*') -AND !($_.Operatingsystem -like '*server*')} | `
			Sort-Object Name
		
		Write-Verbose "$(Get-Date): `t`t`tGetting unknown OS counts"
		$UnknownComputers += $Results | `
			Where-Object {!($_.Operatingsystem -like '*windows*') -AND !($_.serviceprincipalname -like '*MSClusterVirtualServer*')} | `
			Sort-Object Name
		
		$Computers += $UnknownComputers
		$UnknownComputers = $UnknownComputers | Sort DistinguishedName
		
		$Computers = $Computers | Group-Object operatingsystem | Sort-Object Count -Descending

		Write-Verbose "$(Get-Date): `t`tBuild table for OS counts"
		WriteWordLine 3 0 "Windows Computer Operating Systems"
		$TableRange   = $doc.Application.Selection.Range
		[int]$Columns = 2
		If($Computers -is [array])
		{
			[int]$Rows = $Computers.Count
		}
		Else
		{
			[int]$Rows = 1
		}
		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.Style = $myHash.Word_TableGrid
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
		
		[int]$xRow = 0
		
		ForEach($Computer in $Computers)
		{
			$xRow++
			[string]$CountStr = "{0,7:N0}" -f $Computer.Count
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			If([String]::IsNullOrEmpty($Computer.Name))
			{
				$Table.Cell($xRow,1).Range.Text = "<No OS name>"
			}
			Else
			{
				$Table.Cell($xRow,1).Range.Text = $Computer.Name
			}
			$Table.Cell($xRow,2).Range.ParagraphFormat.Alignment = $wdCellAlignVerticalTop
			$Table.Cell($xRow,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
			$Table.Cell($xRow,2).Range.Text = $CountStr
		}
		
		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitContent)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null
		
		If($UnknownComputers -ne $Null)
		{
			Write-Verbose "$(Get-Date): `t`tBuild table for unknown computers"
			WriteWordLine 3 0 "Non-Windows Computer Operating Systems"
			$TableRange   = $doc.Application.Selection.Range
			[int]$Columns = 2
			If($UnknownComputers -is [array])
			{
				[int]$Rows = $UnknownComputers.Count + 1
			}
			Else
			{
				[int]$Rows = 2
			}
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.AutoFitBehavior($wdAutoFitFixed)
			$Table.Style = $myHash.Word_TableGrid
			$Table.rows.first.headingformat = $wdHeadingFormatTrue
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
			$Table.Cell(1,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell(1,1).Range.Font.Bold = $True
			$Table.Cell(1,1).Range.Text = "Distinguished Name"
			$Table.Cell(1,2).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell(1,2).Range.Font.Bold = $True
			$Table.Cell(1,2).Range.Text = "Operating System"
			
			[int]$xRow = 1
			
			ForEach($Computer in $UnknownComputers)
			{
				$xRow++
				[string]$CountStr = "{0,7:N0}" -f $Computer.Count
				$Table.Cell($xRow,1).Range.Text = $Computer.DistinguishedName
				If([String]::IsNullOrEmpty($Computer.OperatingSystem))
				{
					$Table.Cell($xRow,2).Range.Text = "<No OS name>"
				}
				Else
				{
					$Table.Cell($xRow,2).Range.Text = $Computer.OperatingSystem
				}
			}
			
			#set column widths
			$xcols = $table.columns

			ForEach($xcol in $xcols)
			{
			    switch ($xcol.Index)
			    {
				  1 {$xcol.width = 400}
				  2 {$xcol.width = 100}
			    }
			}

			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitFixed)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
		}
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving computer data for domain $($xDomain)"
		WriteWordLine 0 0 "Error retrieving computer data for domain $($xDomain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No computer data was retrieved for domain $($xDomain)" "" $Null 0 $False $True
	}
	$Computers = $Null
	$UnknownComputers = $Null
	$Results = $Null
}

#Script begins

$script:startTime = Get-Date

CheckWordPreReq

#If hardware inventory or services are requested, make sure user is running the script with Domain Admin rights
$DARights = $False
If($Hardware -or $Services)
{
	Write-Verbose "$(Get-Date): `tTesting to see if $($env:username) has Domain Admin rights"
	If($Hardware -and -not $Services)
	{
		Write-Verbose "$(Get-Date): Hardware inventory requested"
	}
	ElseIf($Services -and -not $Hardware)
	{
		Write-Verbose "$(Get-Date): Services requested"
	}
	ElseIf($Hardware -and $Services)
	{
		Write-Verbose "$(Get-Date): Hardware inventory and Services requested"
	}

	If(UserIsaDomainAdmin)
	{
		#user has Domain Admin rights
		Write-Verbose "$(Get-Date): $($env:username) has Domain Admin rights in the $($ADForest) Forest"
		$DARights = $True
	}
	Else
	{
		#user does not have Domain Admin rights
		If($Hardware -and -not $Services)
		{
			#don't abort script, set $hardware to false
			Write-Warning "`n`n`t`tHardware inventory was requested but $($WindowsIdentity.Name) does not have Domain Admin rights."
			Write-Warning "`n`n`t`tHardware inventory option will be turned off."
			$Hardware = $False
		}
		ElseIf($Services -and -not $Hardware)
		{
			#don't abort script, set $services to false
			Write-Warning "`n`n`t`tServices were requested but $($WindowsIdentity.Name) does not have Domain Admin rights."
			Write-Warning "`n`n`t`tServices option will be turned off."
			$Services = $False
		}
		ElseIf($Hardware -and $Services)
		{
			#don't abort script, set $hardware and $services to false
			Write-Warning "`n`n`t`tHardware inventory and Services were requested but $($WindowsIdentity.Name) does not have Domain Admin rights."
			Write-Warning "`n`n`t`tHardware inventory and Services options will be turned off."
			$Hardware = $False
			$Services = $False
		}
	}
}

#make sure ActiveDirectory module is loaded
If(!(Check-LoadedModule "ActiveDirectory"))
{
	$ErrorActionPreference = $SaveEAPreference
	Write-Error "`n`n`t`tThe ActiveDirectory module could not be loaded.`nScript cannot continue.`n`n"
	Exit
}

If(![String]::IsNullOrEmpty($ComputerName)) 
{
	#get server name
	#first test to make sure the server is reachable
	Write-Verbose "$(Get-Date): Testing to see if $($ComputerName) is online and reachable"
	If(Test-Connection -ComputerName $ComputerName -quiet)
	{
		Write-Verbose "$(Get-Date): Server $($ComputerName) is online."
		Write-Verbose "$(Get-Date): `tTesting to see if it is a Domain Controller."
		#the server may be online but is it really a domain controller?

		#is the ComputerName in the current domain
		$Results = Get-ADDomainController $ComputerName
		
		If(!$?)
		{
			#try using the Forest name
			$Results = Get-ADDomainController $ComputerName -Server $ADForest
			If(!$?)
			{
				$ErrorActionPreference = $SaveEAPreference
				Write-Error "`n`n`t`t$($ComputerName) is not a domain controller for $($ADForest).`n`t`tScript cannot continue.`n`n"
				Exit
			}
		}
		$Results = $Null
	}
	Else
	{
		Write-Verbose "$(Get-Date): Computer $($ComputerName) is offline"
		$ErrorActionPreference = $SaveEAPreference
		Write-Error "`n`n`t`tComputer $($ComputerName) is offline.`nScript cannot continue.`n`n"
		Exit
	}
}

#if computer name is localhost, get actual server name
If($ComputerName -eq "localhost")
{
	$ComputerName = $env:ComputerName
	Write-Verbose "$(Get-Date): Computer name has been renamed from localhost to $($ComputerName)"
}

#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 = $ComputerName -as [System.Net.IpAddress]
If($ip)
{
	$Result = [System.Net.Dns]::gethostentry($ip)
	
	If($? -and $Result -ne $Null)
	{
		$ComputerName = $Result.HostName
		Write-Verbose "$(Get-Date): Computer name has been renamed from $($ip) to $($ComputerName)"
	}
	Else
	{
		Write-Warning "Unable to resolve $($ComputerName) to a hostname"
	}
}
Else
{
	#server is online but for some reason $ComputerName cannot be converted to a System.Net.IpAddress
}

#get forest information so output filename can be generated
Write-Verbose "$(Get-Date): Testing to see if $($ADForest) is a valid forest name"
If([String]::IsNullOrEmpty($ComputerName))
{
	$Forest = Get-ADForest -Identity $ADForest
	
	If(!$?)
	{
		$ErrorActionPreference = $SaveEAPreference
		Write-Error "`n`n`t`tCould not find a forest identified by: $($ADForest).`nScript cannot continue.`n`n"
		Exit
	}
}
Else
{
	$Forest = Get-ADForest -Identity $ADForest -Server $ComputerName

	If(!$?)
	{
		$ErrorActionPreference = $SaveEAPreference
		Write-Error "`n`n`t`tCould not find a forest with the name of $($ADForest).`n`n`t`tScript cannot continue.`n`n`t`tIs $($ComputerName) running Active Directory Web Services?"
		Exit
	}
}
Write-Verbose "$(Get-Date): $($ADForest) is a valid forest name"
#store root domain so it only has to be accessed once
[string]$ForestRootDomain = $Forest.RootDomain

[string]$ForestName = $Forest.Name
[string]$Title      = "Inventory Report for the $($ForestName) Forest"
If($AddDateTime)
{
	[string]$filename1  = "$($pwd.path)\$($ForestName)"
	If($PDF)
	{
		[string]$filename2 = "$($pwd.path)\$($ForestName)"
	}
}
Else
{
	[string]$filename1  = "$($pwd.path)\$($ForestName).docx"
	If($PDF)
	{
		[string]$filename2 = "$($pwd.path)\$($ForestName).pdf"
	}
}

Write-Verbose "$(Get-Date): Setting up Word"

# Setup word for output
Write-Verbose "$(Get-Date): Create Word comObject.  If you are not running Word 2007, ignore the next message."
$Word = New-Object -comobject "Word.Application" -EA 0

If(!$? -or $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
}

[int]$WordVersion = [int] $Word.Version
If($WordVersion -eq $wdWord2013)
{
	$WordProduct = "Word 2013"
}
ElseIf($WordVersion -eq $wdWord2010)
{
	$WordProduct = "Word 2010"
}
ElseIf($WordVersion -eq $wdWord2007)
{
	$WordProduct = "Word 2007"
}
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
}

If($PDF -and $WordVersion -eq $wdWord2007)
{
	Write-Verbose "$(Get-Date): Verify the Word 2007 Save As PDF add-in is installed"
	If(CheckWord2007SaveAsPDFInstalled)
	{
		Write-Verbose "$(Get-Date): The Word 2007 Save As PDF add-in is installed"
	}
	Else
	{
		AbortScript
	}
}

Write-Verbose "$(Get-Date): Validate company name"
#only validate CompanyName if the field is blank
If([String]::IsNullOrEmpty($CompanyName))
{
	$CompanyName = ValidateCompanyName
	If([String]::IsNullOrEmpty($CompanyName))
	{
		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"
	}
}

Write-Verbose "$(Get-Date): Check Default Cover Page for language specific version"
[bool]$CPChanged = $False
Switch ($PSCulture.Substring(0,3))
{
	'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($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"
[bool]$ValidCP = ValidateCoverPage $WordVersion $CoverPage
If(!$ValidCP)
{
	$ErrorActionPreference = $SaveEAPreference
	Write-Error "`n`n`t`tFor $WordProduct, $CoverPage is not a valid Cover Page option.`n`n`t`tScript cannot continue.`n`n"
	AbortScript
}

Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): Company Name : $CompanyName"
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): HW Inventory : $Hardware"
Write-Verbose "$(Get-Date): Services     : $Services"
Write-Verbose "$(Get-Date): Forest Name  : $ADForest"
Write-Verbose "$(Get-Date): Title        : $Title"
Write-Verbose "$(Get-Date): Filename1    : $filename1"
If($PDF)
{
	Write-Verbose "$(Get-Date): Filename2    : $filename2"
}
Write-Verbose "$(Get-Date): Add DateTime : $AddDateTime"
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 : $WordProduct"
Write-Verbose "$(Get-Date): Word language: $($Word.Language)"
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): "

$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]$CoverPagesExist = $False
[bool]$BuildingBlocksExist = $False

$word.Templates.LoadBuildingBlocks()
If($WordVersion -eq $wdWord2007)
{
	$BuildingBlocks = $word.Templates | Where {$_.name -eq "Building Blocks.dotx"}
}
Else
{
	#word 2010/2013
	$BuildingBlocks = $word.Templates | Where {$_.name -eq "Built-In Building Blocks.dotx"}
}

Write-Verbose "$(Get-Date): Attempt to load cover page $($CoverPage)"
$part = $Null

If($BuildingBlocks -ne $Null)
{
	$BuildingBlocksExist = $True

	Try 
	{
		$part = $BuildingBlocks.BuildingBlockEntries.Item($CoverPage)
	}

	Catch
	{
		$part = $Null
	}

	If($part -ne $Null)
	{
		$CoverPagesExist = $True
	}
}

If(!$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"
$Doc = $Word.Documents.Add()
If($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
}

$Selection = $Word.Selection
If($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"
$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
$CurrentGrammarOption = $Word.Options.CheckGrammarAsYouType
$CurrentSpellingOption = $Word.Options.CheckSpellingAsYouType
$Word.Options.CheckGrammarAsYouType = $False
$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($selection.Range,$True) | Out-Null
	$selection.InsertNewPage()

	#table of contents
	Write-Verbose "$(Get-Date): Table of Contents - $($myHash.Word_TableOfContents)"
	$toc = $BuildingBlocks.BuildingBlockEntries.Item($myHash.Word_TableOfContents)
	If($toc -eq $Null)
	{
		Write-Verbose "$(Get-Date): "
		Write-Verbose "$(Get-Date): Table of Content - $($myHash.Word_TableOfContents) could not be retrieved."
		Write-Warning "This report will not have a Table of Contents."
	}
	Else
	{
		$toc.insert($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"
$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekPrimaryFooter
#get the footer and format font
$footers = $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"
$selection.HeaderFooter.Range.Text = $footerText

#add page numbering
Write-Verbose "$(Get-Date): Add page numbering"
$selection.HeaderFooter.PageNumbers.Add($wdAlignPageNumberRight) | Out-Null

#return focus to main document
$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

#move to the end of the current document
Write-Verbose "$(Get-Date):"
$selection.EndKey($wdStory,$wdMove) | Out-Null
#end of Jeff Hicks 
[gc]::collect() 
######################START OF BUILDING REPORT

#Forest information

#set naming context
$ConfigNC = (Get-ADRootDSE -Server $ADForest).ConfigurationNamingContext

Write-Verbose "$(Get-Date): Writing forest data"

$selection.InsertNewPage()
WriteWordLine 1 0 "Forest Information"

Switch ($Forest.ForestMode)
{
	"Windows2000Forest"        {$ForestMode = "Windows 2000"}
	"Windows2003InterimForest" {$ForestMode = "Windows Server 2003 interim"}
	"Windows2003Forest"        {$ForestMode = "Windows Server 2003"}
	"Windows2008Forest"        {$ForestMode = "Windows Server 2008"}
	"Windows2008R2Forest"      {$ForestMode = "Windows Server 2008 R2"}
	"Windows2012Forest"        {$ForestMode = "Windows Server 2012"}
	"Windows2012R2Forest"      {$ForestMode = "Windows Server 2012 R2"}
	"UnknownForest"            {$ForestMode = "Unknown Forest Mode"}
	Default                    {$ForestMode = "Unable to determine Forest Mode: $($Forest.ForestMode)"}
}

$TableRange = $doc.Application.Selection.Range
[int]$Columns = 2
[int]$Rows = 12
[int]$xRow = 1
$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
$Table.AutoFitBehavior($wdAutoFitFixed)
$Table.Style = $myHash.Word_TableGrid
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle

$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Forest mode"
$Table.Cell($xRow,2).Range.Text = $ForestMode

$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Forest name"
$Table.Cell($xRow,2).Range.Text = $Forest.Name

$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Root domain"
$Table.Cell($xRow,2).Range.Text = $ForestRootDomain

$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Domain naming master"
$Table.Cell($xRow,2).Range.Text = $Forest.DomainNamingMaster

$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Schema master"
$Table.Cell($xRow,2).Range.Text = $Forest.SchemaMaster

$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Partitions container"
$Table.Cell($xRow,2).Range.Text = $Forest.PartitionsContainer

Write-Verbose "$(Get-Date): `tApplication partitions"
$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Application partitions"

$AppPartitions = $Forest.ApplicationPartitions | Sort
If($AppPartitions -eq $Null)
{
	$Table.Cell($xRow,2).Range.Text = "<None>"
}
Else
{
	$tmp = @()
	ForEach($AppPartition in $AppPartitions)
	{
		$tmp += "$($AppPartition)`r"
	}
	$Table.Cell($xRow,2).Range.Text = $tmp
}
$AppPartitions = $Null
$tmp = $Null

Write-Verbose "$(Get-Date): `tCross forest references"
$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Cross forest references"

$CrossForestReferences = $Forest.CrossForestReferences | Sort
If($CrossForestReferences -eq $Null)
{
	$Table.Cell($xRow,2).Range.Text = "<None>"
}
Else
{
	$tmp = @()
	ForEach($CrossForestReference in $CrossForestReferences)
	{
		$tmp += "$($CrossForestReference)`r"
	}
	$Table.Cell($xRow,2).Range.Text = $tmp
}
$CrossForestReferences = $Null
$tmp = $Null

Write-Verbose "$(Get-Date): `tSPN suffixes"
$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "SPN suffixes"
$SPNSuffixes = $Forest.SPNSuffixes | Sort
If($SPNSuffixes -eq $Null)
{
	$Table.Cell($xRow,2).Range.Text = "<None>"
}
Else
{
	$tmp = @()
	ForEach($SPNSuffix in $SPNSuffixes)
	{
		$tmp += "$($SPNSuffix)`r"
	}
	$Table.Cell($xRow,2).Range.Text = $tmp
}
$SPNSuffixes = $Null
$tmp = $Null

Write-Verbose "$(Get-Date): `tUPN suffixes"
$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "UPN Suffixes"
$UPNSuffixes = $Forest.UPNSuffixes | Sort
If($UPNSuffixes -eq $Null)
{
	$Table.Cell($xRow,2).Range.Text = "<None>"
}
Else
{
	$tmp = @()
	ForEach($UPNSuffix in $UPNSuffixes)
	{
		$tmp += "$($UPNSuffix)`r"
	}
	$Table.Cell($xRow,2).Range.Text = $tmp
}
$UPNSuffixes = $Null
$tmp = $Null

Write-Verbose "$(Get-Date): `tDomains in forest"
$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Domains in forest"
$Domains = $Forest.Domains | Sort
If($Domains -eq $Null)
{
	$Table.Cell($xRow,2).Range.Text = "<None>"
}
Else
{
	#redo list of domains so forest root domain is listed first
	$tmpDomains = @($ForestRootDomain)
	$tmpDomains2 = @("$($ForestRootDomain)`r")
	ForEach($Domain in $Domains)
	{
		If($Domain -ne $ForestRootDomain)
		{
			$tmpDomains += "$($Domain)"
			$tmpDomains2 += "$($Domain)`r"
		}
	}
	
	$Domains = $tmpDomains
	$Table.Cell($xRow,2).Range.Text = $tmpDomains2
}

Write-Verbose "$(Get-Date): `tSites"
$xRow++
$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Sites"
$Sites = $Forest.Sites | Sort
If($Sites -eq $Null)
{
	$Table.Cell($xRow,2).Range.Text = "<None>"
}
Else
{
	$tmp = @()
	ForEach($Site in $Sites)
	{
		$tmp += "$($Site)`r"
	}
	$Table.Cell($xRow,2).Range.Text = $tmp
}
$Sites = $Null
$tmp = $Null

#set column widths
$xcols = $table.columns

ForEach($xcol in $xcols)
{
    switch ($xcol.Index)
    {
	  1 {$xcol.width = 125}
	  2 {$xcol.width = 300}
    }
}

$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)

#return focus back to document
$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

#move to the end of the current document
$selection.EndKey($wdStory,$wdMove) | Out-Null
$TableRange = $Null
$Table = $Null

[gc]::collect() 

Write-Verbose "$(Get-Date): `tDomain controllers"
WriteWordLine 3 0 "Domain Controllers"
#get all DCs in the forest
#http://www.superedge.net/2012/09/how-to-get-ad-forest-in-powershell.html
#http://msdn.microsoft.com/en-us/library/vstudio/system.directoryservices.activedirectory.forest.getforest%28v=vs.90%29
$ADContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("forest", $ADForest) 
$Forest2 = [system.directoryservices.activedirectory.Forest]::GetForest($ADContext)
$AllDCs = $Forest2.domains | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name} 
$AllDCs = $AllDCs | Sort
$ADContext = $Null
$Forest2 = $Null

If($AllDCs -eq $Null)
{
	WriteWordLine 0 0 "<None>"
}
Else
{
	$TableRange = $doc.Application.Selection.Range
	[int]$Columns = 3
	If($AllDCs -is [array])
	{
		[int]$Rows = $AllDCs.Count + 1
	}
	Else
	{
		[int]$Rows = 2
	}
	$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
	$Table.Style = $myHash.Word_TableGrid
	$Table.Borders.InsideLineStyle = $wdLineStyleSingle
	$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
	$Table.rows.first.headingformat = $wdHeadingFormatTrue
	$Table.Cell(1,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell(1,1).Range.Font.Bold = $True
	$Table.Cell(1,1).Range.Text = "Name"
	$Table.Cell(1,2).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell(1,2).Range.Font.Bold = $True
	$Table.Cell(1,2).Range.Text = "Global Catalog"
	$Table.Cell(1,3).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell(1,3).Range.Font.Bold = $True
	$Table.Cell(1,3).Range.Text = "Read-only"
	[int]$xRow = 1
	ForEach($DC in $AllDCs)
	{
		$DCName = $DC.SubString(0,$DC.IndexOf("."))
		$SrvName = $DC.SubString($DC.IndexOf(".")+1)
		$xRow++
		$Table.Cell($xRow,1).Range.Text = $DC
		
		$Results = Get-ADDomainController -Identity $DCName -Server $SrvName
		
		If($? -and $Results -ne $Null)
		{
			$Table.Cell($xRow,2).Range.Text = $Results.IsGlobalCatalog
			$Table.Cell($xRow,3).Range.Text = $Results.IsReadOnly
		}
		Else
		{
			$Table.Cell($xRow,2).Range.Text = "Unknown"
			$Table.Cell($xRow,3).Range.Text = "Unknown"
		}
		$Results = $Null
	}
	$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
	$Table.AutoFitBehavior($wdAutoFitContent)

	#return focus back to document
	$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

	#move to the end of the current document
	$selection.EndKey($wdStory,$wdMove) | Out-Null
	$TableRange = $Null
	$Table = $Null
}
$AllDCs = $Null
[gc]::collect() 

#Site information
Write-Verbose "$(Get-Date): Writing sites and services data"

$selection.InsertNewPage()
WriteWordLine 1 0 "Site and Services"

#get site information
#some of the following was taken from
#http://blogs.msdn.com/b/adpowershell/archive/2009/08/18/active-directory-powershell-to-manage-sites-and-subnets-part-3-getting-site-and-subnets.aspx

$tmp = $Forest.PartitionsContainer
$ConfigurationBase = $tmp.SubString($tmp.IndexOf(",") + 1)
$Sites = $Null
$Sites = Get-ADObject -Filter 'ObjectClass -eq "site"' -SearchBase $ConfigurationBase -Properties Name, SiteObjectBl -Server $ADForest | Sort Name

$siteContainerDN = ("CN=Sites," + $configNC)

If($? -and $Sites -ne $Null)
{
	WriteWordLine 2 0 "Inter-Site Transports"
	Write-Verbose "$(Get-Date): `tProcessing Inter-Site Transports"
	#adapted from code provided by Jeremy Saunders
	# Report of all site links and related settings
	$AllSiteLinks = Get-ADObject -Searchbase $ConfigNC -Server $ComputerName `
	-Filter 'objectClass -eq "siteLink"' -Property Description, Options, Cost, ReplInterval, SiteList, Schedule `
	| Select-Object Name, Description, @{Name="SiteCount";Expression={$_.SiteList.Count}}, Cost, ReplInterval, `
	@{Name="Schedule";Expression={If($_.Schedule){If(($_.Schedule -Join " ").Contains("240")){"NonDefault"}Else{"24x7"}}Else{"24x7"}}}, `
	Options, SiteList, DistinguishedName
	
	If($? -and $AllSiteLinks -ne $Null)
	{
		ForEach($SiteLink in $AllSiteLinks)
		{
			Write-Verbose "$(Get-Date): `t`tProcessing site link $($SiteLink.Name)"
			$SiteLinkTypeDN = @()
			$SiteLinkTypeDN = $SiteLink.DistinguishedName.Split(",")
			$SiteLinkType = $SiteLinkTypeDN[1].SubString(3)
			$SitesInLink = ""
			$SiteLinkSiteList = $SiteLink.SiteList
			ForEach($xSite in $SiteLinkSiteList)
			{
				$tmp = $xSite.Split(",")
				$SitesInLink += "$($tmp[0].SubString(3))`r"
			}
			
			$TableRange = $doc.Application.Selection.Range
			[int]$Columns = 2
			If([String]::IsNullOrEmpty($SiteLink.Description))
			{
				[int]$Rows = 7
			}
			Else
			{
				[int]$Rows = 8
			}
			[int]$xRow = 0
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.Style = $myHash.Word_TableGrid
			$Table.rows.first.headingformat = $wdHeadingFormatTrue
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Name"
			$Table.Cell($xRow,2).Range.Text = $SiteLink.Name
			If(![String]::IsNullOrEmpty($SiteLink.Description))
			{
				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Description"
				$Table.Cell($xRow,2).Range.Text = $SiteLink.Description
			}
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Sites in Link"
			If($SitesInLink -ne " ")
			{
				$Table.Cell($xRow,2).Range.Text = $SitesInLink
			}
			Else
			{
				$Table.Cell($xRow,2).Range.Text = "<None>"
			}
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Cost"
			$Table.Cell($xRow,2).Range.Text = $SiteLink.Cost
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Replication Interval"
			$Table.Cell($xRow,2).Range.Text = $SiteLink.ReplInterval
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Schedule"
			$Table.Cell($xRow,2).Range.Text = $SiteLink.Schedule
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Options"
			If([String]::IsNullOrEmpty($SiteLink.Options))
			{
				$Table.Cell($xRow,2).Range.Text = "Change Notification is Disabled"
			}
			ElseIf($SiteLink.Options -eq "1" -or $SiteLink.Options -eq "5")
			{
				$Table.Cell($xRow,2).Range.Text = "Change Notification is Enabled"
			}
			Else
			{
				$Table.Cell($xRow,2).Range.Text = "Unknown"
			}
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Type"
			$Table.Cell($xRow,2).Range.Text = $SiteLinkType
			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitContent)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
			WriteWordLine 0 0 ""
		}
	}
	$AllSiteLinks = $Null
	
	ForEach($Site in $Sites)
	{
		Write-Verbose "$(Get-Date): `tProcessing site $($Site.Name)"
		WriteWordLine 2 0 $Site.Name

		WriteWordLine 3 0 "Subnets"
		Write-Verbose "$(Get-Date): `t`tProcessing subnets"
		$subnetArray = New-Object -Type string[] -ArgumentList $Site.siteObjectBL.Count
		$i = 0
		$SitesiteObjectBL = $Site.siteObjectBL
		foreach ($subnetDN in $SitesiteObjectBL) 
		{
			$subnetName = $subnetDN.SubString(3, $subnetDN.IndexOf(",CN=Subnets,CN=Sites,") - 3)
			$subnetArray[$i] = $subnetName
			$i++
		}
		$subnetArray = $subnetArray | Sort
		If($subnetArray -eq $Null)
		{
			WriteWordLine 0 0 "<None>"
		}
		Else
		{
			BuildMultiColumnTable $subnetArray "Subnets"
		}
		
		Write-Verbose "$(Get-Date): `t`tProcessing servers"
		WriteWordLine 3 0 "Servers"
		$siteName = $Site.Name
		
		#build array of connect objects
		Write-Verbose "$(Get-Date): `t`t`tProcessing automatic connection objects"
		$Connections = @()
		$ConnnectionObjects = $Null
		$ConnectionObjects = Get-ADObject -Filter 'objectClass -eq "nTDSConnection" -and options -bor 1' -Searchbase $ConfigNC -Property DistinguishedName, fromServer -Server $ADForest
		
		If($? -and $ConnectionObjects -ne $Null)
		{
			ForEach($ConnectionObject in $ConnectionObjects)
			{
				$xArray = $ConnectionObject.DistinguishedName.Split(",")
				#server name is 3rd item in array (element 2)
				$ToServer = $xArray[2].SubString($xArray[2].IndexOf("=")+1) #get past the = sign
				$xArray = $ConnectionObject.FromServer.Split(",")
				#server name is 2nd item in array (element 1)
				$FromServer = $xArray[1].SubString($xArray[1].IndexOf("=")+1) #get past the = sign
				#site name is 4th item in array (element 3)
				$FromServerSite = $xArray[3].SubString($xArray[3].IndexOf("=")+1) #get past the = sign
				$xArray = $Null
				$obj = New-Object -TypeName PSObject
				$obj | Add-Member -MemberType NoteProperty -Name Name           -Value "<automatically generated>"
				$obj | Add-Member -MemberType NoteProperty -Name ToServer       -Value $ToServer
				$obj | Add-Member -MemberType NoteProperty -Name FromServer     -Value $FromServer
				$obj | Add-Member -MemberType NoteProperty -Name FromServerSite -Value $FromServerSite
				$Connections += $obj
			}
		}
		
		Write-Verbose "$(Get-Date): `t`t`tProcessing manual connection objects"
		$ConnectionObjects = $Null
		$ConnectionObjects = Get-ADObject -Filter 'objectClass -eq "nTDSConnection" -and -not options -bor 1' -Searchbase $ConfigNC -Property Name, DistinguishedName, fromServer -Server $ADForest
		
		If($? -and $ConnectionObjects -ne $Null)
		{
			ForEach($ConnectionObject in $ConnectionObjects)
			{
				$xArray = $ConnectionObject.DistinguishedName.Split(",")
				#server name is 3rd item in array (element 2)
				$ToServer = $xArray[2].SubString($xArray[2].IndexOf("=")+1) #get past the = sign
				$xArray = $ConnectionObject.FromServer.Split(",")
				#server name is 2nd item in array (element 1)
				$FromServer = $xArray[1].SubString($xArray[1].IndexOf("=")+1) #get past the = sign
				#site name is 4th item in array (element 3)
				$FromServerSite = $xArray[3].SubString($xArray[3].IndexOf("=")+1) #get past the = sign
				$xArray = $Null
				$obj = New-Object -TypeName PSObject
				$obj | Add-Member -MemberType NoteProperty -Name Name           -Value $ConnectionObject.Name
				$obj | Add-Member -MemberType NoteProperty -Name ToServer       -Value $ToServer
				$obj | Add-Member -MemberType NoteProperty -Name FromServer     -Value $FromServer
				$obj | Add-Member -MemberType NoteProperty -Name FromServerSite -Value $FromServerSite
				$Connections += $obj
			}
		}

		If($Connections -ne $Null)
		{
			$Connections = $Connections | Sort Name, ToServer, FromServer
		}
		
		#list each server
		$serverContainerDN = "CN=Servers,CN=" + $siteName + "," + $siteContainerDN
		$SiteServers = $Null
		$SiteServers = Get-ADObject -SearchBase $serverContainerDN -SearchScope OneLevel -Filter { objectClass -eq "Server" } -Properties "DNSHostName" -Server $ADForest | Select DNSHostName, Name | Sort DNSHostName
		
		If($? -and $SiteServers -ne $Null)
		{
			$First = $True
			ForEach($SiteServer in $SiteServers)
			{
				If(!$First)
				{
					WriteWordLine 0 0 ""
				}
				WriteWordLine 0 0 $SiteServer.DNSHostName
				#for each server list each connection object
				If($Connections -ne $Null)
				{
					$Results = $Connections | Where {$_.ToServer -eq $SiteServer.Name}

					If($? -and $Results -ne $Null)
					{
						WriteWordLine 0 1 "Connection Objects to source server $($SiteServer.Name)"
						$TableRange = $doc.Application.Selection.Range
						[int]$Columns = 3
						If($Results -is [array])
						{
							[int]$Rows = $Results.Count + 1
						}
						Else
						{
							[int]$Rows = 2
						}
						[int]$xRow = 1
						$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
						$Table.Style = $myHash.Word_TableGrid
						$Table.rows.first.headingformat = $wdHeadingFormatTrue
						$Table.Borders.InsideLineStyle = $wdLineStyleSingle
						$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
						$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
						$Table.Cell($xRow,1).Range.Font.Bold = $True
						$Table.Cell($xRow,1).Range.Text = "Name"
						$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
						$Table.Cell($xRow,2).Range.Font.Bold = $True
						$Table.Cell($xRow,2).Range.Text = "From Server"
						$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
						$Table.Cell($xRow,3).Range.Font.Bold = $True
						$Table.Cell($xRow,3).Range.Text = "From Site"
						ForEach($Result in $Results)
						{
							$xRow++
							$Table.Cell($xRow,1).Range.Text = $Result.Name
							$Table.Cell($xRow,2).Range.Text = $Result.FromServer
							$Table.Cell($xRow,3).Range.Text = $Result.FromServerSite
						}
						$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustNone)
						$Table.AutoFitBehavior($wdAutoFitContent)

						#return focus back to document
						$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

						#move to the end of the current document
						$selection.EndKey($wdStory,$wdMove) | Out-Null
						$TableRange = $Null
						$Table = $Null
					}
				}
				Else
				{
					WriteWordLine 0 3 "Connection Objects: "
					WriteWordLine 0 4 "<None>"
				}
				$First = $False
			}
		}
		ElseIf(!$?)
		{
			Write-Warning "No Site Servers were retrieved."
			WriteWordLine 0 0 "Warning: No Site Servers were retrieved" "" $Null 0 $False $True
		}
		Else
		{
			WriteWordLine 0 0 "No servers in this site"
		}
	}
}
ElseIf(!$?)
{
	Write-Warning "No Sites were retrieved."
	WriteWordLine 0 0 "Warning: No Sites were retrieved" "" $Null 0 $False $True
}
Else
{
	Write-Warning "There were no sites found to retrieve."
	WriteWordLine 0 0 "There were no sites found to retrieve" "" $Null 0 $False $True
}
$Sites = $Null
$siteContainerDN = $Null
$AllSiteLinks = $Null
$SiteLinkTypeDN = $Null
$SiteLinkType = $Null
$SitesInLink = $Null
$SiteLinkSiteList = $Null
$subnetArray = $Null
$subnetName = $Null
$connections = $Null
$ConnectionObjects = $Null
$SiteName = $Null
$serverContainerDN = $Null
$SiteServers = $Null
$Results = $Null

#domains
Write-Verbose "$(Get-Date): Writing domain data"

$selection.InsertNewPage()
WriteWordLine 1 0 "Domain Information"
$AllDomainControllers = @()
$First = $True
#http://technet.microsoft.com/en-us/library/bb125224(v=exchg.150).aspx
#http://support.microsoft.com/kb/556086/he
$SchemaVersionTable = @{ 
"13" = "Windows 2000"; 
"30" = "Windows 2003 RTM, SP1, SP2"; 
"31" = "Windows 2003 R2";
"44" = "Windows 2008"; 
"47" = "Windows 2008 R2";
"56" = "Windows Server 2012"
"69" = "Windows Server 2012 R2"
"4397" = "Exchange 2000 RTM"; 
"4406" = "Exchange 2000 SP3";
"6870" = "Exchange 2003 RTM, SP1, SP2"; 
"6936" = "Exchange 2003 SP3"; 
"10637" = "Exchange 2007 RTM";
"11116" = "Exchange 2007 SP1"; 
"14622" = "Exchange 2007 SP2, Exchange 2010 RTM";
"14625" = "Exchange 2007 SP3";
"14726" = "Exchange 2010 SP1";
"14732" = "Exchange 2010 SP2";
"14734" = "Exchange 2010 SP3";
"15137" = "Exchange 2013 RTM";
"15254" = "Exchange 2013 CU1";
"15281" = "Exchange 2013 CU2";
"15283" = "Exchange 2013 CU3";
"15292" = "Exchange 2013 SP1"
}

ForEach($Domain in $Domains)
{
	Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"

	$DomainInfo = Get-ADDomain -Identity $Domain
	
	If($? -and $DomainInfo -ne $Null)
	{
		If(!$First)
		{
			#put each domain, starting with the second, on a new page
			$selection.InsertNewPage()
		}
		
		If($Domain -eq $ForestRootDomain)
		{
			WriteWordLine 2 0 "$($Domain) (Forest Root)"
		}
		Else
		{
			WriteWordLine 2 0 $Domain
		}

		Switch ($DomainInfo.DomainMode)
		{
			"Windows2000Domain"   {$DomainMode = "Windows 2000"}
			"Windows2003Mixed"    {$DomainMode = "Windows Server 2003 mixed"}
			"Windows2003Domain"   {$DomainMode = "Windows Server 2003"}
			"Windows2008Domain"   {$DomainMode = "Windows Server 2008"}
			"Windows2008R2Domain" {$DomainMode = "Windows Server 2008 R2"}
			"Windows2012Domain"   {$DomainMode = "Windows Server 2012"}
			"Windows2012R2Domain" {$DomainMode = "Windows Server 2012 R2"}
			"UnknownForest"       {$DomainMode = "Unknown Domain Mode"}
			Default               {$DomainMode = "Unable to determine Domain Mode: $($ADDomain.DomainMode)"}
		}
		
		#http://blogs.technet.com/b/poshchap/archive/2014/03/07/ad-schema-version.aspx
		$ADSchemaInfo = $Null
		$ExchangeSchemaInfo = $Null
		
		$ADSchemaInfo = Get-ADObject (Get-ADRootDSE -Server $Domain).schemaNamingContext -Property objectVersion -Server $Domain
		
		If($? -and $ADSchemaInfo -ne $Null)
		{
			$ADSchemaVersion = $ADSchemaInfo.objectversion
			$ADSchemaVersionName = $SchemaVersionTable.Get_Item("$ADSchemaVersion")
			If($ADSchemaVersionName -eq $Null)
			{
				$ADSchemaVersionName = "Unknown"
			}
		}
		Else
		{
			$ADSchemaVersion = "Unknown"
			$ADSchemaVersionName = "Unknown"
		}
		
		If($Domain -eq $ForestRootDomain)
		{
			$ExchangeSchemaInfo = Get-ADObject "cn=ms-exch-schema-version-pt,cn=Schema,cn=Configuration,$($DomainInfo.DistinguishedName)" -properties rangeupper -Server $Domain

			If($? -and $ExchangeSchemaInfo -ne $Null)
			{
				$ExchangeSchemaVersion = $ExchangeSchemaInfo.rangeupper
				$ExchangeSchemaVersionName = $SchemaVersionTable.Get_Item("$ExchangeSchemaVersion")
				If($ExchangeSchemaVersionName -eq $Null)
				{
					$ExchangeSchemaVersionName = "Unknown"
				}
			}
			Else
			{
				$ExchangeSchemaVersion = "Unknown"
				$ExchangeSchemaVersionName = "Unknown"
			}
		}
		
		$TableRange = $doc.Application.Selection.Range
		[int]$Columns = 2
		[int]$Rows = 22
		If(![String]::IsNullOrEmpty($DomainInfo.ManagedBy))
		{
			$Rows++
		}
		
		If(![String]::IsNullOrEmpty($ExchangeSchemaInfo))
		{
			$Rows++
		}
		
		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.AutoFitBehavior($wdAutoFitFixed)	
		$Table.Style = $myHash.Word_TableGrid
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
		
		[int]$xRow = 1
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Domain mode"
		$Table.Cell($xRow,2).Range.Text = $DomainMode

		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Domain name"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.Name

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "NetBIOS name"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.NetBIOSName

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "DNS root"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.DNSRoot

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Distinguished name"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.DistinguishedName

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Infrastructure master"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.InfrastructureMaster

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "PDC Emulator"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.PDCEmulator

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "RID Master"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.RIDMaster

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Default computers container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.ComputersContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Default users container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.UsersContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Deleted objects container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.DeletedObjectsContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Domain controllers container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.DomainControllersContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Foreign security principals container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.ForeignSecurityPrincipalsContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Lost and Found container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.LostAndFoundContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Quotas container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.QuotasContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Systems container"
		$Table.Cell($xRow,2).Range.Text = $DomainInfo.SystemsContainer

		$xRow++		
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "AD Schema"
		$Table.Cell($xRow,2).Range.Text = "($($ADSchemaVersion)) - $($ADSchemaVersionName)"
		
		If(![String]::IsNullOrEmpty($ExchangeSchemaInfo))
		{
			$xRow++		
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Exchange Schema"
			$Table.Cell($xRow,2).Range.Text = "($($ExchangeSchemaVersion)) - $($ExchangeSchemaVersionName)"
		}
		
		If(![String]::IsNullOrEmpty($DomainInfo.ManagedBy))
		{
			$xRow++
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Managed by"
			$Table.Cell($xRow,2).Range.Text = $DomainInfo.ManagedBy
		}

		Write-Verbose "$(Get-Date): `t`tGetting Allowed DNS Suffixes"
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Allowed DNS Suffixes"
		$DNSSuffixes = $DomainInfo.AllowedDNSSuffixes | Sort
		If($DNSSuffixes -eq $Null)
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$tmp = @()
			ForEach($DNSSuffix in $DNSSuffixes)
			{
				$tmp += "$($DNSSuffix)`r"
			}
			$Table.Cell($xRow,2).Range.Text = $tmp
		}
		$DNSSuffixes = $Null
		$tmp = $Null

		Write-Verbose "$(Get-Date): `t`tGetting Child domains"
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Child domains"
		$ChildDomains = $DomainInfo.ChildDomains | Sort
		If($ChildDomains -eq $Null)
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$tmp = @()
			ForEach($ChildDomain in $ChildDomains)
			{
				$tmp += "$($ChildDomain)`r"
			}
			$Table.Cell($xRow,2).Range.Text = $tmp
		}
		$ChildDOmains = $Null
		$tmp = $Null

		Write-Verbose "$(Get-Date): `t`tGetting Read-only replica directory servers"
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Read-only replica directory servers"
		$ReadOnlyReplicas = $DomainInfo.ReadOnlyReplicaDirectoryServers | Sort
		If($ReadOnlyReplicas -eq $Null)
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$tmp = @()
			ForEach($ReadOnlyReplica in $ReadOnlyReplicas)
			{
				$tmp += "$($ReadOnlyReplica)`r"
			}
			$Table.Cell($xRow,2).Range.Text = $tmp
		}
		$ReadOnlyReplicas = $Null
		$tmp = $Null

		Write-Verbose "$(Get-Date): `t`tGetting Replica directory servers"
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Replica directory servers"
		$Replicas = $DomainInfo.ReplicaDirectoryServers | Sort
		If($Replicas -eq $Null)
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$tmp = @()
			ForEach($Replica in $Replicas)
			{
				$tmp += "$($Replica)`r"
			}
			$Table.Cell($xRow,2).Range.Text = $tmp
		}
		$Replicas = $Null
		$tmp = $Null

		Write-Verbose "$(Get-Date): `t`tGetting Subordinate references"
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Subordinate references"
		$SubordinateReferences = $DomainInfo.SubordinateReferences | Sort
		If($SubordinateReferences -eq $Null)
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$tmp = @()
			ForEach($SubordinateReference in $SubordinateReferences)
			{
				$tmp += "$($SubordinateReference)`r"
			}
			$Table.Cell($xRow,2).Range.Text = $tmp
		}
		$SubordinateReferences = $Null
		$tmp = $Null
		
		#set column widths
		$xcols = $table.columns

		ForEach($xcol in $xcols)
		{
		    switch ($xcol.Index)
		    {
			  1 {$xcol.width = 175}
			  2 {$xcol.width = 300}
		    }
		}
		
		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitFixed)	

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null

		Write-Verbose "$(Get-Date): `t`tGetting domain trusts"
		WriteWordLine 3 0 "Domain trusts"
		
		$ADDomainTrusts = $Null
		$ADDomainTrusts = Get-ADObject -Filter {ObjectClass -eq "trustedDomain"} -Server $Domain -Properties *

		If($? -and $ADDomainTrusts -ne $Null)
		{
			
			ForEach($Trust in $ADDomainTrusts) 
			{ 
				$TableRange = $doc.Application.Selection.Range
				[int]$Columns = 2
				If([String]::IsNullOrEmpty($Trust.Description))
				{
					[int]$Rows = 6
				}
				Else
				{
					[int]$Rows = 7
				}
				[int]$xRow = 0
				$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
				$Table.Style = $myHash.Word_TableGrid
				$Table.Borders.InsideLineStyle = $wdLineStyleSingle
				$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Name"
				$Table.Cell($xRow,2).Range.Text = $Trust.Name 
				
				If(![String]::IsNullOrEmpty($Trust.Description))
				{
					$xRow++
					$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
					$Table.Cell($xRow,1).Range.Font.Bold = $True
					$Table.Cell($xRow,1).Range.Text = "Description"
					$Table.Cell($xRow,2).Range.Text = $Trust.Description
				}
				
				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Created"
				$Table.Cell($xRow,2).Range.Text = $Trust.Created
				
				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Modified"
				$Table.Cell($xRow,2).Range.Text = $Trust.Modified

				$TrustDirectionNumber = $Trust.TrustDirection
				$TrustTypeNumber = $Trust.TrustType
				$TrustAttributesNumber = $Trust.TrustAttributes

				#http://msdn.microsoft.com/en-us/library/cc234293.aspx
				Switch ($TrustTypeNumber) 
				{ 
					1 { $TrustType = "Trust with a Windows domain not running Active Directory"} 
					2 { $TrustType = "Trust with a Windows domain running Active Directory"} 
					3 { $TrustType = "Trust with a non-Windows-compliant Kerberos distribution"} 
					4 { $TrustType = "Trust with a DCE realm (not used)"} 
					Default { $TrustType = "Invalid Trust Type of $($TrustTypeNumber)" }
				} 
				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Type"
				If($TrustTypeNumber -lt 1 -or $TrustTypeNumber -gt 4)
				{
					$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorRed
					$Table.Cell($xRow,2).Range.Font.Bold  = $True
					$Table.Cell($xRow,2).Range.Font.Color = $WDColorBlack
				}
				$Table.Cell($xRow,2).Range.Text = $TrustType

				#http://msdn.microsoft.com/en-us/library/cc223779.aspx
				#thanks to fellow CTP Jeremy Saunders for the following switch stmt for trustAttributes
				#I adapted his code
				$attributes = @()
				$hextrustAttributesValue = '{0:X}' -f $trustAttributesNumber
				Switch ($hextrustAttributesValue)
				{
					{($hextrustAttributesValue -bor 0x00000001) -eq $hextrustAttributesValue} 
						{$attributes += "Non-Transitive"}
					
					{($hextrustAttributesValue -bor 0x00000002) -eq $hextrustAttributesValue} 
						{$attributes += "Uplevel clients only"}
					
					{($hextrustAttributesValue -bor 0x00000004) -eq $hextrustAttributesValue} 
						{$attributes += "Quarantined Domain (External, SID Filtering)"}
					
					{($hextrustAttributesValue -bor 0x00000008) -eq $hextrustAttributesValue} 
						{$attributes += "Cross-Organizational Trust (Selective Authentication)"}
					
					{($hextrustAttributesValue -bor 0x00000010) -eq $hextrustAttributesValue} 
						{$attributes += "Intra-Forest Trust"}
					
					{($hextrustAttributesValue -bor 0x00000020) -eq $hextrustAttributesValue} 
						{$attributes += "Inter-Forest Trust"}
					
					{($hextrustAttributesValue -bor 0x00000040) -eq $hextrustAttributesValue} 
						{$attributes += "MIT Trust using RC4 Encryption"}
					
					{($hextrustAttributesValue -bor 0x00000200) -eq $hextrustAttributesValue} 
						{$attributes += "Cross organization Trust no TGT delegation"}
				}

				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Attributes"
				$tmp = @()
				ForEach($attribute in $attributes)
				{
					$tmp += "$($attribute)`r"
				}
				$Table.Cell($xRow,2).Range.Text = $tmp

				#http://msdn.microsoft.com/en-us/library/cc223768.aspx
				Switch ($TrustDirectionNumber) 
				{ 
					0 { $TrustDirection = "Disabled"} 
					1 { $TrustDirection = "Inbound"} 
					2 { $TrustDirection = "Outbound"} 
					3 { $TrustDirection = "Bidirectional"} 
					Default { $TrustDirection = $TrustDirectionNumber }
				}
				$xRow++
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Direction"
				$Table.Cell($xRow,2).Range.Text = $TrustDirection
				
				$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
				$Table.AutoFitBehavior($wdAutoFitContent)

				#return focus back to document
				$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

				#move to the end of the current document
				$selection.EndKey($wdStory,$wdMove) | Out-Null
				$TableRange = $Null
				$Table = $Null
				WriteWordLine 0 0 ""
			}
		}
		ElseIf(!$?)
		{
			#error retrieving domain trusts
			Write-Warning "Error retrieving domain trusts for $($Domain)"
			WriteWordLine 0 0 "Error retrieving domain trusts for $($Domain)" "" $Null 0 $False $True
		}
		Else
		{
			#no domain trust data
			WriteWordLine 0 0 "<None>"
		}

		Write-Verbose "$(Get-Date): `t`tProcessing domain controllers"
		$DomainControllers = $Null
		$DomainControllers = Get-ADDomainController -Filter * -Server $DomainInfo.DNSRoot | Sort Name
		
		If($? -and $DomainControllers -ne $Null)
		{
			$AllDomainControllers += $DomainControllers
			WriteWordLine 3 0 "Domain Controllers"
			$TableRange = $doc.Application.Selection.Range
			[int]$Columns = 1
			If($DomainControllers -is [array])
			{
				[int]$Rows = $DomainControllers.Count
			}
			Else
			{
				[int]$Rows = 1
			}
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.AutoFitBehavior($wdAutoFitFixed)
			$Table.Style = $myHash.Word_TableGrid
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
			[int]$xRow = 0
			ForEach($DomainController in $DomainControllers)
			{
				$xRow++
				$Table.Cell($xRow,1).Range.Text = $DomainController.Name
			}
			#set column widths
			$xcols = $table.columns

			ForEach($xcol in $xcols)
			{
			    switch ($xcol.Index)
			    {
				  1 {$xcol.width = 100}
			    }
			}

			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitFixed)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
		}
		ElseIf(!$?)
		{
			Write-Warning "Error retrieving domain controller data for domain $($Domain)"
			WriteWordLine 0 0 "Error retrieving domain controller data for domain $($Domain)" "" $Null 0 $False $True
		}
		Else
		{
			WriteWordLine 0 0 "No Domain controller data was retrieved for domain $($Domain)" "" $Null 0 $False $True
		}
		
		$DomainControllers = $Null
		$LinkedGPOs = $Null
		$SubordinateReferences = $Null
		$Replicas = $Null
		$ReadOnlyReplicas = $Null
		$ChildDomains = $Null
		$DNSSuffixes = $Null
		$First = $False
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving domain data for domain $($Domain)."
		WriteWordLine 0 0 "Error retrieving domain data for domain $($Domain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No Domain data was retrieved for domain $($Domain)" "" $Null 0 $False $True
	}
}
$DomainControllers = $Null
$LinkedGPOs = $Null
$SubordinateReferences = $Null
$Replicas = $Null
$ReadOnlyReplicas = $Null
$ChildDomains = $Null
$DNSSuffixes = $Null
$First = $False
$SchemaVersionTable = $Null
$DomainInfo = $Null
$ADSchemaInfo = $Null
$ExchangeSchemaInfo = $Null
$ADDomainTrusts = $Null
$attributes = $Null
[gc]::collect() 

#domain controllers
Write-Verbose "$(Get-Date): Writing domain controller data"

$selection.InsertNewPage()
WriteWordLine 1 0 "Domain Controllers in $($ForestName)"
$AllDomainControllers = $AllDomainControllers | Sort Name
$First = $True

ForEach($DC in $AllDomainControllers)
{
	Write-Verbose "$(Get-Date): `tProcessing domain controller $($DC.name)"
	
	If(!$First)
	{
		#put each DC, starting with the second, on a new page
		$selection.InsertNewPage()
	}
	
	WriteWordLine 2 0 $DC.Name
	$TableRange = $doc.Application.Selection.Range
	[int]$Columns = 2
	If(!$Hardware)
	{
		[int]$Rows = 16
	}
	Else
	{
		[int]$Rows = 14
	}
	$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
	$Table.AutoFitBehavior($wdAutoFitFixed)
	$Table.Style = $myHash.Word_TableGrid
	$Table.Borders.InsideLineStyle = $wdLineStyleSingle
	$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
	$xRow = 1
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Default partition"
	$Table.Cell($xRow,2).Range.Text = $DC.DefaultPartition
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Domain"
	$Table.Cell($xRow,2).Range.Text = $DC.domain
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Enabled"
	If($DC.Enabled -eq $True)
	{
		$Table.Cell($xRow,2).Range.Text = "True"
	}
	Else
	{
		$Table.Cell($xRow,2).Range.Text = "False"
	}
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Hostname"
	$Table.Cell($xRow,2).Range.Text = $DC.HostName
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Global Catalog"
	If($DC.IsGlobalCatalog -eq $True)
	{
		$Table.Cell($xRow,2).Range.Text = "Yes" 
	}
	Else
	{
		$Table.Cell($xRow,2).Range.Text = "No"
	}
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Read-only"
	If($DC.IsReadOnly -eq $True)
	{
		$Table.Cell($xRow,2).Range.Text = "Yes"
	}
	Else
	{
		$Table.Cell($xRow,2).Range.Text = "No"
	}
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "LDAP port"
	$Table.Cell($xRow,2).Range.Text = $DC.LdapPort
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "SSL port"
	$Table.Cell($xRow,2).Range.Text = $DC.SslPort
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Operation Master roles"
	$FSMORoles = $DC.OperationMasterRoles | Sort
	If($FSMORoles -eq $Null)
	{
		$Table.Cell($xRow,2).Range.Text = "<None>"
	}
	Else
	{
		$tmp = ""
		ForEach($FSMORole in $FSMORoles)
		{
			$tmp += ($FSMORole.ToString() + "`n")
		}
		$Table.Cell($xRow,2).Range.Text = $tmp
	}
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Partitions"
	$Partitions = $DC.Partitions | Sort
	If($Partitions -eq $Null)
	{
		$Table.Cell($xRow,2).Range.Text = "<None>"
	}
	Else
	{
		$tmp = ""
		ForEach($Partition in $Partitions)
		{
			$tmp += ($Partition + "`n")
		}
		$Table.Cell($xRow,2).Range.Text = $tmp
	}
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Site"
	$Table.Cell($xRow,2).Range.Text = $DC.Site

	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Operating System"
	$Table.Cell($xRow,2).Range.Text = $DC.OperatingSystem
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Service Pack"
	$Table.Cell($xRow,2).Range.Text = $DC.OperatingSystemServicePack
	
	$xRow++
	$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
	$Table.Cell($xRow,1).Range.Font.Bold = $True
	$Table.Cell($xRow,1).Range.Text = "Operating System version"
	$Table.Cell($xRow,2).Range.Text = $DC.OperatingSystemVersion
	
	If(!$Hardware)
	{
		
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "IPv4 Address"
		If([String]::IsNullOrEmpty($DC.IPv4Address))
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$Table.Cell($xRow,2).Range.Text = $DC.IPv4Address
		}
		
		$xRow++
		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "IPv6 Address"
		If([String]::IsNullOrEmpty($DC.IPv6Address))
		{
			$Table.Cell($xRow,2).Range.Text = "<None>"
		}
		Else
		{
			$Table.Cell($xRow,2).Range.Text = $DC.IPv6Address
		}
	}
	
	#set column widths
	$xcols = $table.columns

	ForEach($xcol in $xcols)
	{
	    switch ($xcol.Index)
	    {
		  1 {$xcol.width = 140}
		  2 {$xcol.width = 300}
	    }
	}

	$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
	$Table.AutoFitBehavior($wdAutoFitFixed)

	#return focus back to document
	$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

	#move to the end of the current document
	$selection.EndKey($wdStory,$wdMove) | Out-Null
	$TableRange = $Null
	$Table = $Null
	
	If($Hardware -or $Services)
	{
		If(Test-Connection -ComputerName $DC.name -quiet -EA 0)
		{
			If($Hardware)
			{
				GetComputerWMIInfo $DC.Name
			}
			
			If($Services)
			{
				GetComputerServices $DC.Name
			}
		}
		Else
		{
			Write-Verbose "$(Get-Date): `t`t$($DC.Name) is offline or unreachable.  Hardware inventory is skipped."
			WriteWordLine 0 0 "Server $($DC.Name) was offline or unreachable at "(get-date).ToString()
			If($Hardware -and -not $Services)
			{
				WriteWordLine 0 0 "Hardware inventory was skipped."
			}
			ElseIf($Services -and -not $Hardware)
			{
				WriteWordLine 0 0 "Services was skipped."
			}
			ElseIf($Hardware -and $Services)
			{
				WriteWordLine 0 0 "Hardware inventory and Services were skipped."
			}
		}
	}
	$First = $False
}
$AllDomainControllers = $Null
[gc]::collect() 

#organizational units
Write-Verbose "$(Get-Date): Writing OU data by Domain"
$selection.InsertNewPage()
WriteWordLine 1 0 "Organizational Units"
$First = $True

ForEach($Domain in $Domains)
{
	Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"
	If(!$First)
	{
		#put each domain, starting with the second, on a new page
		$selection.InsertNewPage()
	}
	If($Domain -eq $ForestRootDomain)
	{
		WriteWordLine 2 0 "OUs in Domain $($Domain) (Forest Root)"
	}
	Else
	{
		WriteWordLine 2 0 "OUs in Domain $($Domain)"
	}
	#get all OUs for the domain
	$OUs = $Null
	$OUs = Get-ADOrganizationalUnit -Filter * -Server $Domain `
	-Properties CanonicalName, DistinguishedName, Name, Created, ProtectedFromAccidentalDeletion | `
	Select CanonicalName, DistinguishedName, Name, Created, ProtectedFromAccidentalDeletion | `
	Sort CanonicalName
	
	If($? -and $OUs -ne $Null)
	{
		$TableRange = $doc.Application.Selection.Range
		[int]$Columns = 6
		If($OUs -is [array])
		{
			[int]$Rows = $OUs.Count + 1
			[int]$NumOUs = $OUs.Count
		}
		Else
		{
			[int]$Rows = 2
			[int]$NumOUs = 1
		}
		[int]$xRow = 1
		[int]$OUCount = 0

		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.AutoFitBehavior($wdAutoFitFixed)
		$Table.Style = $myHash.Word_TableGrid
		$Table.rows.first.headingformat = $wdHeadingFormatTrue
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle

		$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,1).Range.Font.Bold = $True
		$Table.Cell($xRow,1).Range.Text = "Name"
		
		$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,2).Range.Font.Bold = $True
		$Table.Cell($xRow,2).Range.Text = "Created"
		
		$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,3).Range.Font.Bold = $True
		$Table.Cell($xRow,3).Range.Text = "Protected"
		
		$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,4).Range.Font.Bold = $True
		$Table.Cell($xRow,4).Range.Text = "# Users"
		
		$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,5).Range.Font.Bold = $True
		$Table.Cell($xRow,5).Range.Text = "# Computers"
		
		$Table.Cell($xRow,6).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell($xRow,6).Range.Font.Bold = $True
		$Table.Cell($xRow,6).Range.Text = "# Groups"

		ForEach($OU in $OUs)
		{
			$xRow++
			$OUCount++
			If($xRow % 2 -eq 0)
			{
				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray05
				$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray05
				$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray05
				$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorGray05
				$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorGray05
				$Table.Cell($xRow,6).Shading.BackgroundPatternColor = $wdColorGray05
			}
			$OUDisplayName = $OU.CanonicalName.SubString($OU.CanonicalName.IndexOf("/")+1)
			Write-Verbose "$(Get-Date): `t`tProcessing OU $($OU.CanonicalName) - OU # $OUCount of $NumOUs"
			
			#get counts of users, computers and groups in the OU
			Write-Verbose "$(Get-Date): `t`t`tGetting user count"
			
			[int]$UserCount = 0
			[int]$ComputerCount = 0
			[int]$GroupCount = 0
			
			$Results = Get-ADUser -Filter * -SearchBase $OU.DistinguishedName -Server $Domain
			If($Results -eq $Null)
			{
				$UserCount = 0
			}
			ElseIf($Results -is [array])
			{
				$UserCount = $Results.Count
			}
			Else
			{
				$UserCount = 1
			}
			Write-Verbose "$(Get-Date): `t`t`tGetting computer count"
			$Results = Get-ADComputer -Filter * -SearchBase $OU.DistinguishedName -Server $Domain
			If($Results -eq $Null)
			{
				$ComputerCount = 0
			}
			ElseIf($Results -is [array])
			{
				$ComputerCount = $Results.Count
			}
			Else
			{
				$ComputerCount = 1
			}
			Write-Verbose "$(Get-Date): `t`t`tGetting group count"
			$Results = Get-ADGroup -Filter * -SearchBase $OU.DistinguishedName -Server $Domain
			If($Results -eq $Null)
			{
				$GroupCount = 0
			}
			ElseIf($Results -is [array])
			{
				$GroupCount = $Results.Count
			}
			Else
			{
				$GroupCount = 1
			}
			
			Write-Verbose "$(Get-Date): `t`t`tPopulating table row"
			$Table.Cell($xRow,1).Range.Text = $OUDisplayName
			$Table.Cell($xRow,2).Range.Text = $OU.Created
			If($OU.ProtectedFromAccidentalDeletion -eq $True)
			{
				$Table.Cell($xRow,3).Range.Text = "Yes"
			}
			Else
			{
				$Table.Cell($xRow,3).Range.Text = "No"
			}
			
			[string]$UserCountStr = "{0,7:N0}" -f $UserCount
			[string]$ComputerCountStr = "{0,7:N0}" -f $ComputerCount
			[string]$GroupCountStr = "{0,7:N0}" -f $GroupCount

			$Table.Cell($xRow,4).Range.ParagraphFormat.Alignment = $wdCellAlignVerticalTop
			$Table.Cell($xRow,4).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
			$Table.Cell($xRow,4).Range.Text = $UserCountStr
			$Table.Cell($xRow,5).Range.ParagraphFormat.Alignment = $wdCellAlignVerticalTop
			$Table.Cell($xRow,5).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
			$Table.Cell($xRow,5).Range.Text = $ComputerCountStr
			$Table.Cell($xRow,6).Range.ParagraphFormat.Alignment = $wdCellAlignVerticalTop
			$Table.Cell($xRow,6).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
			$Table.Cell($xRow,6).Range.Text = $GroupCountStr
			$Results = $Null
			$UserCountStr = $Null
			$ComputerCountStr = $Null
			$GroupCountStr = $Null
		}
		
		#set column widths
		$xcols = $table.columns

		ForEach($xcol in $xcols)
		{
		    switch ($xcol.Index)
		    {
			  1 {$xcol.width = 214}
			  2 {$xcol.width = 68}
			  3 {$xcol.width = 56}
			  4 {$xcol.width = 56}
			  5 {$xcol.width = 70}
			  6 {$xcol.width = 56}
		    }
		}
		
		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitFixed)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null
		$Results = $Null
		$UserCountStr = $Null
		$ComputerCountStr = $Null
		$GroupCountStr = $Null
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving OU data for domain $($Domain)"
		WriteWordLine 0 0 "Error retrieving OU data for domain $($Domain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No OU data was retrieved for domain $($Domain)" "" $Null 0 $False $True
	}
	$First = $False
	[gc]::collect() 
	[gc]::WaitForPendingFinalizers()
}
$OUs = $Null
$OUDisplayName = $Null
$Results = $Null
$UserCountStr = $Null
$ComputerCountStr = $Null
$GroupCountStr = $Null
[gc]::collect() 

#Group information
Write-Verbose "$(Get-Date): Writing group data"

$selection.InsertNewPage()
WriteWordLine 1 0 "Groups"
$First = $True

ForEach($Domain in $Domains)
{
	Write-Verbose "$(Get-Date): `tProcessing groups in domain $($Domain)"
	If(!$First)
	{
		#put each domain, starting with the second, on a new page
		$selection.InsertNewPage()
	}
	If($Domain -eq $ForestRootDomain)
	{
		WriteWordLine 2 0 "Domain $($Domain) (Forest Root)"
	}
	Else
	{
		WriteWordLine 2 0 "Domain $($Domain)"
	}

	#get all Groups for the domain
	$Groups = $Null
	$Groups = Get-ADGroup -Filter * -Server $Domain -Properties Name, GroupCategory, GroupType | Sort Name

	If($? -and $Groups -ne $Null)
	{
		#get counts
		
		Write-Verbose "$(Get-Date): `t`tGetting counts"
		
		[int]$SecurityCount = 0
		[int]$DistributionCount = 0
		[int]$GlobalCount = 0
		[int]$UniversalCount = 0
		[int]$DomainLocalCount = 0
		[int]$ContactsCount = 0
		[int]$GroupsWithSIDHistory = 0
		
		Write-Verbose "$(Get-Date): `t`t`tSecurity Groups"
		$Results = $groups | Where {$_.groupcategory -eq "Security"}
		
		If($Results -eq $Null)
		{
			[int]$SecurityCount = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$SecurityCount = $Results.Count
		}
		Else
		{
			[int]$SecurityCount = 1
		}
		
		Write-Verbose "$(Get-Date): `t`t`tDistribution Groups"
		$Results = $groups | Where {$_.groupcategory -eq "Distribution"}
		
		If($Results -eq $Null)
		{
			[int]$DistributionCount = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$DistributionCount = $Results.Count
		}
		Else
		{
			[int]$DistributionCount = 1
		}

		Write-Verbose "$(Get-Date): `t`t`tGlobal Groups"
		$Results = $groups | Where {$_.groupscope -eq "Global"}

		If($Results -eq $Null)
		{
			[int]$GlobalCount = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$GlobalCount = $Results.Count
		}
		Else
		{
			[int]$GlobalCount = 1
		}

		Write-Verbose "$(Get-Date): `t`t`tUniversal Groups"
		$Results = $groups | Where {$_.groupscope -eq "Universal"}

		If($Results -eq $Null)
		{
			[int]$UniversalCount = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$UniversalCount = $Results.Count
		}
		Else
		{
			[int]$UniversalCount = 1
		}
		
		Write-Verbose "$(Get-Date): `t`t`tDomain Local Groups"
		$Results = $groups | Where {$_.groupscope -eq "DomainLocal"}

		If($Results -eq $Null)
		{
			[int]$DomainLocalCount = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$DomainLocalCount = $Results.Count
		}
		Else
		{
			[int]$DomainLocalCount = 1
		}

		Write-Verbose "$(Get-Date): `t`t`tGroups with SID History"
		$Results = $Null
		$Results = Get-ADObject -LDAPFilter "(sIDHistory=*)" -Server $Domain -Property objectClass, sIDHistory

		If($Results -eq $Null)
		{
			[int]$GroupsWithSIDHistory = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$GroupsWithSIDHistory = ($Results | Where {$_.objectClass -eq 'group'}).Count
		}
		Else
		{
			[int]$GroupsWithSIDHistory = 1
		}

		Write-Verbose "$(Get-Date): `t`t`tContacts"
		$Results = $Null
		$Results = Get-ADObject -LDAPFilter "objectClass=Contact" -Server $Domain

		If($Results -eq $Null)
		{
			[int]$ContactsCount = 0
		}
		ElseIf($Results -is [array])
		{
			[int]$ContactsCount = $Results.Count
		}
		Else
		{
			[int]$ContactsCount = 1
		}

		[string]$TotalCountStr = "{0,7:N0}" -f ($SecurityCount + $DistributionCount)
		[string]$SecurityCountStr = "{0,7:N0}" -f $SecurityCount
		[string]$DomainLocalCountStr = "{0,7:N0}" -f $DomainLocalCount
		[string]$GlobalCountStr = "{0,7:N0}" -f $GlobalCount
		[string]$UniversalCountStr = "{0,7:N0}" -f $UniversalCount
		[string]$DistributionCountStr = "{0,7:N0}" -f $DistributionCount
		[string]$GroupsWithSIDHistoryStr = "{0,7:N0}" -f $GroupsWithSIDHistory
		[string]$ContactsCountStr = "{0,7:N0}" -f $ContactsCount
		
		Write-Verbose "$(Get-Date): `t`tBuild groups table"
		$TableRange = $doc.Application.Selection.Range
		[int]$Columns = 2
		[int]$Rows = 8
		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.Style = $myHash.Word_TableGrid
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
		$Table.Cell(1,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(1,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(1,1).Range.Font.Bold = $True
		$Table.Cell(1,1).Range.Text = "Total Groups"
		$Table.Cell(1,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(1,2).Range.Text = $TotalCountStr
		$Table.Cell(2,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(2,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(2,1).Range.Font.Bold = $True
		$Table.Cell(2,1).Range.Text = "`tSecurity Groups"
		$Table.Cell(2,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(2,2).Range.Text = $SecurityCountStr
		$Table.Cell(3,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(3,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(3,1).Range.Font.Bold = $True
		$Table.Cell(3,1).Range.Text = "`t`tDomain Local"
		$Table.Cell(3,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(3,2).Range.Text = $DomainLocalCountStr
		$Table.Cell(4,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(4,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(4,1).Range.Font.Bold = $True
		$Table.Cell(4,1).Range.Text = "`t`tGlobal"
		$Table.Cell(4,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(4,2).Range.Text = $GlobalCountStr
		$Table.Cell(5,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(5,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(5,1).Range.Font.Bold = $True
		$Table.Cell(5,1).Range.Text = "`t`tUniversal"
		$Table.Cell(5,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(5,2).Range.Text = $UniversalCountStr
		$Table.Cell(6,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(6,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(6,1).Range.Font.Bold = $True
		$Table.Cell(6,1).Range.Text = "`tDistribution Groups"
		$Table.Cell(6,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(6,2).Range.Text = $DistributionCountStr
		$Table.Cell(7,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(7,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(7,1).Range.Font.Bold = $True
		$Table.Cell(7,1).Range.Text = "Groups with SID History"
		$Table.Cell(7,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(7,2).Range.Text = $GroupsWithSIDHistoryStr
		$Table.Cell(8,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(8,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(8,1).Range.Font.Bold = $True
		$Table.Cell(8,1).Range.Text = "Contacts"
		$Table.Cell(8,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(8,2).Range.Text = $ContactsCountStr

		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitContent)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null
		
		#get members of privileged groups
		$DomainInfo = $Null
		$DomainInfo = Get-ADDomain -Identity $Domain
		
		If($? -and $DomainInfo -ne $Null)
		{
			$DomainAdminsSID = "$($DomainInfo.DomainSID)-512"
			$EnterpriseAdminsSID = "$($DomainInfo.DomainSID)-519"
			$SchemaAdminsSID = "$($DomainInfo.DomainSID)-518"
		}
		Else
		{
			$DomainAdminsSID = $Null
			$EnterpriseAdminsSID = $Null
			$SchemaAdminsSID = $Null
		}
		
		WriteWordLine 3 0 "Privileged Groups"
		Write-Verbose "$(Get-Date): `t`tListing domain admins"
		$Admins = $Null
		$Admins = Get-ADGroupMember -Identity $DomainAdminsSID -Server $Domain
		
		If($? -and $Admins -ne $Null)
		{
			If($Admins -is [array])
			{
				[int]$AdminsCount = $Admins.Count
			}
			Else
			{
				[int]$AdminsCount = 1
			}
			$Admins = $Admins | Sort Name
			[string]$AdminsCountStr = "{0:N0}" -f $AdminsCount
			
			WriteWordLine 4 0 "Domain Admins ($($AdminsCountStr) members):"
			$TableRange = $doc.Application.Selection.Range
			[int]$Columns = 4
			[int]$Rows = $AdminsCount + 1
			[int]$xRow = 1
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.AutoFitBehavior($wdAutoFitFixed)
			$Table.Style = $myHash.Word_TableGrid
			$Table.rows.first.headingformat = $wdHeadingFormatTrue
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle

			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Name"
			$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,2).Range.Font.Bold = $True
			$Table.Cell($xRow,2).Range.Text = "Password Last Changed"
			$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,3).Range.Font.Bold = $True
			$Table.Cell($xRow,3).Range.Text = "Password Never Expires"
			$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,4).Range.Font.Bold = $True
			$Table.Cell($xRow,4).Range.Text = "Account Enabled"
			#$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorGray15
			#$Table.Cell($xRow,5).Range.Font.Bold = $True
			#$Table.Cell($xRow,5).Range.Text = "Password Policy"
			ForEach($Admin in $Admins)
			{
				$User = Get-ADUser -Identity $Admin.SID -Server $Domain -Properties PasswordLastSet, Enabled, PasswordNeverExpires 

				$xRow++
				
				If($? -and $User -ne $Null)
				{
					$Table.Cell($xRow,1).Range.Text = $User.Name
					If($User.PasswordLastSet -eq $Null)
					{
						$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorRed
						$Table.Cell($xRow,2).Range.Font.Bold  = $True
						$Table.Cell($xRow,2).Range.Font.Color = $WDColorBlack
						$Table.Cell($xRow,2).Range.Text = "No Date Set"
					}
					Else
					{
						$Table.Cell($xRow,2).Range.Text = (get-date $User.PasswordLastSet -f d)
					}
					If($User.PasswordNeverExpires -eq $True)
					{
						$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorRed
						$Table.Cell($xRow,3).Range.Font.Bold  = $True
						$Table.Cell($xRow,3).Range.Font.Color = $WDColorBlack
					}
					$Table.Cell($xRow,3).Range.Text = $User.PasswordNeverExpires
					If($User.Enabled -eq $False)
					{
						$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorRed
						$Table.Cell($xRow,4).Range.Font.Bold  = $True
						$Table.Cell($xRow,4).Range.Font.Color = $WDColorBlack
					}
					$Table.Cell($xRow,4).Range.Text = $User.Enabled
					#$Table.Cell($xRow,5).Range.Text = ""
				}
				Else
				{
					$Table.Cell($xRow,2).Range.Text = $Admin.SID
					$Table.Cell($xRow,3).Range.Text = "Unknown"
					$Table.Cell($xRow,4).Range.Text = "Unknown"
					#$Table.Cell($xRow,5).Range.Text = "Unknown"
				}
			}
			
			#set column widths
			$xcols = $table.columns

			ForEach($xcol in $xcols)
			{
			    switch ($xcol.Index)
			    {
				  1 {$xcol.width = 200}
				  2 {$xcol.width = 66}
				  3 {$xcol.width = 56}
				  4 {$xcol.width = 50}
				  5 {$xcol.width = 142}
			    }
			}
			
			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitFixed)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
		}
		ElseIf(!$?)
		{
			WriteWordLine 0 0 "Unable to retrieve Domain Admins group membership" "" $Null 0 $False $True
		}
		Else
		{
			WriteWordLine 4 0 "Domain Admins: "
			WriteWordLine 0 0 "<None>"
		}

		Write-Verbose "$(Get-Date): `t`tListing enterprise admins"
		
		If($Domain -eq $ForestRootDomain)
		{
			$Admins = Get-ADGroupMember -Identity $EnterpriseAdminsSID -Server $Domain 
			
			If($? -and $Admins -ne $Null)
			{
				If($Admins -is [array])
				{
					[int]$AdminsCount = $Admins.Count
				}
				Else
				{
					[int]$AdminsCount = 1
				}
				$Admins = $Admins | Sort Name
				[string]$AdminsCountStr = "{0:N0}" -f $AdminsCount
				
				WriteWordLine 4 0 "Enterprise Admins ($($AdminsCountStr) members):"
				$TableRange = $doc.Application.Selection.Range
				[int]$Columns = 5
				[int]$Rows = $AdminsCount + 1
				[int]$xRow = 1
				$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
				$Table.AutoFitBehavior($wdAutoFitFixed)
				$Table.Style = $myHash.Word_TableGrid
				$Table.rows.first.headingformat = $wdHeadingFormatTrue
				$Table.Borders.InsideLineStyle = $wdLineStyleSingle
				$Table.Borders.OutsideLineStyle = $wdLineStyleSingle

				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Name"
				$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,2).Range.Font.Bold = $True
				$Table.Cell($xRow,2).Range.Text = "Domain"
				$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,3).Range.Font.Bold = $True
				$Table.Cell($xRow,3).Range.Text = "Password Last Changed"
				$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,4).Range.Font.Bold = $True
				$Table.Cell($xRow,4).Range.Text = "Password Never Expires"
				$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,5).Range.Font.Bold = $True
				$Table.Cell($xRow,5).Range.Text = "Account Enabled"
				#$Table.Cell($xRow,6).Shading.BackgroundPatternColor = $wdColorGray15
				#$Table.Cell($xRow,6).Range.Font.Bold = $True
				#$Table.Cell($xRow,6).Range.Text = "Password Policy"
				ForEach($Admin in $Admins)
				{
					$xRow++
					$xArray = $Admin.DistinguishedName.Split(",")
					$xServer = ""
					$xCnt = 0
					ForEach($xItem in $xArray)
					{
						$xCnt++
						If($xItem.StartsWith("DC="))
						{
							$xtmp = $xItem.Substring($xItem.IndexOf("=")+1)
							If($xCnt -eq $xArray.Count)
							{
								$xServer += $xTmp
							}
							Else
							{
								$xServer += "$($xTmp)."
							}
						}
					}

					If($Admin.ObjectClass -eq 'user')
					{
						$User = Get-ADUser -Identity $Admin.SID.value -Server $xServer -Properties PasswordLastSet, Enabled, PasswordNeverExpires 
					}
					ElseIf($Admin.ObjectClass -eq 'group')
					{
						$User = Get-ADGroup -Identity $Admin.SID.value -Server $xServer 
					}
					Else
					{
						$User = $Null
					}
					
					If($? -and $User -ne $Null)
					{
						If($Admin.ObjectClass -eq 'user')
						{
							$Table.Cell($xRow,1).Range.Text = $User.Name
							$Table.Cell($xRow,2).Range.Text = $xServer
							If($User.PasswordLastSet -eq $Null)
							{
								$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorRed
								$Table.Cell($xRow,3).Range.Font.Bold  = $True
								$Table.Cell($xRow,3).Range.Font.Color = $WDColorBlack
								$Table.Cell($xRow,3).Range.Text = "No Date Set"
							}
							Else
							{
								$Table.Cell($xRow,3).Range.Text = (get-date $User.PasswordLastSet -f d)
							}
							If($User.PasswordNeverExpires -eq $True)
							{
								$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorRed
								$Table.Cell($xRow,4).Range.Font.Bold  = $True
								$Table.Cell($xRow,4).Range.Font.Color = $WDColorBlack
							}
							$Table.Cell($xRow,4).Range.Text = $User.PasswordNeverExpires
							If($User.Enabled -eq $False)
							{
								$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorRed
								$Table.Cell($xRow,5).Range.Font.Bold  = $True
								$Table.Cell($xRow,5).Range.Font.Color = $WDColorBlack
							}
							$Table.Cell($xRow,5).Range.Text = $User.Enabled
							#$Table.Cell($xRow,6).Range.Text = ""
						}
						ElseIf($Admin.ObjectClass -eq 'group')
						{
							$Table.Cell($xRow,1).Range.Text = "$($User.Name) (group)"
							$Table.Cell($xRow,2).Range.Text = $xServer
							$Table.Cell($xRow,3).Range.Text = "N/A"
							$Table.Cell($xRow,4).Range.Text = "N/A"
							$Table.Cell($xRow,5).Range.Text = "N/A"
							#$Table.Cell($xRow,6).Range.Text = ""
						}
						
					}
					Else
					{
						$Table.Cell($xRow,1).Range.Text = $Admin.SID.Value
						$Table.Cell($xRow,2).Range.Text = $xServer
						$Table.Cell($xRow,3).Range.Text = "Unknown"
						$Table.Cell($xRow,4).Range.Text = "Unknown"
						$Table.Cell($xRow,5).Range.Text = "Unknown"
						#$Table.Cell($xRow,6).Range.Text = "Unknown"
					}
				}
			
				#set column widths
				$xcols = $table.columns

				ForEach($xcol in $xcols)
				{
				    switch ($xcol.Index)
				    {
					  1 {$xcol.width = 100}
					  2 {$xcol.width = 108}
					  3 {$xcol.width = 66}
					  4 {$xcol.width = 56}
					  5 {$xcol.width = 56}
					  6 {$xcol.width = 100}
				    }
				}

				$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
				$Table.AutoFitBehavior($wdAutoFitFixed)

				#return focus back to document
				$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

				#move to the end of the current document
				$selection.EndKey($wdStory,$wdMove) | Out-Null
				$TableRange = $Null
				$Table = $Null
			}
			ElseIf(!$?)
			{
				WriteWordLine 0 0 "Unable to retrieve Enterprise Admins group membership" "" $Null 0 $False $True
			}
			Else
			{
				WriteWordLine 0 0 "<None>"
			}
		}
		Else
		{
			WriteWordLine 4 0 "Enterprise Admins: "
			WriteWordLine 0 0 "<None>"
		}
		
		Write-Verbose "$(Get-Date): `t`tListing schema admins"
		
		If($Domain -eq $ForestRootDomain)
		{
			$Admins = Get-ADGroupMember -Identity $SchemaAdminsSID -Server $Domain 
			
			If($? -and $Admins -ne $Null)
			{
				If($Admins -is [array])
				{
					[int]$AdminsCount = $Admins.Count
				}
				Else
				{
					[int]$AdminsCount = 1
				}
				$Admins = $Admins | Sort Name
				[string]$AdminsCountStr = "{0:N0}" -f $AdminsCount
				
				WriteWordLine 4 0 "Schema Admins ($($AdminsCountStr) members):"
				$TableRange = $doc.Application.Selection.Range
				[int]$Columns = 5
				[int]$Rows = $AdminsCount + 1
				[int]$xRow = 1
				$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
				$Table.AutoFitBehavior($wdAutoFitFixed)
				$Table.Style = $myHash.Word_TableGrid
				$Table.rows.first.headingformat = $wdHeadingFormatTrue
				$Table.Borders.InsideLineStyle = $wdLineStyleSingle
				$Table.Borders.OutsideLineStyle = $wdLineStyleSingle

				$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,1).Range.Font.Bold = $True
				$Table.Cell($xRow,1).Range.Text = "Name"
				$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,2).Range.Font.Bold = $True
				$Table.Cell($xRow,2).Range.Text = "Domain"
				$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,3).Range.Font.Bold = $True
				$Table.Cell($xRow,3).Range.Text = "Password Last Changed"
				$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,4).Range.Font.Bold = $True
				$Table.Cell($xRow,4).Range.Text = "Password Never Expires"
				$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorGray15
				$Table.Cell($xRow,5).Range.Font.Bold = $True
				$Table.Cell($xRow,5).Range.Text = "Account Enabled"
				#$Table.Cell($xRow,6).Shading.BackgroundPatternColor = $wdColorGray15
				#$Table.Cell($xRow,6).Range.Font.Bold = $True
				#$Table.Cell($xRow,6).Range.Text = "Password Policy"
				ForEach($Admin in $Admins)
				{
					$xRow++
					$xArray = $Admin.DistinguishedName.Split(",")
					$xServer = ""
					$xCnt = 0
					ForEach($xItem in $xArray)
					{
						$xCnt++
						If($xItem.StartsWith("DC="))
						{
							$xtmp = $xItem.Substring($xItem.IndexOf("=")+1)
							If($xCnt -eq $xArray.Count)
							{
								$xServer += $xTmp
							}
							Else
							{
								$xServer += "$($xTmp)."
							}
						}
					}

					If($Admin.ObjectClass -eq 'user')
					{
						$User = Get-ADUser -Identity $Admin.SID.value -Server $xServer -Properties PasswordLastSet, Enabled, PasswordNeverExpires 
					}
					ElseIf($Admin.ObjectClass -eq 'group')
					{
						$User = Get-ADGroup -Identity $Admin.SID.value -Server $xServer 
					}
					Else
					{
						$User = $Null
					}
					
					If($? -and $User -ne $Null)
					{
						If($Admin.ObjectClass -eq 'user')
						{
							$Table.Cell($xRow,1).Range.Text = $User.Name
							$Table.Cell($xRow,2).Range.Text = $xServer
							If($User.PasswordLastSet -eq $Null)
							{
								$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorRed
								$Table.Cell($xRow,3).Range.Font.Bold  = $True
								$Table.Cell($xRow,3).Range.Font.Color = $WDColorBlack
								$Table.Cell($xRow,3).Range.Text = "No Date Set"
							}
							Else
							{
								$Table.Cell($xRow,3).Range.Text = (get-date $User.PasswordLastSet -f d)
							}
							If($User.PasswordNeverExpires -eq $True)
							{
								$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorRed
								$Table.Cell($xRow,4).Range.Font.Bold  = $True
								$Table.Cell($xRow,4).Range.Font.Color = $WDColorBlack
							}
							$Table.Cell($xRow,4).Range.Text = $User.PasswordNeverExpires
							If($User.Enabled -eq $False)
							{
								$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorRed
								$Table.Cell($xRow,5).Range.Font.Bold  = $True
								$Table.Cell($xRow,5).Range.Font.Color = $WDColorBlack
							}
							$Table.Cell($xRow,5).Range.Text = $User.Enabled
							#$Table.Cell($xRow,6).Range.Text = ""
						}
						ElseIf($Admin.ObjectClass -eq 'group')
						{
							$Table.Cell($xRow,1).Range.Text = "$($User.Name) (group)"
							$Table.Cell($xRow,2).Range.Text = $xServer
							$Table.Cell($xRow,3).Range.Text = "N/A"
							$Table.Cell($xRow,4).Range.Text = "N/A"
							$Table.Cell($xRow,5).Range.Text = "N/A"
							#$Table.Cell($xRow,6).Range.Text = ""
						}
						
					}
					Else
					{
						$Table.Cell($xRow,1).Range.Text = $Admin.SID.Value
						$Table.Cell($xRow,2).Range.Text = $xServer
						$Table.Cell($xRow,3).Range.Text = "Unknown"
						$Table.Cell($xRow,4).Range.Text = "Unknown"
						$Table.Cell($xRow,5).Range.Text = "Unknown"
						#$Table.Cell($xRow,6).Range.Text = "Unknown"
					}
				}
			
				#set column widths
				$xcols = $table.columns

				ForEach($xcol in $xcols)
				{
				    switch ($xcol.Index)
				    {
					  1 {$xcol.width = 100}
					  2 {$xcol.width = 108}
					  3 {$xcol.width = 66}
					  4 {$xcol.width = 56}
					  5 {$xcol.width = 56}
					  6 {$xcol.width = 100}
				    }
				}
				
				$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
				$Table.AutoFitBehavior($wdAutoFitFixed)

				#return focus back to document
				$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

				#move to the end of the current document
				$selection.EndKey($wdStory,$wdMove) | Out-Null
				$TableRange = $Null
				$Table = $Null
			}
			ElseIf(!$?)
			{
				WriteWordLine 0 0 "Unable to retrieve Schema Admins group membership" "" $Null 0 $False $True
			}
			Else
			{
				WriteWordLine 0 0 "<None>"
			}
		}
		Else
		{
			WriteWordLine 4 0 "Schema Admins: "
			WriteWordLine 0 0 "<None>"
		}

		#http://www.shariqsheikh.com/blog/index.php/200908/use-powershell-to-look-up-admincount-from-adminsdholder-and-sdprop/		
		Write-Verbose "$(Get-Date): `t`tListing users with AdminCount = 1"
		$AdminCounts = Get-ADUser -LDAPFilter "(admincount=1)"  -Server $Domain 
		
		If($? -and $AdminCounts -ne $Null)
		{
			$AdminCounts = $AdminCounts | Sort Name
			If($AdminCounts -is [array])
			{
				[int]$AdminsCount = $AdminCounts.Count
			}
			Else
			{
				[int]$AdminsCount = 1
			}
			[string]$AdminsCountStr = "{0:N0}" -f $AdminsCount
			
			WriteWordLine 4 0 "Users with AdminCount=1 ($($AdminsCountStr) members):"
			$TableRange = $doc.Application.Selection.Range
			[int]$Columns = 4
			[int]$Rows = $AdminCounts.Count + 1
			[int]$xRow = 1
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.AutoFitBehavior($wdAutoFitFixed)
			$Table.Style = $myHash.Word_TableGrid
			$Table.rows.first.headingformat = $wdHeadingFormatTrue
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
			
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Name"
			$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,2).Range.Font.Bold = $True
			$Table.Cell($xRow,2).Range.Text = "Password Last Changed"
			$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,3).Range.Font.Bold = $True
			$Table.Cell($xRow,3).Range.Text = "Password Never Expires"
			$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,4).Range.Font.Bold = $True
			$Table.Cell($xRow,4).Range.Text = "Account Enabled"
			#$Table.Cell($xRow,5).Shading.BackgroundPatternColor = $wdColorGray15
			#$Table.Cell($xRow,5).Range.Font.Bold = $True
			#$Table.Cell($xRow,5).Range.Text = "Password Policy"
			ForEach($Admin in $AdminCounts)
			{
				$User = Get-ADUser -Identity $Admin.SID -Server $Domain -Properties PasswordLastSet, Enabled, PasswordNeverExpires 

				$xRow++
				
				If($? -and $User -ne $Null)
				{
					$Table.Cell($xRow,1).Range.Text = $User.Name
					If($User.PasswordLastSet -eq $Null)
					{
						$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorRed
						$Table.Cell($xRow,2).Range.Font.Bold  = $True
						$Table.Cell($xRow,2).Range.Font.Color = $WDColorBlack
						$Table.Cell($xRow,2).Range.Text = "No Date Set"
					}
					Else
					{
						$Table.Cell($xRow,2).Range.Text = (get-date $User.PasswordLastSet -f d)
					}
					If($User.PasswordNeverExpires -eq $True)
					{
						$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorRed
						$Table.Cell($xRow,3).Range.Font.Bold  = $True
						$Table.Cell($xRow,3).Range.Font.Color = $WDColorBlack
					}
					$Table.Cell($xRow,3).Range.Text = $User.PasswordNeverExpires
					If($User.Enabled -eq $False)
					{
						$Table.Cell($xRow,4).Shading.BackgroundPatternColor = $wdColorRed
						$Table.Cell($xRow,4).Range.Font.Bold  = $True
						$Table.Cell($xRow,4).Range.Font.Color = $WDColorBlack
					}
					$Table.Cell($xRow,4).Range.Text = $User.Enabled
					#$Table.Cell($xRow,5).Range.Text = ""
				}
				Else
				{
					$Table.Cell($xRow,2).Range.Text = $Admin.SID
					$Table.Cell($xRow,3).Range.Text = "Unknown"
					$Table.Cell($xRow,4).Range.Text = "Unknown"
					#$Table.Cell($xRow,5).Range.Text = "Unknown"
				}
			}
			
			#set column widths
			$xcols = $table.columns

			ForEach($xcol in $xcols)
			{
			    switch ($xcol.Index)
			    {
				  1 {$xcol.width = 200}
				  2 {$xcol.width = 66}
				  3 {$xcol.width = 56}
				  4 {$xcol.width = 50}
				  5 {$xcol.width = 142}
			    }
			}

			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitFixed)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
		}
		ElseIf(!$?)
		{
			WriteWordLine 0 0 "Unable to retrieve users with AdminCount=1" "" $Null 0 $False $True
		}
		Else
		{
			WriteWordLine 4 0 "Users with AdminCount=1: "
			WriteWordLIne 0 0 "<None>"
		}
		
		Write-Verbose "$(Get-Date): `t`tListing groups with AdminCount = 1"
		$AdminCounts = Get-ADGroup -LDAPFilter "(admincount=1)" -Server $Domain  | Select Name
		
		If($? -and $AdminCounts -ne $Null)
		{
			$AdminCounts = $AdminCounts | Sort Name
			If($AdminCounts -is [array])
			{
				[int]$AdminsCount = $AdminCounts.Count
			}
			Else
			{
				[int]$AdminsCount = 1
			}
			[string]$AdminsCountStr = "{0:N0}" -f $AdminsCount
			
			WriteWordLine 4 0 "Groups with AdminCount=1 ($($AdminsCountStr) members):"
			$TableRange = $doc.Application.Selection.Range
			[int]$Columns = 2
			[int]$Rows = $AdminCounts.Count + 1
			[int]$xRow = 1
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.AutoFitBehavior($wdAutoFitFixed)
			$Table.Style = $myHash.Word_TableGrid
			$Table.rows.first.headingformat = $wdHeadingFormatTrue
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
			$Table.Cell($xRow,1).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,1).Range.Font.Bold = $True
			$Table.Cell($xRow,1).Range.Text = "Group Name"
			$Table.Cell($xRow,2).Shading.BackgroundPatternColor = $wdColorGray15
			$Table.Cell($xRow,2).Range.Font.Bold = $True
			$Table.Cell($xRow,2).Range.Text = "Members"
			ForEach($Admin in $AdminCounts)
			{
				Write-Verbose "$(Get-Date): `t`t`t$($Admin.Name)"
				$xRow++
				$Members = Get-ADGroupMember -Identity $Admin.Name -Server $Domain | Sort Name
				
				If($? -and $Members -ne $Null)
				{
					If($Members -is [array])
					{
						$MembersCount = $Members.Count
					}
					Else
					{
						$MembersCount = 1
					}
				}
				Else
				{
					$MembersCount = 0
				}

				[string]$MembersCountStr = "{0:N0}" -f $MembersCount
				$Table.Cell($xRow,1).Range.Text = "$($Admin.Name) ($($MembersCountStr) members)"
				$MbrStr = ""
				If($MembersCount -gt 0)
				{
					ForEach($Member in $Members)
					{
						$MbrStr += "$($Member.Name)`r"
					}
					$Table.Cell($xRow,2).Range.Text = $MbrStr
				}
			}
			
			#set column widths
			$xcols = $table.columns

			ForEach($xcol in $xcols)
			{
			    switch ($xcol.Index)
			    {
				  1 {$xcol.width = 200}
				  2 {$xcol.width = 172}
			    }
			}
			
			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitFixed)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
		}
		ElseIf(!$?)
		{
			WriteWordLine 0 0 "Unable to retrieve Groups with AdminCount=1" "" $Null 0 $False $True
		}
		Else
		{
			WriteWordLine 4 0 "Groups with AdminCount=1: "
			WriteWordLine 0 0 "<None>"
		}
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving Group data for domain $($Domain)"
		WriteWordLine 0 0 "Error retrieving Group data for domain $($Domain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No Group data was retrieved for domain $($Domain)" "" $Null 0 $False $True
	}
	$First = $False
}
$Groups = $Null
$Admins = $Null
$Members = $Null
$Results = $Null
$DomainInfo = $Null
$User = $Null
$AdminCounts = $Null
$TotalCountStr = $Null
$SecurityCountStr = $Null
$DomainLocalCountStr = $Null
$GlobalCountStr = $Null
$UniversalCountStr = $Null
$DistributionCountStr = $Null
$GroupsWithSIDHistoryStr = $Null
$ContactsCountStr = $Null
$DomainAdminsSID = $Null
$EnterpriseAdminsSID = $Null
$SchemaAdminsSID = $Null
$AdminsCountStr = $Null
$MembersCountStr = $Null
[gc]::collect() 

#GPOs by domain
Write-Verbose "$(Get-Date): Writing domain group policy data"

$selection.InsertNewPage()
WriteWordLine 1 0 "Group Policies by Domain"
$First = $True

ForEach($Domain in $Domains)
{
	Write-Verbose "$(Get-Date): `tProcessing group policies for domain $($Domain)"

	$DomainInfo = Get-ADDomain -Identity $Domain 
	
	If($? -and $DomainInfo -ne $Null)
	{
		If(!$First)
		{
			#put each domain, starting with the second, on a new page
			$selection.InsertNewPage()
		}
		
		If($Domain -eq $ForestRootDomain)
		{
			WriteWordLine 2 0 "$($Domain) (Forest Root)"
		}
		Else
		{
			WriteWordLine 2 0 $Domain
		}

		Write-Verbose "$(Get-Date): `t`tGetting linked GPOs"
		WriteWordLine 3 0 "Linked Group Policy Objects" 
		$LinkedGPOs = $DomainInfo.LinkedGroupPolicyObjects | Sort
		If($LinkedGpos -eq $Null)
		{
			WriteWordLine 0 0 "<None>"
		}
		Else
		{
			$TableRange = $doc.Application.Selection.Range
			[int]$Columns = 1
			If($LinkedGpos -is [array])
			{
				[int]$Rows = $LinkedGpos.Count
			}
			Else
			{
				[int]$Rows = 1
			}
			$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
			$Table.Style = $myHash.Word_TableGrid
			$Table.Borders.InsideLineStyle = $wdLineStyleSingle
			$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
			$GPOArray = @()
			ForEach($LinkedGpo in $LinkedGpos)
			{
				#taken from Michael B. Smith's work on the XenApp 6.x scripts
				#this way we don't need the GroupPolicy module
				$gpObject = [ADSI]( "LDAP://" + $LinkedGPO )
				If($gpObject.DisplayName -eq $Null)
				{
					$p1 = $LinkedGPO.IndexOf("{")
					#38 is length of guid (32) plus the four "-"s plus the beginning "{" plus the ending "}"
					$GUID = $LinkedGPO.SubString($p1,38)
					$tmp = "GPO with GUID $($GUID) was not found in this domain"
				}
				Else
				{
					$tmp = $gpObject.DisplayName	### name of the group policy object
				}
				$GPOArray += $tmp
			}

			$GPOArray = $GPOArray | Sort
			
			[int]$xRow = 0
			ForEach($Item in $GPOArray)
			{
				$xRow++
				$Table.Cell($xRow,1).Range.Text = $Item
			}
			$GPOArray = $Null

			$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
			$Table.AutoFitBehavior($wdAutoFitContent)

			#return focus back to document
			$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

			#move to the end of the current document
			$selection.EndKey($wdStory,$wdMove) | Out-Null
			$TableRange = $Null
			$Table = $Null
		}
		$LinkedGPOs = $Null
		$First = $False
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving domain data for domain $($Domain)"
		WriteWordLine 0 0 "Error retrieving domain data for domain $($Domain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No Domain data was retrieved for domain $($Domain)" "" $Null 0 $False $True
	}
}
$DomainInfo = $Null
$LinkedGPOs = $Null
$GPOArray = $Null
[gc]::collect() 

#group policies by organizational units
Write-Verbose "$(Get-Date): Writing Group Policy data by Domain by OU"
$selection.InsertNewPage()
WriteWordLine 1 0 "Group Policies by Organizational Unit"
$First = $True

ForEach($Domain in $Domains)
{
	Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"
	If(!$First)
	{
		#put each domain, starting with the second, on a new page
		$selection.InsertNewPage()
	}
	If($Domain -eq $ForestRootDomain)
	{
		WriteWordLine 2 0 "Group Policies by OUs in Domain $($Domain) (Forest Root)"
	}
	Else
	{
		WriteWordLine 2 0 "Group Policies by OUs in Domain $($Domain)"
	}
	#print disclaimer line in 8 point bold italics
	WriteWordLine 0 0 "(Contains only OUs with linked Group Policies)" "" $Null 8 $True $True
	#get all OUs for the domain
	$OUs = Get-ADOrganizationalUnit -Filter * -Server $Domain -Properties CanonicalName, DistinguishedName, Name  | Select CanonicalName, DistinguishedName, Name | Sort CanonicalName
	
	If($? -and $OUs -ne $Null)
	{
		If($OUs -is [array])
		{
			[int]$NumOUs = $OUs.Count
		}
		Else
		{
			[int]$NumOUs = 1
		}
		[int]$OUCount = 0

		ForEach($OU in $OUs)
		{
			$OUCount++
			$OUDisplayName = $OU.CanonicalName.SubString($OU.CanonicalName.IndexOf("/")+1)
			Write-Verbose "$(Get-Date): `t`tProcessing OU $($OU.CanonicalName) - OU # $OUCount of $NumOUs"
			
			#get data for the individual OU
			$OUInfo = Get-ADOrganizationalUnit -Identity $OU.DistinguishedName -Server $Domain -Properties * 
			
			If($? -and $OUInfo -ne $Null)
			{
				Write-Verbose "$(Get-Date): `t`t`tGetting linked GPOs"
				$LinkedGPOs = $OUInfo.LinkedGroupPolicyObjects | Sort
				If($LinkedGpos -eq $Null)
				{
					# do nothing
				}
				Else
				{
					WriteWordLine 3 0 "$($OUDisplayName)"
					$TableRange = $doc.Application.Selection.Range
					[int]$Columns = 1
					If($LinkedGpos -is [array])
					{
						[int]$Rows = $LinkedGpos.Count
					}
					Else
					{
						[int]$Rows = 1
					}
					$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
					$Table.Style = $myHash.Word_TableGrid
					$Table.Borders.InsideLineStyle = $wdLineStyleSingle
					$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
					$GPOArray = @()
					ForEach($LinkedGpo in $LinkedGpos)
					{
						#taken from Michael B. Smith's work on the XenApp 6.x scripts
						#this way we don't need the GroupPolicy module
						$gpObject = [ADSI]( "LDAP://" + $LinkedGPO )
						If($gpObject.DisplayName -eq $Null)
						{
							$p1 = $LinkedGPO.IndexOf("{")
							#38 is length of guid (32) plus the four "-"s plus the beginning "{" plus the ending "}"
							$GUID = $LinkedGPO.SubString($p1,38)
							$tmp = "GPO with GUID $($GUID) was not found in this domain"
						}
						Else
						{
							$tmp = $gpObject.DisplayName	### name of the group policy object
						}
						$GPOArray += $tmp
					}

					$GPOArray = $GPOArray | Sort
					
					[int]$xRow = 0
					ForEach($Item in $GPOArray)
					{
						$xRow++
						$Table.Cell($xRow,1).Range.Text = $Item
					}
					$GPOArray = $Null

					$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
					$Table.AutoFitBehavior($wdAutoFitContent)

					#return focus back to document
					$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

					#move to the end of the current document
					$selection.EndKey($wdStory,$wdMove) | Out-Null
					$TableRange = $Null
					$Table = $Null
				}
			}
			ElseIf(!$?)
			{
				Write-Warning "Error retrieving OU data for OU $($OU.CanonicalName)"
			}
			Else
			{
				$Table.Cell($xRow,1).Range.Text = "<None>"
				$Table.Cell($xRow,2).Range.Text = "<None>"
				$Table.Cell($xRow,3).Range.Text = "<None>"
				$Table.Cell($xRow,4).Range.Text = "<None>"
				$Table.Cell($xRow,5).Range.Text = "<None>"
				$Table.Cell($xRow,6).Range.Text = "<None>"
			}
		}
		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitContent)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving OU data for domain $($Domain)"
		WriteWordLine 0 0 "Error retrieving OU data for domain $($Domain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No OU data was retrieved for domain $($Domain)" "" $Null 0 $False $True
	}
	$First = $False
}
$OUs = $Null
$OUDisplayName = $Null
$OUInfo = $Null
$LinkedGPOs = $Null
$GPOArray = $Null
[gc]::collect() 

#misc info by domain
Write-Verbose "$(Get-Date): Writing miscellaneous data by domain"

$selection.InsertNewPage()
WriteWordLine 1 0 "Miscellaneous Data by Domain"
$First = $True

ForEach($Domain in $Domains)
{
	Write-Verbose "$(Get-Date): `tProcessing misc data for domain $($Domain)"

	$DomainInfo = Get-ADDomain -Identity $Domain 
	
	If($? -and $DomainInfo -ne $Null)
	{
		If(!$First)
		{
			#put each domain, starting with the second, on a new page
			$selection.InsertNewPage()
		}
		
		If($Domain -eq $ForestRootDomain)
		{
			WriteWordLine 2 0 "$($Domain) (Forest Root)"
		}
		Else
		{
			WriteWordLine 2 0 $Domain
		}

		Write-Verbose "$(Get-Date): `t`tGathering user misc data"
		
		$Users = Get-ADUser -Filter * -Server $Domain -Properties CannotChangePassword, Enabled, LockedOut, PasswordExpired, PasswordNeverExpires, PasswordNotRequired, lastLogonTimestamp, DistinguishedName 
		
		If($? -and $Users -ne $Null)
		{
			If($Users -is [array])
			{
				[int]$UsersCount = $Users.Count
			}
			Else
			{
				[int]$UsersCount = 1
			}
			
			Write-Verbose "$(Get-Date): `t`t`tDisabled users"
			$Results = $Users | Where {$_.Enabled -eq $False}
		
			If($Results -eq $Null)
			{
				[int]$UsersDisabled = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersDisabled = $Results.Count
			}
			Else
			{
				[int]$UsersDisabled = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tUnknown users"
			$Results = $Users | Where {$_.Enabled -eq $Null}
		
			If($Results -eq $Null)
			{
				[int]$UsersUnknown = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersUnknown = $Results.Count
			}
			Else
			{
				[int]$UsersUnknown = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tLocked out users"
			$Results = $Users | Where {$_.LockedOut -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$UsersLockedOut = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersLockedOut = $Results.Count
			}
			Else
			{
				[int]$UsersLockedOut = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tAll users with password expired"
			$Results = $Users | Where {$_.PasswordExpired -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$UsersPasswordExpired = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersPasswordExpired = $Results.Count
			}
			Else
			{
				[int]$UsersPasswordExpired = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tAll users password never expires"
			$Results = $Users | Where {$_.PasswordNeverExpires -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$UsersPasswordNeverExpires = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersPasswordNeverExpires = $Results.Count
			}
			Else
			{
				[int]$UsersPasswordNeverExpires = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tAll users password not required"
			$Results = $Users | Where {$_.PasswordNotRequired -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$UsersPasswordNotRequired = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersPasswordNotRequired = $Results.Count
			}
			Else
			{
				[int]$UsersPasswordNotRequired = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tAll users who cannot change password"
			$Results = $Users | Where {$_.CannotChangePassword -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$UsersCannotChangePassword = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersCannotChangePassword = $Results.Count
			}
			Else
			{
				[int]$UsersCannotChangePassword = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tAll users with SID History"
			$Results = $Null
			$Results = Get-ADObject -LDAPFilter "(sIDHistory=*)" -Server $Domain -Property objectClass, sIDHistory

			If($Results -eq $Null)
			{
				[int]$UsersWithSIDHistory = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$UsersWithSIDHistory = ($Results | Where {$_.objectClass -eq 'user'}).Count
			}
			Else
			{
				[int]$UserssWithSIDHistory = 1
			}

			#active users now
			Write-Verbose "$(Get-Date): `t`t`tActive users"
			$EnabledUsers = $Users | Where {$_.Enabled -eq $True}
		
			If($EnabledUsers -eq $Null)
			{
				[int]$ActiveUsersCount = 0
			}
			ElseIf($EnabledUsers -is [array])
			{
				[int]$ActiveUsersCount = $EnabledUsers.Count
			}
			Else
			{
				[int]$ActiveUsersCount = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tActive users password expired"
			$Results = $EnabledUsers | Where {$_.PasswordExpired -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$ActiveUsersPasswordExpired = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$ActiveUsersPasswordExpired = $Results.Count
			}
			Else
			{
				[int]$ActiveUsersPasswordExpired = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tActive users password never expires"
			$Results = $EnabledUsers | Where {$_.PasswordNeverExpires -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$ActiveUsersPasswordNeverExpires = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$ActiveUsersPasswordNeverExpires = $Results.Count
			}
			Else
			{
				[int]$ActiveUsersPasswordNeverExpires = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tActive users password not required"
			$Results = $EnabledUsers | Where {$_.PasswordNotRequired -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$ActiveUsersPasswordNotRequired = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$ActiveUsersPasswordNotRequired = $Results.Count
			}
			Else
			{
				[int]$ActiveUsersPasswordNotRequired = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tActive Users cannot change password"
			$Results = $EnabledUsers | Where {$_.CannotChangePassword -eq $True}
		
			If($Results -eq $Null)
			{
				[int]$ActiveUsersCannotChangePassword = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$ActiveUsersCannotChangePassword = $Results.Count
			}
			Else
			{
				[int]$ActiveUsersCannotChangePassword = 1
			}

			Write-Verbose "$(Get-Date): `t`t`tActive Users no lastLogonTimestamp"
			$Results = $EnabledUsers | Where {$_.lastLogonTimestamp -eq $Null}
		
			If($Results -eq $Null)
			{
				[int]$ActiveUserslastLogonTimestamp = 0
			}
			ElseIf($Results -is [array])
			{
				[int]$ActiveUserslastLogonTimestamp = $Results.Count
			}
			Else
			{
				[int]$ActiveUserslastLogonTimestamp = 1
			}
		}
		Else
		{
			[int]$UsersCount = 0
			[int]$UsersDisabled = 0
			[int]$UsersLockedOut = 0
			[int]$UsersPasswordExpired = 0
			[int]$UsersPasswordNeverExpires = 0
			[int]$UsersPasswordNotRequired = 0
			[int]$UsersCannotChangePassword = 0
			[int]$UsersWithSIDHistory = 0
			[int]$ActiveUsersCount = 0
			[int]$ActiveUsersPasswordExpired = 0
			[int]$ActiveUsersPasswordNeverExpires = 0
			[int]$ActiveUsersPasswordNotRequired = 0
			[int]$ActiveUsersCannotChangePassword = 0
			[int]$ActiveUserslastLogonTimestamp = 0
		}

		Write-Verbose "$(Get-Date): `t`tFormat numbers into strings"
		[string]$UsersCountStr = "{0,7:N0}" -f $UsersCount
		[string]$UsersDisabledStr = "{0,7:N0}" -f $UsersDisabled
		[string]$UsersUnknownStr = "{0,7:N0}" -f $UsersUnknown
		[string]$UsersLockedOutStr = "{0,7:N0}" -f $UsersLockedOut
		[string]$UsersPasswordExpiredStr = "{0,7:N0}" -f $UsersPasswordExpired
		[string]$UsersPasswordNeverExpiresStr = "{0,7:N0}" -f $UsersPasswordNeverExpires
		[string]$UsersPasswordNotRequiredStr = "{0,7:N0}" -f $UsersPasswordNotRequired
		[string]$UsersCannotChangePasswordStr = "{0,7:N0}" -f $UsersCannotChangePassword
		[string]$UsersWithSIDHistoryStr = "{0,7:N0}" -f $UsersWithSIDHistory
		[string]$ActiveUsersCountStr = "{0,7:N0}" -f $ActiveUsersCount
		[string]$ActiveUsersPasswordExpiredStr = "{0,7:N0}" -f $ActiveUsersPasswordExpired
		[string]$ActiveUsersPasswordNeverExpiresStr = "{0,7:N0}" -f $ActiveUsersPasswordNeverExpires
		[string]$ActiveUsersPasswordNotRequiredStr = "{0,7:N0}" -f $ActiveUsersPasswordNotRequired
		[string]$ActiveUsersCannotChangePasswordStr = "{0,7:N0}" -f $ActiveUsersCannotChangePassword
		[string]$ActiveUserslastLogonTimestampStr = "{0,7:N0}" -f $ActiveUserslastLogonTimestamp

		Write-Verbose "$(Get-Date): `t`tBuild table for All Users"
		WriteWordLine 3 0 "All Users"
		$TableRange   = $doc.Application.Selection.Range
		[int]$Columns = 3
		[int]$Rows = 9
		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.Style = $myHash.Word_TableGrid
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
		$Table.Cell(1,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(1,1).Range.Font.Bold = $True
		$Table.Cell(1,1).Range.Text = "Total Users"
		$Table.Cell(1,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(1,2).Range.Text = $UsersCountStr
		$Table.Cell(2,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(2,1).Range.Font.Bold = $True
		$Table.Cell(2,1).Range.Text = "Disabled users"
		$Table.Cell(2,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(2,2).Range.Text = $UsersDisabledStr
		[single]$pct = (($UsersDisabled / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(2,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(2,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(3,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(3,1).Range.Font.Bold = $True
		$Table.Cell(3,1).Range.Text = "Unknown users*"
		$Table.Cell(3,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(3,2).Range.Text = $UsersUnknownStr
		[single]$pct = (($UsersUnknown / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(3,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(3,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(4,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(4,1).Range.Font.Bold = $True
		$Table.Cell(4,1).Range.Text = "Locked out users"
		$Table.Cell(4,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(4,2).Range.Text = $UsersLockedOutStr
		[single]$pct = (($UsersLockedOut / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(4,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(4,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(5,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(5,1).Range.Font.Bold = $True
		$Table.Cell(5,1).Range.Text = "Password expired"
		$Table.Cell(5,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(5,2).Range.Text = $UsersPasswordExpiredStr
		[single]$pct = (($UsersPasswordExpired / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(5,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(5,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(6,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(6,1).Range.Font.Bold = $True
		$Table.Cell(6,1).Range.Text = "Password never expires"
		$Table.Cell(6,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(6,2).Range.Text = $UsersPasswordNeverExpiresStr
		[single]$pct = (($UsersPasswordNeverExpires / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(6,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(6,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(7,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(7,1).Range.Font.Bold = $True
		$Table.Cell(7,1).Range.Text = "Password not required"
		$Table.Cell(7,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(7,2).Range.Text = $UsersPasswordNotRequiredStr
		[single]$pct = (($UsersPasswordNotRequired / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(7,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(7,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(8,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(8,1).Range.Font.Bold = $True
		$Table.Cell(8,1).Range.Text = "Can't change password"
		$Table.Cell(8,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(8,2).Range.Text = $UsersCannotChangePasswordStr
		[single]$pct = (($UsersCannotChangePassword / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(8,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(8,3).Range.Text = "$($pctstr)% of Total Users"
		$Table.Cell(9,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(9,1).Range.Font.Bold = $True
		$Table.Cell(9,1).Range.Text = "With SID History"
		$Table.Cell(9,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(9,2).Range.Text = $UsersWithSIDHistoryStr
		[single]$pct = (($UsersWithSIDHistory / $UsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(9,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(9,3).Range.Text = "$($pctstr)% of Total Users"

		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitContent)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null

		WriteWordLine 0 0 "*Unknown users are user accounts with no Enabled property." "" $Null 8 $False $True
		If($DARights -eq $False)
		{
			WriteWordLine 0 0 "*Rerun the script with Domain Admin rights in $($ADForest)." "" $Null 8 $False $True
		}
		Else
		{
			WriteWordLine 0 0 "*This may be a permissions issue if this is a Trusted Forest." "" $Null 8 $False $True
		}
		
		Write-Verbose "$(Get-Date): `t`tBuild table for Active Users"
		WriteWordLine 3 0 "Active Users"
		$TableRange   = $doc.Application.Selection.Range
		[int]$Columns = 3
		[int]$Rows = 6
		$Table = $doc.Tables.Add($TableRange, $Rows, $Columns)
		$Table.Style = $myHash.Word_TableGrid
		$Table.Borders.InsideLineStyle = $wdLineStyleSingle
		$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
		$Table.Cell(1,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(1,1).Range.Font.Bold = $True
		$Table.Cell(1,1).Range.Text = "Total Active Users"
		$Table.Cell(1,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(1,2).Range.Text = $ActiveUsersCountStr
		$Table.Cell(2,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(2,1).Range.Font.Bold = $True
		$Table.Cell(2,1).Range.Text = "Password expired"
		$Table.Cell(2,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(2,2).Range.Text = $ActiveUsersPasswordExpiredStr
		[single]$pct = (($ActiveUsersPasswordExpired / $ActiveUsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(2,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(2,3).Range.Text = "$($pctstr)% of Active Users"
		$Table.Cell(3,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(3,1).Range.Font.Bold = $True
		$Table.Cell(3,1).Range.Text = "Password never expires"
		$Table.Cell(3,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(3,2).Range.Text = $ActiveUsersPasswordNeverExpiresStr
		[single]$pct = (($ActiveUsersPasswordNeverExpires / $ActiveUsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(3,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(3,3).Range.Text = "$($pctstr)% of Active Users"
		$Table.Cell(4,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(4,1).Range.Font.Bold = $True
		$Table.Cell(4,1).Range.Text = "Password not required"
		$Table.Cell(4,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(4,2).Range.Text = $ActiveUsersPasswordNotRequiredStr
		[single]$pct = (($ActiveUsersPasswordNotRequired / $ActiveUsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(4,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(4,3).Range.Text = "$($pctstr)% of Active Users"
		$Table.Cell(5,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(5,1).Range.Font.Bold = $True
		$Table.Cell(5,1).Range.Text = "Can't change password"
		$Table.Cell(5,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(5,2).Range.Text = $ActiveUsersCannotChangePasswordStr
		[single]$pct = (($ActiveUsersCannotChangePassword / $ActiveUsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(5,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(5,3).Range.Text = "$($pctstr)% of Active Users"
		$Table.Cell(6,1).Shading.BackgroundPatternColor = $wdColorGray15
		$Table.Cell(6,1).Range.Font.Bold = $True
		$Table.Cell(6,1).Range.Text = "No lastLogonTimestamp"
		$Table.Cell(6,2).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(6,2).Range.Text = $ActiveUserslastLogonTimestampStr
		[single]$pct = (($ActiveUserslastLogonTimestamp / $ActiveUsersCount)*100)
		$pctstr = "{0,5:N2}" -f $pct
		$Table.Cell(6,3).Range.ParagraphFormat.Alignment = $wdAlignParagraphRight
		$Table.Cell(6,3).Range.Text = "$($pctstr)% of Active Users"

		$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
		$Table.AutoFitBehavior($wdAutoFitContent)

		#return focus back to document
		$doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument

		#move to the end of the current document
		$selection.EndKey($wdStory,$wdMove) | Out-Null
		$TableRange = $Null
		$Table = $Null

		#put computer info on a separate page
		$selection.InsertNewPage()
		
		GetComputerCountByOS $Domain
		
	}
	ElseIf(!$?)
	{
		Write-Warning "Error retrieving domain data for domain $($Domain)"
		WriteWordLine 0 0 "Error retrieving domain data for domain $($Domain)" "" $Null 0 $False $True
	}
	Else
	{
		WriteWordLine 0 0 "No Domain data was retrieved for domain $($Domain)" "" $Null 0 $False $True
	}
	$First = $False
}
$Domains = $Null
$DomainInfo = $Null
$Users = $Null
$EnabledUsers = $Null
$Results = $Null
$UsersCountStr = $Null
$UsersDisabledStr = $Null
$UsersUnknownStr = $Null
$UsersLockedOutStr = $Null
$UsersPasswordExpiredStr = $Null
$UsersPasswordNeverExpiresStr = $Null
$UsersPasswordNotRequiredStr = $Null
$UsersCannotChangePasswordStr = $Null
$UsersWithSIDHistoryStr = $Null
$ActiveUsersCountStr = $Null
$ActiveUsersPasswordExpiredStr = $Null
$ActiveUsersPasswordNeverExpiresStr = $Null
$ActiveUsersPasswordNotRequiredStr = $Null
$ActiveUsersCannotChangePasswordStr = $Null
$ActiveUserslastLogonTimestampStr = $Null
$pctstr = $Null
[gc]::collect() 

Write-Verbose "$(Get-Date): Finishing up Word document"
#end of document processing

#Update document properties
If($CoverPagesExist)
{
	Write-Verbose "$(Get-Date): Set Cover Page Properties"
	_SetDocumentProperty $doc.BuiltInDocumentProperties "Company" $CompanyName
	_SetDocumentProperty $doc.BuiltInDocumentProperties "Title" $title
	_SetDocumentProperty $doc.BuiltInDocumentProperties "Subject" "Active Directory Inventory"
	_SetDocumentProperty $doc.BuiltInDocumentProperties "Author" $username

	#Get the Coverpage XML part
	$cp = $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($CompanyName))
	{
		[string]$abstract = "Microsoft Active Directory Inventory"
	}
	Else
	{
		[string]$abstract = "Microsoft Active Directory Inventory for $CompanyName"
	}

	$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
	$doc.TablesOfContents.item(1).Update()
	$cp = $Null
	$ab = $Null
	$abstract = $Null
}

#bug fix 1-Apr-2014
#reset Grammar and Spelling options back to their original settings
$Word.Options.CheckGrammarAsYouType = $CurrentGrammarOption
$Word.Options.CheckSpellingAsYouType = $CurrentSpellingOption

Write-Verbose "$(Get-Date): Save and Close document and Shutdown Word"
If($WordVersion -eq $wdWord2007)
{
	#Word 2007
	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)
	{
		$FileName1 += "_$(Get-Date -f yyyy-MM-dd_HHmm).docx"
		If($PDF)
		{
			$FileName2 += "_$(Get-Date -f yyyy-MM-dd_HHmm).pdf"
		}
	}
	Write-Verbose "$(Get-Date): Running Word 2007 and detected operating system $($RunningOS)"
	If($RunningOS.Contains("Server 2008 R2") -or $RunningOS.Contains("Server 2012"))
	{
		$SaveFormat = "microsoft.office.interop.word.WdSaveFormat" -as [type] 
		$doc.SaveAs($filename1, $SaveFormat)
		If($PDF)
		{
			Write-Verbose "$(Get-Date): Now saving as PDF"
			$SaveFormat = $wdSaveFormatPDF
			$doc.SaveAs($filename2, $SaveFormat)
		}
	}
	Else
	{
		#works for Server 2008 and Windows 7
		$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatDocumentDefault")
		$doc.SaveAs([REF]$filename1, [ref]$SaveFormat)
		If($PDF)
		{
			Write-Verbose "$(Get-Date): Now saving as PDF"
			$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatPDF")
			$doc.SaveAs([REF]$filename2, [ref]$saveFormat)
		}
	}
}
Else
{
	#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)
	{
		$FileName1 += "_$(Get-Date -f yyyy-MM-dd_HHmm).docx"
		If($PDF)
		{
			$FileName2 += "_$(Get-Date -f yyyy-MM-dd_HHmm).pdf"
		}
	}
	$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatDocumentDefault")
	$doc.SaveAs([REF]$filename1, [ref]$SaveFormat)
	If($PDF)
	{
		Write-Verbose "$(Get-Date): Now saving as PDF"
		$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatPDF")
		$doc.SaveAs([REF]$filename2, [ref]$saveFormat)
	}
}

Write-Verbose "$(Get-Date): Closing Word"
$doc.Close()
$Word.Quit()
If($PDF)
{
	Write-Verbose "$(Get-Date): Deleting $($filename1) since only $($filename2) is needed"
	Remove-Item $filename1
}
Write-Verbose "$(Get-Date): System Cleanup"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word) | Out-Null
If(Test-Path variable:global:word)
{
	Remove-Variable -Name word -Scope Global
}
$SaveFormat = $Null
[gc]::collect() 
[gc]::WaitForPendingFinalizers()
Write-Verbose "$(Get-Date): Script has completed"
Write-Verbose "$(Get-Date): "

If($PDF)
{
	Write-Verbose "$(Get-Date): $($filename2) is ready for use"
}
Else
{
	Write-Verbose "$(Get-Date): $($filename1) is ready for use"
}
Write-Verbose "$(Get-Date): "

#http://poshtips.com/measuring-elapsed-time-in-powershell/
Write-Verbose "$(Get-Date): Script started: $($Script:StartTime)"
Write-Verbose "$(Get-Date): Script ended: $(Get-Date)"
$runtime = $(Get-Date) - $Script:StartTime
$Str = [string]::format("{0} days, {1} hours, {2} minutes, {3}.{4} seconds", `
	$runtime.Days, `
	$runtime.Hours, `
	$runtime.Minutes, `
	$runtime.Seconds,
	$runtime.Milliseconds)
Write-Verbose "$(Get-Date): Elapsed time: $($Str)"
$runtime = $Null
$Str = $Null
$ErrorActionPreference = $SaveEAPreference

Open in new window

0
Comment
Question by:claudiamcse
  • 2
  • 2
6 Comments
 
LVL 39

Accepted Solution

by:
footech earned 500 total points
ID: 40457888
There is no single change that would make this export to a .CSV.  From what I see, pretty much the whole thing is designed around creating and formatting a Word document.  This is a completely different direction than what you need to create a .CSV.

My suggestion would be for you to identify which parts of the script are generating the actual information you're interested in.  It might be that there's only a few commands that you need to run, instead of the 6000+ lines of code there is now.  Your other option might be to try to just pull the information (i.e. copy and paste) manually from the generated Word document and then put it in Excel, then you could save as a .CSV.

If I were you I wouldn't hold my breath waiting for someone to rewrite 6000 lines of code to do what you ask.  You've got to narrow down the issue a lot.
0
 

Author Comment

by:claudiamcse
ID: 40474857
Can someone recommend script that does the same thing but exports it to excel file instead of word? Thank you.
0
 

Author Comment

by:claudiamcse
ID: 40474864
I am interested in all the information that this script provides but instead of outputting results into word, I would like to export the results to excel file instead. Is there a script that does the same thing but exports it to excel? Could you please recommend the alternative scripts. Thank you so much.

http://carlwebster.com/active-directory-documentation-script-updated-5-jun-2014/
0
 
LVL 39

Expert Comment

by:footech
ID: 40485260
I'd like to help you, but...
I tried running the script just to see what the output is, but it hung on me.   Probably just an issue with the machine I tried running it on, but I'm not going to try to troubleshoot it.  You're going to have to contribute some effort to get an answer.  Maybe try posting some sample output.  However, my guess is that the output doesn't lend itself to being exported to a single .CSV, but instead you'd have to have serveral .CSV files for each of the different types of output.  

Here's my last advice.  Open up new questions for each type of information you want to retrieve.  Describe exactly what that information is and what format you need it in.  Don't leave it to others to run some script you post (particularly such a lengthy one), examine the output and the code, and then magically convert it to do as you desire.  In my opinion, that's far too much to ask of a single question here.  You have to do some of the analysis and specifying of results yourself.
0

Featured Post

The problems with reply email signatures

Do you wish that you could place an email signature under a reply? Well, unfortunately, you can't. That great Exchange/Office 365 signature you've created will just appear at the bottom of an email chain. What a pain! Is there really no way to solve this? Well, there might be...

Join & Write a Comment

We are happy to announce a brand new addition to our line of acclaimed email signature management products – CodeTwo Email Signatures for Office 365.
Create and license users in Office 365 in bulk based on a CSV file. A step-by-step guide with PowerShell script examples.
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
To add imagery to an HTML email signature, you have two options available to you. You can either add a logo/image by embedding it directly into the signature or hosting it externally and linking to it. The vast majority of email clients display l…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now