ADDS Inventory V2
ADDS Inventory V2
0
#requires -Module ActiveDirectory
#requires -Module GroupPolicy
#This File is in Unicode format. Do not edit in an ASCII editor. Notepad++ UTF-8-
BOM
<#
.SYNOPSIS
Creates a complete inventory of a Microsoft Active Directory Forest.
.DESCRIPTION
Creates a complete inventory of a Microsoft Active Directory Forest using
Microsoft
PowerShell, Word, plain text or HTML.
Creates a Word or PDF document, text or HTML file named after the Active
Directory Forest.
Word and PDF document includes a Cover Page, Table of Contents and Footer.
Includes support for the following language versions of Microsoft Word:
Catalan
Chinese
Danish
Dutch
English
Finnish
French
German
Norwegian
Portuguese
Spanish
Swedish
The script requires at least PowerShell version 3 but runs best in version 5.
Word is NOT needed to run the script. This script will output in Text and
HTML.
You do NOT have to run this script on a domain controller. This script was
developed
and run from a Windows 10 VM.
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 or enterprise admin
rights.
The Hardware and Services parameters require domain admin privileges.
Version 2.0 of the script adds gathering information on Time Server and AD
database,
log file, and SYSVOL locations. Those require access to the registry on each
domain
controller, which means the script should now always be run from an elevated
PowerShell
session with an account with a minimum of domain admin rights.
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".
Remote Server Administration Tools for Windows 7 with Service Pack 1 (SP1)
http://www.microsoft.com/en-us/download/details.aspx?id=7887
.PARAMETER CompanyAddress
Company Address to use for the Cover Page, if the Cover Page has the Address
field.
This parameter is only valid with the MSWORD and PDF output parameters.
This parameter has an alias of CA.
.PARAMETER CompanyEmail
Company Email to use for the Cover Page, if the Cover Page has the Email
field.
This parameter is only valid with the MSWORD and PDF output parameters.
This parameter has an alias of CE.
.PARAMETER CompanyFax
Company Fax to use for the Cover Page, if the Cover Page has the Fax field.
This parameter is only valid with the MSWORD and PDF output parameters.
This parameter has an alias of CF.
.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.
This parameter is only valid with the MSWORD and PDF output parameters.
.PARAMETER CompanyPhone
Company Phone to use for the Cover Page if the Cover Page has the Phone
field.
This parameter is only valid with the MSWORD and PDF output parameters.
This parameter has an alias of CPh.
.PARAMETER CoverPage
What Microsoft Word Cover Page to use.
Only Word 2010, 2013 and 2016 are supported.
(default cover pages in Word en-US)
attribute values.
The identifier in parentheses is the LDAP display name for the attribute.
property values. The identifier in parentheses is the LDAP display name for
the
attribute. All values are for the domainDNS object that represents the
domain.
Distinguished Name
Example: DC=tullahoma,DC=corp,DC=labaddomain,DC=com
GUID (objectGUID)
Example: b9fa5fbd-4334-4a98-85f1-3a3a44069fc6
Example: S-1-5-21-3643273344-1505409314-3732760578
Example: tullahoma.corp.labaddomain.com
Example: Tullahoma
Disabled users
Unknown users
Locked out users
All users with password expired
All users whose password never expires
All users with password not required
All users who cannot change password
All users with SID History
All users with Homedrive set in ADUC
All users whose Primary Group is not Domain Users
All users with RDS HomeDrive set in ADUC
WARNING: Using this parameter can create an extremely large report and
can take a very long time to run.
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 Section
Processes one or more sections of the report.
Valid options are:
Forest
Sites
Domains (includes Domain Controllers and optional Hardware, Services
and
DCDNSInfo)
OUs (Organizational Units)
Groups
GPOs
Misc (Miscellaneous data)
All
.PARAMETER SmtpServer
Specifies the optional email server to send the output report.
.PARAMETER SmtpPort
Specifies the SMTP port.
The default is 25.
.PARAMETER UseSSL
Specifies whether to use SSL for the SmtpServer.
The default is False.
.PARAMETER From
Specifies the username for the From email address.
If SmtpServer is used, this is a required parameter.
.PARAMETER To
Specifies the username for the To email address.
If SmtpServer is used, this is a required parameter.
.PARAMETER Dev
Clears errors at the beginning of the script.
Outputs all errors to a text file at the end of the script.
This is used when the script developer requests more troubleshooting data.
The text file is placed in the same folder from where the script is run.
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
Carl Webster for the Company Name.
Sideline for the Cover Page format.
Administrator for the User Name.
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
Because both ADForest and ADDomain are specified, ADDomain wins and
child.company.tld
is used for AD Domain.
ADForest is set to the value of ADDomain.
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
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
Will use all default values and save the document as a formatted text 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.
Will use all default values and save the document as an HTML 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.
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.
Will use all default values and add additional information for the services
running
on each domain controller.
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.
Will use all default values and add additional information for each domain
controller
about its DNS IP configuration.
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
Will use:
Carl Webster Consulting for the Company Name.
Mod for the Cover Page format.
Carl Webster for the User Name.
ADForest defaults to the value of $Env:USERDNSDOMAIN.
Domain Controller named ADDC01 for the ComputerName.
.EXAMPLE
PS C:\PSScript .\ADDS_Inventory_V2.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).
Will use:
Sherlock Holmes Consulting for the Company Name.
Exposure for the Cover Page format.
Dr. Watson for the User Name.
221B Baker Street, London, England for the Company Address.
+44 1753 276600 for the Company Fax.
+44 1753 276200 for the Company Phone.
Will use:
Sherlock Holmes Consulting for the Company Name.
Facet for the Cover Page format.
Dr. Watson for the User Name.
[email protected] for the Company Email.
ADForest defaults to the value of $Env:USERDNSDOMAIN.
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator.
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
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
The script will use the email server mail.domain.tld, sending from
[email protected],
sending to [email protected].
The script will use the default SMPTP port 25 and will not use SSL.
If the current user's credentials are not valid to send email, the user will
be prompted
to enter valid credentials.
.EXAMPLE
PS C:\PSScript > .\ADDS_Inventory_V2.ps1 -ADForest corp.carlwebster.com
-SmtpServer smtp.office365.com
-SmtpPort 587
-UseSSL
-From [email protected]
-To [email protected]
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
corp.carlwebster.com for the AD Forest
The script will use the email server smtp.office365.com on port 587 using
SSL, sending
from [email protected], sending to [email protected].
If the current user's credentials are not valid to send email, the user will
be prompted
to enter valid credentials.
.EXAMPLE
PS C:\PSScript > .\ADDS_Inventory_V2.ps1 -Section Forest
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
The report will include only the Groups and Miscellaneous sections.
.EXAMPLE
PS C:\PSScript > .\ADDS_Inventory_V2.ps1 -MaxDetails
Webster" or
HKEY_CURRENT_USER\Software\Microsoft\Office\Common\UserInfo\Company="Carl
Webster"
$env:username = Administrator
Section = "All"
.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_V2.ps1
VERSION: 2.22
AUTHOR: Carl Webster, Sr. Solutions Architect, Choice Solutions, LLC and
Michael B. Smith
LASTEDIT: February 13, 2019
#>
#thanks to @jeffwouters and Michael B. Smith for helping me with these parameters
[CmdletBinding(SupportsShouldProcess = $False, ConfirmImpact = "None",
DefaultParameterSetName = "Word") ]
Param(
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("CA")]
[ValidateNotNullOrEmpty()]
[string]$CompanyAddress="",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("CE")]
[ValidateNotNullOrEmpty()]
[string]$CompanyEmail="",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("CF")]
[ValidateNotNullOrEmpty()]
[string]$CompanyFax="",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("CN")]
[ValidateNotNullOrEmpty()]
[string]$CompanyName="",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("CPh")]
[ValidateNotNullOrEmpty()]
[string]$CompanyPhone="",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("CP")]
[ValidateNotNullOrEmpty()]
[string]$CoverPage="Sideline",
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Alias("UN")]
[ValidateNotNullOrEmpty()]
[string]$UserName=$env:username,
[parameter(ParameterSetName="HTML",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Switch]$HTML=$False,
[parameter(ParameterSetName="Word",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Switch]$MSWord=$False,
[parameter(ParameterSetName="PDF",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Switch]$PDF=$False,
[parameter(ParameterSetName="Text",Mandatory=$False)]
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[Switch]$Text=$False,
[parameter(Mandatory=$False)]
[Switch]$AddDateTime=$False,
[parameter(Mandatory=$False)]
[string]$ADForest=$Env:USERDNSDOMAIN,
[parameter(Mandatory=$False)]
[string]$ADDomain="",
[parameter(Mandatory=$False)]
[Alias("ServerName")]
[string]$ComputerName=$Env:USERDNSDOMAIN,
[parameter(Mandatory=$False)]
[Switch]$DCDNSInfo=$False,
[parameter(Mandatory=$False)]
[string]$Folder="",
[parameter(Mandatory=$False)]
[Switch]$GPOInheritance=$False,
[parameter(Mandatory=$False)]
[Switch]$Hardware=$False,
[parameter(Mandatory=$False)]
[Alias("IU")]
[Switch]$IncludeUserInfo=$False,
[parameter(Mandatory=$False)]
[Alias("MAX")]
[Switch]$MaxDetails=$False,
[parameter(Mandatory=$False )]
[Switch]$Services=$False,
[parameter(Mandatory=$False)]
[array]$Section="All",
[parameter(ParameterSetName="SMTP",Mandatory=$True)]
[string]$SmtpServer="",
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[int]$SmtpPort=25,
[parameter(ParameterSetName="SMTP",Mandatory=$False)]
[switch]$UseSSL=$False,
[parameter(ParameterSetName="SMTP",Mandatory=$True)]
[string]$From="",
[parameter(ParameterSetName="SMTP",Mandatory=$True)]
[string]$To="",
[parameter(Mandatory=$False)]
[Switch]$Dev=$False,
[parameter(Mandatory=$False)]
[Alias("SI")]
[Switch]$ScriptInfo=$False,
[parameter(Mandatory=$False)]
[Switch]$Log=$False
#[email protected]
#Sr. Solutions Architect at Choice Solutions, LLC
#@carlwebster on Twitter
#http://www.CarlWebster.com
#Created on April 10, 2014
Set-StrictMode -Version 2
#force on
$PSDefaultParameterValues = @{"*:Verbose"=$True}
$SaveEAPreference = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
#V2.18 added
If($Log)
{
#start transcript logging
$Script:ThisScriptPath = Split-Path -Parent
$MyInvocation.MyCommand.Definition
$Script:LogPath = "$Script:ThisScriptPath\ADDSDocScriptTranscript_$(Get-Date
-f yyyy-MM-dd_HHmm).txt"
try
{
Start-Transcript -Path $Script:LogPath -Force -Verbose:$false | Out-
Null
Write-Verbose "$(Get-Date): Transcript/log started at $Script:LogPath"
$Script:StartLog = $true
}
catch
{
Write-Verbose "$(Get-Date): Transcript/log failed at $Script:LogPath"
$Script:StartLog = $false
}
}
If($Dev)
{
$Error.Clear()
$Script:DevErrorFile = "$($pwd.Path)\ADInventoryScriptErrors_$(Get-Date -f
yyyy-MM-dd_HHmm).txt"
}
If($MSWord -eq $False -and $PDF -eq $False -and $Text -eq $False -and $HTML -eq
$False)
{
$MSWord = $True
}
If($MSWord)
{
Write-Verbose "$(Get-Date): MSWord is set"
}
ElseIf($PDF)
{
Write-Verbose "$(Get-Date): PDF is set"
}
ElseIf($Text)
{
Write-Verbose "$(Get-Date): Text is set"
}
ElseIf($HTML)
{
Write-Verbose "$(Get-Date): HTML is set"
}
Else
{
$ErrorActionPreference = $SaveEAPreference
Write-Verbose "$(Get-Date): Unable to determine output parameter"
If($Null -eq $MSWord)
{
Write-Verbose "$(Get-Date): MSWord is Null"
}
ElseIf($Null -eq $PDF)
{
Write-Verbose "$(Get-Date): PDF is Null"
}
ElseIf($Null -eq $Text)
{
Write-Verbose "$(Get-Date): Text is Null"
}
ElseIf($Null -eq $HTML)
{
Write-Verbose "$(Get-Date): HTML is Null"
}
Else
{
Write-Verbose "$(Get-Date): MSWord is $($MSWord)"
Write-Verbose "$(Get-Date): PDF is $($PDF)"
Write-Verbose "$(Get-Date): Text is $($Text)"
Write-Verbose "$(Get-Date): HTML is $($HTML)"
}
Write-Error "Unable to determine output parameter. Script cannot continue"
Exit
}
$ValidSection = $False
Switch ($Section)
{
"Forest" {$ValidSection = $True}
"Sites" {$ValidSection = $True}
"Domains" {$ValidSection = $True}
"OUs" {$ValidSection = $True}
"Groups" {$ValidSection = $True}
"GPOs" {$ValidSection = $True}
"Misc" {$ValidSection = $True}
"All" {$ValidSection = $True}
}
`t`tForest
`t`tSites
`t`tDomains
`t`tOUs
`t`tGroups
`t`tGPOs
`t`tMisc
`t`tAll
[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
}
If($HTML)
{
Set-Variable htmlredmask -Option AllScope -Value "#FF0000" 4>$Null
Set-Variable htmlcyanmask -Option AllScope -Value "#00FFFF" 4>$Null
Set-Variable htmlbluemask -Option AllScope -Value "#0000FF" 4>$Null
Set-Variable htmldarkbluemask -Option AllScope -Value "#0000A0" 4>$Null
Set-Variable htmllightbluemask -Option AllScope -Value "#ADD8E6" 4>$Null
Set-Variable htmlpurplemask -Option AllScope -Value "#800080" 4>$Null
Set-Variable htmlyellowmask -Option AllScope -Value "#FFFF00" 4>$Null
Set-Variable htmllimemask -Option AllScope -Value "#00FF00" 4>$Null
Set-Variable htmlmagentamask -Option AllScope -Value "#FF00FF" 4>$Null
Set-Variable htmlwhitemask -Option AllScope -Value "#FFFFFF" 4>$Null
Set-Variable htmlsilvermask -Option AllScope -Value "#C0C0C0" 4>$Null
Set-Variable htmlgraymask -Option AllScope -Value "#808080" 4>$Null
Set-Variable htmlblackmask -Option AllScope -Value "#000000" 4>$Null
Set-Variable htmlorangemask -Option AllScope -Value "#FFA500" 4>$Null
Set-Variable htmlmaroonmask -Option AllScope -Value "#800000" 4>$Null
Set-Variable htmlgreenmask -Option AllScope -Value "#008000" 4>$Null
Set-Variable htmlolivemask -Option AllScope -Value "#808000" 4>$Null
$emailAttachment = $Attachments
$emailSubject = $Script:Title
$emailBody = @"
Hello, <br />
<br />
$Script:Title is attached.
"@
If($Dev)
{
Out-File -FilePath $Script:DevErrorFile -InputObject $error 4>$Null
}
$error.Clear()
If($UseSSL)
{
Write-Verbose "$(Get-Date): Trying to send email using current user's
credentials with SSL"
Send-MailMessage -Attachments $emailAttachment -Body $emailBody
-BodyAsHtml -From $From `
-Port $SmtpPort -SmtpServer $SmtpServer -Subject $emailSubject -To $To
`
-UseSSL *>$Null
}
Else
{
Write-Verbose "$(Get-Date): Trying to send email using current user's
credentials without SSL"
Send-MailMessage -Attachments $emailAttachment -Body $emailBody
-BodyAsHtml -From $From `
-Port $SmtpPort -SmtpServer $SmtpServer -Subject $emailSubject -To $To
*>$Null
}
$e = $error[0]
If($e.Exception.ToString().Contains("5.7.57"))
{
#The server response was: 5.7.57 SMTP; Client was not authenticated to
send anonymous mail during MAIL FROM
Write-Verbose "$(Get-Date): Current user's credentials failed. Ask for
usable credentials."
If($Dev)
{
Out-File -FilePath $Script:DevErrorFile -InputObject $error
-Append 4>$Null
}
$error.Clear()
If($UseSSL)
{
Send-MailMessage -Attachments $emailAttachment -Body $emailBody
-BodyAsHtml -From $From `
-Port $SmtpPort -SmtpServer $SmtpServer -Subject $emailSubject
-To $To `
-UseSSL -credential $emailCredentials *>$Null
}
Else
{
Send-MailMessage -Attachments $emailAttachment -Body $emailBody
-BodyAsHtml -From $From `
-Port $SmtpPort -SmtpServer $SmtpServer -Subject $emailSubject
-To $To `
-credential $emailCredentials *>$Null
}
$e = $error[0]
Try
{
$Results = Get-WmiObject -computername $RemoteComputerName
win32_computersystem
}
Catch
{
$Results = $Null
}
ForEach($Item in $ComputerItems)
{
OutputComputerItem $Item $ComputerOS
}
}
ElseIf(!$?)
{
Write-Verbose "$(Get-Date): Get-WmiObject win32_computersystem failed
for $($RemoteComputerName)"
Write-Warning "Get-WmiObject win32_computersystem failed for $
($RemoteComputerName)"
If($MSWORD -or $PDF)
{
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
}
ElseIf($Text)
{
Line 2 "Get-WmiObject win32_computersystem failed for $
($RemoteComputerName)"
Line 2 "On $($RemoteComputerName) you may need to run winmgmt
/verifyrepository"
Line 2 "and winmgmt /salvagerepository. If this is a trusted
Forest, you may"
Line 2 "need to rerun the script with Domain Admin credentials
from the trusted Forest."
Line 2 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 2 "Get-WmiObject win32_computersystem failed for
$($RemoteComputerName)" "" $Null 0 $False $True
WriteHTMLLine 0 2 "On $($RemoteComputerName) you may need to run
winmgmt /verifyrepository" "" $Null 0 $False $True
WriteHTMLLine 0 2 "and winmgmt /salvagerepository. If this is a
trusted Forest, you may" "" $Null 0 $False $True
WriteHTMLLine 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"
If($MSWORD -or $PDF)
{
WriteWordLine 0 2 "No results Returned for Computer information"
"" $Null 0 $False $True
}
ElseIf($Text)
{
Line 2 "No results Returned for Computer information"
}
ElseIf($HTML)
{
WriteHTMLLine 0 2 "No results Returned for Computer information"
"" $Null 0 $False $True
}
}
Try
{
$Results = Get-WmiObject -computername $RemoteComputerName
Win32_LogicalDisk
}
Catch
{
$Results = $Null
}
Try
{
$Results = Get-WmiObject -computername $RemoteComputerName
win32_Processor
}
Catch
{
$Results = $Null
}
#Get Nics
Write-Verbose "$(Get-Date): `t`t`tNIC information"
[bool]$GotNics = $True
Try
{
$Results = Get-WmiObject -computername $RemoteComputerName
win32_networkadapterconfiguration
}
Catch
{
$Results = $Null
}
If($GotNics)
{
ForEach($nic in $nics)
{
Try
{
$ThisNic = Get-WmiObject -computername
$RemoteComputerName win32_networkadapter | Where-Object {$_.index -eq $nic.index}
}
Catch
{
$ThisNic = $Null
}
Function OutputComputerItem
{
Param([object]$Item, [string]$OS)
If($MSWord -or $PDF)
{
$ItemInformation = New-Object System.Collections.ArrayList
$ItemInformation.Add(@{ Data = "Manufacturer"; Value =
$Item.manufacturer; }) > $Null
$ItemInformation.Add(@{ Data = "Model"; Value = $Item.model; }) > $Null
$ItemInformation.Add(@{ Data = "Domain"; Value = $Item.domain; }) >
$Null
$ItemInformation.Add(@{ Data = "Operating System"; Value = $OS; }) >
$Null
$ItemInformation.Add(@{ Data = "Total Ram"; Value = "$
($Item.totalphysicalram) GB"; }) > $Null
$ItemInformation.Add(@{ Data = "Physical Processors (sockets)"; Value =
$Item.NumberOfProcessors; }) > $Null
$ItemInformation.Add(@{ Data = "Logical Processors (cores w/HT)"; Value
= $Item.NumberOfLogicalProcessors; }) > $Null
$Table = AddWordTable -Hashtable $ItemInformation `
-Columns Data,Value `
-List `
-AutoFit $wdAutoFitFixed;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 2 "Manufacturer`t`t`t: " $Item.manufacturer
Line 2 "Model`t`t`t`t: " $Item.model
Line 2 "Domain`t`t`t`t: " $Item.domain
Line 2 "Operating System`t`t: " $OS
Line 2 "Total Ram`t`t`t: $($Item.totalphysicalram) GB"
Line 2 "Physical Processors (sockets)`t: " $Item.NumberOfProcessors
Line 2 "Logical Processors (cores w/HT)`t: "
$Item.NumberOfLogicalProcessors
Line 2 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Manufacturer",($htmlsilver -bor $htmlbold),
$Item.manufacturer,$htmlwhite)
$rowdata += @(,('Model',($htmlsilver -bor $htmlbold),$Item.model,
$htmlwhite))
$rowdata += @(,('Domain',($htmlsilver -bor $htmlbold),$Item.domain,
$htmlwhite))
$rowdata += @(,('Total Ram',($htmlsilver -bor $htmlbold),"$
($Item.totalphysicalram) GB",$htmlwhite))
$rowdata += @(,('Physical Processors (sockets)',($htmlsilver -bor
$htmlbold),$Item.NumberOfProcessors,$htmlwhite))
$rowdata += @(,('Logical Processors (cores w/HT)',($htmlsilver -bor
$htmlbold),$Item.NumberOfLogicalProcessors,$htmlwhite))
$msg = ""
$columnWidths = @("150px","200px")
FormatHTMLTable $msg -rowarray $rowdata -columnArray $columnheaders
-fixedWidth $columnWidths -tablewidth "350"
WriteHTMLLine 0 0 " "
}
}
Function OutputDriveItem
{
Param([object]$Drive)
$xDriveType = ""
Switch ($drive.drivetype)
{
0 {$xDriveType = "Unknown"; Break}
1 {$xDriveType = "No Root Directory"; Break}
2 {$xDriveType = "Removable Disk"; Break}
3 {$xDriveType = "Local Disk"; Break}
4 {$xDriveType = "Network Drive"; Break}
5 {$xDriveType = "Compact Disc"; Break}
6 {$xDriveType = "RAM Disk"; Break}
Default {$xDriveType = "Unknown"; Break}
}
$xVolumeDirty = ""
If(![String]::IsNullOrEmpty($drive.volumedirty))
{
If($drive.volumedirty)
{
$xVolumeDirty = "Yes"
}
Else
{
$xVolumeDirty = "No"
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 2 ""
}
ElseIf($Text)
{
Line 2 "Caption`t`t: " $drive.caption
Line 2 "Size`t`t: $($drive.drivesize) GB"
If(![String]::IsNullOrEmpty($drive.filesystem))
{
Line 2 "File System`t: " $drive.filesystem
}
Line 2 "Free Space`t: $($drive.drivefreespace) GB"
If(![String]::IsNullOrEmpty($drive.volumename))
{
Line 2 "Volume Name`t: " $drive.volumename
}
If(![String]::IsNullOrEmpty($drive.volumedirty))
{
Line 2 "Volume is Dirty`t: " $xVolumeDirty
}
If(![String]::IsNullOrEmpty($drive.volumeserialnumber))
{
Line 2 "Volume Serial #`t: " $drive.volumeserialnumber
}
Line 2 "Drive Type`t: " $xDriveType
Line 2 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Caption",($htmlsilver -bor $htmlbold),
$Drive.caption,$htmlwhite)
$rowdata += @(,('Size',($htmlsilver -bor $htmlbold),"$
($drive.drivesize) GB",$htmlwhite))
If(![String]::IsNullOrEmpty($drive.filesystem))
{
$rowdata += @(,('File System',($htmlsilver -bor $htmlbold),
$Drive.filesystem,$htmlwhite))
}
$rowdata += @(,('Free Space',($htmlsilver -bor $htmlbold),"$
($drive.drivefreespace) GB",$htmlwhite))
If(![String]::IsNullOrEmpty($drive.volumename))
{
$rowdata += @(,('Volume Name',($htmlsilver -bor $htmlbold),
$Drive.volumename,$htmlwhite))
}
If(![String]::IsNullOrEmpty($drive.volumedirty))
{
$rowdata += @(,('Volume is Dirty',($htmlsilver -bor $htmlbold),
$xVolumeDirty,$htmlwhite))
}
If(![String]::IsNullOrEmpty($drive.volumeserialnumber))
{
$rowdata += @(,('Volume Serial Number',($htmlsilver -bor
$htmlbold),$Drive.volumeserialnumber,$htmlwhite))
}
$rowdata += @(,('Drive Type',($htmlsilver -bor $htmlbold),$xDriveType,
$htmlwhite))
$msg = ""
$columnWidths = @("150px","200px")
FormatHTMLTable $msg -rowarray $rowdata -columnArray $columnheaders
-fixedWidth $columnWidths -tablewidth "350"
WriteHTMLLine 0 0 " "
}
}
Function OutputProcessorItem
{
Param([object]$Processor)
$xAvailability = ""
Switch ($processor.availability)
{
1 {$xAvailability = "Other"; Break}
2 {$xAvailability = "Unknown"; Break}
3 {$xAvailability = "Running or Full Power"; Break}
4 {$xAvailability = "Warning"; Break}
5 {$xAvailability = "In Test"; Break}
6 {$xAvailability = "Not Applicable"; Break}
7 {$xAvailability = "Power Off"; Break}
8 {$xAvailability = "Off Line"; Break}
9 {$xAvailability = "Off Duty"; Break}
10 {$xAvailability = "Degraded"; Break}
11 {$xAvailability = "Not Installed"; Break}
12 {$xAvailability = "Install Error"; Break}
13 {$xAvailability = "Power Save - Unknown"; Break}
14 {$xAvailability = "Power Save - Low Power Mode"; Break}
15 {$xAvailability = "Power Save - Standby"; Break}
16 {$xAvailability = "Power Cycle"; Break}
17 {$xAvailability = "Power Save - Warning"; Break}
Default {$xAvailability = "Unknown"; Break}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 2 "Name`t`t`t`t: " $processor.name
Line 2 "Description`t`t`t: " $processor.description
Line 2 "Max Clock Speed`t`t`t: $($processor.maxclockspeed) MHz"
If($processor.l2cachesize -gt 0)
{
Line 2 "L2 Cache Size`t`t`t: $($processor.l2cachesize) KB"
}
If($processor.l3cachesize -gt 0)
{
Line 2 "L3 Cache Size`t`t`t: $($processor.l3cachesize) KB"
}
If($processor.numberofcores -gt 0)
{
Line 2 "# of Cores`t`t`t: " $processor.numberofcores
}
If($processor.numberoflogicalprocessors -gt 0)
{
Line 2 "# of Logical Procs (cores w/HT)`t: "
$processor.numberoflogicalprocessors
}
Line 2 "Availability`t`t`t: " $xAvailability
Line 2 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Name",($htmlsilver -bor $htmlbold),$Processor.name,
$htmlwhite)
$rowdata += @(,('Description',($htmlsilver -bor $htmlbold),
$Processor.description,$htmlwhite))
$msg = ""
$columnWidths = @("150px","200px")
FormatHTMLTable $msg -rowarray $rowdata -columnArray $columnheaders
-fixedWidth $columnWidths -tablewidth "350"
WriteHTMLLine 0 0 " "
}
}
Function OutputNicItem
{
Param([object]$Nic, [object]$ThisNic)
$xAvailability = ""
Switch ($processor.availability)
{
1 {$xAvailability = "Other"; Break}
2 {$xAvailability = "Unknown"; Break}
3 {$xAvailability = "Running or Full Power"; Break}
4 {$xAvailability = "Warning"; Break}
5 {$xAvailability = "In Test"; Break}
6 {$xAvailability = "Not Applicable"; Break}
7 {$xAvailability = "Power Off"; Break}
8 {$xAvailability = "Off Line"; Break}
9 {$xAvailability = "Off Duty"; Break}
10 {$xAvailability = "Degraded"; Break}
11 {$xAvailability = "Not Installed"; Break}
12 {$xAvailability = "Install Error"; Break}
13 {$xAvailability = "Power Save - Unknown"; Break}
14 {$xAvailability = "Power Save - Low Power Mode"; Break}
15 {$xAvailability = "Power Save - Standby"; Break}
16 {$xAvailability = "Power Cycle"; Break}
17 {$xAvailability = "Power Save - Warning"; Break}
Default {$xAvailability = "Unknown"; Break}
}
$xdnsenabledforwinsresolution = ""
If($nic.dnsenabledforwinsresolution)
{
$xdnsenabledforwinsresolution = "Yes"
}
Else
{
$xdnsenabledforwinsresolution = "No"
}
$xTcpipNetbiosOptions = ""
Switch ($nic.TcpipNetbiosOptions)
{
0 {$xTcpipNetbiosOptions = "Use NetBIOS setting from DHCP Server";
Break}
1 {$xTcpipNetbiosOptions = "Enable NetBIOS"; Break}
2 {$xTcpipNetbiosOptions = "Disable NetBIOS"; Break}
Default {$xTcpipNetbiosOptions = "Unknown"; Break}
}
$xwinsenablelmhostslookup = ""
If($nic.winsenablelmhostslookup)
{
$xwinsenablelmhostslookup = "Yes"
}
Else
{
$xwinsenablelmhostslookup = "No"
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 2 "Name`t`t`t: " $ThisNic.Name
If($ThisNic.Name -ne $nic.description)
{
Line 2 "Description`t`t: " $nic.description
}
Line 2 "Connection ID`t`t: " $ThisNic.NetConnectionID
If(validObject $Nic Manufacturer)
{
Line 2 "Manufacturer`t`t: " $Nic.manufacturer
}
Line 2 "Availability`t`t: " $xAvailability
Line 2 "Allow computer to turn "
Line 2 "off device to save power: " $PowerSaving
Line 2 "Physical Address`t: " $nic.macaddress
Line 2 "IP Address`t`t: " $xIPAddress[0]
$cnt = -1
ForEach($tmp in $xIPAddress)
{
$cnt++
If($cnt -gt 0)
{
Line 5 " " $tmp
}
}
Line 2 "Default Gateway`t`t: " $Nic.Defaultipgateway
Line 2 "Subnet Mask`t`t: " $xIPSubnet[0]
$cnt = -1
ForEach($tmp in $xIPSubnet)
{
$cnt++
If($cnt -gt 0)
{
Line 5 " " $tmp
}
}
If($nic.dhcpenabled)
{
$DHCPLeaseObtainedDate =
$nic.ConvertToDateTime($nic.dhcpleaseobtained)
$DHCPLeaseExpiresDate =
$nic.ConvertToDateTime($nic.dhcpleaseexpires)
Line 2 "DHCP Enabled`t`t: " $nic.dhcpenabled
Line 2 "DHCP Lease Obtained`t: " $dhcpleaseobtaineddate
Line 2 "DHCP Lease Expires`t: " $dhcpleaseexpiresdate
Line 2 "DHCP Server`t`t:" $nic.dhcpserver
}
If(![String]::IsNullOrEmpty($nic.dnsdomain))
{
Line 2 "DNS Domain`t`t: " $nic.dnsdomain
}
If($Null -ne $nic.dnsdomainsuffixsearchorder -and
$nic.dnsdomainsuffixsearchorder.length -gt 0)
{
[int]$x = 1
Line 2 "DNS Search Suffixes`t: "
$xnicdnsdomainsuffixsearchorder[0]
$cnt = -1
ForEach($tmp in $xnicdnsdomainsuffixsearchorder)
{
$cnt++
If($cnt -gt 0)
{
Line 5 " " $tmp
}
}
}
Line 2 "DNS WINS Enabled`t: " $xdnsenabledforwinsresolution
If($Null -ne $nic.dnsserversearchorder -and
$nic.dnsserversearchorder.length -gt 0)
{
[int]$x = 1
Line 2 "DNS Servers`t`t: " $xnicdnsserversearchorder[0]
$cnt = -1
ForEach($tmp in $xnicdnsserversearchorder)
{
$cnt++
If($cnt -gt 0)
{
Line 5 " " $tmp
}
}
}
Line 2 "NetBIOS Setting`t`t: " $xTcpipNetbiosOptions
Line 2 "WINS:"
Line 3 "Enabled LMHosts`t: " $xwinsenablelmhostslookup
If(![String]::IsNullOrEmpty($nic.winshostlookupfile))
{
Line 3 "Host Lookup File`t: " $nic.winshostlookupfile
}
If(![String]::IsNullOrEmpty($nic.winsprimaryserver))
{
Line 3 "Primary Server`t: " $nic.winsprimaryserver
}
If(![String]::IsNullOrEmpty($nic.winssecondaryserver))
{
Line 3 "Secondary Server`t: " $nic.winssecondaryserver
}
If(![String]::IsNullOrEmpty($nic.winsscopeid))
{
Line 3 "Scope ID`t`t: " $nic.winsscopeid
}
Line 0 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Name",($htmlsilver -bor $htmlbold),$ThisNic.Name,
$htmlwhite)
If($ThisNic.Name -ne $nic.description)
{
$rowdata += @(,('Description',($htmlsilver -bor $htmlbold),
$Nic.description,$htmlwhite))
}
$rowdata += @(,('Connection ID',($htmlsilver -bor $htmlbold),
$ThisNic.NetConnectionID,$htmlwhite))
If(validObject $Nic Manufacturer)
{
$rowdata += @(,('Manufacturer',($htmlsilver -bor $htmlbold),
$Nic.manufacturer,$htmlwhite))
}
$rowdata += @(,('Availability',($htmlsilver -bor $htmlbold),
$xAvailability,$htmlwhite))
$rowdata += @(,('Allow the computer to turn off this device to save
power',($htmlsilver -bor $htmlbold),$PowerSaving,$htmlwhite))
$rowdata += @(,('Physical Address',($htmlsilver -bor $htmlbold),
$Nic.macaddress,$htmlwhite))
$rowdata += @(,('IP Address',($htmlsilver -bor $htmlbold),
$xIPAddress[0],$htmlwhite))
$cnt = -1
ForEach($tmp in $xIPAddress)
{
$cnt++
If($cnt -gt 0)
{
$rowdata += @(,('IP Address',($htmlsilver -bor $htmlbold),
$tmp,$htmlwhite))
}
}
$rowdata += @(,('Default Gateway',($htmlsilver -bor $htmlbold),
$Nic.Defaultipgateway[0],$htmlwhite))
$rowdata += @(,('Subnet Mask',($htmlsilver -bor $htmlbold),
$xIPSubnet[0],$htmlwhite))
$cnt = -1
ForEach($tmp in $xIPSubnet)
{
$cnt++
If($cnt -gt 0)
{
$rowdata += @(,('Subnet Mask',($htmlsilver -bor $htmlbold),
$tmp,$htmlwhite))
}
}
If($nic.dhcpenabled)
{
$DHCPLeaseObtainedDate =
$nic.ConvertToDateTime($nic.dhcpleaseobtained)
$DHCPLeaseExpiresDate =
$nic.ConvertToDateTime($nic.dhcpleaseexpires)
$rowdata += @(,('DHCP Enabled',($htmlsilver -bor $htmlbold),
$Nic.dhcpenabled,$htmlwhite))
$rowdata += @(,('DHCP Lease Obtained',($htmlsilver -bor
$htmlbold),$dhcpleaseobtaineddate,$htmlwhite))
$rowdata += @(,('DHCP Lease Expires',($htmlsilver -bor
$htmlbold),$dhcpleaseexpiresdate,$htmlwhite))
$rowdata += @(,('DHCP Server',($htmlsilver -bor $htmlbold),
$Nic.dhcpserver,$htmlwhite))
}
If(![String]::IsNullOrEmpty($nic.dnsdomain))
{
$rowdata += @(,('DNS Domain',($htmlsilver -bor $htmlbold),
$Nic.dnsdomain,$htmlwhite))
}
If($Null -ne $nic.dnsdomainsuffixsearchorder -and
$nic.dnsdomainsuffixsearchorder.length -gt 0)
{
$rowdata += @(,('DNS Search Suffixes',($htmlsilver -bor
$htmlbold),$xnicdnsdomainsuffixsearchorder[0],$htmlwhite))
$cnt = -1
ForEach($tmp in $xnicdnsdomainsuffixsearchorder)
{
$cnt++
If($cnt -gt 0)
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$rowdata += @(,('DNS WINS Enabled',($htmlsilver -bor $htmlbold),
$xdnsenabledforwinsresolution,$htmlwhite))
If($Null -ne $nic.dnsserversearchorder -and
$nic.dnsserversearchorder.length -gt 0)
{
$rowdata += @(,('DNS Servers',($htmlsilver -bor $htmlbold),
$xnicdnsserversearchorder[0],$htmlwhite))
$cnt = -1
ForEach($tmp in $xnicdnsserversearchorder)
{
$cnt++
If($cnt -gt 0)
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$rowdata += @(,('NetBIOS Setting',($htmlsilver -bor $htmlbold),
$xTcpipNetbiosOptions,$htmlwhite))
$rowdata += @(,('WINS: Enabled LMHosts',($htmlsilver -bor $htmlbold),
$xwinsenablelmhostslookup,$htmlwhite))
If(![String]::IsNullOrEmpty($nic.winshostlookupfile))
{
$rowdata += @(,('Host Lookup File',($htmlsilver -bor $htmlbold),
$Nic.winshostlookupfile,$htmlwhite))
}
If(![String]::IsNullOrEmpty($nic.winsprimaryserver))
{
$rowdata += @(,('Primary Server',($htmlsilver -bor $htmlbold),
$Nic.winsprimaryserver,$htmlwhite))
}
If(![String]::IsNullOrEmpty($nic.winssecondaryserver))
{
$rowdata += @(,('Secondary Server',($htmlsilver -bor $htmlbold),
$Nic.winssecondaryserver,$htmlwhite))
}
If(![String]::IsNullOrEmpty($nic.winsscopeid))
{
$rowdata += @(,('Scope ID',($htmlsilver -bor $htmlbold),
$Nic.winsscopeid,$htmlwhite))
}
$msg = ""
$columnWidths = @("150px","200px")
FormatHTMLTable $msg -rowarray $rowdata -columnArray $columnheaders
-fixedWidth $columnWidths -tablewidth "350"
WriteHTMLLine 0 0 " "
}
}
#endregion
#region GetComputerServices
Function GetComputerServices
{
Param([string]$RemoteComputerName)
# modified 29-Apr-2018 to change from Arrays to New-Object
System.Collections.ArrayList
Try
{
#Iain Brighton optimization 5-Jun-2014
#Replaced with a single call to retrieve services via WMI. The repeated
## "Get-WMIObject Win32_Service -Filter" calls were the major delays in
the script.
## If we need to retrieve the StartUp type might as well just use WMI.
Catch
{
$Services = $Null
}
#V2.16 addition
[int]$MaxDisplayNameLength = ($Services.DisplayName | Measure-
Object -Maximum -Property Length).Maximum
If($MaxDisplayNameLength -gt 12) #12 is length of "Display Name"
{
#10 is length of "Display Name" minus 2 to allow for
spacing between columns
Line 1 ("Display Name" + (' ' * ($MaxDisplayNameLength -
10))) -NoNewLine
}
Else
{
Line 1 "Display Name " -NoNewLine
}
Line 1 "Status " -NoNewLine
Line 1 "Startup Type"
}
ElseIf($HTML)
{
WriteHTMLLine 0 1 "Services ($NumServices Services found)"
$rowdata = @()
}
ForEach($Service in $Services)
{
#Write-Verbose "$(Get-Date): `t`t`t Processing service $
($Service.DisplayName)";
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
#V2.16 change
Line 0 ""
}
ElseIf($HTML)
{
$columnHeaders = @('Display Name',($htmlsilver -bor
$htmlbold),'Status',($htmlsilver -bor $htmlbold),'Startup Type',($htmlsilver -bor
$htmlbold))
$msg = ""
FormatHTMLTable $msg "auto" -rowArray $rowdata -columnArray
$columnHeaders
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
Write-Warning "No services were retrieved."
If($MSWORD -or $PDF)
{
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
}
ElseIf($Text)
{
Line 0 "Warning: No Services were retrieved"
Line 1 "If this is a trusted Forest, you may need to rerun the"
Line 1 "script with Domain Admin credentials from the trusted
Forest."
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 "Warning: No Services were retrieved" "" $Null
0 $htmlbold
WriteHTMLLine 0 1 "If this is a trusted Forest, you may need to
rerun the" "" $Null 0 $htmlbold
WriteHTMLLine 0 1 "script with Domain Admin credentials from the
trusted Forest." "" $Null 0 $htmlbold
}
}
Else
{
Write-Warning "Services retrieval was successful but no services were
returned."
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 "Services retrieval was successful but no
services were returned." "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 "Services retrieval was successful but no services were
returned."
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 "Services retrieval was successful but no
services were returned." "" $Null 0 $htmlbold
}
}
}
#endregion
#region BuildDCDNSIPConfigTable
Function BuildDCDNSIPConfigTable
{
Param([string]$RemoteComputerName, [string]$Site)
[bool]$GotNics = $True
Try
{
$Results = Get-WmiObject -computername $RemoteComputerName
win32_networkadapterconfiguration
}
Catch
{
$Results = $Null
}
If($GotNics)
{
ForEach($nic in $nics)
{
Try
{
$ThisNic = Get-WmiObject -computername
$RemoteComputerName win32_networkadapter | Where-Object {$_.index -eq $nic.index}
}
Catch
{
$ThisNic = $Null
}
[void]$Script:DCDNSIPInfo.Add($obj)
}
}
}
}
Else
{
Write-Verbose "$(Get-Date): No results Returned for NIC configuration
information"
If($MSWORD -or $PDF)
{
WriteWordLine 0 2 "No results Returned for NIC configuration
information" "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 2 "No results Returned for NIC configuration information"
}
ElseIf($HTML)
{
WriteHTMLLine 0 2 "No results Returned for NIC configuration
information" "" $Null 0 $False $True
}
}
}
#endregion
#ca - Catalan
#da - Danish
#de - German
#en - English
#es - Spanish
#fi - Finnish
#fr - French
#nb - Norwegian
#nl - Dutch
#pt - Portuguese
#sv - Swedish
#zh - Chinese
[string]$toc = $(
Switch ($CultureCode)
{
'ca-' { 'Taula automática 2'; Break }
'da-' { 'Automatisk tabel 2'; Break }
'de-' { 'Automatische Tabelle 2'; Break }
'en-' { 'Automatic Table 2'; Break }
'es-' { 'Tabla automática 2'; Break }
'fi-' { 'Automaattinen taulukko 2'; Break }
'fr-' { 'Table automatique 2'; Break } #changed 13-feb-2017 david
roquier and samuel legrand
'nb-' { 'Automatisk tabell 2'; Break }
'nl-' { 'Automatische inhoudsopgave 2'; Break }
'pt-' { 'Sumário Automático 2'; Break }
'sv-' { 'Automatisk innehållsförteckning2'; Break }
'zh-' { '自动目录 2'; Break }
}
)
$Script:myHash = @{}
$Script:myHash.Word_TableOfContents = $toc
$Script:myHash.Word_NoSpacing = $wdStyleNoSpacing
$Script:myHash.Word_Heading1 = $wdStyleheading1
$Script:myHash.Word_Heading2 = $wdStyleheading2
$Script:myHash.Word_Heading3 = $wdStyleheading3
$Script:myHash.Word_Heading4 = $wdStyleheading4
$Script:myHash.Word_TableGrid = $wdTableGrid
}
Function GetCulture
{
Param([int]$WordValue)
#ca - Catalan
#da - Danish
#de - German
#en - English
#es - Spanish
#fi - Finnish
#fr - French
#nb - Norwegian
#nl - Dutch
#pt - Portuguese
#sv - Swedish
#zh - Chinese
Switch ($WordValue)
{
{$CatalanArray -contains $_} {$CultureCode = "ca-"}
{$ChineseArray -contains $_} {$CultureCode = "zh-"}
{$DanishArray -contains $_} {$CultureCode = "da-"}
{$DutchArray -contains $_} {$CultureCode = "nl-"}
{$EnglishArray -contains $_} {$CultureCode = "en-"}
{$FinnishArray -contains $_} {$CultureCode = "fi-"}
{$FrenchArray -contains $_} {$CultureCode = "fr-"}
{$GermanArray -contains $_} {$CultureCode = "de-"}
{$NorwegianArray -contains $_} {$CultureCode = "nb-"}
{$PortugueseArray -contains $_} {$CultureCode = "pt-"}
{$SpanishArray -contains $_} {$CultureCode = "es-"}
{$SwedishArray -contains $_} {$CultureCode = "sv-"}
Default {$CultureCode = "en-"}
}
Return $CultureCode
}
Function ValidateCoverPage
{
Param([int]$xWordVersion, [string]$xCP, [string]$CultureCode)
$xArray = ""
Switch ($CultureCode)
{
'ca-' {
If($xWordVersion -eq $wdWord2016)
{
$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ó
principal", "Whisp")
}
ElseIf($xWordVersion -eq $wdWord2013)
{
$xArray = ("Austin", "En bandes", "Faceta",
"Filigrana",
"Integral", "Ió (clar)", "Ió (fosc)", "Línia
lateral",
"Moviment", "Quadrícula", "Retrospectiu", "Sector
(clar)",
"Sector (fosc)", "Semàfor", "Visualització", "Whisp")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabet", "Anual", "Austin",
"Conservador",
"Contrast", "Cubicles", "Diplomàtic", "Exposició",
"Línia lateral", "Mod", "Mosiac", "Moviment", "Paper
de diari",
"Perspectiva", "Piles", "Quadrícula", "Sobri",
"Transcendir", "Trencaclosques")
}
}
'da-' {
If($xWordVersion -eq $wdWord2016)
{
$xArray = ("Austin", "BevægElse", "Brusen", "Facet",
"Filigran",
"Gitter", "Integral", "Ion (lys)", "Ion (mørk)",
"Retro", "Semafor", "Sidelinje", "Stribet",
"Udsnit (lys)", "Udsnit (mørk)", "Visningsmaster")
}
ElseIf($xWordVersion -eq $wdWord2013)
{
$xArray = ("BevægElse", "Brusen", "Ion (lys)",
"Filigran",
"Retro", "Semafor", "Visningsmaster", "Integral",
"Facet", "Gitter", "Stribet", "Sidelinje", "Udsnit
(lys)",
"Udsnit (mørk)", "Ion (mørk)", "Austin")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("BevægElse", "Moderat", "Perspektiv",
"Firkanter",
"Overskrid", "Alfabet", "Kontrast", "Stakke",
"Fliser", "Gåde",
"Gitter", "Austin", "Eksponering", "Sidelinje",
"Enkel",
"Nålestribet", "Årlig", "Avispapir", "Tradionel")
}
}
'de-' {
If($xWordVersion -eq $wdWord2016)
{
$xArray = ("Austin", "Bewegung", "Facette",
"Filigran",
"Gebändert", "Integral", "Ion (dunkel)", "Ion
(hell)",
"Pfiff", "Randlinie", "Raster", "Rückblick",
"Segment (dunkel)", "Segment (hell)", "Semaphor",
"ViewMaster")
}
ElseIf($xWordVersion -eq $wdWord2013)
{
$xArray = ("Semaphor", "Segment (hell)", "Ion
(hell)",
"Raster", "Ion (dunkel)", "Filigran", "Rückblick",
"Pfiff",
"ViewMaster", "Segment (dunkel)", "Verbunden",
"Bewegung",
"Randlinie", "Austin", "Integral", "Facette")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alphabet", "Austin", "Bewegung",
"Durchscheinend",
"Herausgestellt", "Jährlich", "Kacheln", "Kontrast",
"Kubistisch",
"Modern", "Nadelstreifen", "Perspektive", "Puzzle",
"Randlinie",
"Raster", "Schlicht", "Stapel", "Traditionell",
"Zeitungspapier")
}
}
'en-' {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion -eq
$wdWord2016)
{
$xArray = ("Austin", "Banded", "Facet", "Filigree",
"Grid",
"Integral", "Ion (Dark)", "Ion (Light)", "Motion",
"Retrospect",
"Semaphore", "Sideline", "Slice (Dark)", "Slice
(Light)", "ViewMaster",
"Whisp")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alphabet", "Annual", "Austere", "Austin",
"Conservative",
"Contrast", "Cubicles", "Exposure", "Grid", "Mod",
"Motion", "Newsprint",
"Perspective", "Pinstripes", "Puzzle", "Sideline",
"Stacks", "Tiles", "Transcend")
}
}
'es-' {
If($xWordVersion -eq $wdWord2016)
{
$xArray = ("Austin", "Con bandas", "Cortar (oscuro)",
"Cuadrícula",
"Whisp", "Faceta", "Filigrana", "Integral", "Ion
(claro)",
"Ion (oscuro)", "Línea lateral", "Movimiento",
"Retrospectiva",
"Semáforo", "Slice (luz)", "Vista principal",
"Whisp")
}
ElseIf($xWordVersion -eq $wdWord2013)
{
$xArray = ("Whisp", "Vista principal", "Filigrana",
"Austin",
"Slice (luz)", "Faceta", "Semáforo", "Retrospectiva",
"Cuadrícula",
"Movimiento", "Cortar (oscuro)", "Línea lateral",
"Ion (oscuro)",
"Ion (claro)", "Integral", "Con bandas")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabeto", "Anual", "Austero", "Austin",
"Conservador",
"Contraste", "Cuadrícula", "Cubículos", "Exposición",
"Línea lateral",
"Moderno", "Mosaicos", "Movimiento", "Papel
periódico",
"Perspectiva", "Pilas", "Puzzle", "Rayas",
"Sobrepasar")
}
}
'fi-' {
If($xWordVersion -eq $wdWord2016)
{
$xArray = ("Filigraani", "Integraali", "Ioni
(tumma)",
"Ioni (vaalea)", "Opastin", "Pinta", "Retro",
"Sektori (tumma)",
"Sektori (vaalea)", "Vaihtuvavärinen", "ViewMaster",
"Austin",
"Kuiskaus", "Liike", "Ruudukko", "Sivussa")
}
ElseIf($xWordVersion -eq $wdWord2013)
{
$xArray = ("Filigraani", "Integraali", "Ioni
(tumma)",
"Ioni (vaalea)", "Opastin", "Pinta", "Retro",
"Sektori (tumma)",
"Sektori (vaalea)", "Vaihtuvavärinen", "ViewMaster",
"Austin",
"Kiehkura", "Liike", "Ruudukko", "Sivussa")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Aakkoset", "Askeettinen", "Austin",
"Kontrasti",
"Laatikot", "Liike", "Liituraita", "Mod", "Osittain
peitossa",
"Palapeli", "Perinteinen", "Perspektiivi", "Pinot",
"Ruudukko",
"Ruudut", "Sanomalehtipaperi", "Sivussa",
"Vuotuinen", "Ylitys")
}
}
'fr-' {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion -eq
$wdWord2016)
{
$xArray = ("À bandes", "Austin", "Facette",
"Filigrane",
"Guide", "Intégrale", "Ion (clair)", "Ion (foncé)",
"Lignes latérales", "Quadrillage", "Rétrospective",
"Secteur (clair)",
"Secteur (foncé)", "Sémaphore", "ViewMaster",
"Whisp")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alphabet", "Annuel", "Austère", "Austin",
'nb-' {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion -eq
$wdWord2016)
{
$xArray = ("Austin", "BevegElse", "Dempet", "Fasett",
"Filigran",
"Integral", "Ion (lys)", "Ion (mørk)", "Retrospekt",
"Rutenett",
"Sektor (lys)", "Sektor (mørk)", "Semafor",
"Sidelinje", "Stripet",
"ViewMaster")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabet", "Årlig", "Avistrykk", "Austin",
"Avlukker",
"BevegElse", "Engasjement", "Enkel", "Fliser",
"Konservativ",
"Kontrast", "Mod", "Perspektiv", "Puslespill",
"Rutenett", "Sidelinje",
"Smale striper", "Stabler", "Transcenderende")
}
}
'nl-' {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion -eq
$wdWord2016)
{
$xArray = ("Austin", "Beweging", "Facet",
"Filigraan", "Gestreept",
"Integraal", "Ion (donker)", "Ion (licht)", "Raster",
"Segment (Light)", "Semafoor", "Slice (donker)",
"Spriet",
"Terugblik", "Terzijde", "ViewMaster")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Aantrekkelijk", "Alfabet", "Austin",
"Bescheiden",
"Beweging", "Blikvanger", "Contrast", "Eenvoudig",
"Jaarlijks",
"Krantenpapier", "Krijtstreep", "Kubussen", "Mod",
"Perspectief",
"Puzzel", "Raster", "Stapels",
"Tegels", "Terzijde")
}
}
'pt-' {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion -eq
$wdWord2016)
{
$xArray = ("Animação", "Austin", "Em Tiras",
"Exibição Mestra",
"Faceta", "Fatia (Clara)", "Fatia (Escura)",
"Filete", "Filigrana",
"Grade", "Integral", "Íon (Claro)", "Íon (Escuro)",
"Linha Lateral",
"Retrospectiva", "Semáforo")
}
ElseIf($xWordVersion -eq $wdWord2010)
{
$xArray = ("Alfabeto", "Animação", "Anual",
"Austero", "Austin", "Baias",
"Conservador", "Contraste", "Exposição", "Grade",
"Ladrilhos",
"Linha Lateral", "Listras", "Mod", "Papel Jornal",
"Perspectiva", "Pilhas",
"Quebra-cabeça", "Transcend")
}
}
'sv-' {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion -eq
$wdWord2016)
{
$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")
}
}
'zh-' {
If($xWordVersion -eq $wdWord2010 -or $xWordVersion -eq
$wdWord2013 -or $xWordVersion -eq $wdWord2016)
{
$xArray = ('奥斯汀', '边线型', '花丝', '怀旧', '积分',
'离子(浅色)', '离子(深色)', '母版型', '平面', '切片(浅色)',
'切片(深色)', '丝状', '网格', '镶边', '信号灯',
'运动型')
}
}
Default {
If($xWordVersion -eq $wdWord2013 -or $xWordVersion
-eq $wdWord2016)
{
$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")
}
}
}
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
}
Function ValidateCompanyName
{
[bool]$xResult = Test-RegistryValue
"HKCU:\Software\Microsoft\Office\Common\UserInfo" "CompanyName"
If($xResult)
{
Return Get-LocalRegistryValue
"HKCU:\Software\Microsoft\Office\Common\UserInfo" "CompanyName"
}
Else
{
$xResult = Test-RegistryValue
"HKCU:\Software\Microsoft\Office\Common\UserInfo" "Company"
If($xResult)
{
Return Get-LocalRegistryValue
"HKCU:\Software\Microsoft\Office\Common\UserInfo" "Company"
}
Else
{
Return ""
}
}
}
Function Set-DocumentProperty {
<#
.SYNOPSIS
Function to set the Title Page document properties in MS Word
.DESCRIPTION
Long description
.PARAMETER Document
Current Document Object
.PARAMETER DocProperty
Parameter description
.PARAMETER Value
Parameter description
.EXAMPLE
Set-DocumentProperty -Document $Script:Doc -DocProperty Title -Value
'MyTitle'
.EXAMPLE
Set-DocumentProperty -Document $Script:Doc -DocProperty Company -Value
'MyCompany'
.EXAMPLE
Set-DocumentProperty -Document $Script:Doc -DocProperty Author -Value 'Jim
Moyle'
.EXAMPLE
Set-DocumentProperty -Document $Script:Doc -DocProperty Subject -Value
'MySubjectTitle'
.NOTES
Function Created by Jim Moyle June 2017
Twitter : @JimMoyle
#>
param (
[object]$Document,
[String]$DocProperty,
[string]$Value
)
try {
$binding = "System.Reflection.BindingFlags" -as [type]
$builtInProperties = $Document.BuiltInDocumentProperties
$property = [System.__ComObject].invokemember("item",
$binding::GetProperty, $null, $BuiltinProperties, $DocProperty)
[System.__ComObject].invokemember("value", $binding::SetProperty, $null,
$property, $Value)
}
catch {
Write-Warning "Failed to set $DocProperty to $Value"
}
}
Function FindWordDocumentEnd
{
#return focus to main document
$Script:Doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument
#move to the end of the current document
$Script:Selection.EndKey($wdStory,$wdMove) | Out-Null
}
Function SetupWord
{
Write-Verbose "$(Get-Date): Setting up Word"
SetWordHashTable $Script:WordCultureCode
[int]$Script:WordVersion = [int]$Script:Word.Version
If($Script:WordVersion -eq $wdWord2016)
{
$Script:WordProduct = "Word 2016"
}
ElseIf($Script:WordVersion -eq $wdWord2013)
{
$Script:WordProduct = "Word 2013"
}
ElseIf($Script:WordVersion -eq $wdWord2010)
{
$Script:WordProduct = "Word 2010"
}
ElseIf($Script:WordVersion -eq $wdWord2007)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tMicrosoft Word 2007 is no longer
supported.`n`n`t`tScript will end.`n`n"
AbortScript
}
Else
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tYou are running an untested or unsupported version
of Microsoft Word.`n`n`t`tScript will end.`n`n`t`tPlease send info on your version
of Word to [email protected]`n`n"
AbortScript
}
If([String]::IsNullOrEmpty($TmpName))
{
Write-Warning "`n`n`t`tCompany Name is blank so Cover Page will
not show a Company Name."
Write-Warning "`n`t`tCheck
HKCU:\Software\Microsoft\Office\Common\UserInfo for Company or CompanyName value."
Write-Warning "`n`t`tYou may want to use the -CompanyName
parameter if you need a Company Name on the cover page.`n`n"
}
Else
{
$Script:CoName = $TmpName
Write-Verbose "$(Get-Date): Updated company name to $
($Script:CoName)"
}
}
'de-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Randlinie"
$CPChanged = $True
}
}
'es-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Línea lateral"
$CPChanged = $True
}
}
'fi-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "Sivussa"
$CPChanged = $True
}
}
'fr-' {
If($CoverPage -eq "Sideline")
{
If($Script:WordVersion -eq $wdWord2013 -or
$Script:WordVersion -eq $wdWord2016)
{
$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
}
}
'zh-' {
If($CoverPage -eq "Sideline")
{
$CoverPage = "边线型"
$CPChanged = $True
}
}
}
If($CPChanged)
{
Write-Verbose "$(Get-Date): Changed Default Cover Page from
Sideline to $($CoverPage)"
}
}
If(!$ValidCP)
{
$ErrorActionPreference = $SaveEAPreference
Write-Verbose "$(Get-Date): Word language value $
($Script:WordLanguageValue)"
Write-Verbose "$(Get-Date): Culture code $($Script:WordCultureCode)"
Write-Error "`n`n`t`tFor $($Script:WordProduct), $($CoverPage) is not a
valid Cover Page option.`n`n`t`tScript cannot continue.`n`n"
AbortScript
}
ShowScriptOptions
$Script:Word.Visible = $False
#http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-
slides-and-demos/
#using Jeff's Demo-WordReport.ps1 file for examples
Write-Verbose "$(Get-Date): Load Word Templates"
[bool]$Script:CoverPagesExist = $False
[bool]$BuildingBlocksExist = $False
$Script:Word.Templates.LoadBuildingBlocks()
#word 2010/2013/2016
$BuildingBlocksCollection = $Script:Word.Templates | Where-Object {$_.name
-eq "Built-In Building Blocks.dotx"}
$BuildingBlocksCollection |
ForEach-Object{
If ($_.BuildingBlockEntries.Item($CoverPage).Name -eq $CoverPage)
{
$BuildingBlocks = $_
}
}
Try
{
$part = $BuildingBlocks.BuildingBlockEntries.Item($CoverPage)
}
Catch
{
$part = $Null
}
If(!$Script:CoverPagesExist)
{
Write-Verbose "$(Get-Date): Cover Pages are not installed or the Cover
Page $($CoverPage) does not exist."
Write-Warning "Cover Pages are not installed or the Cover Page $
($CoverPage) does not exist."
Write-Warning "This report will not have a Cover Page."
}
$Script:Selection = $Script:Word.Selection
If($Null -eq $Script:Selection)
{
Write-Verbose "$(Get-Date): "
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tAn unknown error happened selecting the entire
Word document for default formatting options.`n`n`t`tScript cannot continue.`n`n"
AbortScript
}
#set Default tab stops to 1/2 inch (this line is not from Jeff Hicks)
#36 = .50"
$Script:Word.ActiveDocument.DefaultTabStop = 36
#Disable Spell and Grammar Check to resolve issue and improve performance
(from Pat Coughlin)
Write-Verbose "$(Get-Date): Disable grammar and spell checking"
#bug reported 1-Apr-2014 by Tim Mangan
#save current options first before turning them off
$Script:CurrentGrammarOption = $Script:Word.Options.CheckGrammarAsYouType
$Script:CurrentSpellingOption = $Script:Word.Options.CheckSpellingAsYouType
$Script:Word.Options.CheckGrammarAsYouType = $False
$Script:Word.Options.CheckSpellingAsYouType = $False
If($BuildingBlocksExist)
{
#insert new page, getting ready for table of contents
Write-Verbose "$(Get-Date): Insert new page, getting ready for table of
contents"
$part.Insert($Script:Selection.Range,$True) | Out-Null
$Script:Selection.InsertNewPage()
#table of contents
Write-Verbose "$(Get-Date): Table of Contents - $
($Script:MyHash.Word_TableOfContents)"
$toc =
$BuildingBlocks.BuildingBlockEntries.Item($Script:MyHash.Word_TableOfContents)
If($Null -eq $toc)
{
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): Table of Content - $
($Script:MyHash.Word_TableOfContents) could not be retrieved."
Write-Warning "This report will not have a Table of Contents."
}
Else
{
$toc.insert($Script:Selection.Range,$True) | Out-Null
}
}
Else
{
Write-Verbose "$(Get-Date): Table of Contents are not installed."
Write-Warning "Table of Contents are not installed so this report will
not have a Table of Contents."
}
FindWordDocumentEnd
Write-Verbose "$(Get-Date):"
#end of Jeff Hicks
}
Function UpdateDocumentProperties
{
Param([string]$AbstractTitle, [string]$SubjectTitle)
#updated 8-Jun-2017 with additional cover page fields
#Update document properties
If($MSWORD -or $PDF)
{
If($Script:CoverPagesExist)
{
Write-Verbose "$(Get-Date): Set Cover Page Properties"
#8-Jun-2017 put these 4 items in alpha order
Set-DocumentProperty -Document $Script:Doc -DocProperty Author -Value
$UserName
Set-DocumentProperty -Document $Script:Doc -DocProperty Company -Value
$Script:CoName
Set-DocumentProperty -Document $Script:Doc -DocProperty Subject -Value
$SubjectTitle
Set-DocumentProperty -Document $Script:Doc -DocProperty Title -Value
$Script:title
#added 8-Jun-2017
$ab = $cp.documentelement.ChildNodes | Where-Object {$_.basename
-eq "CompanyAddress"}
#set the text
[string]$abstract = $CompanyAddress
$ab.Text = $abstract
#added 8-Jun-2017
$ab = $cp.documentelement.ChildNodes | Where-Object {$_.basename
-eq "CompanyEmail"}
#set the text
[string]$abstract = $CompanyEmail
$ab.Text = $abstract
#added 8-Jun-2017
$ab = $cp.documentelement.ChildNodes | Where-Object {$_.basename
-eq "CompanyFax"}
#set the text
[string]$abstract = $CompanyFax
$ab.Text = $abstract
#added 8-Jun-2017
$ab = $cp.documentelement.ChildNodes | Where-Object {$_.basename
-eq "CompanyPhone"}
#set the text
[string]$abstract = $CompanyPhone
$ab.Text = $abstract
Function Get-RegistryValue
{
# Gets the specified registry value or $Null if it is missing
[CmdletBinding()]
Param([string]$path, [string]$name, [string]$ComputerName)
If($ComputerName -eq $env:computername -or $ComputerName -eq "LocalHost")
{
$key = Get-Item -LiteralPath $path -EA 0
If($key)
{
Return $key.GetValue($name, $Null)
}
Else
{
Return $Null
}
}
Else
{
#path needed here is different for remote registry access
$path1 = $path.SubString(6)
$path2 = $path1.Replace('\','\\')
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',
$ComputerName)
$RegKey= $Reg.OpenSubKey($path2)
$Results = $RegKey.GetValue($name)
If($Null -ne $Results)
{
Return $Results
}
Else
{
Return $Null
}
}
}
#endregion
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 # of tabs
While($tabs -gt 0)
{
$output += "`t"; $tabs--;
}
If(![String]::IsNullOrEmpty($fontName))
{
$Script:Selection.Font.name = $fontName
}
If($fontSize -ne 0)
{
$Script:Selection.Font.size = $fontSize
}
#**********************************************************************************
*************************
# WriteHTMLLine
#**********************************************************************************
*************************
<#
.Synopsis
Writes a line of output for HTML output
.DESCRIPTION
This function formats an HTML line
.USAGE
WriteHTMLLine <Style> <Tabs> <Name> <Value> <Font Name> <Font Size> <Options>
0 for Font Size denotes using the default font size of 2 or 10 point
.EXAMPLE
WriteHTMLLine 0 0 " "
Writes a blank line with no style or tab stops, obviously none needed.
.EXAMPLE
WriteHTMLLine 0 1 "This is a regular line of text indented 1 tab stops"
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in
italics" "" $Null 0 $htmlitalics
Writes a line omitting font and font size and setting the italics attribute
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in
bold" "" $Null 0 $htmlbold
Writes a line omitting font and font size and setting the bold attribute
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in bold
italics" "" $Null 0 ($htmlbold -bor $htmlitalics)
Writes a line omitting font and font size and setting both italics and bold
options
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in the default font in 10
point" "" $Null 2 # 10 point font
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of text in Courier New font" ""
"Courier New" 0
Writes a line using Courier New Font and 0 font point size (default = 2 if
set to 0)
.EXAMPLE
WriteHTMLLine 0 0 "This is a regular line of RED text indented 0 tab stops
with the computer name as data in 10 point Courier New bold italics: "
$env:computername "Courier New" 2 ($htmlbold -bor $htmlred -bor $htmlitalics)
Writes a line using Courier New Font with first and second string values to
be used, also uses 10 point font with bold, italics and red color options set.
.NOTES
Font Size - Unlike word, there is a limited set of font sizes that can be
used in HTML. They are:
0 - default which actually gives it a 2 or 10 point.
1 - 7.5 point font size
2 - 10 point
3 - 13.5 point
4 - 15 point
5 - 18 point
6 - 24 point
7 - 36 point
Any number larger than 7 defaults to 7
Style - Refers to the headers that are used with output and resemble the
headers in word,
HTML supports headers h1-h6 and h1-h4 are more commonly used. Unlike word,
H1 will not
give you a blue colored font, you will have to set that yourself.
htmlbold
htmlitalics
htmlred
htmlcyan
htmlblue
htmldarkblue
htmllightblue
htmlpurple
htmlyellow
htmllime
htmlmagenta
htmlwhite
htmlsilver
htmlgray
htmlolive
htmlorange
htmlmaroon
htmlgreen
htmlblack
#>
Function WriteHTMLLine
#Function created by Ken Avram
#Function created to make output to HTML easy in this script
#headings fixed 12-Oct-2016 by Webster
#errors with $HTMLStyle fixed 7-Dec-2017 by Webster
{
Param([int]$style=0,
[int]$tabs = 0,
[string]$name = '',
[string]$value = '',
[string]$fontName="Calibri",
[int]$fontSize=1,
[int]$options=$htmlblack)
If([String]::IsNullOrEmpty($Name))
{
$HTMLBody = "<p></p>"
}
Else
{
$color = CheckHTMLColor $options
#build # of tabs
While($tabs -gt 0)
{
$output += " "; $tabs--;
}
$HTMLFontName = $fontName
$HTMLBody = ""
Switch ($style)
{
1 {$HTMLStyle = "<h1>"; Break}
2 {$HTMLStyle = "<h2>"; Break}
3 {$HTMLStyle = "<h3>"; Break}
4 {$HTMLStyle = "<h4>"; Break}
Default {$HTMLStyle = ""; Break}
}
Switch ($style)
{
1 {$HTMLStyle = "</h1>"; Break}
2 {$HTMLStyle = "</h2>"; Break}
3 {$HTMLStyle = "</h3>"; Break}
4 {$HTMLStyle = "</h4>"; Break}
Default {$HTMLStyle = ""; Break}
}
If($fixedInfo.Length -eq 0)
{
$htmlbody += "<td style=""background-color:$($tmp)""><font
face='$($fontName)' size='$($fontSize)'>"
}
Else
{
$htmlbody += "<td style=""width:$
($fixedInfo[$columnIndex/2]); background-color:$($tmp)""><font face='$($fontName)'
size='$($fontSize)'>"
}
#**********************************************************************************
*************************
# FormatHTMLTable
# Created by Ken Avram
# modified by Jake Rutski
#**********************************************************************************
*************************
<#
.Synopsis
Format table for HTML output document
.DESCRIPTION
This function formats a table for HTML from an array of strings
.PARAMETER noBorder
If set to $true, a table will be generated without a border (border='0')
.PARAMETER noHeadCols
This parameter should be used when generating tables without column headers
Set this parameter equal to the number of columns in the table
.PARAMETER rowArray
This parameter contains the row data array for the table
.PARAMETER columnArray
This parameter contains column header data for the table
.PARAMETER fixedWidth
This parameter contains widths for columns in pixel format ("100px") to
override auto column widths
The variable should contain a width for each column you wish to override the
auto-size setting
For example: $columnWidths = @("100px","110px","120px","130px","140px")
.USAGE
FormatHTMLTable <Table Header> <Table Format> <Font Name> <Font Size>
.EXAMPLE
FormatHTMLTable "Table Heading" "auto" "Calibri" 3
This example formats a table and writes it out into an html file. All of the
parameters are optional
defaults are used if not supplied.
for <Table format>, the default is auto which will autofit the text into the
columns and adjust to the longest text in that column. You can also use percentage
i.e. 25%
which will take only 25% of the line and will auto word wrap the text to the
next line in the column. Also, instead of using a percentage, you can use pixels
i.e. 400px.
This example creates an HTML table with a heading of 'Table Heading', auto
column spacing, column header data from $columnData and row data from $rowData
This example creates an HTML table with a heading of 'Table Heading', auto
column spacing, no header, and row data from $rowData
.NOTES
In order to use the formatted table it first has to be loaded with data.
Examples below will show how to load the table:
$rowdata = @()
Then Load the array. If you are using column headers then load those into
the column headers array, otherwise the first line of the table goes into the
column headers array
and the second and subsequent lines go into the $rowdata table as shown
below:
The first column is the actual name to display, the second are the attributes
of the column i.e. color anded with bold or italics. For the anding, parens are
required or it will
not format correctly.
$rowdata = @()
$columnHeaders = @("User Name",($htmlsilver -bor $htmlbold),$UserName,
$htmlwhite)
$rowdata += @(,('Save as PDF',($htmlsilver -bor $htmlbold),$PDF.ToString(),
$htmlwhite))
$rowdata += @(,('Save as TEXT',($htmlsilver -bor $htmlbold),$TEXT.ToString(),
$htmlwhite))
$rowdata += @(,('Save as WORD',($htmlsilver -bor $htmlbold),
$MSWORD.ToString(),$htmlwhite))
$rowdata += @(,('Save as HTML',($htmlsilver -bor $htmlbold),$HTML.ToString(),
$htmlwhite))
$rowdata += @(,('Add DateTime',($htmlsilver -bor $htmlbold),
$AddDateTime.ToString(),$htmlwhite))
$rowdata += @(,('Hardware Inventory',($htmlsilver -bor $htmlbold),
$Hardware.ToString(),$htmlwhite))
$rowdata += @(,('Computer Name',($htmlsilver -bor $htmlbold),$ComputerName,
$htmlwhite))
$rowdata += @(,('Filename1',($htmlsilver -bor $htmlbold),
$Script:FileName1,$htmlwhite))
$rowdata += @(,('OS Detected',($htmlsilver -bor $htmlbold),$Script:RunningOS,
$htmlwhite))
$rowdata += @(,('PSUICulture',($htmlsilver -bor $htmlbold),$PSCulture,
$htmlwhite))
$rowdata += @(,('PoSH version',($htmlsilver -bor $htmlbold),
$Host.Version.ToString(),$htmlwhite))
FormatHTMLTable "Example of Horizontal AutoFitContents HTML Table" -rowArray
$rowdata
The 'rowArray' paramater is mandatory to build the table, but it is not set
as such in the function - if nothing is passed, the table will be empty.
htmlbold
htmlitalics
htmlred
htmlcyan
htmlblue
htmldarkblue
htmllightblue
htmlpurple
htmlyellow
htmllime
htmlmagenta
htmlwhite
htmlsilver
htmlgray
htmlolive
htmlorange
htmlmaroon
htmlgreen
htmlblack
#>
Function FormatHTMLTable
{
Param([string]$tableheader,
[string]$tablewidth="auto",
[string]$fontName="Calibri",
[int]$fontSize=2,
[switch]$noBorder=$false,
[int]$noHeadCols=1,
[object[]]$rowArray=@(),
[object[]]$fixedWidth=@(),
[object[]]$columnArray=@())
If($columnArray.Length -eq 0)
{
$NumCols = $noHeadCols + 1
} # means we have no column headers, just a table
Else
{
$NumCols = $columnArray.Length
} # need to add one for the color attrib
If($noBorder)
{
$htmlbody += "<table border='0' width='" + $tablewidth + "'>"
}
Else
{
$htmlbody += "<table border='1' width='" + $tablewidth + "'>"
}
Function SetupHTML
{
Write-Verbose "$(Get-Date): Setting up HTML"
If(!$AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName).html"
}
ElseIf($AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName)_$(Get-Date
-f yyyy-MM-dd_HHmm).html"
}
<#
.Synopsis
Add a table to a Microsoft Word document
.DESCRIPTION
This function adds a table to a Microsoft Word document from either an array
of
Hashtables or an array of PSCustomObjects.
Using this function is quicker than setting each table cell individually but
can
only utilise the built-in MS Word table autoformats. Individual tables cells
can
be altered after the table has been appended to the document (a table
reference
is returned).
.EXAMPLE
AddWordTable -Hashtable $HashtableArray
This example adds table to the MS Word document, utilising all key/value
pairs in
the array of hashtables. Column headers will display the key names as
defined.
Note: the columns might not be displayed in the order that they were defined.
To
ensure columns are displayed in the required order utilise the -Columns
parameter.
.EXAMPLE
AddWordTable -Hashtable $HashtableArray -List
This example adds table to the MS Word document, utilising all key/value
pairs in
the array of hashtables. No column headers will be added, in a ListView
format.
Note: the columns might not be displayed in the order that they were defined.
To
ensure columns are displayed in the required order utilise the -Columns
parameter.
.EXAMPLE
AddWordTable -CustomObject $PSCustomObjectArray
This example adds table to the MS Word document, utilising all note property
names
the array of PSCustomObjects. Column headers will display the note property
names.
Note: the columns might not be displayed in the order that they were defined.
To
ensure columns are displayed in the required order utilise the -Columns
parameter.
.EXAMPLE
AddWordTable -Hashtable $HashtableArray -Columns
FirstName,LastName,EmailAddress
This example adds a table to the MS Word document, but only using the
specified
key names: FirstName, LastName and EmailAddress. If other keys are present in
the
array of Hashtables they will be ignored.
.EXAMPLE
AddWordTable -CustomObject $PSCustomObjectArray -Columns
FirstName,LastName,EmailAddress -Headers "First Name","Last Name","Email Address"
This example adds a table to the MS Word document, but only using the
specified
PSCustomObject note properties: FirstName, LastName and EmailAddress. If
other note
properties are present in the array of PSCustomObjects they will be ignored.
The
display names for each specified column header has been overridden to display
a
custom header. Note: the order of the header names must match the specified
columns.
#>
Function AddWordTable
{
[CmdletBinding()]
Param
(
# Array of Hashtable (including table headers)
[Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True,
ParameterSetName='Hashtable', Position=0)]
[ValidateNotNullOrEmpty()] [System.Collections.Hashtable[]] $Hashtable,
# Array of PSCustomObjects
[Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True,
ParameterSetName='CustomObject', Position=0)]
[ValidateNotNullOrEmpty()] [PSCustomObject[]] $CustomObject,
# Array of Hashtable key names or PSCustomObject property names to
include, in display order.
# If not supplied then all Hashtable keys or all PSCustomObject
properties will be displayed.
[Parameter(ValueFromPipelineByPropertyName=$True)] [AllowNull()]
[string[]] $Columns = $Null,
# Array of custom table header strings in display order.
[Parameter(ValueFromPipelineByPropertyName=$True)] [AllowNull()]
[string[]] $Headers = $Null,
# AutoFit table behavior.
[Parameter(ValueFromPipelineByPropertyName=$True)] [AllowNull()] [int]
$AutoFit = -1,
# List view (no headers)
[Switch] $List,
# Grid lines
[Switch] $NoGridLines,
[Switch] $NoInternalGridLines,
# Built-in Word table formatting style constant
# Would recommend only $wdTableFormatContempory for normal usage
(possibly $wdTableFormatList5 for List view)
[Parameter(ValueFromPipelineByPropertyName=$True)] [int] $Format = 0
)
Begin
{
Write-Debug ("Using parameter set '{0}'" -f
$PSCmdlet.ParameterSetName);
## Check if -Columns wasn't specified but -Headers were (saves some
additional parameter sets!)
If(($Null -eq $Columns) -and ($Null -ne $Headers))
{
Write-Warning "No columns specified and therefore, specified
headers will be ignored.";
$Columns = $Null;
}
ElseIf(($Null -ne $Columns) -and ($Null -ne $Headers))
{
## Check if number of specified -Columns matches number of
specified -Headers
If($Columns.Length -ne $Headers.Length)
{
Write-Error "The specified number of columns does not match
the specified number of headers.";
}
} ## end ElseIf
} ## end Begin
Process
{
## Build the Word table data string to be converted to a range and then
a table later.
[System.Text.StringBuilder] $WordRangeString = New-Object
System.Text.StringBuilder;
Switch ($PSCmdlet.ParameterSetName)
{
'CustomObject'
{
If($Null -eq $Columns)
{
## Build the available columns from all available
PSCustomObject note properties
[string[]] $Columns = @();
## Add each NoteProperty name to the array
ForEach($Property in ($CustomObject | Get-Member
-MemberType NoteProperty))
{
$Columns += $Property.Name;
}
}
Default
{ ## Hashtable
If($Null -eq $Columns)
{
## Build the available columns from all available
hashtable keys. Hopefully
## all Hashtables have the same keys (they should for
a table).
$Columns = $Hashtable[0].Keys;
}
If(!$List)
{
#the next line causes the heading row to flow across page breaks
$WordTable.Rows.First.Headingformat = $wdHeadingFormatTrue;
}
If(!$NoGridLines)
{
$WordTable.Borders.InsideLineStyle = $wdLineStyleSingle;
$WordTable.Borders.OutsideLineStyle = $wdLineStyleSingle;
}
If($NoGridLines)
{
$WordTable.Borders.InsideLineStyle = $wdLineStyleNone;
$WordTable.Borders.OutsideLineStyle = $wdLineStyleNone;
}
If($NoInternalGridLines)
{
$WordTable.Borders.InsideLineStyle = $wdLineStyleNone;
$WordTable.Borders.OutsideLineStyle = $wdLineStyleSingle;
}
Return $WordTable;
} ## end Process
}
<#
.Synopsis
Sets the format of one or more Word table cells
.DESCRIPTION
This function sets the format of one or more table cells, either from a
collection
of Word COM object cell references, an individual Word COM object cell
reference or
a hashtable containing Row and Column information.
The font name, font size, bold, italic , underline and shading values can be
used.
.EXAMPLE
SetWordCellFormat -Hashtable $Coordinates -Table $TableReference -Bold
This example sets all text to bold that is contained within the
$TableReference
Word table, using an array of hashtables. Each hashtable contain a pair of
co-
ordinates that is used to select the required cells. Note: the hashtable must
contain the .Row and .Column key names. For example:
@ { Row = 7; Column = 3 } to set the cell at row 7 and column 3 to bold.
.EXAMPLE
$RowCollection = $Table.Rows.First.Cells
SetWordCellFormat -Collection $RowCollection -Bold -Size 10
This example sets all text to size 8 and bold for all cells that are
contained
within the first row of the table.
Note: the $Table.Rows.First.Cells returns a collection of Word COM cells
objects
that are in the first table row.
.EXAMPLE
$ColumnCollection = $Table.Columns.Item(2).Cells
SetWordCellFormat -Collection $ColumnCollection -BackgroundColor 255
This example sets the background (shading) of all cells in the table's second
column to red.
Note: the $Table.Columns.Item(2).Cells returns a collection of Word COM cells
objects
that are in the table's second column.
.EXAMPLE
SetWordCellFormat -Cell $Table.Cell(17,3) -Font "Tahoma" -Color 16711680
This example sets the font to Tahoma and the text color to blue for the cell
located
in the table's 17th row and 3rd column.
Note: the $Table.Cell(17,3) returns a single Word COM cells object.
#>
Function SetWordCellFormat
{
[CmdletBinding(DefaultParameterSetName='Collection')]
Param (
# Word COM object cell collection reference
[Parameter(Mandatory=$true, ValueFromPipeline=$true,
ParameterSetName='Collection', Position=0)] [ValidateNotNullOrEmpty()] $Collection,
# Word COM object individual cell reference
[Parameter(Mandatory=$true, ParameterSetName='Cell', Position=0)]
[ValidateNotNullOrEmpty()] $Cell,
# Hashtable of cell co-ordinates
[Parameter(Mandatory=$true, ParameterSetName='Hashtable', Position=0)]
[ValidateNotNullOrEmpty()] [System.Collections.Hashtable[]] $Coordinates,
# Word COM object table reference
[Parameter(Mandatory=$true, ParameterSetName='Hashtable', Position=1)]
[ValidateNotNullOrEmpty()] $Table,
# Font name
[Parameter()] [AllowNull()] [string] $Font = $Null,
# Font color
[Parameter()] [AllowNull()] $Color = $Null,
# Font size
[Parameter()] [ValidateNotNullOrEmpty()] [int] $Size = 0,
# Cell background color
[Parameter()] [AllowNull()] $BackgroundColor = $Null,
# Force solid background color
[Switch] $Solid,
[Switch] $Bold,
[Switch] $Italic,
[Switch] $Underline
)
Begin
{
Write-Debug ("Using parameter set '{0}'." -f
$PSCmdlet.ParameterSetName);
}
Process
{
Switch ($PSCmdlet.ParameterSetName)
{
'Collection' {
ForEach($Cell in $Collection)
{
If($Null -ne $BackgroundColor)
{ $Cell.Shading.BackgroundPatternColor = $BackgroundColor; }
If($Bold) { $Cell.Range.Font.Bold = $true; }
If($Italic) { $Cell.Range.Font.Italic = $true; }
If($Underline) { $Cell.Range.Font.Underline = 1; }
If($Null -ne $Font) { $Cell.Range.Font.Name =
$Font; }
If($Null -ne $Color) { $Cell.Range.Font.Color =
$Color; }
If($Size -ne 0) { $Cell.Range.Font.Size = $Size; }
If($Solid) { $Cell.Shading.Texture = 0; } ##
wdTextureNone
} # end ForEach
} # end Collection
'Cell'
{
If($Bold) { $Cell.Range.Font.Bold = $true; }
If($Italic) { $Cell.Range.Font.Italic = $true; }
If($Underline) { $Cell.Range.Font.Underline = 1; }
If($Null -ne $Font) { $Cell.Range.Font.Name = $Font; }
If($Null -ne $Color) { $Cell.Range.Font.Color = $Color; }
If($Size -ne 0) { $Cell.Range.Font.Size = $Size; }
If($Null -ne $BackgroundColor)
{ $Cell.Shading.BackgroundPatternColor = $BackgroundColor; }
If($Solid) { $Cell.Shading.Texture = 0; } ## wdTextureNone
} # end Cell
'Hashtable'
{
ForEach($Coordinate in $Coordinates)
{
$Cell = $Table.Cell($Coordinate.Row,
$Coordinate.Column);
If($Bold) { $Cell.Range.Font.Bold = $true; }
If($Italic) { $Cell.Range.Font.Italic = $true; }
If($Underline) { $Cell.Range.Font.Underline = 1; }
If($Null -ne $Font) { $Cell.Range.Font.Name =
$Font; }
If($Null -ne $Color) { $Cell.Range.Font.Color =
$Color; }
If($Size -ne 0) { $Cell.Range.Font.Size = $Size; }
If($Null -ne $BackgroundColor)
{ $Cell.Shading.BackgroundPatternColor = $BackgroundColor; }
If($Solid) { $Cell.Shading.Texture = 0; } ##
wdTextureNone
}
} # end Hashtable
} # end switch
} # end process
}
<#
.Synopsis
Sets alternate row colors in a Word table
.DESCRIPTION
This function sets the format of alternate rows within a Word table using the
specified $BackgroundColor. This function is expensive (in performance terms)
as
it recursively sets the format on alternate rows. It would be better to pick
one
of the predefined table formats (if one exists)? Obviously the more rows, the
longer it takes :'(
This example sets every-other table (starting with the first) row and sets
the
background color to red (wdColorRed).
.EXAMPLE
SetWordTableAlternateRowColor -Table $TableReference -BackgroundColor 39423
-Seed Second
This example sets every other table (starting with the second) row and sets
the
background color to light orange (weColorLightOrange).
#>
Function SetWordTableAlternateRowColor
{
[CmdletBinding()]
Param (
# Word COM object table reference
[Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]
[ValidateNotNullOrEmpty()] $Table,
# Alternate row background color
[Parameter(Mandatory=$true, Position=1)] [ValidateNotNull()] [int]
$BackgroundColor,
# Alternate row starting seed
[Parameter(ValueFromPipelineByPropertyName=$true, Position=2)]
[ValidateSet('First','Second')] [string] $Seed = 'First'
)
Process
{
$StartDateTime = Get-Date;
Write-Debug ("{0}: `t`tSetting alternate table row colors.." -f
$StartDateTime);
## Determine the row seed (only really need to check for 'Second' and
default to 'First' otherwise
If($Seed.ToLower() -eq 'second')
{
$StartRowIndex = 2;
}
Else
{
$StartRowIndex = 1;
}
$Table.Rows.Item($AlternateRowIndex).Shading.BackgroundPatternColor =
$BackgroundColor;
}
## I've put verbose calls in here we can see how expensive this
functionality actually is.
$EndDateTime = Get-Date;
$ExecutionTime = New-TimeSpan -Start $StartDateTime -End $EndDateTime;
Write-Debug ("{0}: `t`tDone setting alternate row style color in '{1}'
seconds" -f $EndDateTime, $ExecutionTime.TotalSeconds);
}
}
#endregion
$propertyhash = @{
TrustType = $NULL
TrustAttribute = $NULL
TrustDirection = $NULL
}
$TrustDirectionNumber = $TrustInfo.TrustDirection
$TrustTypeNumber = $TrustInfo.TrustType
$TrustAttributesNumber = $TrustInfo.TrustAttributes
#http://msdn.microsoft.com/en-us/library/cc234293.aspx
Switch ($TrustTypeNumber)
{
1 { $propertyhash['TrustType'] = "Trust with a Windows domain not
running Active Directory"; Break}
2 { $propertyhash['TrustType'] = "Trust with a Windows domain running
Active Directory"; Break}
3 { $propertyhash['TrustType'] = "Trust with a non-Windows-compliant
Kerberos distribution"; Break}
4 { $propertyhash['TrustType'] = "Trust with a DCE realm (not used)";
Break}
Default { $propertyhash['TrustType'] = "Invalid Trust Type of $
($TrustTypeNumber)" ; Break}
}
$propertyhash['TrustAttribute'] = @()
#$hextrustAttributesValue = '{0:X}' -f $trustAttributesNumber
Switch ($trustAttributesNumber)
{
1 {$propertyhash['TrustAttribute'] += "Non-Transitive"}
2 {$propertyhash['TrustAttribute'] += "Uplevel clients only"}
4 {$propertyhash['TrustAttribute'] += "Quarantined Domain (External,
SID Filtering)"}
8 {$propertyhash['TrustAttribute'] += "Cross-Organizational Trust
(Selective Authentication)"}
16 {$propertyhash['TrustAttribute'] += "Interforest Trust"}
32 {$propertyhash['TrustAttribute'] += "Intraforest Trust"}
64 {$propertyhash['TrustAttribute'] += "MIT Trust using RC4
Encryption"}
512 {$propertyhash['TrustAttribute'] += "Cross organization Trust no
TGT delegation"}
}
Switch ($TrustDirectionNumber)
{
0 { $propertyhash['TrustDirection'] = "Disabled"; Break}
1 { $propertyhash['TrustDirection'] = "Inbound"; Break}
2 { $propertyhash['TrustDirection'] = "Outbound"; Break}
3 { $propertyhash['TrustDirection'] = "Bidirectional"; Break}
Default { $propertyhash['TrustDirection'] = $TrustDirectionNumber ;
Break}
}
Function AbortScript
{
If($MSWord -or $PDF)
{
$Script:Word.quit()
Write-Verbose "$(Get-Date): System Cleanup"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Script:Word) |
Out-Null
If(Test-Path variable:global:word)
{
Remove-Variable -Name word -Scope Global
}
}
[gc]::collect()
[gc]::WaitForPendingFinalizers()
Write-Verbose "$(Get-Date): Script has been aborted"
$ErrorActionPreference = $SaveEAPreference
Exit
}
Function BuildMultiColumnTable
{
Param([Array]$xArray, [String]$xType)
#added a second parameter to the function so the verbose message would say
whether
#the function is processing servers, security groups or OUs.
$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)
FindWordDocumentEnd
$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")
ForEach($group in $groups)
{
$ID = New-Object System.Security.Principal.SecurityIdentifier($group,0)
If($ID.CompareTo($domainAdminsSID) -eq 0)
{
$IsDA = $True
Break
}
}
Return $IsDA
}
Function ElevatedSession
{
$currentPrincipal = New-Object
Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurre
nt() )
If($currentPrincipal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrat
or ))
{
Write-Verbose "$(Get-Date): This is an elevated PowerShell session"
Return $True
}
Else
{
Write-Host "" -Foreground White
Write-Host "$(Get-Date): This is NOT an elevated PowerShell session"
-Foreground White
Write-Host "" -Foreground White
Return $False
}
}
Function Get-ComputerCountByOS
{
<#
This function is provided by Jeremy Saunders and used with his permission
http://www.jhouseconsulting.com/2014/06/22/script-to-create-an-overview-of-
all-computer-objects-in-a-domain-1385
Jeremy sent me version 1.8 of his script to use as the basis for this
function
This function will provide an overview and count of all computer objects in a
domain based on Operating System and Service Pack. It helps an organisation
to understand the number of stale and active computers against the different
types of operating systems deployed in their environment.
For viewing purposes we sort the output by Operating System and not count.
You may notice a question mark (?) in some of the OperatingSystem strings.
This is a representation of each Double-Byte character that was unable to
be translated. Refer to Microsoft KB829856 for an explanation.
Computers change their passwword if and when they feel like it. The domain
doesn't initiate the change. It is controlled by three values under the
following registry key:
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters
- DisablePasswordChange
- MaximumPasswordAge
- RefusePasswordChange
If these values are not present, the default value of 30 days will be used.
Non Windows operating systems and appliances vary in the way they manage
their password change, with some not doing it at all. It's best to do some
research before drawing any conclusions about the validity of these objects.
i.e. Don't just go and delete them because my script says they are stale.
Syntax examples:
#>
#-------------------------------------------------------------
param([String]$TrustedDomain)
#-------------------------------------------------------------
# Set this to true to include service pack level. This makes the
# output more ganular, as the counts are then based on Operating
# System + Service Pack.
$OperatingSystemIncludesServicePack = $True
# Set this to the maximum value in number of days when the computer
# password last changed. Do not go beyond 90 days.
$MaxPasswordLastChanged = 90
# Set this to the maximum value in number of days when the computer
# last logged onto the domain.
$MaxLastLogonDate = 30
#-------------------------------------------------------------
$TotalComputersProcessed = 0
$ComputerCount = 0
$TotalStaleObjects = 0
$TotalEnabledStaleObjects = 0
$TotalEnabledObjects = 0
$TotalDisabledObjects = 0
$TotalDisabledStaleObjects = 0
$AllComputerObjects = New-Object System.Collections.ArrayList
$WindowsServerObjects = New-Object System.Collections.ArrayList
$WindowsWorkstationObjects = New-Object System.Collections.ArrayList
$NonWindowsComputerObjects = New-Object System.Collections.ArrayList
$CNOandVCOObjects = New-Object System.Collections.ArrayList
$ComputersHashTable = @{}
$context = new-object
System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$TrustedDomain)
Try
{
$domain =
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)
}
Catch [exception]
{
Write-Error $_.Exception.Message
Exit
}
$ADSearchBase = $DomainDistinguishedName
$ADScope = "SUBTREE"
$ADPageSize = 1000
$ADSearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$
($ADSearchBase)")
$ADSearcher = New-Object System.DirectoryServices.DirectorySearcher
$ADSearcher.SearchRoot = $ADSearchRoot
$ADSearcher.PageSize = $ADPageSize
$ADSearcher.Filter = $ADFilter
$ADSearcher.SearchScope = $ADScope
If($ADPropertyList)
{
ForEach($ADProperty in $ADPropertyList)
{
[Void]$ADSearcher.PropertiesToLoad.Add($ADProperty)
}
}
Try
{
Write-Verbose "Please be patient whilst the script retrieves all
computer objects and specified attributes..."
$colResults = $ADSearcher.Findall()
# Dispose of the search and results properly to avoid a memory leak
$ADSearcher.Dispose()
$ComputerCount = $colResults.Count
}
Catch
{
$ComputerCount = 0
Write-Warning "The $ADSearchBase structure cannot be found!"
}
If($ComputerCount -ne 0)
{
Write-Verbose "Processing $ComputerCount computer objects in the
$domain Domain..."
ForEach($objResult in $colResults)
{
$Name = $objResult.Properties.name[0]
$DistinguishedName = $objResult.Properties.distinguishedname[0]
Try
{
If(($objResult.Properties.operatingsystem | Measure-
Object).Count -gt 0)
{
$OperatingSystem =
$objResult.Properties.operatingsystem[0]
}
Else
{
$OperatingSystem = "Undefined"
}
}
Catch
{
$OperatingSystem = "Undefined"
}
Try
{
If(($objResult.Properties.operatingsystemversion | Measure-
Object).Count -gt 0)
{
$OperatingSystemVersion =
$objResult.Properties.operatingsystemversion[0]
}
Else
{
$OperatingSystemVersion = ""
}
}
Catch
{
$OperatingSystemVersion = ""
}
Try
{
If(($objResult.Properties.operatingsystemservicepack |
Measure-Object).Count -gt 0)
{
$OperatingSystemServicePack =
$objResult.Properties.operatingsystemservicepack[0]
}
Else
{
$OperatingSystemServicePack = ""
}
}
Catch
{
$OperatingSystemServicePack = ""
}
Try
{
If(($objResult.Properties.description | Measure-
Object).Count -gt 0)
{
$Description = $objResult.Properties.description[0]
}
Else
{
$Description = ""
}
}
Catch
{
$Description = ""
}
$PasswordTooOld = $False
$PasswordLastSet =
[System.DateTime]::FromFileTime($objResult.Properties.pwdlastset[0])
If($PasswordLastSet -lt (Get-Date).AddDays(-
$MaxPasswordLastChanged))
{
$PasswordTooOld = $True
}
$HasNotRecentlyLoggedOn = $False
Try
{
If(($objResult.Properties.lastlogontimestamp | Measure-
Object).Count -gt 0)
{
$LastLogonTimeStamp =
$objResult.Properties.lastlogontimestamp[0]
$LastLogon =
[System.DateTime]::FromFileTime($LastLogonTimeStamp)
If($LastLogon -le (Get-Date).AddDays(-
$MaxLastLogonDate))
{
$HasNotRecentlyLoggedOn = $True
}
If($LastLogon -match "1/01/1601")
{
$LastLogon = "Never logged on before"
}
}
Else
{
$LastLogon = "Never logged on before"
}
}
Catch
{
$LastLogon = "Never logged on before"
}
$WhenCreated = $objResult.Properties.whencreated[0]
{
$Enabled = $False
}
}
Try
{
If(($objResult.Properties.info | Measure-Object).Count -gt
0)
{
$notes = $objResult.Properties.info[0]
$notes = $notes -replace "`r`n", "|"
}
Else
{
$notes = ""
}
}
Catch
{
$notes = ""
}
If($IsStale)
{
$TotalStaleObjects = $TotalStaleObjects + 1
}
If($Enabled)
{
$TotalEnabledObjects = $TotalEnabledObjects + 1
}
If($Enabled -eq $False)
{
$TotalDisabledObjects = $TotalDisabledObjects + 1
}
If($IsStale -AND $Enabled)
{
$TotalEnabledStaleObjects = $TotalEnabledStaleObjects + 1
}
If($IsStale -AND $Enabled -eq $False)
{
$TotalDisabledStaleObjects = $TotalDisabledStaleObjects + 1
}
}
}
$obj | Add-Member -MemberType NoteProperty -Name "Total"
-value $TotalCount
$obj | Add-Member -MemberType NoteProperty -Name "Stale"
-value $StaleCount
$obj | Add-Member -MemberType NoteProperty -Name "Enabled"
-value $EnabledCount
$obj | Add-Member -MemberType NoteProperty -Name
"Enabled_Stale" -value $EnabledStaleCount
$obj | Add-Member -MemberType NoteProperty -Name "Active"
-value ($EnabledCount - $EnabledStaleCount)
$obj | Add-Member -MemberType NoteProperty -Name "Disabled"
-value $DisabledCount
$obj | Add-Member -MemberType NoteProperty -Name
"Disabled_Stale" -value $DisabledStaleCount
$ComputersHashTable.Set_Item($FullOperatingSystem,$obj)
} # end if
$TotalComputersProcessed ++
}
ForEach($Item in $Output)
{
If($MSWORD -or $PDF)
{
[System.Collections.Hashtable[]] $ScriptInformation = @()
$ScriptInformation += @{ Data = "Operating System"; Value =
$Item.OperatingSystem; }
$ScriptInformation += @{ Data = "Service Pack"; Value =
$Item.ServicePack; }
$ScriptInformation += @{ Data = "Category"; Value =
$Item.Category; }
$ScriptInformation += @{ Data = "Total"; Value =
$Item.Total; }
$ScriptInformation += @{ Data = "Stale"; Value =
$Item.Stale; }
$ScriptInformation += @{ Data = "Enabled"; Value =
$Item.Enabled; }
$ScriptInformation += @{ Data = "Enabled/Stale"; Value =
$Item.Enabled_Stale; }
$ScriptInformation += @{ Data = "Active"; Value =
$Item.Active; }
$ScriptInformation += @{ Data = "Disabled"; Value =
$Item.Disabled; }
$ScriptInformation += @{ Data = "Disabled/Stale"; Value =
$Item.Disabled_Stale; }
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 1 "Operating System`t: " $Item.OperatingSystem
Line 1 "Service Pack`t`t: " $Item.ServicePack
Line 1 "Category`t`t: " $Item.Category
Line 1 "Total`t`t`t: " $Item.Total
Line 1 "Stale`t`t`t: " $Item.Stale
Line 1 "Enabled`t`t`t: " $Item.Enabled
Line 1 "Enabled/Stale`t`t: " $Item.Enabled_Stale
Line 1 "Active`t`t`t: " $Item.Active
Line 1 "Disabled`t`t: " $Item.Disabled
Line 1 "Disabled/Stale`t`t: " $Item.Disabled_Stale
Line 0 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Operating System",($htmlsilver -bor
$htmlbold),$Item.OperatingSystem,$htmlwhite)
$rowdata += @(,('Service Pack',($htmlsilver -bor
$htmlbold),$Item.ServicePack,$htmlwhite))
$rowdata += @(,('Category',($htmlsilver -bor $htmlbold),
$Item.Category,$htmlwhite))
$rowdata += @(,('Total',($htmlsilver -bor $htmlbold),
$Item.Total,$htmlwhite))
$rowdata += @(,('Stale',($htmlsilver -bor $htmlbold),
$Item.Stale,$htmlwhite))
$rowdata += @(,('Enabled',($htmlsilver -bor $htmlbold),
$Item.Enabled,$htmlwhite))
$rowdata += @(,('Enabled/Stale',($htmlsilver -bor
$htmlbold),$Item.Enabled_Stale,$htmlwhite))
$rowdata += @(,('Active',($htmlsilver -bor $htmlbold),
$Item.Active,$htmlwhite))
$rowdata += @(,('Disabled',($htmlsilver -bor $htmlbold),
$Item.Disabled,$htmlwhite))
$rowdata += @(,('Disabled/Stale',($htmlsilver -bor
$htmlbold),$Item.Disabled_Stale,$htmlwhite))
$msg = ""
$columnWidths = @("100","200")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "300"
WriteHTMLLine 0 0 " "
}
}
$percent = "{0:P}" -f ($TotalStaleObjects/$ComputerCount)
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 "A breakdown of the $ComputerCount Computer Objects in the
$domain Domain"
#Notes:
# - Computer objects are filtered into 4 categories:
# - Windows Servers
# - Windows Workstations
# - Other non-Windows (Linux, Mac, etc)
# - CNO or VCO (Windows Cluster Name Objects and Virtual Computer
Objects)
# - A Stale object is derived from 2 values ANDed together:
# PasswordLastChanged > $MaxPasswordLastChanged days ago
# AND
# LastLogonDate > $MaxLastLogonDate days ago
# - If it's never logged on before and was created more than
$MaxLastLogonDate days ago, set the
# HasNotRecentlyLoggedOn variable to True. This will also be used to
help determine if
# it's a stale account. An example of this would be if you prestaged
the account but
# never ended up using it.
# - The Active objects column is calculated by subtracting the
Enabled_Stale value from
# the Enabled value. This gives us an accurate number of active
objects against each
# Operating System.
# - To help provide a high level overview of the computer object
landscape we calculate
# the number of stale objects of enabled and disabled objects
separately.
# Disabled objects are often ignored, but it's pointless leaving old
disabled computer
# objects in the domain.
# - For viewing purposes we sort the output by Operating System and not
count.
# - You may notice a question mark (?) in some of the OperatingSystem
strings. This is a
# representation of each Double-Byte character that was unable to be
translated. Refer
# to Microsoft KB829856 for an explanation.
# - Be aware that a cluster updates the lastLogonTimeStamp of the
CNO/VNO when it brings
# a clustered network name resource online. So it could be running
for months without
# an update to the lastLogonTimeStamp attribute.
# - When a VMware ESX host has been added to Active Directory its
associated computer
# object will appear as an Operating System of unknown, version:
unknown, and service
# pack: Likewise Identity 5.3.0. The lsassd.conf manages the machine
password expiration
# lifespan, which by default is set to 30 days.
# - When a Riverbed SteelHead has been added to Active Directory the
password set on the
# Computer Object will never change by default. This must be enabled
on the command
# line using the 'domain settings pwd-refresh-int <number of days>'
command. The
# lastLogon timestamp is only updated when the SteelHead appliance is
restarted.
}
}
Function ShowScriptOptions
{
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): AddDateTime : $AddDateTime"
If($MSWORD -or $PDF)
{
Write-Verbose "$(Get-Date): Company Name : $Script:CoName"
}
Write-Verbose "$(Get-Date): ComputerName : $ComputerName"
If($MSWORD -or $PDF)
{
Write-Verbose "$(Get-Date): Company Address : $CompanyAddress"
Write-Verbose "$(Get-Date): Company Email : $CompanyEmail"
Write-Verbose "$(Get-Date): Company Fax : $CompanyFax"
Write-Verbose "$(Get-Date): Company Phone : $CompanyPhone"
Write-Verbose "$(Get-Date): Cover Page : $CoverPage"
}
Write-Verbose "$(Get-Date): DCDNSInfo : $DCDNSInfo"
Write-Verbose "$(Get-Date): Dev : $Dev"
If($Dev)
{
Write-Verbose "$(Get-Date): DevErrorFile : $Script:DevErrorFile"
}
Write-Verbose "$(Get-Date): Domain Name : $ADDomain"
Write-Verbose "$(Get-Date): Elevated : $Script:Elevated"
Write-Verbose "$(Get-Date): Filename1 : $Script:filename1"
If($PDF)
{
Write-Verbose "$(Get-Date): Filename2 : $Script:filename2"
}
Write-Verbose "$(Get-Date): Folder : $Folder"
Write-Verbose "$(Get-Date): Forest Name : $ADForest"
Write-Verbose "$(Get-Date): From : $From"
Write-Verbose "$(Get-Date): GPOInheritance : $GPOInheritance"
Write-Verbose "$(Get-Date): HW Inventory : $Hardware"
Write-Verbose "$(Get-Date): IncludeUserInfo : $IncludeUserInfo"
Write-Verbose "$(Get-Date): Log : $($Log)"
Write-Verbose "$(Get-Date): MaxDetail : $MaxDetails"
Write-Verbose "$(Get-Date): Save As HTML : $HTML"
Write-Verbose "$(Get-Date): Save As PDF : $PDF"
Write-Verbose "$(Get-Date): Save As TEXT : $TEXT"
Write-Verbose "$(Get-Date): Save As WORD : $MSWORD"
Write-Verbose "$(Get-Date): ScriptInfo : $ScriptInfo"
Write-Verbose "$(Get-Date): Section : $Section"
Write-Verbose "$(Get-Date): Services : $Services"
Write-Verbose "$(Get-Date): Smtp Port : $SmtpPort"
Write-Verbose "$(Get-Date): Smtp Server : $SmtpServer"
Write-Verbose "$(Get-Date): Title : $Script:Title"
Write-Verbose "$(Get-Date): To : $To"
Write-Verbose "$(Get-Date): Use SSL : $UseSSL"
If($MSWORD -or $PDF)
{
Write-Verbose "$(Get-Date): User Name : $UserName"
}
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): OS Detected : $Script:RunningOS"
Write-Verbose "$(Get-Date): PoSH version : $($Host.Version)"
Write-Verbose "$(Get-Date): PSCulture : $PSCulture"
Write-Verbose "$(Get-Date): PSUICulture : $PSUICulture"
If($MSWORD -or $PDF)
{
Write-Verbose "$(Get-Date): Word language :
$Script:WordLanguageValue"
Write-Verbose "$(Get-Date): Word version : $Script:WordProduct"
}
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): Script start : $Script:StartTime"
Write-Verbose "$(Get-Date): "
Write-Verbose "$(Get-Date): "
}
Function SaveandCloseDocumentandShutdownWord
{
#bug fix 1-Apr-2014
#reset Grammar and Spelling options back to their original settings
$Script:Word.Options.CheckGrammarAsYouType = $Script:CurrentGrammarOption
$Script:Word.Options.CheckSpellingAsYouType = $Script:CurrentSpellingOption
Function SaveandCloseTextDocument
{
If($AddDateTime)
{
$Script:FileName1 += "_$(Get-Date -f yyyy-MM-dd_HHmm).txt"
}
Function SaveandCloseHTMLDocument
{
Out-File -FilePath $Script:FileName1 -Append -InputObject
"<p></p></body></html>" 4>$Null
}
Function SetFileName1andFileName2
{
Param([string]$OutputFileName)
If($pwdpath.EndsWith("\"))
{
#remove the trailing \
$pwdpath = $pwdpath.SubString(0, ($pwdpath.Length - 1))
}
SetupWord
}
ElseIf($Text)
{
If(!$AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName).txt"
}
ShowScriptOptions
}
ElseIf($HTML)
{
If(!$AddDateTime)
{
[string]$Script:FileName1 = "$($pwdpath)\$($OutputFileName).html"
}
SetupHTML
ShowScriptOptions
}
}
#endregion
#Script begins
$AmIReallyDA = UserIsaDomainAdmin
If($AmIReallyDA -eq $True)
{
#user has Domain Admin rights
If($ADDomain -ne "")
{
Write-Verbose "$(Get-Date): $env:username has Domain Admin rights
in the $ADDomain Domain"
}
Else
{
Write-Verbose "$(Get-Date): $env:username has Domain Admin rights
in the $ADForest Forest"
}
$Script:DARights = $True
}
Else
{
#user does nto have Domain Admin rights
If($ADDomain -ne "")
{
Write-Verbose "$(Get-Date): $env:username does not have Domain
Admin rights in the $ADDomain Domain"
}
Else
{
Write-Verbose "$(Get-Date): $env:username does not have Domain
Admin rights in the $ADForest Forest"
}
}
$Script:Elevated = ElevatedSession
If($DCDNSINFO)
{
Write-Verbose "$(Get-Date): Domain Controller DNS configuration
information requested"
}
If($DCDNSINFO)
{
#don't abort script, set $DCDNSINFO to false
Write-Warning "`n`n`t`tDCDNSINFO information was requested
but $($env:username) does not have Domain Admin rights."
Write-Warning "`n`n`t`tDCDNSINFO option will be turned
off."
$Script:DCDNSINFO = $False
}
}
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 -EA 0)
{
Write-Verbose "$(Get-Date): Server $ComputerName is online."
Write-Verbose "$(Get-Date): `tTest #1 to see if $ComputerName is
a Domain Controller."
#the server may be online but is it really a domain controller?
$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(!$?)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tCould not find a forest identified by:
$ADForest.`nScript cannot continue.`n`n"
Exit
}
}
Else
{
$Script:Forest = Get-ADForest -Identity $ADForest -Server
$ComputerName -EA 0
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"
[string]$Script:Title = "AD Inventory Report for the $ADForest Forest"
$Script:Domains = $Script:Forest.Domains | Sort-Object
$Script:ConfigNC = (Get-ADRootDSE -Server $ADForest -EA
0).ConfigurationNamingContext
}
If(!$?)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tCould not find a domain identified by:
$ADDomain.`nScript cannot continue.`n`n"
Exit
}
}
Else
{
$results = Get-ADDomain -Identity $ADDomain -Server $ComputerName
-EA 0
If(!$?)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tCould not find a domain with the name
of $ADDomain.`n`n`t`tScript cannot continue.`n`n`t`tIs $ComputerName running Active
Directory Web Services?"
Exit
}
}
Write-Verbose "$(Get-Date): $ADDomain is a valid domain name"
$Script:Domains = $results.DNSRoot
$Script:DomainDNSRoot = $results.DNSRoot
[string]$Script:Title = "AD Inventory Report for the $Script:Domains
Domain"
$tmp = $results.Forest
#get forest info
Write-Verbose "$(Get-Date): Retrieving forest information"
If([String]::IsNullOrEmpty($ComputerName))
{
$Script:Forest = Get-ADForest -Identity $tmp -EA 0
If(!$?)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tCould not find a forest identified by:
$tmp.`nScript cannot continue.`n`n"
Exit
}
}
Else
{
$Script:Forest = Get-ADForest -Identity $tmp -Server
$ComputerName -EA 0
If(!$?)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tCould not find a forest with the name
of $tmp.`n`n`t`tScript cannot continue.`n`n`t`tIs $ComputerName running Active
Directory Web Services?"
Exit
}
}
Write-Verbose "$(Get-Date): Found forest information for $tmp"
$Script:ConfigNC = (Get-ADRootDSE -Server $tmp -EA
0).ConfigurationNamingContext
}
Switch ($Script:Forest.ForestMode)
{
"0" {$ForestMode = "Windows 2000"; Break}
"1" {$ForestMode = "Windows Server 2003 interim"; Break}
"2" {$ForestMode = "Windows Server 2003"; Break}
"3" {$ForestMode = "Windows Server 2008"; Break}
"4" {$ForestMode = "Windows Server 2008 R2"; Break}
"5" {$ForestMode = "Windows Server 2012"; Break}
"6" {$ForestMode = "Windows Server 2012 R2"; Break}
"7" {$ForestMode = "Windows Server 2016"; Break} #added V2.20
"Windows2000Forest" {$ForestMode = "Windows 2000"; Break}
"Windows2003InterimForest" {$ForestMode = "Windows Server 2003
interim"; Break}
"Windows2003Forest" {$ForestMode = "Windows Server 2003"; Break}
"Windows2008Forest" {$ForestMode = "Windows Server 2008"; Break}
"Windows2008R2Forest" {$ForestMode = "Windows Server 2008 R2";
Break}
"Windows2012Forest" {$ForestMode = "Windows Server 2012"; Break}
"Windows2012R2Forest" {$ForestMode = "Windows Server 2012 R2";
Break}
"WindowsThresholdForest" {$ForestMode = "Windows Server 2016 TP4";
Break}
"Windows2016Forest" {$ForestMode = "Windows Server 2016";
Break}
"UnknownForest" {$ForestMode = "Unknown Forest Mode"; Break}
Default {$ForestMode = "Unable to determine Forest
Mode: $($Script:Forest.ForestMode)"; Break}
}
#added 9-oct-2016
#https://adsecurity.org/?p=81
$DirectoryServicesConfigPartition = Get-ADObject -Identity "CN=Directory
Service,CN=Windows NT,CN=Services,$Script:ConfigNC" -Partition $Script:ConfigNC
-Properties *
$TombstoneLifetime = $DirectoryServicesConfigPartition.tombstoneLifetime
#2.16
#move this duplicated block of code outside the output format test
If($ADDomain -ne "")
{
#2.16 don't mess with the $Script:Domains variable
#redo list of domains so forest root domain is listed first
[array]$tmpDomains = "$Script:ForestRootDomain"
[array]$tmpDomains2 = "$($Script:ForestRootDomain)"
ForEach($Domain in $Forest.Domains)
{
If($Domain -ne $Script:ForestRootDomain)
{
$tmpDomains += "$($Domain.ToString())"
$tmpDomains2 += "$($Domain.ToString())"
}
}
}
Else
{
#redo list of domains so forest root domain is listed first
[array]$tmpDomains = "$Script:ForestRootDomain"
[array]$tmpDomains2 = "$($Script:ForestRootDomain)"
ForEach($Domain in $Script:Domains)
{
If($Domain -ne $Script:ForestRootDomain)
{
$tmpDomains += "$($Domain.ToString())"
$tmpDomains2 += "$($Domain.ToString())"
}
}
$Script:Domains = $tmpDomains
}
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Application
partitions"; Value = $tmp; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value = $tmp; }
}
}
}
$tmp = ""
If($Null -eq $CrossForestReferences)
{
$tmp = "<None>"
$ScriptInformation += @{ Data = "Cross forest references"; Value
= $tmp; }
}
Else
{
$cnt = 0
ForEach($CrossForestReference in $CrossForestReferences)
{
$cnt++
$tmp = "$($CrossForestReference.ToString())"
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Cross forest
references"; Value = $tmp; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value = $tmp; }
}
}
}
$ScriptInformation += @{ Data = "Domain naming master"; Value =
$Script:Forest.DomainNamingMaster; }
$tmp = ""
If($Null -eq $Script:Domains)
{
$tmp = "<None>"
$ScriptInformation += @{ Data = "Domains in forest"; Value =
$tmp; }
}
Else
{
$cnt = 0
ForEach($Domain in $tmpDomains2)
{
$cnt++
$tmp = "$($Domain.ToString())"
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Domains in forest";
Value = $tmp; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value = $tmp; }
}
}
}
$ScriptInformation += @{ Data = "Partitions container"; Value =
$Script:Forest.PartitionsContainer; }
$ScriptInformation += @{ Data = "Root domain"; Value =
$Script:ForestRootDomain; }
$ScriptInformation += @{ Data = "Schema master"; Value =
$Script:Forest.SchemaMaster; }
$tmp = ""
If($Null -eq $Sites)
{
$tmp = "<None>"
$ScriptInformation += @{ Data = "Sites"; Value = $tmp; }
}
Else
{
$cnt = 0
ForEach($Site in $Sites)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Sites"; Value =
$Site.ToString(); }
}
Else
{
$ScriptInformation += @{ Data = ""; Value =
$Site.ToString(); }
}
}
}
$tmp = ""
If($Null -eq $SPNSuffixes)
{
$tmp = "<None>"
$ScriptInformation += @{ Data = "SPN suffixes"; Value = $tmp; }
}
Else
{
$cnt = 0
ForEach($SPNSuffix in $SPNSuffixes)
{
$cnt++
$tmp = "$($SPNSuffix.ToString())"
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "SPN suffixes"; Value
= $tmp; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value = $tmp; }
}
}
}
$ScriptInformation += @{ Data = "Tombstone lifetime"; Value = "$
($TombstoneLifetime) days"; }
$tmp = ""
If($Null -eq $UPNSuffixes)
{
$tmp = "<None>"
$ScriptInformation += @{ Data = "UPN suffixes"; Value = $tmp; }
}
Else
{
$cnt = 0
ForEach($UPNSuffix in $UPNSuffixes)
{
$cnt++
$tmp = "$($UPNSuffix.ToString())"
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "UPN suffixes"; Value
= $tmp; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value = $tmp; }
}
}
}
$tmp = $Null
$Table.Columns.Item(1).Width = 125;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 "Forest mode`t`t: " $ForestMode
Line 0 "Forest name`t`t: " $Script:Forest.Name
#V2.20 reorder to alpha order
If($Null -eq $AppPartitions)
{
Line 0 "Application partitions`t: <None>"
}
Else
{
Line 0 "Application partitions`t: " -NoNewLine
$cnt = 0
ForEach($AppPartition in $AppPartitions)
{
$cnt++
If($cnt -eq 1)
{
Line 0 "$($AppPartition.ToString())"
}
Else
{
Line 3 " $($AppPartition.ToString())"
}
}
}
If($Null -eq $CrossForestReferences)
{
Line 0 "Cross forest references`t: <None>"
}
Else
{
Line 0 "Cross forest references`t: " -NoNewLine
$cnt = 0
ForEach($CrossForestReference in $CrossForestReferences)
{
$cnt++
If($cnt -eq 1)
{
Line 0 "$($CrossForestReference.ToString())"
}
Else
{
Line 3 " $($CrossForestReference.ToString())"
}
}
}
Line 0 "Domain naming master`t: " $Script:Forest.DomainNamingMaster
If($Null -eq $Script:Domains)
{
Line 0 "Domains in forest`t: <None>"
}
Else
{
Line 0 "Domains in forest`t: " -NoNewLine
$cnt = 0
ForEach($Domain in $tmpDomains2)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $Domain
}
Else
{
Line 3 " " $Domain
}
}
}
Line 0 "Partitions container`t: " $Script:Forest.PartitionsContainer
Line 0 "Root domain`t`t: " $Script:ForestRootDomain
Line 0 "Schema master`t`t: " $Script:Forest.SchemaMaster
If($Null -eq $Sites)
{
Line 0 "Sites`t`t`t: <None>"
}
Else
{
Line 0 "Sites`t`t`t: " -NoNewLine
$cnt = 0
ForEach($Site in $Sites)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $Site.ToString()
}
Else
{
Line 3 " $($Site.ToString())"
}
}
}
If($Null -eq $SPNSuffixes)
{
Line 0 "SPN suffixes`t`t: <None>"
}
Else
{
Line 0 "SPN suffixes`t`t: " -NoNewLine
$cnt = 0
ForEach($SPNSuffix in $SPNSuffixes)
{
$cnt++
If($cnt -eq 1)
{
Line 0 "$($SPNSuffix.ToString())"
}
Else
{
Line 3 " $($SPNSuffix.ToString())"
}
}
}
Line 0 "Tombstone lifetime`t: " "$($TombstoneLifetime) days"
If($Null -eq $UPNSuffixes)
{
Line 0 "UPN Suffixes`t`t: <None>"
}
Else
{
Line 0 "UPN Suffixes`t`t: " -NoNewLine
$cnt = 0
ForEach($UPNSuffix in $UPNSuffixes)
{
$cnt++
If($cnt -eq 1)
{
Line 0 "$($UPNSuffix.ToString())"
}
Else
{
Line 3 " $($UPNSuffix.ToString())"
}
}
}
Line 0 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Forest mode",($htmlsilver -bor $htmlbold),
$ForestMode,$htmlwhite)
$rowdata += @(,('Forest name',($htmlsilver -bor $htmlbold),
$Script:Forest.Name,$htmlwhite))
$rowdata += @(,('Root domain',($htmlsilver -bor $htmlbold),
$Script:ForestRootDomain,$htmlwhite))
#V2.20 reorder to alpha order
$tmp = ""
If($Null -eq $AppPartitions)
{
$tmp = "None"
If($cnt -eq 1)
{
$rowdata += @(,('Application partitions',($htmlsilver
-bor $htmlbold),$tmp,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$tmp = ""
If($Null -eq $CrossForestReferences)
{
$tmp = "None"
$rowdata += @(,('Cross forest references',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
}
Else
{
$cnt = 0
ForEach($CrossForestReference in $CrossForestReferences)
{
$cnt++
$tmp = "$($CrossForestReference.ToString())"
If($cnt -eq 1)
{
$rowdata += @(,('Cross forest references',
($htmlsilver -bor $htmlbold),$tmp,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$rowdata += @(,('Domain naming master',($htmlsilver -bor $htmlbold),
$Script:Forest.DomainNamingMaster,$htmlwhite))
$tmp = ""
If($Null -eq $Script:Domains)
{
$tmp = "None"
$rowdata += @(,('Domains in forest',($htmlsilver -bor $htmlbold),
$tmp,$htmlwhite))
}
Else
{
$cnt = 0
ForEach($Domain in $tmpDomains2)
{
$cnt++
$tmp = "$($Domain.ToString())"
If($cnt -eq 1)
{
$rowdata += @(,('Domains in forest',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$rowdata += @(,('Partitions container',($htmlsilver -bor $htmlbold),
$Script:Forest.PartitionsContainer,$htmlwhite))
$rowdata += @(,('Schema master',($htmlsilver -bor $htmlbold),
$Script:Forest.SchemaMaster,$htmlwhite))
$tmp = ""
If($Null -eq $Sites)
{
$tmp = "None"
$rowdata += @(,('Sites',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
Else
{
$cnt = 0
ForEach($Site in $Sites)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Sites',($htmlsilver -bor $htmlbold),
$Site.ToString(),$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),
$Site.ToString(),$htmlwhite))
}
}
}
$tmp = ""
If($Null -eq $SPNSuffixes)
{
$tmp = "None"
$rowdata += @(,('SPN suffixes',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
Else
{
$cnt = 0
ForEach($SPNSuffix in $SPNSuffixes)
{
$cnt++
$tmp = "$($SPNSuffix.ToString())"
If($cnt -eq 1)
{
$rowdata += @(,('SPN suffixes',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$rowdata += @(,('Tombstone lifetime',($htmlsilver -bor $htmlbold),"$
($TombstoneLifetime) days",$htmlwhite))
$tmp = ""
If($Null -eq $UPNSuffixes)
{
$tmp = "None"
$rowdata += @(,('UPN suffixes',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
Else
{
$cnt = 0
ForEach($UPNSuffix in $UPNSuffixes)
{
$cnt++
$tmp = "$($UPNSuffix.ToString())"
If($cnt -eq 1)
{
$rowdata += @(,('UPN suffixes',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
}
}
}
$tmp = $Null
$msg = ""
$columnWidths = @("125","300")
FormatHTMLTable $msg -rowArray $rowdata -columnArray $columnHeaders
-fixedWidth $columnWidths -tablewidth "425"
WriteHTMLLine 0 0 " "
}
}
#endregion
$WordTableRowHash += @{
DCName = $DC;
GC = $GC;
ReadOnly = $ReadOnly;
ServerOS = $ServerOS;
ServerCore = $ServerCore
}
$Results = $Null
}
}
ElseIf($Text)
{
#V2.16 addition
[int]$MaxDCNameLength = ($AllDCs | Measure-Object -Maximum
-Property Length).Maximum
ForEach($DC in $AllDCs)
{
Write-Verbose "$(Get-Date): `t`t`t$DC"
$DCName = $DC.SubString(0,$DC.IndexOf("."))
$SrvName = $DC.SubString($DC.IndexOf(".")+1)
$Results = Get-ADDomainController -Identity $DCName -Server
$SrvName -EA 0
#V2.16 change
If($? -and $Null -ne $Results)
{
$xGC = $Results.IsGlobalCatalog.ToString()
$xRO = $Results.IsReadOnly.ToString()
#ServerOS and ServerCore added in V2.20
$ServerOS = $Results.OperatingSystem
#https://blogs.msmvps.com/russel/2017/03/16/how-to-
tell-if-youre-running-on-windows-server-core/
$tmp = Get-RegistryValue
"HKLM:\software\microsoft\windows nt\currentversion" "installationtype" $DCName
If($tmp -eq "Server Core")
{
$ServerCore = "Yes"
}
Else
{
$ServerCore = "No"
}
}
Else
{
$xGC = "Unable to retrieve status"
$xRO = "Unable to retrieve status"
$ServerOS = "Unable to retrieve"
$ServerCore = "N/A"
}
$Results = $Null
}
Line 0 ""
}
ElseIf($HTML)
{
$rowdata = @()
ForEach($DC in $AllDCs)
{
Write-Verbose "$(Get-Date): `t`t`t$DC"
$DCName = $DC.SubString(0,$DC.IndexOf("."))
$SrvName = $DC.SubString($DC.IndexOf(".")+1)
$rowdata += @(,($DC,$htmlwhite,
$GC,$htmlwhite,
$ReadOnly,$htmlwhite,
$ServerOS,$htmlwhite,
$ServerCore,$htmlwhite
))
}
}
}
If($MSWord -or $PDF)
{
Write-Verbose "$(Get-Date): `t`tCreate Domain Controller in Forest Word
table"
$Table = AddWordTable -Hashtable $WordTableRowHash `
-Columns DCName, GC, ReadOnly, ServerOS, ServerCore `
-Headers "Name", "Global Catalog", "Read-only", "Server OS", "Server
Core" `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 150;
$Table.Columns.Item(2).Width = 50;
$Table.Columns.Item(3).Width = 50;
$Table.Columns.Item(4).Width = 130;
$Table.Columns.Item(5).Width = 45;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
#nothing to do
}
ElseIf($HTML)
{
$columnHeaders = @('Name',($htmlsilver -bor $htmlbold),
'Global Catalog',($htmlsilver -bor
$htmlbold),
'Read-only',($htmlsilver -bor $htmlbold),
'Server OS',($htmlsilver -bor $htmlbold),
'Server Core',($htmlsilver -bor
$htmlbold))
$msg = ""
FormatHTMLTable $msg "auto" -rowArray $rowdata -columnArray
$columnHeaders
WriteHTMLLine 0 0 " "
}
$AllDCs = $Null
}
#endregion
$rootDSE = [ADSI]"LDAP://RootDSE"
$configNC = $rootDSE.Properties[ 'configurationNamingContext' ].Value -as
[String]
$Table.Columns.Item(1).Width = 125;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 1 "Common name`t`t: " $obj.cn
Line 1 "Distinguished name`t: " $obj.distinguishedName
Line 1 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Common name",($htmlsilver -bor
$htmlbold),$obj.cn,$htmlwhite)
$rowdata += @(,('Distinguished name',($htmlsilver -bor
$htmlbold),$obj.distinguishedName,$htmlwhite))
$msg = ""
$columnWidths = @("125","400")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "525"
WriteHTMLLine 0 0 " "
}
}
If($RootCnt -gt 1)
{
$txt = "Possible error: There are more than one Certification
Authority Root(s)"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
WriteHTMLLine 0 0 ""
}
}
}
#ElseIf($Null -eq $rootObj) changed in V2.22 by Michael B. Smith
If($RootCnt -eq 0 -or $Null -eq $rootObj)
{
$txt = "No Certification Authority Root(s) were retrieved"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt "" $Null 0 $False $True
WriteHTMLLine 0 0 " "
}
}
If([string]::isnullorempty($allObj.psbase.children) -and !
([string]::isnullorempty($rootObj.psbase.children)))
{
#uh oh error
$txt = "Error: Certification Authority Root(s) exist, but no
Certification Authority Issuers(s) (also known as Enrollment Agents) exist"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
WriteHTMLLine 0 0 ""
}
}
ElseIf(!([string]::isnullorempty($allObj.psbase.children)) -and !
([string]::isnullorempty($rootObj.psbase.children)))
{
$AllCnt = 0
ForEach($obj in $allObj.psbase.children)
{
$AllCnt++
If($MSWORD -or $PDF)
{
[System.Collections.Hashtable[]] $ScriptInformation = @()
$ScriptInformation += @{ Data = "Common name"; Value =
$obj.cn; }
$ScriptInformation += @{ Data = "Distinguished name"; Value
= $obj.distinguishedName; }
Write-Verbose "$(Get-Date): `t`tCreate CA Authorities Word
table"
$Table = AddWordTable -Hashtable $ScriptInformation `
-Columns Data,Value `
-List `
-Format $wdTableGrid `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 125;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 1 "Common name`t`t: " $obj.cn
Line 1 "Distinguished name`t: " $obj.distinguishedName
Line 1 ""
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Common name",($htmlsilver -bor
$htmlbold),$obj.cn,$htmlwhite)
$rowdata += @(,('Distinguished name',($htmlsilver -bor
$htmlbold),$obj.distinguishedName,$htmlwhite))
$msg = ""
$columnWidths = @("125","400")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "525"
WriteHTMLLine 0 0 " "
}
}
If($AllCnt -lt $RootCnt)
{
$txt = "Error: More Certification Authority Root(s) exist than
there are Certification Authority Issuers(s) (also known as Enrollment Agents)"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
WriteHTMLLine 0 0 ""
}
}
}
ElseIf(([string]::isnullorempty($allObj.psbase.children)) -and
([string]::isnullorempty($rootObj.psbase.children)))
{
$txt = "No Certification Authority Issuer(s) were retrieved"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt "" $Null 0 $False $True
WriteHTMLLine 0 0 " "
}
}
#if you have enrollment authorities and no roots – that’s a BIG error
If($AllCnt -gt 0 -and $RootCnt -eq 0)
{
$txt = "Error: Certification Authority Issuers(s) (also known as
Enrollment Agents) exist, but no Certification Authority Root(s) exist"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
WriteHTMLLine 0 0 ""
}
}
}
#endregion
$cnt = 0
ForEach($Scope in $EnabledScopes)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Enabled
Scopes"; Value = $Scope; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value
= $($Scope); }
}
}
}
Write-Verbose "$(Get-Date): `t`tCreate AD Optional Features
Word table"
$Table = AddWordTable -Hashtable $ScriptInformation `
-Columns Data,Value `
-List `
-Format $wdTableGrid `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 125;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 1 "Feature Name`t: " $Item.Name
Line 1 "Enabled`t`t: " $Enabled
$cnt = 0
ForEach($Scope in $EnabledScopes)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $Scope
}
Else
{
Line 3 " $($Scope)"
}
}
Line 0 ""
}
Else
{
Line 0 ""
}
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Feature Name",($htmlsilver -bor
$htmlbold),$Item.Name,$htmlwhite)
$rowdata += @(,('Enabled',($htmlsilver -bor $htmlbold),
$Enabled,$htmlwhite))
$cnt = 0
ForEach($Scope in $EnabledScopes)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Enabled Scopes',
($htmlsilver -bor $htmlbold),$Scope,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),$Scope,$htmlwhite))
}
}
}
$msg = ""
$columnWidths = @("125","400")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "525"
WriteHTMLLine 0 0 " "
}
}
}
ElseIf($? -and $Null -eq $ADOptionalFeatures)
{
$txt = "No AD Optional Features were retrieved"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt "" $Null 0 $False $True
WriteHTMLLine 0 0 " "
}
}
Else
{
$txt = "Error retieving AD Optional Features"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $txt
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt "" $Null 0 $False $True
WriteHTMLLine 0 0 " "
}
}
}
#endregion
Switch ($item)
{
'User-Account-Control' {$tmp = "Flags that control
the behavior of a user account"}
'msNPAllowDialin' {$tmp = "RAS Server"}
'ms-Mcs-AdmPwd' {$tmp = "LAPS"}
'ms-Mcs-AdmPwdExpirationTime' {$tmp = "LAPS"}
'ms-SMS-Assignment-Site-Code' {$tmp = "SCCM"}
'ms-SMS-Capabilities' {$tmp = "SCCM"}
'msRTCSIP-UserRoutingGroupId' {$tmp = "Lync/Skype for Business"}
'msRTCSIP-MirrorBackEndServer' {$tmp = "Lync/Skype for
Business"}
'ms-exch-schema-version-pt' {$tmp = "Exchange"}
Default {$tmp = "Unknown"}
}
If( $mem )
{
$Itemobj | Add-Member -MemberType NoteProperty -Name ItemName
-Value $item
$Itemobj | Add-Member -MemberType NoteProperty -Name ItemState
-Value "Present"
$Itemobj | Add-Member -MemberType NoteProperty -Name ItemDesc
-Value $tmp
$SchemaItems.Add($Itemobj) > $Null
}
Else
{
$Itemobj | Add-Member -MemberType NoteProperty -Name ItemName
-Value $item
$Itemobj | Add-Member -MemberType NoteProperty -Name ItemState
-Value "Not Present"
$Itemobj | Add-Member -MemberType NoteProperty -Name ItemDesc
-Value $tmp
$SchemaItems.Add($Itemobj) > $Null
}
$mem = $null
$obj = $null
}
$Table.rows.first.headingformat = $wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Schema item name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Present"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Used for"
}
ElseIf($Text)
{
#V2.16 change
Line 1 "Schema item name Present Used for
"
Line 1
"==================================================================================
============"
}
ElseIf($HTML)
{
$rowdata = @()
}
ForEach($item in $SchemaItems)
{
If($MSWORD -or $PDF)
{
$xRow++
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,1).Range.Text = $Item.ItemName
$Table.Cell($xRow,2).Range.Text = $Item.ItemState
$Table.Cell($xRow,3).Range.Text = $Item.ItemDesc
}
ElseIf($Text)
{
#V2.16 change
Line 1 ( "{0,-30} {1,-11} {2,-50}" -f $Item.ItemName,
$Item.ItemState,$Item.ItemDesc)
}
ElseIf($HTML)
{
$rowdata += @(,(
$Item.ItemName,$htmlwhite,
$Item.ItemState,$htmlwhite,
$Item.ItemDesc,$htmlwhite))
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 175; Break}
2 {$xcol.width = 75; Break}
3 {$xcol.width = 175; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$rootDS = $null
$schemaNC = $null
$objDN = $null
$SchemaItems = $null
}
#endregion
$tmp = $Script:Forest.PartitionsContainer
$ConfigurationBase = $tmp.SubString($tmp.IndexOf(",") + 1)
$Sites = $Null
$Sites = Get-ADObject -Filter 'ObjectClass -eq "site"' -SearchBase
$ConfigurationBase -Properties Name, SiteObjectBl -Server $ADForest -EA 0 | Sort-
Object Name
#http://blogs.technet.com/b/ashleymcglone/archive/2011/06/29/report-and-edit-
ad-site-links-from-powershell-turbo-your-ad-replication.aspx
# Report of all site links and related settings
If($cnt -eq 1)
{
$ScriptInformation += @{ Data =
"Sites in Link"; Value = $xSite; }
}
Else
{
$ScriptInformation += @{ Data = "";
Value = $xSite; }
}
}
}
Else
{
$ScriptInformation += @{ Data = "Sites in
Link"; Value = <None>; }
}
$ScriptInformation += @{ Data = "Cost"; Value =
$SiteLink.Cost.ToString(); }
$ScriptInformation += @{ Data = "Replication
Interval"; Value = $SiteLink.ReplInterval.ToString(); }
$ScriptInformation += @{ Data = "Schedule"; Value =
$SiteLink.Schedule; }
#https://msdn.microsoft.com/en-
us/library/cc223552.aspx
$tmp = ""
If([String]::IsNullOrEmpty($SiteLink.Options) -or
$SiteLink.Options -eq "0")
{
$tmp = "Change Notification is Disabled"
}
ElseIf($SiteLink.Options -eq "1")
{
$tmp = "Change Notification is Enabled with
Compression"
}
ElseIf($SiteLink.Options -eq "2")
{
$tmp = "Force sync in opposite direction at end
of sync"
}
ElseIf($SiteLink.Options -eq "3")
{
$tmp = "Change Notification is Enabled with
Compression and Force sync in opposite direction at end of sync"
}
ElseIf($SiteLink.Options -eq "4")
{
$tmp = "Disable compression of Change
Notification messages"
}
ElseIf($SiteLink.Options -eq "5")
{
$tmp = "Change Notification is Enabled without
Compression"
}
ElseIf($SiteLink.Options -eq "6")
{
$tmp = "Force sync in opposite direction at end
of sync and Disable compression of Change Notification messages"
}
ElseIf($SiteLink.Options -eq "7")
{
$tmp = "Change Notification is Enabled without
Compression and Force sync in opposite direction at end of sync"
}
Else
{
$tmp = "Unknown"
}
$ScriptInformation += @{ Data = "Options"; Value =
$tmp; }
$ScriptInformation += @{ Data = "Type"; Value =
$SiteLinkType; }
SetWordCellFormat -Collection
$Table.Columns.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
}
$AllSiteLinks = $Null
ForEach($Site in $Sites)
{
Write-Verbose "$(Get-Date): `tProcessing site $
($Site.Name)"
WriteWordLine 2 0 "Site: " $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-Object
If($Null -eq $subnetArray)
{
WriteWordLine 0 0 "<None>"
}
Else
{
BuildMultiColumnTable $subnetArray "Subnets"
}
SetWordCellFormat -Collection
$Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Columns.Item(1).Width = 200;
$Table.Columns.Item(2).Width = 100;
$Table.Columns.Item(3).Width = 100;
$Table.Rows.SetLeftIndent($Indent1TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
}
Else
{
WriteWordLine 0 3 "Connection Objects: "
WriteWordLine 0 4 "<None>"
WriteWordLine 0 0 ""
}
$First = $False
}
}
ElseIf(!$?)
{
Write-Warning "No Site Servers were retrieved."
WriteWordLine 0 0 "Warning: No Site Servers were
retrieved" "" $Null 0 $False $True
WriteWordLine 0 0 ""
}
Else
{
WriteWordLine 0 0 "No servers in this site"
WriteWordLine 0 0 ""
}
}
}
ElseIf($Text)
{
Line 0 "/// Inter-Site Transports \\\"
If($? -and $Null -ne $AllSiteLinks)
{
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 = New-Object
System.Collections.ArrayList
$SiteLinkSiteList = $SiteLink.SiteList
ForEach($xSite in $SiteLinkSiteList)
{
$tmp = $xSite.Split(",")
$SitesInLink.Add("$($tmp[0].SubString(3))") >
$Null
}
If($cnt -eq 1)
{
Line 0 $xSite
}
Else
{
Line 3 " $($xSite)"
}
}
}
Else
{
Line 0 "<None>"
}
Line 0 "Cost`t`t`t: " $SiteLink.Cost.ToString()
Line 0 "Replication Interval`t: "
$SiteLink.ReplInterval.ToString()
Line 0 "Schedule`t`t: " $SiteLink.Schedule
Line 0 "Options`t`t`t: " -NoNewLine
#https://msdn.microsoft.com/en-
us/library/cc223552.aspx
If([String]::IsNullOrEmpty($SiteLink.Options) -or
$SiteLink.Options -eq "0")
{
Line 0 "Change Notification is Disabled"
}
ElseIf($SiteLink.Options -eq "1")
{
Line 0 "Change Notification is Enabled with
Compression"
}
ElseIf($SiteLink.Options -eq "2")
{
Line 0 "Force sync in opposite direction at end
of sync"
}
ElseIf($SiteLink.Options -eq "3")
{
Line 0 "Change Notification is Enabled with
Compression and Force sync in opposite direction at end of sync"
}
ElseIf($SiteLink.Options -eq "4")
{
Line 0 "Disable compression of Change
Notification messages"
}
ElseIf($SiteLink.Options -eq "5")
{
Line 0 "Change Notification is Enabled without
Compression"
}
ElseIf($SiteLink.Options -eq "6")
{
Line 0 "Force sync in opposite direction at end
of sync and Disable compression of Change Notification messages"
}
ElseIf($SiteLink.Options -eq "7")
{
Line 0 "Change Notification is Enabled without
Compression and Force sync in opposite direction at end of sync"
}
Else
{
Line 0 "Unknown"
}
Line 0 "Type`t`t`t: " $SiteLinkType
Line 0 ""
}
}
$AllSiteLinks = $Null
ForEach($Site in $Sites)
{
Write-Verbose "$(Get-Date): `tProcessing site $
($Site.Name)"
Line 0 "/// Site: $($Site.Name) \\\"
Line 1 "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-Object
If($Null -eq $subnetArray)
{
Line 2 "<None>"
}
Else
{
ForEach($xSubnet in $subnetArray)
{
Line 2 $xSubnet
}
}
Line 0 ""
#http://blogs.technet.com/b/ashleymcglone/archive/2011/06/29/report-and-edit-
ad-site-links-from-powershell-turbo-your-ad-replication.aspx
# Report of all site links and related settings
If($cnt -eq 1)
{
$rowdata += @(,('Sites in Link',
($htmlsilver -bor $htmlbold),$xSite,$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver
-bor $htmlbold),$xSite,$htmlwhite))
}
}
}
Else
{
$rowdata += @(,('Sites in Link',($htmlsilver
-bor $htmlbold),"None",$htmlwhite))
}
$rowdata += @(,('Cost',($htmlsilver -bor $htmlbold),
$SiteLink.Cost.ToString(),$htmlwhite))
$rowdata += @(,('Replication Interval',($htmlsilver
-bor $htmlbold),$SiteLink.ReplInterval.ToString(),$htmlwhite))
$rowdata += @(,('Schedule',($htmlsilver -bor
$htmlbold),$SiteLink.Schedule,$htmlwhite))
#https://msdn.microsoft.com/en-
us/library/cc223552.aspx
$tmp = ""
If([String]::IsNullOrEmpty($SiteLink.Options) -or
$SiteLink.Options -eq "0")
{
$tmp = "Change Notification is Disabled"
}
ElseIf($SiteLink.Options -eq "1")
{
$tmp = "Change Notification is Enabled with
Compression"
}
ElseIf($SiteLink.Options -eq "2")
{
$tmp = "Force sync in opposite direction at end
of sync"
}
ElseIf($SiteLink.Options -eq "3")
{
$tmp = "Change Notification is Enabled with
Compression and Force sync in opposite direction at end of sync"
}
ElseIf($SiteLink.Options -eq "4")
{
$tmp = "Disable compression of Change
Notification messages"
}
ElseIf($SiteLink.Options -eq "5")
{
$tmp = "Change Notification is Enabled without
Compression"
}
ElseIf($SiteLink.Options -eq "6")
{
$tmp = "Force sync in opposite direction at end
of sync and Disable compression of Change Notification messages"
}
ElseIf($SiteLink.Options -eq "7")
{
$tmp = "Change Notification is Enabled without
Compression and Force sync in opposite direction at end of sync"
}
Else
{
$tmp = "Unknown"
}
$rowdata += @(,('Options',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
$rowdata += @(,('Type',($htmlsilver -bor $htmlbold),
$SiteLinkType,$htmlwhite))
$msg = ""
$columnWidths = @("200","250")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "450"
WriteHTMLLine 0 0 " "
}
}
$AllSiteLinks = $Null
ForEach($Site in $Sites)
{
Write-Verbose "$(Get-Date): `tProcessing site $
($Site.Name)"
WriteHTMLLine 2 0 "/// Site: $
($Site.Name) \\\"
WriteHTMLLine 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-Object
If($Null -eq $subnetArray)
{
WriteHTMLLine 0 0 "None"
}
Else
{
$rowdata = @()
ForEach($xSubnet in $subnetArray)
{
$rowdata += @(,($xSubnet,$htmlwhite))
}
$columnHeaders = @('Subnets',($htmlsilver -bor
$htmlbold))
$msg = ""
FormatHTMLTable $msg "auto" -rowArray $rowdata
-columnArray $columnHeaders
WriteHTMLLine 0 0 " "
}
$rowdata += @(,($tmp,
$htmlwhite,
$Result.FromServer,$htmlwhite,
$Result.FromServerSite,$htmlwhite))
}
$columnWidths =
@("175px","125px","150px")
$columnHeaders = @('Name',
($htmlsilver -bor $htmlbold),
'From
Server',($htmlsilver -bor $htmlbold),
'From
Site',($htmlsilver -bor $htmlbold))
$msg = "Connection Objects to
source server $($SiteServer.Name)"
FormatHTMLTable $msg -rowArray
$rowdata -columnArray $columnHeaders -fixedWidth $columnWidths -tablewidth "450"
WriteHTMLLine 0 0 " "
}
}
Else
{
WriteHTMLLine 0 3 "Connection Objects:
None"
}
}
}
ElseIf(!$?)
{
Write-Warning "No Site Servers were retrieved."
WriteHTMLLine 0 0 "Warning: No Site Servers were
retrieved" "" $Null 0 $False $True
}
Else
{
WriteHTMLLine 0 0 "No servers in this site"
}
}
}
}
ElseIf(!$?)
{
Write-Warning "No Sites were retrieved."
$txt = "Warning: No Sites were retrieved"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
WriteWordLine 0 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "There were no sites found to retrieve"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
WriteWordLine 0 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
}
#endregion
#region domains
Function ProcessDomains
{
Write-Verbose "$(Get-Date): Writing domain data"
#http://technet.microsoft.com/en-us/library/bb125224(v=exchg.150).aspx
#http://support.microsoft.com/kb/556086/he
#https://eightwone.com/references/ad-schema-versions/
#https://eightwone.com/references/schema-versions/
$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";
"72" = "Windows Server 2016 TP4";
"87" = "Windows Server 2016";
"88" = "Windows Server 2019"; #added V2.20, updated in 2.22
"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/CU4";
"15300" = "Exchange 2013 CU5";
"15303" = "Exchange 2013 CU6";
"15312" = "Exchange 2013 CU7 through CU 21"; #updated in 2.20
"15317" = "Exchange 2016";
"15323" = "Exchange 2016 CU1";
"15325" = "Exchange 2016 CU2";
"15326" = "Exchange 2016 CU3/CU4/CU5"; #added in 2.16
"15330" = "Exchange 2016 CU6"; #added in 2.16
"15332" = "Exchange 2016 CU7 through CU11"; #added in 2.16 and updated in
2.20, updated in 2.22
"17000" = "Exchange 2019 RTM"; #added in 2.22
}
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"
Switch ($DomainInfo.DomainMode)
{
"0" {$DomainMode = "Windows 2000"; Break}
"1" {$DomainMode = "Windows Server 2003 mixed"; Break}
"2" {$DomainMode = "Windows Server 2003"; Break}
"3" {$DomainMode = "Windows Server 2008"; Break}
"4" {$DomainMode = "Windows Server 2008 R2"; Break}
"5" {$DomainMode = "Windows Server 2012"; Break}
"6" {$DomainMode = "Windows Server 2012 R2"; Break}
"7" {$DomainMode = "Windows Server 2016"; Break} #added
V2.20
"Windows2000Domain" {$DomainMode = "Windows
2000"; Break}
"Windows2003Mixed" {$DomainMode = "Windows
Server 2003 mixed"; Break}
"Windows2003Domain" {$DomainMode = "Windows
Server 2003"; Break}
"Windows2008Domain" {$DomainMode = "Windows
Server 2008"; Break}
"Windows2008R2Domain" {$DomainMode = "Windows
Server 2008 R2"; Break}
"Windows2012Domain" {$DomainMode = "Windows
Server 2012"; Break}
"Windows2012R2Domain" {$DomainMode = "Windows
Server 2012 R2"; Break}
"WindowsThresholdDomain" {$DomainMode = "Windows
Server 2016 TP"; Break}
"Windows2016Domain" {$DomainMode = "Windows
Server 2016"; Break}
"UnknownDomain" {$DomainMode = "Unknown
Domain Mode"; Break}
Default {$DomainMode = "Unable to
determine Domain Mode: $($DomainInfo.DomainMode)"; Break}
}
#http://blogs.technet.com/b/poshchap/archive/2014/03/07/ad-
schema-version.aspx
$ADSchemaInfo = $Null
$ExchangeSchemaInfo = $Null
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Allowed
DNS Suffixes"; Value = "$($DNSSuffix.ToString())"; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value
= "$($DNSSuffix.ToString())"; }
}
}
}
$ChildDomains = $DomainInfo.ChildDomains | Sort-Object
If($Null -eq $ChildDomains)
{
$ScriptInformation += @{ Data = "Child domains";
Value = "<None>"; }
}
Else
{
$cnt = 0
ForEach($ChildDomain in $ChildDomains)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Child
domains"; Value = "$($ChildDomain.ToString())"; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value
= "$($ChildDomain.ToString())"; }
}
}
}
$ScriptInformation += @{ Data = "Default computers
container"; Value = $DomainInfo.ComputersContainer; }
$ScriptInformation += @{ Data = "Default users container";
Value = $DomainInfo.UsersContainer; }
$ScriptInformation += @{ Data = "Deleted objects
container"; Value = $DomainInfo.DeletedObjectsContainer; }
$ScriptInformation += @{ Data = "Distinguished name"; Value
= $DomainInfo.DistinguishedName; }
$ScriptInformation += @{ Data = "DNS root"; Value =
$DomainInfo.DNSRoot; }
$ScriptInformation += @{ Data = "Domain controllers
container"; Value = $DomainInfo.DomainControllersContainer; }
If(![String]::IsNullOrEmpty($ExchangeSchemaInfo))
{
$ScriptInformation += @{ Data = "Exchange Schema";
Value = "($($ExchangeSchemaVersion)) - $($ExchangeSchemaVersionName)"; }
}
$ScriptInformation += @{ Data = "Foreign security
principals container"; Value = $DomainInfo.ForeignSecurityPrincipalsContainer; }
$ScriptInformation += @{ Data = "Infrastructure master";
Value = $DomainInfo.InfrastructureMaster; }
#V2.20 added
$ScriptInformation += @{ Data = "Last logon replication
interval"; Value = $LastLogonReplicationInterval; }
$ScriptInformation += @{ Data = "Lost and Found container";
Value = $DomainInfo.LostAndFoundContainer; }
If(![String]::IsNullOrEmpty($DomainInfo.ManagedBy))
{
$ScriptInformation += @{ Data = "Managed by"; Value =
$DomainInfo.ManagedBy; }
}
$ScriptInformation += @{ Data = "PDC Emulator"; Value =
$DomainInfo.PDCEmulator; }
#V2.20 added
If(validObject $DomainInfo
PublicKeyRequiredPasswordRolling)
{
$ScriptInformation += @{ Data = "Public key required
password rolling"; Value = $DomainInfo.PublicKeyRequiredPasswordRolling.ToString();
}
}
$ScriptInformation += @{ Data = "Quotas container"; Value =
$DomainInfo.QuotasContainer; }
$ReadOnlyReplicas =
$DomainInfo.ReadOnlyReplicaDirectoryServers | Sort-Object
If($Null -eq $ReadOnlyReplicas)
{
$ScriptInformation += @{ Data = "Read-only replica
directory servers"; Value = "<None>"; }
}
Else
{
$cnt = 0
ForEach($ReadOnlyReplica in $ReadOnlyReplicas)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Read-
only replica directory servers"; Value = "$($ReadOnlyReplica.ToString())"; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value
= "$($ReadOnlyReplica.ToString())"; }
}
}
}
$Replicas = $DomainInfo.ReplicaDirectoryServers | Sort-
Object
If($Null -eq $Replicas)
{
$ScriptInformation += @{ Data = "Replica directory
servers"; Value = "<None>"; }
}
Else
{
$cnt = 0
ForEach($Replica in $Replicas)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Replica
directory servers"; Value = "$($Replica.ToString())"; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value
= "$($Replica.ToString())"; }
}
}
}
$ScriptInformation += @{ Data = "RID Master"; Value =
$DomainInfo.RIDMaster; }
$SubordinateReferences = $DomainInfo.SubordinateReferences
| Sort-Object
If($Null -eq $SubordinateReferences)
{
$ScriptInformation += @{ Data = "Subordinate
references"; Value = "<None>"; }
}
Else
{
$cnt = 0
ForEach($SubordinateReference in
$SubordinateReferences)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data =
"Subordinate references"; Value = "$($SubordinateReference.ToString())"; }
}
Else
{
$ScriptInformation += @{ Data = ""; Value
= "$($SubordinateReference.ToString())"; }
}
}
}
$ScriptInformation += @{ Data = "Systems container"; Value
= $DomainInfo.SystemsContainer; }
$Table.Columns.Item(1).Width = 175;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
$ADDomainTrusts = $Null
$ADDomainTrusts = Get-ADObject -Filter {ObjectClass -eq
"trustedDomain"} `
-Server $Domain -Properties * -EA 0
ForEach($Trust in $ADDomainTrusts)
{
[System.Collections.Hashtable[]]
$ScriptInformation = @()
$ScriptInformation += @{ Data = "Name"; Value =
$Trust.Name; }
If(!
[String]::IsNullOrEmpty($Trust.Description))
{
$ScriptInformation += @{ Data =
"Description"; Value = $Trust.Description; }
}
$TrustExtendedAttributes = Get-ADTrustInfo
$Trust
$cnt = 0
ForEach($attribute in
$TrustExtendedAttributes.TrustAttribute)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data =
"Attributes"; Value = $attribute.ToString(); }
}
Else
{
$ScriptInformation += @{ Data = "";
Value = "$($attribute.ToString())"; }
}
}
SetWordCellFormat -Collection
$Table.Columns.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Columns.Item(1).Width = 175;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
FindWordDocumentEnd
$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>"
}
SetWordCellFormat -Collection
$Table.Rows.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Columns.Item(1).Width = 105;
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
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
}
ForEach($FGPP in $FGPPs)
{
[System.Collections.Hashtable[]]
$ScriptInformation = @()
$ScriptInformation += @{ Data = "Name";
Value = $FGPP.Name; }
$ScriptInformation += @{ Data =
"Precedence"; Value = $FGPP.Precedence.ToString(); }
If($FGPP.MinPasswordLength -eq 0)
{
$ScriptInformation += @{ Data =
"Enforce minimum password length"; Value = "Not enabled"; }
}
Else
{
$ScriptInformation += @{ Data =
"Enforce minimum password length"; Value = "Enabled"; }
$ScriptInformation += @{ Data = "
Minimum password length (characters)"; Value =
$FGPP.MinPasswordLength.ToString(); }
}
If($FGPP.PasswordHistoryCount -eq 0)
{
$ScriptInformation += @{ Data =
"Enforce password history"; Value = "Not enabled"; }
}
Else
{
$ScriptInformation += @{ Data =
"Enforce password history"; Value = "Enabled"; }
$ScriptInformation += @{ Data = "
Number of passwords remembered"; Value = $FGPP.PasswordHistoryCount.ToString(); }
}
If($FGPP.ReversibleEncryptionEnabled -eq
$True)
{
$ScriptInformation += @{ Data =
"Store password using reversible encryption"; Value = "Enabled"; }
}
Else
{
$ScriptInformation += @{ Data =
"Store password using reversible encryption"; Value = "Not enabled"; }
}
If($FGPP.ProtectedFromAccidentalDeletion
-eq $True)
{
$ScriptInformation += @{ Data =
"Protect from accidental deletion"; Value = "Enabled"; }
}
Else
{
$ScriptInformation += @{ Data =
"Protect from accidental deletion"; Value = "Not enabled"; }
}
If($FGPP.MaxPasswordAge -eq 0)
{
$ScriptInformation += @{ Data = "
Enforce maximum password age"; Value = "Not enabled"; }
}
Else
{
$ScriptInformation += @{ Data = "
Enforce maximum password age"; Value = "Enabled"; }
$ScriptInformation += @{ Data = "
User must change the password after (days)"; Value =
$FGPP.MaxPasswordAge.TotalDays.ToString(); }
}
If($FGPP.LockoutThreshold -eq 0)
{
$ScriptInformation += @{ Data =
"Enforce account lockout policy"; Value = "Not enabled"; }
}
Else
{
$ScriptInformation += @{ Data =
"Enforce account lockout policy"; Value = "Enabled"; }
$ScriptInformation += @{ Data = "
Number of failed logon attempts allowed"; Value =
$FGPP.LockoutThreshold.ToString(); }
$ScriptInformation += @{ Data = "
Reset failed logon attempts count after (mins)"; Value =
$FGPP.LockoutObservationWindow.TotalMinutes.ToString(); }
If($FGPP.LockoutDuration -eq 0)
{
$ScriptInformation += @{ Data
= " Account will be locked out"; Value = ""; }
$ScriptInformation += @{ Data
= " Until an administrator manually unlocks the account"; Value = ""; }
}
Else
{
$ScriptInformation += @{ Data
= " Account will be locked out for a duration of (mins)"; Value =
$FGPP.LockoutDuration.TotalMinutes.ToString(); }
}
$ScriptInformation += @{ Data =
"Description"; Value = $FGPP.Description; }
$results = Get-
ADFineGrainedPasswordPolicySubject -Identity $FGPP.Name -EA 0 | Sort-Object Name
If($cnt -eq 1)
{
$ScriptInformation += @{
Data = "Directly Applies To"; Value = $Item.Name; }
}
Else
{
$ScriptInformation += @{
Data = ""; Value = $($Item.Name); }
}
}
}
Else
{
}
SetWordCellFormat -Collection
$Table.Columns.Item(1).Cells -Bold -BackgroundColor $wdColorGray15;
$Table.Columns.Item(1).Width = 275;
$Table.Columns.Item(2).Width = 200;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
}
ElseIf(!$?)
{
Write-Warning "Error retrieving Fine Grained
Password Policy data for domain $($Domain)"
WriteWordLine 0 0 "Error retrieving Fine
Grained Password Policy data for domain $($Domain)"
}
Else
{
WriteWordLine 0 0 "No Fine Grained Password
Policy data was retrieved for domain $($Domain)"
}
WriteWordLine 0 0 ""
}
Else
{
#FGPP cmdlets are not available
}
}
ElseIf($Text)
{
Line 1 "Domain mode`t`t`t`t: " $DomainMode
Line 1 "Domain name`t`t`t`t: " $DomainInfo.Name
Line 1 "NetBIOS name`t`t`t`t: " $DomainInfo.NetBIOSName
#V2.20 reorder the following properties in alpha order
Line 1 "AD Schema`t`t`t`t: ($($ADSchemaVersion)) - $
($ADSchemaVersionName)"
Line 1 "Allowed DNS Suffixes`t`t`t: " -NoNewLine
$DNSSuffixes = $DomainInfo.AllowedDNSSuffixes | Sort-Object
If($cnt -eq 1)
{
Line 0 $DNSSuffix.ToString()
}
Else
{
Line 6 " $($DNSSuffix.ToString())"
}
}
}
Line 1 "Child domains`t`t`t`t: " -NoNewLine
$ChildDomains = $DomainInfo.ChildDomains | Sort-Object
If($Null -eq $ChildDomains)
{
Line 0 "<None>"
}
Else
{
$cnt = 0
ForEach($ChildDomain in $ChildDomains)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $ChildDomain.ToString()
}
Else
{
Line 6 " $($ChildDomain.ToString())"
}
}
}
Line 1 "Default computers container`t`t: "
$DomainInfo.ComputersContainer
Line 1 "Default users container`t`t`t: "
$DomainInfo.UsersContainer
Line 1 "Deleted objects container`t`t: "
$DomainInfo.DeletedObjectsContainer
Line 1 "Distinguished name`t`t`t: "
$DomainInfo.DistinguishedName
Line 1 "DNS root`t`t`t`t: " $DomainInfo.DNSRoot
Line 1 "Domain controllers container`t`t: "
$DomainInfo.DomainControllersContainer
If(![String]::IsNullOrEmpty($ExchangeSchemaInfo))
{
Line 1 "Exchange Schema`t`t`t`t: ($
($ExchangeSchemaVersion)) - $($ExchangeSchemaVersionName)"
}
Line 1 "Foreign security principals container`t: "
$DomainInfo.ForeignSecurityPrincipalsContainer
Line 1 "Infrastructure master`t`t`t: "
$DomainInfo.InfrastructureMaster
#V2.20 added
Line 1 "Last logon replication interval`t`t: "
$LastLogonReplicationInterval
Line 1 "Lost and Found container`t`t: "
$DomainInfo.LostAndFoundContainer
If(![String]::IsNullOrEmpty($DomainInfo.ManagedBy))
{
Line 1 "Managed by`t`t`t`t: " $DomainInfo.ManagedBy
}
Line 1 "PDC Emulator`t`t`t`t: " $DomainInfo.PDCEmulator
#V2.20 added
If(validObject $DomainInfo
PublicKeyRequiredPasswordRolling)
{
Line 1 "Public key required password rolling`t: "
$DomainInfo.PublicKeyRequiredPasswordRolling.ToString()
}
Line 1 "Quotas container`t`t`t: "
$DomainInfo.QuotasContainer
Line 1 "Read-only replica directory servers`t: " -NoNewLine
$ReadOnlyReplicas =
$DomainInfo.ReadOnlyReplicaDirectoryServers | Sort-Object
If($Null -eq $ReadOnlyReplicas)
{
Line 0 "<None>"
}
Else
{
$cnt = 0
ForEach($ReadOnlyReplica in $ReadOnlyReplicas)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $ReadOnlyReplica.ToString()
}
Else
{
Line 6 " $($ReadOnlyReplica.ToString())"
}
}
}
Line 1 "Replica directory servers`t`t: " -NoNewLine
$Replicas = $DomainInfo.ReplicaDirectoryServers | Sort-
Object
If($Null -eq $Replicas)
{
Line 0 "<None>"
}
Else
{
$cnt = 0
ForEach($Replica in $Replicas)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $Replica.ToString()
}
Else
{
Line 6 " $($Replica.ToString())"
}
}
}
Line 1 "RID Master`t`t`t`t: " $DomainInfo.RIDMaster
Line 1 "Subordinate references`t`t`t: " -NoNewLine
$SubordinateReferences = $DomainInfo.SubordinateReferences
| Sort-Object
If($Null -eq $SubordinateReferences)
{
Line 0 "<None>"
}
Else
{
$cnt = 0
ForEach($SubordinateReference in
$SubordinateReferences)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $SubordinateReference.ToString()
}
Else
{
Line 6 " $
($SubordinateReference.ToString())"
}
}
}
Line 1 "Systems container`t`t`t: "
$DomainInfo.SystemsContainer
$ADDomainTrusts = $Null
$ADDomainTrusts = Get-ADObject -Filter {ObjectClass -eq
"trustedDomain"} -Server $Domain -Properties * -EA 0
ForEach($Trust in $ADDomainTrusts)
{
Line 1 "Name`t`t: " $Trust.Name
If(!
[String]::IsNullOrEmpty($Trust.Description))
{
Line 1 "Description`t: "
$Trust.Description
}
$TrustExtendedAttributes = Get-ADTrustInfo
$Trust
If($cnt -eq 1)
{
Line 0 $attribute.ToString()
}
Else
{
Line 3 " $($attribute.ToString())"
}
}
ForEach($FGPP in $FGPPs)
{
Line 1 "Name`t`t`t`t`t`t`t`t: "
$FGPP.Name
Line 1 "Precedence`t`t`t`t`t`t`t: "
$FGPP.Precedence.ToString()
If($FGPP.MaxPasswordAge -eq 0)
{
Line 2 "Enforce maximum password
age`t`t`t`t: Not enabled"
}
Else
{
Line 2 "Enforce maximum password
age`t`t`t`t: Enabled"
Line 3 "User must change the
password after (days)`t: " $FGPP.MaxPasswordAge.TotalDays.ToString()
}
$results = Get-
ADFineGrainedPasswordPolicySubject -Identity $FGPP.Name -EA 0 | Sort-Object Name
If($cnt -eq 1)
{
Line 0 $Item.Name
}
Else
{
Line 9 " $($Item.Name)"
}
}
}
Else
{
}
Line 0 ""
}
}
ElseIf(!$?)
{
Write-Warning "Error retrieving Fine Grained
Password Policy data for domain $($Domain)"
Line 0 "Error retrieving Fine Grained Password
Policy data for domain $($Domain)"
}
Else
{
Line 0 "No Fine Grained Password Policy data
was retrieved for domain $($Domain)"
}
Line 0 ""
}
Else
{
#FGPP cmdlets are not available
}
}
ElseIf($HTML)
{
$rowdata = @()
$columnHeaders = @("Domain mode",($htmlsilver -bor
$htmlbold),$DomainMode,$htmlwhite)
$rowdata += @(,('Domain name',($htmlsilver -bor $htmlbold),
$DomainInfo.Name,$htmlwhite))
$rowdata += @(,('NetBIOS name',($htmlsilver -bor
$htmlbold),$DomainInfo.NetBIOSName,$htmlwhite))
#V2.20 reorder the following properties in alpha order
$rowdata += @(,('AD Schema',($htmlsilver -bor
$htmlbold),"($($ADSchemaVersion)) - $($ADSchemaVersionName)",$htmlwhite))
$DNSSuffixes = $DomainInfo.AllowedDNSSuffixes | Sort-Object
If($cnt -eq 1)
{
$rowdata += @(,('Allowed DNS Suffixes',
($htmlsilver -bor $htmlbold),"$($DNSSuffix.ToString())",$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),"$($DNSSuffix.ToString())",$htmlwhite))
}
}
}
$ChildDomains = $DomainInfo.ChildDomains | Sort-Object
If($Null -eq $ChildDomains)
{
$rowdata += @(,('Child domains',($htmlsilver -bor
$htmlbold),"None",$htmlwhite))
}
Else
{
$cnt = 0
ForEach($ChildDomain in $ChildDomains)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Child domains',
($htmlsilver -bor $htmlbold),"$($ChildDomain.ToString())",$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),"$($ChildDomain.ToString())",$htmlwhite))
}
}
}
$rowdata += @(,('Default computers container',($htmlsilver
-bor $htmlbold),$DomainInfo.ComputersContainer,$htmlwhite))
$rowdata += @(,('Default users container',($htmlsilver -bor
$htmlbold),$DomainInfo.UsersContainer,$htmlwhite))
$rowdata += @(,('Deleted objects container',($htmlsilver
-bor $htmlbold),$DomainInfo.DeletedObjectsContainer,$htmlwhite))
$rowdata += @(,('Distinguished name',($htmlsilver -bor
$htmlbold),$DomainInfo.DistinguishedName,$htmlwhite))
$rowdata += @(,('DNS root',($htmlsilver -bor $htmlbold),
$DomainInfo.DNSRoot,$htmlwhite))
$rowdata += @(,('Domain controllers container',($htmlsilver
-bor $htmlbold),$DomainInfo.DomainControllersContainer,$htmlwhite))
If(![String]::IsNullOrEmpty($ExchangeSchemaInfo))
{
$rowdata += @(,('Exchange Schema',($htmlsilver -bor
$htmlbold),"($($ExchangeSchemaVersion)) - $($ExchangeSchemaVersionName)",
$htmlwhite))
}
$rowdata += @(,('Foreign security principals container',
($htmlsilver -bor $htmlbold),$DomainInfo.ForeignSecurityPrincipalsContainer,
$htmlwhite))
$rowdata += @(,('Infrastructure master',($htmlsilver -bor
$htmlbold),$DomainInfo.InfrastructureMaster,$htmlwhite))
#V2.20 added
$rowdata += @(,("Last logon replication interval",
($htmlsilver -bor $htmlbold),$LastLogonReplicationInterval,$htmlwhite))
$rowdata += @(,('Lost and Found container',($htmlsilver
-bor $htmlbold),$DomainInfo.LostAndFoundContainer,$htmlwhite))
If(![String]::IsNullOrEmpty($DomainInfo.ManagedBy))
{
$rowdata += @(,('Managed by',($htmlsilver -bor
$htmlbold),$DomainInfo.ManagedBy,$htmlwhite))
}
$rowdata += @(,('PDC Emulator',($htmlsilver -bor
$htmlbold),$DomainInfo.PDCEmulator,$htmlwhite))
#V2.20 added
If(validObject $DomainInfo
PublicKeyRequiredPasswordRolling)
{
$rowdata += @(,("Public key required password
rolling",($htmlsilver -bor $htmlbold),
$DomainInfo.PublicKeyRequiredPasswordRolling.ToString(),$htmlwhite))
}
$rowdata += @(,('Quotas container',($htmlsilver -bor
$htmlbold),$DomainInfo.QuotasContainer,$htmlwhite))
$ReadOnlyReplicas =
$DomainInfo.ReadOnlyReplicaDirectoryServers | Sort-Object
If($Null -eq $ReadOnlyReplicas)
{
$rowdata += @(,('Read-only replica directory
servers',($htmlsilver -bor $htmlbold),"None",$htmlwhite))
}
Else
{
$cnt = 0
ForEach($ReadOnlyReplica in $ReadOnlyReplicas)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Read-only replica
directory servers',($htmlsilver -bor $htmlbold),"$($ReadOnlyReplica.ToString())",
$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),"$($ReadOnlyReplica.ToString())",$htmlwhite))
}
}
}
$Replicas = $DomainInfo.ReplicaDirectoryServers | Sort-
Object
If($Null -eq $Replicas)
{
$rowdata += @(,('Replica directory servers',
($htmlsilver -bor $htmlbold),"None",$htmlwhite))
}
Else
{
$cnt = 0
ForEach($Replica in $Replicas)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Replica directory
servers',($htmlsilver -bor $htmlbold),"$($Replica.ToString())",$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),"$($Replica.ToString())",$htmlwhite))
}
}
}
$rowdata += @(,('RID Master',($htmlsilver -bor $htmlbold),
$DomainInfo.RIDMaster,$htmlwhite))
$SubordinateReferences = $DomainInfo.SubordinateReferences
| Sort-Object
If($Null -eq $SubordinateReferences)
{
$rowdata += @(,('Subordinate references',($htmlsilver
-bor $htmlbold),"None",$htmlwhite))
}
Else
{
$cnt = 0
ForEach($SubordinateReference in
$SubordinateReferences)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Subordinate references',
($htmlsilver -bor $htmlbold),"$($SubordinateReference.ToString())",$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),"$($SubordinateReference.ToString())",$htmlwhite))
}
}
}
$rowdata += @(,('Systems container',($htmlsilver -bor
$htmlbold),$DomainInfo.SystemsContainer,$htmlwhite))
$msg = ""
$columnWidths = @("175","300")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "475"
WriteHTMLLine 0 0 " "
$ADDomainTrusts = $Null
$ADDomainTrusts = Get-ADObject -Filter {ObjectClass -eq
"trustedDomain"} -Server $Domain -Properties * -EA 0
ForEach($Trust in $ADDomainTrusts)
{
$rowdata = @()
$columnHeaders = @("Name",($htmlsilver -bor
$htmlbold),$Trust.Name,$htmlwhite)
If(!
[String]::IsNullOrEmpty($Trust.Description))
{
$rowdata += @(,('Description',
($htmlsilver -bor $htmlbold),$Trust.Description,$htmlwhite))
}
$TrustExtendedAttributes = Get-ADTrustInfo
$Trust
$cnt = 0
ForEach($attribute in
$TrustExtendedAttributes.Trustattribute)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Attributes',
($htmlsilver -bor $htmlbold),$attribute.ToString(),$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver
-bor $htmlbold),$attribute.ToString(),$htmlwhite))
}
}
$msg = ""
$columnWidths = @("175","300")
FormatHTMLTable $msg -rowArray $rowdata
-columnArray $columnHeaders -fixedWidth $columnWidths -tablewidth "475"
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
#error retrieving domain trusts
Write-Warning "Error retrieving domain trusts for $
($Domain)"
WriteHTMLLine 0 0 "Error retrieving domain trusts for
$($Domain)" "" $Null 0 $False $True
}
Else
{
#no domain trust data
WriteHTMLLine 0 0 "None"
}
ForEach($FGPP in $FGPPs)
{
$rowdata = @()
$columnHeaders = @("Precedence",
($htmlsilver -bor $htmlbold),$FGPP.Precedence.ToString(),$htmlwhite)
If($FGPP.MinPasswordLength -eq 0)
{
$rowdata += @(,("Enforce minimum
password length",($htmlsilver -bor $htmlbold),"Not enabled",$htmlwhite))
}
Else
{
$rowdata += @(,("Enforce minimum
password length",($htmlsilver -bor $htmlbold),"Enabled",$htmlwhite))
$rowdata += @(,(" Minimum
password length (characters)",($htmlsilver -bor $htmlbold),
$FGPP.MinPasswordLength.ToString(),$htmlwhite))
}
If($FGPP.PasswordHistoryCount -eq 0)
{
$rowdata += @(,("Enforce password
history",($htmlsilver -bor $htmlbold),"Not enabled",$htmlwhite))
}
Else
{
$rowdata += @(,("Enforce password
history",($htmlsilver -bor $htmlbold),"Enabled",$htmlwhite))
$rowdata += @(,(" Number of
passwords remembered",($htmlsilver -bor $htmlbold),
$FGPP.PasswordHistoryCount.ToString(),$htmlwhite))
}
If($FGPP.ReversibleEncryptionEnabled -eq
$True)
{
$rowdata += @(,("Store password
using reversible encryption",($htmlsilver -bor $htmlbold),"Enabled",$htmlwhite))
}
Else
{
$rowdata += @(,("Store password
using reversible encryption",($htmlsilver -bor $htmlbold),"Not enabled",
$htmlwhite))
}
If($FGPP.ProtectedFromAccidentalDeletion
-eq $True)
{
$rowdata += @(,("Protect from
accidental deletion",($htmlsilver -bor $htmlbold),"Enabled",$htmlwhite))
}
Else
{
$rowdata += @(,("Protect from
accidental deletion",($htmlsilver -bor $htmlbold),"Not enabled",$htmlwhite))
}
If($FGPP.MaxPasswordAge -eq 0)
{
$rowdata += @(,(" Enforce
maximum password age",($htmlsilver -bor $htmlbold),"Not enabled",$htmlwhite))
}
Else
{
$rowdata += @(,(" Enforce
maximum password age",($htmlsilver -bor $htmlbold),"Enabled",$htmlwhite))
$rowdata += @(,(" User
must change the password after (days)",($htmlsilver -bor $htmlbold),
$FGPP.MaxPasswordAge.TotalDays.ToString(),$htmlwhite))
}
If($FGPP.LockoutThreshold -eq 0)
{
$rowdata += @(,("Enforce account
lockout policy",($htmlsilver -bor $htmlbold),"Not enabled",$htmlwhite))
}
Else
{
$rowdata += @(,("Enforce account
lockout policy",($htmlsilver -bor $htmlbold),"Enabled",$htmlwhite))
$rowdata += @(,(" Number of
failed logon attempts allowed",($htmlsilver -bor $htmlbold),
$FGPP.LockoutThreshold.ToString(),$htmlwhite))
$rowdata += @(,(" Reset failed
logon attempts count after (mins)",($htmlsilver -bor $htmlbold),
$FGPP.LockoutObservationWindow.TotalMinutes.ToString(),$htmlwhite))
If($FGPP.LockoutDuration -eq 0)
{
$rowdata += @(,(" Account
will be locked out",($htmlsilver -bor $htmlbold),"",$htmlwhite))
$rowdata += @(,("
Until an administrator manually unlocks the account",($htmlsilver -bor
$htmlbold),"",$htmlwhite))
}
Else
{
$rowdata += @(,(" Account
will be locked out for a duration of (mins)",($htmlsilver -bor $htmlbold),
$FGPP.LockoutDuration.TotalMinutes.ToString(),$htmlwhite))
}
$rowdata += @(,("Description",
($htmlsilver -bor $htmlbold),$FGPP.Description,$htmlwhite))
$results = Get-
ADFineGrainedPasswordPolicySubject -Identity $FGPP.Name -EA 0 | Sort-Object Name
If($cnt -eq 1)
{
$rowdata += @(,
("Directly Applies To",($htmlsilver -bor $htmlbold),$Item.Name,$htmlwhite))
}
Else
{
$rowdata += @(,("",
($htmlsilver -bor $htmlbold),$($Item.Name),$htmlwhite))
}
}
}
Else
{
}
$First = $False
}
ElseIf(!$?)
{
$txt = "Error retrieving domain data for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "No Domain data was retrieved for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
}
$ADDomainTrusts = $Null
$ADSchemaInfo = $Null
$ChildDomains = $Null
$DNSSuffixes = $Null
$DomainControllers = $Null
$ExchangeSchemaInfo = $Null
$FGPPs = $Null
$First = $Null
$ReadOnlyReplicas = $Null
$Replicas = $Null
$SubordinateReferences = $Null
$Table = $Null
}
#endregion
#region domain controllers
Function ProcessDomainControllers
{
Write-Verbose "$(Get-Date): Writing domain controller data"
ForEach($DC in $Script:AllDomainControllers)
{
Write-Verbose "$(Get-Date): `tProcessing domain controller $($DC.name)"
$FSMORoles = $DC.OperationMasterRoles | Sort-Object
$Partitions = $DC.Partitions | Sort-Object
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Operation
Master roles"; Value = $FSMORole.ToString(); }
}
Else
{
$ScriptInformation += @{ Data = ""; Value =
$FSMORole.ToString(); }
}
}
}
If($Null -eq $Partitions)
{
$ScriptInformation += @{ Data = "Partitions"; Value =
"<None>"; }
}
Else
{
$cnt = 0
ForEach($Partition in $Partitions)
{
$cnt++
If($cnt -eq 1)
{
$ScriptInformation += @{ Data = "Partitions";
Value = $Partition.ToString(); }
}
Else
{
$ScriptInformation += @{ Data = ""; Value =
$Partition.ToString(); }
}
}
}
$ScriptInformation += @{ Data = "Site"; Value = $DC.Site; }
$ScriptInformation += @{ Data = "Operating System"; Value =
$DC.OperatingSystem; }
If(![String]::IsNullOrEmpty($DC.OperatingSystemServicePack))
{
$ScriptInformation += @{ Data = "Service Pack"; Value =
$DC.OperatingSystemServicePack; }
}
$ScriptInformation += @{ Data = "Operating System version"; Value
= $DC.OperatingSystemVersion; }
If(!$Hardware)
{
If([String]::IsNullOrEmpty($DC.IPv4Address))
{
$tmp = "<None>"
}
Else
{
$tmp = $DC.IPv4Address
}
$ScriptInformation += @{ Data = "IPv4 Address"; Value =
$tmp; }
If([String]::IsNullOrEmpty($DC.IPv6Address))
{
$tmp = "<None>"
}
Else
{
$tmp = $DC.IPv6Address
}
$ScriptInformation += @{ Data = "IPv6 Address"; Value =
$tmp; }
}
$Table.Columns.Item(1).Width = 140;
$Table.Columns.Item(2).Width = 300;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 "/// DC: $($DC.Name) \\\"
Line 1 "Default partition`t`t: " $DC.DefaultPartition
Line 1 "Domain`t`t`t`t: " $DC.domain
If($DC.Enabled -eq $True)
{
$tmp = "True"
}
Else
{
$tmp = "False"
}
Line 1 "Enabled`t`t`t`t: " $tmp
Line 1 "Hostname`t`t`t: " $DC.HostName
If($DC.IsGlobalCatalog -eq $True)
{
$tmp = "Yes"
}
Else
{
$tmp = "No"
}
Line 1 "Global Catalog`t`t`t: " $tmp
If($DC.IsReadOnly -eq $True)
{
$tmp = "Yes"
}
Else
{
$tmp = "No"
}
Line 1 "Read-only`t`t`t: " $tmp
Line 1 "LDAP port`t`t`t: " $DC.LdapPort.ToString()
Line 1 "SSL port`t`t`t: " $DC.SslPort.ToString()
Line 1 "Operation Master roles`t`t: " -NoNewLine
If($Null -eq $FSMORoles)
{
Line 0 "<None>"
}
Else
{
$cnt = 0
ForEach($FSMORole in $FSMORoles)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $FSMORole.ToString()
}
Else
{
Line 5 " $($FSMORole.ToString())"
}
}
}
Line 1 "Partitions`t`t`t: " -NoNewLine
If($Null -eq $Partitions)
{
Line 0 "<None>"
}
Else
{
$cnt = 0
ForEach($Partition in $Partitions)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $Partition.ToString()
}
Else
{
Line 5 " $($Partition.ToString())"
}
}
}
Line 1 "Site`t`t`t`t: " $DC.Site
Line 1 "Operating System`t`t: " $DC.OperatingSystem
If(![String]::IsNullOrEmpty($DC.OperatingSystemServicePack))
{
Line 1 "Service Pack`t`t`t: "
$DC.OperatingSystemServicePack
}
Line 1 "Operating System version`t: " $DC.OperatingSystemVersion
If(!$Hardware)
{
Line 1 "IPv4 Address`t`t`t: " -NoNewLine
If([String]::IsNullOrEmpty($DC.IPv4Address))
{
Line 0 "<None>"
}
Else
{
Line 0 $DC.IPv4Address
}
Line 1 "IPv6 Address`t`t`t: " -NoNewLine
If([String]::IsNullOrEmpty($DC.IPv6Address))
{
Line 0 "<None>"
}
Else
{
Line 0 $DC.IPv6Address
}
}
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 2 0 "/// $($DC.Name) \\\"
$rowdata = @()
$columnHeaders = @("Default partition",($htmlsilver -bor
$htmlbold),$DC.DefaultPartition,$htmlwhite)
$rowdata += @(,('Domain',($htmlsilver -bor $htmlbold),$DC.domain,
$htmlwhite))
If($DC.Enabled -eq $True)
{
$tmp = "True"
}
Else
{
$tmp = "False"
}
$rowdata += @(,('Enabled',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
$rowdata += @(,('Hostname',($htmlsilver -bor $htmlbold),
$DC.HostName,$htmlwhite))
If($DC.IsGlobalCatalog -eq $True)
{
$tmp = "Yes"
}
Else
{
$tmp = "No"
}
$rowdata += @(,('Global Catalog',($htmlsilver -bor $htmlbold),
$tmp,$htmlwhite))
If($DC.IsReadOnly -eq $True)
{
$tmp = "Yes"
}
Else
{
$tmp = "No"
}
$rowdata += @(,('Read-only',($htmlsilver -bor $htmlbold),$tmp,
$htmlwhite))
$rowdata += @(,('LDAP port',($htmlsilver -bor $htmlbold),
$DC.LdapPort.ToString(),$htmlwhite))
$rowdata += @(,('SSL port',($htmlsilver -bor $htmlbold),
$DC.SslPort.ToString(),$htmlwhite))
If($Null -eq $FSMORoles)
{
$rowdata += @(,('Operation Master roles',($htmlsilver -bor
$htmlbold),"None",$htmlwhite))
}
Else
{
$cnt = 0
ForEach($FSMORole in $FSMORoles)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Operation Master roles',
($htmlsilver -bor $htmlbold),$FSMORole.ToString(),$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),$FSMORole.ToString(),$htmlwhite))
}
}
}
If($Null -eq $Partitions)
{
$rowdata += @(,('Partitions',($htmlsilver -bor
$htmlbold),"None",$htmlwhite))
}
Else
{
$cnt = 0
ForEach($Partition in $Partitions)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,('Partitions',($htmlsilver -bor
$htmlbold),$Partition.ToString(),$htmlwhite))
}
Else
{
$rowdata += @(,('',($htmlsilver -bor
$htmlbold),$Partition.ToString(),$htmlwhite))
}
}
}
$rowdata += @(,('Site',($htmlsilver -bor $htmlbold),$DC.Site,
$htmlwhite))
$rowdata += @(,('Operating System',($htmlsilver -bor $htmlbold),
$DC.OperatingSystem,$htmlwhite))
If(![String]::IsNullOrEmpty($DC.OperatingSystemServicePack))
{
$rowdata += @(,('Service Pack',($htmlsilver -bor
$htmlbold),$DC.OperatingSystemServicePack,$htmlwhite))
}
$rowdata += @(,('Operating System version',($htmlsilver -bor
$htmlbold),$DC.OperatingSystemVersion,$htmlwhite))
If(!$Hardware)
{
If([String]::IsNullOrEmpty($DC.IPv4Address))
{
$tmp = "None"
}
Else
{
$tmp = $DC.IPv4Address
}
$rowdata += @(,('IPv4 Address',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
If([String]::IsNullOrEmpty($DC.IPv6Address))
{
$tmp = "None"
}
Else
{
$tmp = $DC.IPv6Address
}
$rowdata += @(,('IPv6 Address',($htmlsilver -bor
$htmlbold),$tmp,$htmlwhite))
}
$msg = ""
$columnWidths = @("140","300")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "440"
WriteHTMLLine 0 0 " "
}
OutputADFileLocations $DC.HostName
OutputEventLogInfo $DC.HostName
}
If($DCDNSInfo)
{
BuildDCDNSIPConfigTable $DC.HostName $DC.Site
}
If($Services)
{
GetComputerServices $DC.HostName
}
}
Else
{
$txt = "$(Get-Date): `t`t$($DC.Name) is offline or
unreachable. Hardware inventory is skipped."
Write-Verbose $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
Function OutputTimeServerRegistryKeys
{
Param( [string] $DCName )
#HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClie
nt SpecialPollInterval
#HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTim
eProvider Enabled
$AnnounceFlags = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Config" "AnnounceFlags" $DCName
$MaxNegPhaseCorrection = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Config" "MaxNegPhaseCorrection"
$DCName
$MaxPosPhaseCorrection = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Config" "MaxPosPhaseCorrection"
$DCName
$NtpServer = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Parameters" "NtpServer" $DCName
$NtpType = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Parameters" "Type" $DCName
$SpecialPollInterval = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient"
"SpecialPollInterval" $DCName
$VMICTimeProviderEnabled = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider"
"Enabled" $DCName
$NTPSource = w32tm /query /computer:$DCName /source
If($VMICTimeProviderEnabled -eq 0)
{
$VMICEnabled = "Disabled"
}
Else
{
$VMICEnabled = "Enabled"
}
[void]$Script:TimeServerInfo.Add($obj)
$Table.Columns.Item(1).Width = 335;
$Table.Columns.Item(2).Width = 130;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 "Time Server Information"
Line 0 ""
Line 1 "Time source: " $NTPSource
Line 1 "HKLM:\SYSTEM\CCS\Services\W32Time\"
Line 2 "Config\AnnounceFlags`t`t`t`t: " $AnnounceFlags
Line 2 "Config\MaxNegPhaseCorrection`t`t`t: " $MaxNegPhaseCorrection
Line 2 "Config\MaxPosPhaseCorrection`t`t`t: " $MaxPosPhaseCorrection
Line 2 "Parameters\NtpServer`t`t`t`t: " $NtpServer
Line 2 "Parameters\Type`t`t`t`t`t: " $NtpType
Line 2 "TimeProviders\NtpClient\SpecialPollInterval`t: "
$SpecialPollInterval
Line 2 "TimeProviders\VMICTimeProvider\Enabled`t`t: " $VMICEnabled
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 3 0 "Time Server Information"
$rowdata = @()
$columnHeaders = @("Time source",($htmlsilver -bor $htmlbold),
$NTPSource,$htmlwhite)
$rowdata += @(,
('HKLM:\SYSTEM\CCS\Services\W32Time\Config\AnnounceFlags',($htmlsilver -bor
$htmlbold),$AnnounceFlags,$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CCS\Services\W32Time\Config\MaxNegPhaseCorrection',($htmlsilver -bor
$htmlbold),$MaxNegPhaseCorrection,$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CCS\Services\W32Time\Config\MaxPosPhaseCorrection',($htmlsilver -bor
$htmlbold),$MaxPosPhaseCorrection,$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CCS\Services\W32Time\Parameters\NtpServer',($htmlsilver -bor
$htmlbold),$NtpServer,$htmlwhite))
$rowdata += @(,('HKLM:\SYSTEM\CCS\Services\W32Time\Parameters\Type',
($htmlsilver -bor $htmlbold),$NtpType,$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CCS\Services\W32Time\TimeProviders\NtpClient\SpecialPollInterval',
($htmlsilver -bor $htmlbold),$SpecialPollInterval,$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CCS\Services\W32Time\TimeProviders\VMICTimeProvider\Enabled',
($htmlsilver -bor $htmlbold),$VMICEnabled,$htmlwhite))
$msg = ""
$columnWidths = @("335","130")
FormatHTMLTable $msg -rowarray $rowdata -columnArray $columnheaders
-fixedWidth $columnWidths -tablewidth "465"
WriteHTMLLine 0 0 " "
}
}
Function OutputADFileLocations
{
Param( [string] $DCName )
Write-Verbose "$(Get-Date): `tAD Database, Logfile and SYSVOL locations"
#HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters 'DSA
Database file'
#HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters
'Database log files path'
#HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters
SysVol
$DSADatabaseFile = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" "DSA Database file"
$DCName
$DatabaseLogFilesPath = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" "Database log files path"
$DCName
$SysVol = Get-RegistryValue
"HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" "SysVol" $DCName
$Scriptinformation += @{ Data =
"HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\DSA Database file"; Value
= $DSADatabaseFile; }
$Scriptinformation += @{ Data = "DSA Database file size "; Value = "$
($DSADatabaseFileSize) GB"; }
$Scriptinformation += @{ Data =
"HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\Database log files path";
Value = $DatabaseLogFilesPath; }
$Scriptinformation += @{ Data =
"HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\SysVol"; Value =
$SysVol; }
$Table.Columns.Item(1).Width = 335;
$Table.Columns.Item(2).Width = 130;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 "AD Database, Logfile and SYSVOL Locations"
Line 0 ""
Line 1 "HKLM:\SYSTEM\CCS\Services\"
Line 2 "NTDS\Parameters\DSA Database file`t: " $DSADatabaseFile
Line 2 "DSA Database file size`t`t`t: $($DSADatabaseFileSize) GB"
Line 2 "NTDS\Parameters\Database log files path`t: "
$DatabaseLogFilesPath
Line 2 "Netlogon\Parameters\SysVol`t`t: " $SysVol
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 3 0 "AD Database, Logfile and SYSVOL Locations"
$rowdata = @()
$columnHeaders =
@("HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\DSA Database file",
($htmlsilver -bor $htmlbold),$DSADatabaseFile,$htmlwhite)
$rowdata += @(,('DSA Database file size',($htmlsilver -bor
$htmlbold),"$($DSADatabaseFileSize) GB",$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\Database log files path',
($htmlsilver -bor $htmlbold),$DatabaseLogFilesPath,$htmlwhite))
$rowdata += @(,
('HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\SysVol',($htmlsilver
-bor $htmlbold),$SysVol,$htmlwhite))
$msg = ""
$columnWidths = @("335","130")
FormatHTMLTable $msg -rowarray $rowdata -columnArray $columnheaders
-fixedWidth $columnWidths -tablewidth "465"
WriteHTMLLine 0 0 " "
}
}
Function OutputEventLogInfo
{
Param( [string] $DCName )
#V2.19 added
[void]$Script:DCEventLogInfo.Add($obj)
[void]$ELInfo.Add($obj)
}
}
Else
{
[string]$ELSize = "{0,10:N0}" -f 0
[void]$Script:DCEventLogInfo.Add($obj)
[void]$ELInfo.Add($obj)
}
$Table.rows.first.headingformat = $wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Event Log Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Event Log Size (KB)"
}
ElseIf($Text)
{
Line 0 "Event Log Information"
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 3 0 "Event Log Information"
$rowdata = @()
}
ForEach($Item in $xEventLogInfo)
{
If($MSWord -or $PDF)
{
$xRow++
$Table.Cell($xRow,1).Range.Text = $Item.EventLogName
$Table.Cell($xRow,2).Range.ParagraphFormat.Alignment =
$wdCellAlignVerticalTop
$Table.Cell($xRow,2).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell($xRow,2).Range.Text = $Item.EventLogSize
}
ElseIf($Text)
{
Line 1 "Event Log Name`t`t: " $Item.EventLogName
Line 1 "Event Log Size (KB)`t: " $Item.EventLogSize
Line 0 ""
}
ElseIf($HTML)
{
$rowdata += @(,(
$Item.EventLogName,$htmlwhite,
$Item.EventLogSize,$htmlwhite
))
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 150; Break}
2 {$xcol.width = 100; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$msg = ""
$columnWidths = @("175px","125px")
FormatHTMLTable $msg -rowArray $rowdata -columnArray $columnHeaders
-fixedWidth $columnWidths -tablewidth "300"
WriteHTMLLine 0 0 " "
}
}
#endregion
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"
$Table.rows.first.headingformat = $wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Created"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Protected"
$Table.Cell($xRow,4).Range.Font.Bold = $True
$Table.Cell($xRow,4).Range.Text = "# Users"
$Table.Cell($xRow,5).Range.Font.Bold = $True
$Table.Cell($xRow,5).Range.Text = "# Computers"
$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"
[int]$UserCount = 0
[int]$ComputerCount = 0
[int]$GroupCount = 0
$Table.Cell($xRow,1).Range.Text = $OUDisplayName
$Table.Cell($xRow,2).Range.Text =
$OU.Created.ToString()
If($OU.ProtectedFromAccidentalDeletion -eq $True)
{
$Table.Cell($xRow,3).Range.Text = "Yes"
}
Else
{
$Table.Cell($xRow,3).Range.Text = "No"
#not added in V2.22 now
##$Table.Cell($xRow,3).Shading.BackgroundPatternColor = $wdColorYellow
$Table.Cell($xRow,3).Range.Font.Bold = $True
$UnprotectedOUs++
}
$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
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 214; Break}
2 {$xcol.width = 68; Break}
3 {$xcol.width = 56; Break}
4 {$xcol.width = 56; Break}
5 {$xcol.width = 70; Break}
6 {$xcol.width = 56; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
#added in V2.22
If($UnprotectedOUs -gt 0)
{
WriteWordLine 0 0 "There are $($UnprotectedOUs)
unprotected OUs out of $($NumOUs) OUs"
}
}
ElseIf($Text)
{
[int]$NumOUs = $OUs.Count
[int]$UnprotectedOUs = 0 #added in V2.22
#V2.16 addition
[int]$MaxOUNameLength =
($OUs.CanonicalName.SubString($OUs[0].CanonicalName.IndexOf("/")+1) | measure-
object -maximum -property length).maximum
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"
[int]$UserCount = 0
[int]$ComputerCount = 0
[int]$GroupCount = 0
#V2.16 change
If(($OUDisplayName).Length -lt ($MaxOUNameLength))
{
[int]$NumOfSpaces = ($MaxOUNameLength * -1)
}
Else
{
[int]$NumOfSpaces = -4
}
Line 1 ( "{0,$NumOfSpaces} {1,-22} {2,-9} {3,-7}
{4,-12} {5,-7}" -f $OUDisplayName,$OU.Created.ToString(),$tmp,$UserCountStr,
$ComputerCountStr,$GroupCountStr)
$Results = $Null
$UserCountStr = $Null
$ComputerCountStr = $Null
$GroupCountStr = $Null
}
Line 0 ""
#added in V2.22
If($UnprotectedOUs -gt 0)
{
Line 0 "There are $($UnprotectedOUs) unprotected OUs
out of $($NumOUs) OUs"
}
$Results = $Null
$UserCountStr = $Null
$ComputerCountStr = $Null
$GroupCountStr = $Null
}
ElseIf($HTML)
{
[int]$NumOUs = $OUs.Count
[int]$UnprotectedOUs = 0 #added in V2.22
$rowdata = @()
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"
[int]$UserCount = 0
[int]$ComputerCount = 0
[int]$GroupCount = 0
$Results = $Null
$UserCountStr = $Null
$ComputerCountStr = $Null
$GroupCountStr = $Null
}
$columnHeaders = @('Name',($htmlsilver -bor $htmlbold),
'Created',($htmlsilver -bor
$htmlbold),
'Protected',($htmlsilver -bor
$htmlbold),
'# Users',($htmlsilver -bor
$htmlbold),
'# Computers',($htmlsilver
-bor $htmlbold),
'# Groups',($htmlsilver -bor
$htmlbold)
)
$msg = ""
$columnWidths = @("214","68","56","56","75","56")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "525"
#added in V2.22
If($UnprotectedOUs -gt 0)
{
WriteHTMLLine 0 0 "There are $($UnprotectedOUs)
unprotected OUs out of $($NumOUs) OUs"
}
}
}
ElseIf(!$?)
{
$txt = "Error retrieving OU data for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "No OU data was retrieved for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
$First = $False
}
}
#endregion
$First = $True
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing groups in domain $($Domain)"
If(($MSWORD -or $PDF) -and !$First)
{
#put each domain, starting with the second, on a new page
$Script:selection.InsertNewPage()
}
[int]$SecurityCount = 0
[int]$DistributionCount = 0
[int]$GlobalCount = 0
[int]$UniversalCount = 0
[int]$DomainLocalCount = 0
[int]$ContactsCount = 0
[int]$GroupsWithSIDHistory = 0
[int]$SecurityCount = $Results.Count
[int]$DistributionCount = $Results.Count
[int]$GlobalCount = $Results.Count
[int]$DomainLocalCount = $Results.Count
[int]$ContactsCount = $Results.Count
$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 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).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).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).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).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).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).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).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)
$msg = ""
$columnWidths = @("150","75")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "225"
WriteHTMLLine 0 0 " "
}
$Table.rows.first.headingformat =
$wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Password Last
Changed"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Password Never
Expires"
$Table.Cell($xRow,4).Range.Font.Bold = $True
$Table.Cell($xRow,4).Range.Text = "Account Enabled"
ForEach($Admin in $Admins)
{
$xRow++
$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 =
"True"
}
Else
{
$Table.Cell($xRow,3).Range.Text =
"False"
}
If($User.Enabled -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 =
"True"
}
Else
{
$Table.Cell($xRow,4).Range.Text =
"False"
}
}
Else
{
$Table.Cell($xRow,1).Range.Text =
$Admin.SID
$Table.Cell($xRow,2).Range.Text =
"Unknown"
$Table.Cell($xRow,3).Range.Text =
"Unknown"
$Table.Cell($xRow,4).Range.Text =
"Unknown"
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$columnHeaders = @(
'Name',($htmlsilver -bor $htmlbold),
'Password Last Changed',($htmlsilver -bor $htmlbold),
'Password Never Expires',($htmlsilver -bor
$htmlbold),
'Account Enabled',($htmlsilver -bor $htmlbold)
)
$columnWidths = @("200","66","56","56")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "378"
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
$txt = "Unable to retrieve Domain Admins group membership"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "Domain Admins: <None>"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 "Domain Admins: None"
}
}
$Table.rows.first.headingformat =
$wdHeadingFormatTrue
$Table.Borders.InsideLineStyle =
$wdLineStyleSingle
$Table.Borders.OutsideLineStyle =
$wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Domain"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Password
Last Changed"
$Table.Cell($xRow,4).Range.Font.Bold = $True
$Table.Cell($xRow,4).Range.Text = "Password
Never Expires"
$Table.Cell($xRow,5).Range.Font.Bold = $True
$Table.Cell($xRow,5).Range.Text = "Account
Enabled"
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)."
}
}
}
$Table.Cell($xRow,1).Range.Text = $User.Name
$Table.Cell($xRow,2).Range.Text = $xServer
If($Null -eq
$User.PasswordLastSet)
{
$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,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.ToString()
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.ToString()
}
ElseIf($Admin.ObjectClass -eq
'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"
}
}
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"
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 100; Break}
2 {$xcol.width = 108; Break}
3 {$xcol.width = 66; Break}
4 {$xcol.width = 56; Break}
5 {$xcol.width = 56; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$Script:doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument
}
Else
{
$UserName = $Admin.SID.Value
$Domain = $xServer
$PasswordLastSet = "Unknown"
$PasswordNeverExpires = "Unknown"
$Enabled = "Unknown"
}
$rowdata += @(,(
$UserName,$htmlwhite,
$Domain,$htmlwhite,
$PasswordLastSet,$htmlwhite,
$PasswordNeverExpires,$htmlwhite,
$Enabled,$htmlwhite))
}
$columnHeaders = @(
'Name',($htmlsilver -bor $htmlbold),
'Domain',($htmlsilver -bor $htmlbold),
'Password Last Changed',($htmlsilver -bor
$htmlbold),
'Password Never Expires',($htmlsilver -bor
$htmlbold),
'Account Enabled',($htmlsilver -bor $htmlbold)
)
$columnWidths = @("100","108","66","56","56")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata
-columnArray $columnHeaders -fixedWidth $columnWidths -tablewidth "386"
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
$txt1 = "Enterprise Admins:"
$txt2 = "Unable to retrieve Enterprise Admins group
membership"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt1
WriteWordLine 0 0 $txt2 "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt1
Line 0 $txt2
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $txt1
WriteHTMLLine 0 0 $txt2
}
}
Else
{
$txt1 = "Enterprise Admins:"
$txt2 = "<None>"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt1
WriteWordLine 0 0 $txt2
}
ElseIf($Text)
{
Line 0 $txt1
Line 0 $txt2
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $txt1
WriteHTMLLine 0 0 "None"
}
}
}
$Table.rows.first.headingformat =
$wdHeadingFormatTrue
$Table.Borders.InsideLineStyle =
$wdLineStyleSingle
$Table.Borders.OutsideLineStyle =
$wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Domain"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Password
Last Changed"
$Table.Cell($xRow,4).Range.Font.Bold = $True
$Table.Cell($xRow,4).Range.Text = "Password
Never Expires"
$Table.Cell($xRow,5).Range.Font.Bold = $True
$Table.Cell($xRow,5).Range.Text = "Account
Enabled"
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 -EA 0
}
ElseIf($Admin.ObjectClass -eq 'group')
{
$User = Get-ADGroup -Identity
$Admin.SID.value -Server $xServer -EA 0
}
Else
{
$User = $Null
}
$Table.Cell($xRow,1).Range.Text = $User.Name
$Table.Cell($xRow,2).Range.Text = $xServer
If($Null -eq
$User.PasswordLastSet)
{
$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,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.ToString()
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.ToString()
#$Table.Cell($xRow,6).Range.Text = ""
}
ElseIf($Admin.ObjectClass -eq
'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"
}
}
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"
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 100; Break}
2 {$xcol.width = 108; Break}
3 {$xcol.width = 66; Break}
4 {$xcol.width = 56; Break}
5 {$xcol.width = 56; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
#return focus back to document
$Script:doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument
}
Else
{
$UserName = $Admin.SID.Value
$Domain = $xServer
$PasswordLastSet = "Unknown"
$PasswordNeverExpires = "Unknown"
$Enabled = "Unknown"
}
$rowdata += @(,(
$UserName,$htmlwhite,
$Domain,$htmlwhite,
$PasswordLastSet,$htmlwhite,
$PasswordNeverExpires,$htmlwhite,
$Enabled,$htmlwhite))
}
$columnHeaders = @(
'Name',($htmlsilver -bor $htmlbold),
'Domain',($htmlsilver -bor $htmlbold),
'Password Last Changed',($htmlsilver -bor
$htmlbold),
'Password Never Expires',($htmlsilver -bor
$htmlbold),
'Account Enabled',($htmlsilver -bor $htmlbold)
)
$columnWidths = @("100","108","66","56","56")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata
-columnArray $columnHeaders -fixedWidth $columnWidths -tablewidth "386"
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
$txt1 = "Schema Admins: "
$txt2 = "Unable to retrieve Schema Admins group
membership"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt1
WriteWordLine 0 0 $txt2 "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt1
Line 0 $txt2
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $txt1
WriteHTMLLine 0 0 $txt2
}
}
Else
{
$txt1 = "Schema Admins: "
$txt2 = "<None>"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt1
WriteWordLine 0 0 $txt2
}
ElseIf($Text)
{
Line 0 $txt1
Line 0 $txt2
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $txt1
WriteHTMLLine 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"
#V2.20 changed to @()
$AdminCounts = @(Get-ADUser -LDAPFilter "(admincount=1)" -Server
$Domain -EA 0)
$Table.rows.first.headingformat =
$wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "Password Last
Changed"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Password Never
Expires"
$Table.Cell($xRow,4).Range.Font.Bold = $True
$Table.Cell($xRow,4).Range.Text = "Account Enabled"
ForEach($Admin in $AdminCounts)
{
$User = Get-ADUser -Identity $Admin.SID -Server
$Domain `
-Properties PasswordLastSet, Enabled,
PasswordNeverExpires -EA 0
$xRow++
$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.ToString()
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.ToString()
}
Else
{
$Table.Cell($xRow,2).Range.Text =
$Admin.SID
$Table.Cell($xRow,3).Range.Text =
"Unknown"
$Table.Cell($xRow,4).Range.Text =
"Unknown"
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 200; Break}
2 {$xcol.width = 66; Break}
3 {$xcol.width = 56; Break}
4 {$xcol.width = 56; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$columnWidths = @("200","66","56","56")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "378"
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
$txt = "Unable to retrieve users with AdminCount=1"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt1 = "Users with AdminCount=1: "
$txt2 = "<None>"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt1
WriteWordLIne 0 0 $txt2
}
ElseIf($Text)
{
Line 0 $txt1
Line 0 $txt2
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $txt1
WriteHTMLLIne 0 0 "None"
}
}
$Table.rows.first.headingformat =
$wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Group Name"
$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++
#V2.20 changed to @()
$Members = @(Get-ADGroupMember -Identity
$Admin.Name -Server $Domain -EA 0 | Sort-Object Name)
[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
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 200; Break}
2 {$xcol.width = 172; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
[string]$MembersCountStr = "{0:N0}" -f
$MembersCount
Line 2 "Group Name`t: $($Admin.Name) ($
($MembersCountStr) members)"
$MbrStr = ""
If($MembersCount -gt 0)
{
Line 2 "Members`t`t: " -NoNewLine
$cnt = 0
ForEach($Member in $Members)
{
$cnt++
If($cnt -eq 1)
{
Line 0 $Member.Name
}
Else
{
Line 4 " $($Member.Name)"
}
}
}
Else
{
Line 2 "Members`t`t: None"
}
Line 0 ""
}
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 "Groups with AdminCount=1 ($
($AdminsCountStr) members):"
$rowdata = @()
ForEach($Admin in $AdminCounts)
{
Write-Verbose "$(Get-Date): `t`t`t$
($Admin.Name)"
#V2.20 changed to @()
$Members = @(Get-ADGroupMember -Identity
$Admin.Name -Server $Domain -EA 0 | Sort-Object Name)
[string]$MembersCountStr = "{0:N0}" -f
$MembersCount
$GroupName = "$($Admin.Name) ($
($MembersCountStr) members)"
$MbrStr = ""
If($MembersCount -gt 0)
{
$cnt = 0
ForEach($Member in $Members)
{
$cnt++
If($cnt -eq 1)
{
$rowdata += @(,(
$GroupName,$htmlwhite,
$Member.Name,$htmlwhite))
}
Else
{
$rowdata += @(,(
"",$htmlwhite,
$Member.Name,$htmlwhite))
}
}
}
Else
{
$rowdata += @(,(
$GroupName,$htmlwhite,
"",$htmlwhite))
}
}
$columnHeaders = @(
'Group Name',($htmlsilver -bor $htmlbold),
'Members',($htmlsilver -bor $htmlbold)
)
$columnWidths = @("200","172")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "372"
WriteHTMLLine 0 0 " "
}
}
ElseIf(!$?)
{
$txt = "Unable to retrieve Groups with AdminCount=1"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt1 = "Groups with AdminCount=1: "
$txt2 = "<None>"
If($MSWORD -or $PDF)
{
WriteWordLine 4 0 $txt1
WriteWordLine 0 0 $txt2
}
ElseIf($Text)
{
Line 0 $txt1
Line 0 $txt2
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $txt1
WriteHTMLLine 0 0 "None"
}
}
}
ElseIf(!$?)
{
$txt = "Error retrieving Group data for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "No Group data was retrieved for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
$First = $False
}
}
#endregion
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing group policies for domain $
($Domain)"
$Table.Borders.InsideLineStyle = $wdLineStyleNone
$Table.Borders.OutsideLineStyle = $wdLineStyleNone
[int]$xRow = 0
ForEach($Item in $GPOArray)
{
$xRow++
$Table.Cell($xRow,1).Range.Text = $Item
}
$Table.Rows.SetLeftIndent($Indent0TabStops,
$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitContent)
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"
If(($MSWORD -or $PDF) -and !$First)
{
#put each domain, starting with the second, on a new page
$Script:selection.InsertNewPage()
}
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"
[int]$Rows = $LinkedGpos.Count
$Table.Borders.InsideLineStyle =
$wdLineStyleNone
$Table.Borders.OutsideLineStyle =
$wdLineStyleNone
[int]$xRow = 0
ForEach($Item in $GPOArray)
{
$xRow++
$Table.Cell($xRow,1).Range.Text =
$Item
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitContent)
Function ProcessgGPOsByOUNew
{
Write-Verbose "$(Get-Date): Writing Group Policy data by Domain by OU"
If($MSWORD -or $PDF)
{
$Script:selection.InsertNewPage()
WriteWordLine 1 0 "Group Policies by Organizational Unit"
}
ElseIf($Text)
{
Line 0 "/// Group Policies by Organizational Unit \\\"
}
ElseIf($HTML)
{
WriteHTMLLine 1 0 "/// Group Policies by Organizational
Unit \\\"
}
$First = $True
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing domain $($Domain)"
If(($MSWORD -or $PDF) -and !$First)
{
#put each domain, starting with the second, on a new page
$Script:selection.InsertNewPage()
}
If(($Results.gpoLinks).Count -gt 0)
{
$LinkedGPOs = $Results.gpolinks.DisplayName
}
Else
{
$LinkedGPOs = $Null
}
If(($Results.inheritedgpoLinks).Count -gt 0)
{
$InheritedGPOs =
$Results.inheritedgpolinks.DisplayName
}
Else
{
$InheritedGPOs = $Null
}
ForEach($item in $InheritedGPOs)
{
$obj = New-Object -TypeName PSObject
$GPOType = ""
if(!($LinkedGPOs -contains $item))
{
$GPOType = "Inherited"
}
else
{
$GPOType = "Linked"
}
$obj | Add-Member -MemberType
NoteProperty -Name "GPOName" -value $Item
$obj | Add-Member -MemberType
NoteProperty -Name "GPOType" -value $GPOType
[int]$Rows = 0
$Rows = $AllGPOS.Count
$Table.rows.first.headingformat =
$wdHeadingFormatTrue
$Table.Borders.InsideLineStyle =
$wdLineStyleSingle
$Table.Borders.OutsideLineStyle =
$wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor = $wdColorGray15
[int]$xRow = 1
$Table.Cell($xRow,1).Range.Font.Bold =
$True
$Table.Cell($xRow,1).Range.Text = "GPO
Name"
$Table.Cell($xRow,2).Range.Font.Bold =
$True
$Table.Cell($xRow,2).Range.Text = "GPO
Type"
ForEach($Item in $AllGPOS)
{
$xRow++
$Table.Cell($xRow,1).Range.Text =
$Item.GPOName
$Table.Cell($xRow,2).Range.Text =
$Item.GPOType
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 300; Break}
2 {$xcol.width = 65; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$Script:doc.ActiveWindow.ActivePane.view.SeekView = $wdSeekMainDocument
$columnWidths = @("350","65")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata
-columnArray $columnHeaders -fixedWidth $columnWidths -tablewidth "415"
WriteHTMLLine 0 0 " "
}
}
}
ElseIf(!$?)
{
Write-Warning "Error retrieving OU data for OU $
($OU.CanonicalName)"
}
Else
{
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 "<None>"
}
ElseIf($Text)
{
Line 0 "<None>"
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 "None"
}
}
}
}
ElseIf(!$?)
{
$txt = "Error retrieving OU data for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "No OU data was retrieved for domain $($Domain)"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
$First = $False
}
}
#endregion
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter a user's sAMAccountName",
ValueFromPipeline,ParameterSetName="SAM")]
[ValidateNotNullorEmpty()]
[Alias("Name")]
[string]$SAMAccountname,
[Parameter(ParameterSetName="SAM")]
[string]$SearchRoot,
[string]$Server
Begin
{
#remote desktop properties
$TSSettings =
@("TerminalServicesProfilePath","TerminalServicesHomeDirectory","TerminalServicesHo
meDrive")
}
Process
{
Switch ($PSCmdlet.ParameterSetName)
{
"SAM"
{
$searcher = New-Object DirectoryServices.DirectorySearcher
$searcher.Filter = "(&(objectcategory=person)
(objectclass=user)(samAccountname=$sAMAccountname))"
If($SearchRoot)
{
If($Server)
{
$searchPath = "LDAP://$server/$SearchRoot"
}
Else
{
$searchPath = "LDAP://$SearchRoot"
}
$r = New-Object
System.DirectoryServices.DirectoryEntry $SearchPath
$searcher.SearchRoot = $r
}
$user = $searcher.FindOne().GetDirectoryEntry()
}
"DN"
{
If($server)
{
[ADSI]$User = "LDAP://$Server/$DistinguishedName"
}
Else
{
[ADSI]$User = "LDAP://$DistinguishedName"
}
}
} #close Switch
If($user.path)
{
#initialize a hashtable
Try
{
$hash=[ordered]@{
DistinguishedName = $User.DistinguishedName.Value
Name = $user.name.Value
samAccountName = $user.samAccountName.value
AllowLogon = $user.psbase.InvokeGet("AllowLogon") -as
[Boolean]
}
ForEach($property in $TSSettings)
{
$hash.Add($property,
$user.psbase.invokeGet($property))
} #ForEach
#create an object
New-Object -TypeName PSObject -Property $hash
}
Catch
{
#nothing
}
} #if user found
Else
{
#nothing
}
} #Process
End
{
#nothing
} #End
} #end function
Function ProcessMiscDataByDomain
{
Write-Verbose "$(Get-Date): Writing miscellaneous data by domain"
$First = $True
ForEach($Domain in $Script:Domains)
{
Write-Verbose "$(Get-Date): `tProcessing misc data for domain $
($Domain)"
#added in V2.22
If($UsersCount -gt 100000)
{
Write-Verbose "$(Get-Date):
`t`t`t*****************************************************************************
*************************"
Write-Verbose "$(Get-Date): `t`t`tThere are $
($UsersCount) user accounts to process. The following 17 actions will take a long
time. Be patient."
Write-Verbose "$(Get-Date):
`t`t`t*****************************************************************************
*************************"
}
[int]$UsersDisabledcnt = $DisabledUsers.Count
[int]$UsersLockedOutcnt = $LockedOutUsers.Count
[int]$UsersPasswordExpiredcnt =
$AllUsersWithPasswordExpired.Count
[int]$UsersPasswordNeverExpirescnt =
$AllUsersWhosePasswordNeverExpires.Count
[int]$UsersPasswordNotRequiredcnt =
$AllUsersWithPasswordNotRequired.Count
[int]$UsersCannotChangePasswordcnt =
$AllUsersWhoCannotChangePassword.Count
[int]$UsersWithSIDHistorycnt = ($AllUsersWithSIDHistory |
Where-Object {$_.objectClass -eq 'user'}).Count
#2.16
Write-Verbose "$(Get-Date): `t`t`tAll users with Homedrive
set in ADUC"
#V2.20 changed to @()
$HomeDriveUsers = @($Users | Where-Object {$_.HomeDrive -ne
$Null})
[int]$UsersHomeDrivecnt = $HomeDriveUsers.Count
#2.16
Write-Verbose "$(Get-Date): `t`t`tAll users whose Primary
Group is not Domain Users"
#V2.20 changed to @()
$PrimaryGroupUsers = @($Users | Where-Object
{$_.SamAccountName -ne 'Guest' -and $_.PrimaryGroup -notmatch 'Domain Users'})
[int]$UsersPrimaryGroupcnt = $PrimaryGroupUsers.Count
#2.16
Write-Verbose "$(Get-Date): `t`t`tAll users with RDS
HomeDrive set in ADUC"
#V2.20 changed to @()
$RDSHomeDriveUsers = @($users | Get-RDUserSetting | Where-
Object {$_.TerminalServicesHomeDrive -gt 0})
[int]$UsersRDSHomeDrivecnt = $RDSHomeDriveUsers.Count
[int]$ActiveUsersCount = $EnabledUsers.Count
[int]$ActiveUsersPasswordExpired = $Results.Count
[int]$ActiveUsersPasswordNeverExpires = $Results.Count
[int]$ActiveUsersPasswordNotRequired = $Results.Count
[int]$ActiveUsersCannotChangePassword = $Results.Count
[int]$ActiveUserslastLogonTimestamp = $Results.Count
}
Else
{
[int]$UsersCount = 0
[int]$UsersDisabledcnt = 0
[int]$UsersLockedOutcnt = 0
[int]$UsersPasswordExpiredcnt = 0
[int]$UsersPasswordNeverExpirescnt = 0
[int]$UsersPasswordNotRequiredcnt = 0
[int]$UsersCannotChangePasswordcnt = 0
[int]$UsersWithSIDHistorycnt = 0
[int]$UsersHomeDrivecnt = 0
[int]$UsersPrimaryGroupcnt = 0
[int]$UsersRDSHomeDrivecnt = 0
[int]$ActiveUsersCountcnt = 0
[int]$ActiveUsersPasswordExpiredcnt = 0
[int]$ActiveUsersPasswordNeverExpirescnt = 0
[int]$ActiveUsersPasswordNotRequiredcnt = 0
[int]$ActiveUsersCannotChangePasswordcnt = 0
[int]$ActiveUserslastLogonTimestampcnt = 0
}
$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 = (($UsersDisabledcnt / $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 = (($UsersUnknowncnt / $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 = (($UsersLockedOutcnt / $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 = (($UsersPasswordExpiredcnt /
$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 = (($UsersPasswordNeverExpirescnt /
$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 = (($UsersPasswordNotRequiredcnt /
$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 = (($UsersCannotChangePasswordcnt /
$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 = (($UsersWithSIDHistorycnt /
$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.Cell(10,1).Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell(10,1).Range.Font.Bold = $True
$Table.Cell(10,1).Range.Text = "HomeDrive users"
$Table.Cell(10,2).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell(10,2).Range.Text = $UsersHomeDriveStr
[single]$pct = (($UsersHomeDrivecnt / $UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$Table.Cell(10,3).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell(10,3).Range.Text = "$($pctstr)% of Total Users"
$Table.Cell(11,1).Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell(11,1).Range.Font.Bold = $True
$Table.Cell(11,1).Range.Text = "PrimaryGroup users"
$Table.Cell(11,2).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell(11,2).Range.Text = $UsersPrimaryGroupStr
[single]$pct = (($UsersPrimaryGroupcnt / $UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$Table.Cell(11,3).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell(11,3).Range.Text = "$($pctstr)% of Total Users"
$Table.Cell(12,1).Shading.BackgroundPatternColor =
$wdColorGray15
$Table.Cell(12,1).Range.Font.Bold = $True
$Table.Cell(12,1).Range.Text = "RDS HomeDrive users"
$Table.Cell(12,2).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell(12,2).Range.Text = $UsersRDSHomeDriveStr
[single]$pct = (($UsersRDSHomeDrivecnt / $UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$Table.Cell(12,3).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell(12,3).Range.Text = "$($pctstr)% of Total Users"
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitContent)
$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)
[single]$pct = (($UsersPasswordExpiredcnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Password expired`t: $($UsersPasswordExpiredStr)`t$
($pctstr)% of Total Users"
[single]$pct = (($UsersPasswordNeverExpirescnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Password never expires`t: $
($UsersPasswordNeverExpiresStr)`t$($pctstr)% of Total Users"
[single]$pct = (($UsersPasswordNotRequiredcnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Password not required`t: $
($UsersPasswordNotRequiredStr)`t$($pctstr)% of Total Users"
[single]$pct = (($UsersCannotChangePasswordcnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Can't change password`t: $
($UsersCannotChangePasswordStr)`t$($pctstr)% of Total Users"
[single]$pct = (($UsersWithSIDHistorycnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "With SID History`t: $($UsersWithSIDHistoryStr)`t$
($pctstr)% of Total Users"
[single]$pct = (($ActiveUsersPasswordExpired /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Password expired`t: $
($ActiveUsersPasswordExpiredStr)`t$($pctstr)% of Active Users"
[single]$pct = (($ActiveUsersPasswordNeverExpires /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Password never expires`t: $
($ActiveUsersPasswordNeverExpiresStr)`t$($pctstr)% of Active Users"
[single]$pct = (($ActiveUsersPasswordNotRequired /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Password not required`t: $
($ActiveUsersPasswordNotRequiredStr)`t$($pctstr)% of Active Users"
[single]$pct = (($ActiveUsersCannotChangePassword /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "Can't change password`t: $
($ActiveUsersCannotChangePasswordStr)`t$($pctstr)% of Active Users"
[single]$pct = (($ActiveUserslastLogonTimestamp /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
Line 1 "No lastLogonTimestamp`t: $
($ActiveUserslastLogonTimestampStr)`t$($pctstr)% of Active Users"
Line 0 ""
}
ElseIf($HTML)
{
Write-Verbose "$(Get-Date): `t`tBuild table for All Users"
WriteHTMLLine 3 0 "All Users"
$rowdata = @()
$columnHeaders = @("Total Users",($htmlsilver -bor
$htmlbold),
$UsersCountStr,($htmlwhite),
"",($htmlwhite))
[single]$pct = (($UsersPasswordExpiredcnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('Password expired',($htmlsilver -bor
$htmlbold),
$UsersPasswordExpiredStr,($htmlwhite),
"$($pctstr)% of Total User",($htmlwhite)))
[single]$pct = (($UsersPasswordNeverExpirescnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('Password never expires',($htmlsilver -bor
$htmlbold),
$UsersPasswordNeverExpiresStr,($htmlwhite),
"$($pctstr)% of Total Users",($htmlwhite)))
[single]$pct = (($UsersPasswordNotRequiredcnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('Password not required',($htmlsilver -bor
$htmlbold),
$UsersPasswordNotRequiredStr,($htmlwhite),
"$($pctstr)% of Total Users",($htmlwhite)))
[single]$pct = (($UsersCannotChangePasswordcnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,("Can't change password",($htmlsilver -bor
$htmlbold),
$UsersCannotChangePasswordStr,($htmlwhite),
"$($pctstr)% of Total Users",($htmlwhite)))
[single]$pct = (($UsersWithSIDHistorycnt /
$UsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('With SID History',($htmlsilver -bor
$htmlbold),
$UsersWithSIDHistoryStr,($htmlwhite),
"$($pctstr)% of Total Users",($htmlwhite)))
$msg = ""
$columnWidths = @("150","50","150")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "350"
$rowdata = @()
$rowdata += @(,('Total Active Users',($htmlsilver -bor
$htmlbold),
$ActiveUsersCountStr,($htmlwhite),
"",($htmlwhite)))
[single]$pct = (($ActiveUsersPasswordExpired /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('Password expired',($htmlsilver -bor
$htmlbold),
$ActiveUsersPasswordExpiredStr,($htmlwhite),
"$($pctstr)% of Active Users",($htmlwhite)))
[single]$pct = (($ActiveUsersPasswordNeverExpires /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('Password never expires',($htmlsilver -bor
$htmlbold),
$ActiveUsersPasswordNeverExpiresStr,($htmlwhite),
"$($pctstr)% of Active Users",($htmlwhite)))
[single]$pct = (($ActiveUsersPasswordNotRequired /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('Password not required',($htmlsilver -bor
$htmlbold),
$ActiveUsersPasswordNotRequiredStr,($htmlwhite),
"$($pctstr)% of Active Users",($htmlwhite)))
[single]$pct = (($ActiveUsersCannotChangePassword /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,("Can't change password",($htmlsilver -bor
$htmlbold),
$ActiveUsersCannotChangePasswordStr,($htmlwhite),
"$($pctstr)% of Active Users",($htmlwhite)))
[single]$pct = (($ActiveUserslastLogonTimestamp /
$ActiveUsersCount)*100)
$pctstr = "{0,5:N2}" -f $pct
$rowdata += @(,('No lastLogonTimestamp',($htmlsilver -bor
$htmlbold),
$ActiveUserslastLogonTimestampStr,($htmlwhite),
"$($pctstr)% of Active Users",($htmlwhite)))
$msg = ""
$columnWidths = @("150","50","150")
FormatHTMLTable $msg -rowArray $rowdata -columnArray
$columnHeaders -fixedWidth $columnWidths -tablewidth "350"
WriteHTMLLine 0 0 " "
}
Get-ComputerCountByOS $Domain
}
ElseIf(!$?)
{
$txt = "Error retrieving domain data for domain $($Domain)"
Write-Warning $txt
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
Else
{
$txt = "No Domain data was retrieved for domain $($Domain)"
If($MSWORD -or $PDF)
{
WriteWordLine 0 0 $txt "" $Null 0 $False $True
}
ElseIf($Text)
{
Line 0 $txt
}
ElseIf($HTML)
{
WriteHTMLLine 0 0 $txt
}
}
$First = $False
}
$Script:Domains = $Null
}
Function OutputUserInfo
{
Param([object] $Users, [string] $title)
WriteWordLine 4 0 $title
ForEach($User in $Users)
{
$WordTableRowHash = @{
SamAccountName = $User.SamAccountName;
DN = $User.DistinguishedName
}
## Add the table to the document, using the hashtable (-Alt is short
for -AlternateBackgroundColor!)
$Table = AddWordTable -Hashtable $UsersWordTable `
-Columns SamAccountName, DN `
-Headers "SamAccountName", "DistinguishedName" `
-Format $wdTableGrid `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 150;
$Table.Columns.Item(2).Width = 350;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $title
Line 0 ""
Line 1 "samAccountName DistinguishedName"
Line 1
"==================================================================================
============================================================"
###### "1234512345123451234512345
ForEach($User in $Users)
{
Line 1 ( "{0,-25} {1,-116}" -f $User.samAccountName,
$User.DistinguishedName )
}
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $title
$rowdata = @()
ForEach($User in $Users)
{
$rowdata += @(,($User.SamAccountName,$htmlwhite,
$User.DistinguishedName,$htmlwhite))
}
Function OutputHDUserInfo
{
#new for 2.16
Param([object] $Users, [string] $title)
WriteWordLine 4 0 $title
ForEach($User in $Users)
{
$WordTableRowHash = @{
SamAccountName = $User.SamAccountName;
DN = $User.DistinguishedName;
HomeDrive = $User.HomeDrive;
HomeDir = $User.HomeDirectory;
ProfilePath = $User.ProfilePath;
ScriptPath = $User.ScriptPath
}
$CurrentServiceIndex++;
}
## Add the table to the document, using the hashtable (-Alt is short
for -AlternateBackgroundColor!)
$Table = AddWordTable -Hashtable $UsersWordTable `
-Columns SamAccountName, DN, HomeDrive, HomeDir, ProfilePath,
ScriptPath `
-Headers "SamAccountName", "DistinguishedName", "Home drive", "Home
folder", "Profile path", "Login script" `
-Format $wdTableGrid `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 110;
$Table.Columns.Item(3).Width = 35;
$Table.Columns.Item(4).Width = 85;
$Table.Columns.Item(5).Width = 85;
$Table.Columns.Item(6).Width = 85;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $title
Line 0 ""
ForEach($User in $Users)
{
Line 1 "SamAccountName`t`t: " $User.samAccountName
Line 1 "DistinguishedName`t: " $User.DistinguishedName
Line 1 "Home drive`t`t: " $User.HomeDrive
Line 1 "Home folder`t`t: " $User.HomeDirectory
Line 1 "Profile path`t`t: " $User.ProfilePath
Line 1 "Login script`t`t: " $User.ScriptPath
Line 0 ""
}
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $title
$rowdata = @()
ForEach($User in $Users)
{
$rowdata += @(,($User.SamAccountName,$htmlwhite,
$User.DistinguishedName,$htmlwhite,
$User.HomeDrive,$htmlwhite,
$User.HomeDirectory,$htmlwhite,
$User.ProfilePath,$htmlwhite,
$User.ScriptPath,$htmlwhite))
}
$columnHeaders = @(
'SamAccountName',($htmlsilver -bor $htmlbold),
'DistinguishedName',($htmlsilver -bor $htmlbold),
'Home Drive',($htmlsilver -bor $htmlbold),
'Home folder',($htmlsilver -bor $htmlbold),
'Profile path',($htmlsilver -bor $htmlbold),
'Login script',($htmlsilver -bor $htmlbold))
$columnWidths = @("100px","100px","75px","75px","75px","75px")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata -columnArray $columnHeaders
-fixedWidth $columnWidths -tablewidth "500"
WriteHTMLLine 0 0 " "
}
}
Function OutputPGUserInfo
{
#new for 2.16
Param([object] $Users, [string] $title)
WriteWordLine 4 0 $title
ForEach($User in $Users)
{
$WordTableRowHash = @{
SamAccountName = $User.SamAccountName;
DN = $User.DistinguishedName;
PG = $User.PrimaryGroup
}
$CurrentServiceIndex++;
}
## Add the table to the document, using the hashtable (-Alt is short
for -AlternateBackgroundColor!)
$Table = AddWordTable -Hashtable $UsersWordTable `
-Columns SamAccountName, DN, PG `
-Headers "SamAccountName", "DistinguishedName", "Primary Group" `
-Format $wdTableGrid `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 200;
$Table.Columns.Item(3).Width = 200;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $title
Line 0 ""
ForEach($User in $Users)
{
Line 1 "samAccountName`t`t: " $User.samAccountName
Line 1 "DistinguishedName`t: " $User.DistinguishedName
Line 1 "Primary Group`t`t: " $User.PrimaryGroup
Line 0 ""
}
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $title
$rowdata = @()
ForEach($User in $Users)
{
$rowdata += @(,($User.SamAccountName,$htmlwhite,
$User.DistinguishedName,$htmlwhite,
$User.PrimaryGroup,$htmlwhite))
}
$columnHeaders = @(
'SamAccountName',($htmlsilver -bor $htmlbold),
'DistinguishedName',($htmlsilver -bor $htmlbold),
'Primary Group',($htmlsilver -bor $htmlbold))
$columnWidths = @("100px","200px","200px")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata -columnArray $columnHeaders
-fixedWidth $columnWidths -tablewidth "500"
WriteHTMLLine 0 0 " "
}
}
Function OutputRDSHDUserInfo
{
#new for 2.16
Param([object] $Users, [string] $title)
WriteWordLine 4 0 $title
ForEach($User in $Users)
{
$WordTableRowHash = @{
SamAccountName = $User.SamAccountName;
DN = $User.DistinguishedName;
HomeDrive = $User.TerminalServicesHomeDrive;
HomeDir = $User.TerminalServicesHomeDirectory;
ProfilePath = $User.TerminalServicesProfilePath;
AllowLogon = $User.AllowLogon
}
$CurrentServiceIndex++;
}
## Add the table to the document, using the hashtable (-Alt is short
for -AlternateBackgroundColor!)
$Table = AddWordTable -Hashtable $UsersWordTable `
-Columns SamAccountName, DN, HOmeDrive, HomeDir, ProfilePath,
ALlowLogon `
-Headers "SamAccountName", "DistinguishedName", "RDS Home drive", "RDS
Home folder", "RDS Profile path", "Allow Logon" `
-Format $wdTableGrid `
-AutoFit $wdAutoFitFixed;
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 140;
$Table.Columns.Item(3).Width = 35;
$Table.Columns.Item(4).Width = 75;
$Table.Columns.Item(5).Width = 90;
$Table.Columns.Item(6).Width = 60;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
FindWordDocumentEnd
$Table = $Null
WriteWordLine 0 0 ""
}
ElseIf($Text)
{
Line 0 $title
Line 0 ""
ForEach($User in $Users)
{
Line 1 "SamAccountName`t`t: " $User.samAccountName
Line 1 "DistinguishedName`t: " $User.DistinguishedName
Line 1 "RDS Home drive`t`t: " $User.TerminalServicesHomeDrive
Line 1 "RDS Home folder`t`t: "
$User.TerminalServicesHomeDirectory
Line 1 "RDS Profile path`t: " $User.TerminalServicesProfilePath
Line 1 "Allow Logon`t`t: " $User.AllowLogon
Line 0 ""
}
}
ElseIf($HTML)
{
WriteHTMLLine 4 0 $title
$rowdata = @()
ForEach($User in $Users)
{
$rowdata += @(,($User.SamAccountName,$htmlwhite,
$User.DistinguishedName,$htmlwhite,
$User.TerminalServicesHomeDrive,
$htmlwhite,
$User.TerminalServicesHomeDirectory,
$htmlwhite,
$User.TerminalServicesProfilePath,
$htmlwhite,
$User.AllowLogon,$htmlwhite))
}
$columnHeaders = @(
'SamAccountName',($htmlsilver -bor $htmlbold),
'DistinguishedName',($htmlsilver -bor $htmlbold),
'RDS Home Drive',($htmlsilver -bor $htmlbold),
'RDS Home folder',($htmlsilver -bor $htmlbold),
'RDS Profile path',($htmlsilver -bor $htmlbold),
'Allow Logon',($htmlsilver -bor $htmlbold))
$columnWidths = @("100px","100px","75px","75px","90px","60px")
$msg = ""
FormatHTMLTable $msg -rowArray $rowdata -columnArray $columnHeaders
-fixedWidth $columnWidths -tablewidth "500"
WriteHTMLLine 0 0 " "
}
}
#endregion
#region DCDNSInfo
Function ProcessDCDNSInfo
{
If($DCDNSInfo)
{
#Domain Controller DNS IP Configuration
Write-Verbose "$(Get-Date): Create Domain Controller DNS IP
Configuration"
Write-Verbose "$(Get-Date): `tAdd Domain Controller DNS IP
Configuration table to doc"
ForEach($Item in $xDCDNSIPInfo)
{
If($MSWord -or $PDF)
{
## Add the required key/values to the hashtable
$WordTableRowHash = @{
DCName = $Item.DCName;
DCSite = $Item.DCSite;
DCIpAddress1 = $Item.DCIpAddress1;
DCIpAddress2 = $Item.DCIpAddress2;
DCDNS1 = $Item.DCDNS1;
DCDNS2 = $Item.DCDNS2;
DCDNS3 = $Item.DCDNS3;
DCDNS4 = $Item.DCDNS4
}
## Add the hash to the array
$ItemsWordTable += $WordTableRowHash;
$CurrentServiceIndex++;
}
ElseIf($Text)
{
Line 1 "DC Name`t`t: " $Item.DCName
Line 1 "Site Name`t: " $Item.DCSite
Line 1 "IP Address1`t: " $Item.DCIpAddress1
Line 1 "IP Address2`t: " $Item.DCIpAddress2
Line 1 "Preferred DNS`t: " $Item.DCDNS1
Line 1 "Alternate DNS`t: " $Item.DCDNS2
Line 1 "DNS 3`t`t: " $Item.DCDNS3
Line 1 "DNS 4`t`t: " $Item.DCDNS4
Line 0 ""
}
ElseIf($HTML)
{
$rowdata += @(,(
$Item.DCName,$htmlwhite,
$Item.DCSite,$htmlwhite,
$Item.DCIpAddress1,$htmlwhite,
$Item.DCIpAddress2,$htmlwhite,
$Item.DCDNS1,$htmlwhite,
$Item.DCDNS2,$htmlwhite,
$Item.DCDNS3,$htmlwhite,
$Item.DCDNS4,$htmlwhite))
}
}
$Table.Columns.Item(1).Width = 100;
$Table.Columns.Item(2).Width = 60;
$Table.Columns.Item(3).Width = 67;
$Table.Columns.Item(4).Width = 67;
$Table.Columns.Item(5).Width = 40;
$Table.Columns.Item(6).Width = 40;
$Table.Columns.Item(7).Width = 40;
$Table.Columns.Item(8).Width = 40;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
}
ElseIf($Text)
{
#nothing to do
}
ElseIf($HTML)
{
$columnHeaders = @(
'DC Name',($htmlsilver -bor $htmlbold),
'Site',($htmlsilver -bor $htmlbold),
'IP Address 1',($htmlsilver -bor $htmlbold),
'IP Address 2',($htmlsilver -bor $htmlbold),
'Preferred DNS',($htmlsilver -bor $htmlbold),
'Alternate DNS',($htmlsilver -bor $htmlbold),
'DNS 3',($htmlsilver -bor $htmlbold),
'DNS 4',($htmlsilver -bor $htmlbold)
)
$msg = ""
FormatHTMLTable $msg "auto" -rowArray $rowdata -columnArray
$columnHeaders
WriteHTMLLine 0 0 " "
}
#region TimeServerInfo
Function ProcessTimeServerInfo
{
#Domain Controller Time Server Configuration
Write-Verbose "$(Get-Date): Create Domain Controller Time Server
Configuration"
Write-Verbose "$(Get-Date): `tAdd Domain Controller Time Server Configuration
table to doc"
#sort by DC
$xTimeServerInfo = $Script:TimeServerInfo | Sort-Object DCName
ForEach($Item in $xTimeServerInfo)
{
If($MSWord -or $PDF)
{
## Add the required key/values to the hashtable
$WordTableRowHash = @{
DCName = $Item.DCName;
DCTimeSource = $Item.TimeSource;
DCAnnounceFlags = $Item.AnnounceFlags;
DCMaxNegPhaseCorrection = $Item.MaxNegPhaseCorrection;
DCMaxPosPhaseCorrection = $Item.MaxPosPhaseCorrection;
DCNtpServer = $Item.NtpServer;
DCNtpType = $Item.NtpType;
DCSpecialPollInterval = $Item.SpecialPollInterval;
DCVMICTimeProvider = $Item.VMICTimeProvider
}
$CurrentServiceIndex++;
}
ElseIf($Text)
{
Line 1 "DC Name`t`t`t: " $Item.DCName
Line 1 "Time source`t`t: " $Item.TimeSource
Line 1 "Announce flags`t`t: " $Item.AnnounceFlags
Line 1 "Max Neg Phase Correction: " $Item.MaxNegPhaseCorrection
Line 1 "Max Pos Phase Correction: " $Item.MaxPosPhaseCorrection
Line 1 "NTP Server`t`t: " $Item.NtpServer
Line 1 "Type`t`t`t: " $Item.NtpType
Line 1 "Special Poll Interval`t: " $Item.SpecialPollInterval
Line 1 "VMIC Time Provider`t: " $Item.VMICTimeProvider
Line 0 ""
}
ElseIf($HTML)
{
$rowdata += @(,(
$Item.DCName,$htmlwhite,
$Item.TimeSource,$htmlwhite,
$Item.AnnounceFlags,$htmlwhite,
$Item.MaxNegPhaseCorrection,$htmlwhite,
$Item.MaxPosPhaseCorrection,$htmlwhite,
$Item.NtpServer,$htmlwhite,
$Item.NtpType,$htmlwhite,
$Item.SpecialPollInterval,$htmlwhite,
$Item.VMICTimeProvider,$htmlwhite
))
}
}
$Table.Columns.Item(1).Width = 105;
$Table.Columns.Item(2).Width = 73;
$Table.Columns.Item(3).Width = 45;
$Table.Columns.Item(4).Width = 47;
$Table.Columns.Item(5).Width = 47;
$Table.Columns.Item(6).Width = 73;
$Table.Columns.Item(7).Width = 33;
$Table.Columns.Item(8).Width = 37;
$Table.Columns.Item(9).Width = 40;
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustProportional)
FindWordDocumentEnd
$Table = $Null
}
ElseIf($Text)
{
#nothing to do
}
ElseIf($HTML)
{
$columnHeaders = @(
'DC Name',($htmlsilver -bor $htmlbold),
'Time Source',($htmlsilver -bor $htmlbold),
'Announce Flags',($htmlsilver -bor $htmlbold),
'Max Neg Phase Correction',($htmlsilver -bor $htmlbold),
'Max Pos Phase Correction',($htmlsilver -bor $htmlbold),
'NTP Server',($htmlsilver -bor $htmlbold),
'Type',($htmlsilver -bor $htmlbold),
'Special Poll Interval',($htmlsilver -bor $htmlbold),
'VMIC Time Provider',($htmlsilver -bor $htmlbold)
)
$msg = ""
$columnWidths =
@("100px","70px","45px","45px","45px","75px","40px","40px","40px")
FormatHTMLTable $msg -rowArray $rowdata -columnArray $columnHeaders
-fixedWidth $columnWidths -tablewidth "500"
WriteHTMLLine 0 0 " "
}
$Table.rows.first.headingformat = $wdHeadingFormatTrue
$Table.Borders.InsideLineStyle = $wdLineStyleSingle
$Table.Borders.OutsideLineStyle = $wdLineStyleSingle
$Table.Rows.First.Shading.BackgroundPatternColor = $wdColorGray15
$Table.Cell($xRow,1).Range.Font.Bold = $True
$Table.Cell($xRow,1).Range.Text = "Event Log Name"
$Table.Cell($xRow,2).Range.Font.Bold = $True
$Table.Cell($xRow,2).Range.Text = "DC Name"
$Table.Cell($xRow,3).Range.Font.Bold = $True
$Table.Cell($xRow,3).Range.Text = "Event Log Size (KB)"
}
ElseIf($Text)
{
Line 0 "/// Domain Controller Event Log Data \\\"
Line 0 ""
}
ElseIf($HTML)
{
WriteHTMLLine 1 0 "/// Domain Controller Event Log
Data \\\"
$rowdata = @()
}
ForEach($Item in $xEventLogInfo)
{
If($MSWord -or $PDF)
{
$xRow++
$Table.Cell($xRow,1).Range.Text = $Item.EventLogName
$Table.Cell($xRow,2).Range.Text = $Item.DCName
$Table.Cell($xRow,3).Range.ParagraphFormat.Alignment =
$wdCellAlignVerticalTop
$Table.Cell($xRow,3).Range.ParagraphFormat.Alignment =
$wdAlignParagraphRight
$Table.Cell($xRow,3).Range.Text = $Item.EventLogSize
}
ElseIf($Text)
{
Line 1 "Event Log Name`t`t: " $Item.EventLogName
Line 1 "DC Name`t`t`t: " $Item.DCName
Line 1 "Event Log Size (KB)`t: " $Item.EventLogSize
Line 0 ""
}
ElseIf($HTML)
{
$rowdata += @(,(
$Item.EventLogName,$htmlwhite,
$Item.DCName,$htmlwhite,
$Item.EventLogSize,$htmlwhite
))
}
}
ForEach($xcol in $xcols)
{
switch ($xcol.Index)
{
1 {$xcol.width = 150; Break}
2 {$xcol.width = 150; Break}
3 {$xcol.width = 100; Break}
}
}
$Table.Rows.SetLeftIndent($Indent0TabStops,$wdAdjustNone)
$Table.AutoFitBehavior($wdAutoFitFixed)
$GotFile = $False
If($PDF)
{
If(Test-Path "$($Script:FileName2)")
{
Write-Verbose "$(Get-Date): $($Script:FileName2) is ready for
use"
$GotFile = $True
}
Else
{
Write-Warning "$(Get-Date): Unable to save the output file, $
($Script:FileName2)"
Write-Error "Unable to save the output file, $
($Script:FileName2)"
}
}
Else
{
If(Test-Path "$($Script:FileName1)")
{
Write-Verbose "$(Get-Date): $($Script:FileName1) is ready for
use"
$GotFile = $True
}
Else
{
Write-Warning "$(Get-Date): Unable to save the output file, $
($Script:FileName1)"
Write-Error "Unable to save the output file, $
($Script:FileName1)"
}
}
#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)"
If($Dev)
{
If($SmtpServer -eq "")
{
Out-File -FilePath $Script:DevErrorFile -InputObject $error
4>$Null
}
Else
{
Out-File -FilePath $Script:DevErrorFile -InputObject $error
-Append 4>$Null
}
}
If($ScriptInfo)
{
$SIFile = "$($pwd.Path)\ADInventoryScriptInfo_$(Get-Date -f yyyy-MM-
dd_HHmm).txt"
Out-File -FilePath $SIFile -InputObject "" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Add DateTime :
$AddDateTime" 4>$Null
If($MSWORD -or $PDF)
{
Out-File -FilePath $SIFile -Append -InputObject "Company Name :
$Script:CoName" 4>$Null
}
Out-File -FilePath $SIFile -Append -InputObject "ComputerName :
$ComputerName" 4>$Null
If($MSWORD -or $PDF)
{
Out-File -FilePath $SIFile -Append -InputObject "Company Address:
$CompanyAddress" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Company Email :
$CompanyEmail" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Company Fax :
$CompanyFax" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Company Phone :
$CompanyPhone" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Cover Page :
$CoverPage" 4>$Null
}
Out-File -FilePath $SIFile -Append -InputObject "DCDNSInfo :
$DCDNSInfo" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Dev : $Dev"
4>$Null
If($Dev)
{
Out-File -FilePath $SIFile -Append -InputObject "DevErrorFile :
$Script:DevErrorFile" 4>$Null
}
Out-File -FilePath $SIFile -Append -InputObject "Domain name :
$ADDomain" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Elevated :
$Script:Elevated" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Filename1 :
$Script:FileName1" 4>$Null
If($PDF)
{
Out-File -FilePath $SIFile -Append -InputObject "Filename2 :
$Script:FileName2" 4>$Null
}
Out-File -FilePath $SIFile -Append -InputObject "Folder :
$Folder" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Forest name :
$ADForest" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "From :
$From" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "GPOInheritance :
$GPOInheritance" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "HW Inventory :
$Hardware" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "IncludeUserInfo:
$IncludeUserInfo" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Log : $
($Log)" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "MaxDetails :
$MaxDetails" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Save As HTML :
$HTML" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Save As PDF : $PDF"
4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Save As TEXT :
$TEXT" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Save As WORD :
$MSWORD" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Script Info :
$ScriptInfo" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Services :
$Services" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Smtp Port :
$SmtpPort" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Smtp Server :
$SmtpServer" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Title :
$Script:Title" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "To : $To"
4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Use SSL :
$UseSSL" 4>$Null
If($MSWORD -or $PDF)
{
Out-File -FilePath $SIFile -Append -InputObject "User Name :
$UserName" 4>$Null
}
Out-File -FilePath $SIFile -Append -InputObject "" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "OS Detected :
$Script:RunningOS" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "PoSH version : $
($Host.Version)" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "PSCulture :
$PSCulture" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "PSUICulture :
$PSUICulture" 4>$Null
If($MSWORD -or $PDF)
{
Out-File -FilePath $SIFile -Append -InputObject "Word language :
$Script:WordLanguageValue" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Word version :
$Script:WordProduct" 4>$Null
}
Out-File -FilePath $SIFile -Append -InputObject "" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Script start :
$Script:StartTime" 4>$Null
Out-File -FilePath $SIFile -Append -InputObject "Elapsed time : $Str"
4>$Null
}
#V2.18 added
#stop transcript logging
If($Log -eq $True)
{
If($Script:StartLog -eq $true)
{
try
{
Stop-Transcript | Out-Null
Write-Verbose "$(Get-Date): $Script:LogPath is ready for
use"
}
catch
{
Write-Verbose "$(Get-Date): Transcript/log stop failed"
}
}
}
$ErrorActionPreference = $SaveEAPreference
}
#endregion
ProcessScriptStart
ProcessScriptSetup
ProcessAllDCsInTheForest
ProcessCAInformation
ProcessADOptionalFeatures
ProcessADSchemaItems
[gc]::collect()
}
#endregion
ProcessDocumentOutput
ProcessScriptEnd
[gc]::collect()
#endregion