Src/Public/Invoke-AsBuiltReport.Microsoft.Windows.ps1

function Invoke-AsBuiltReport.Microsoft.Windows {
    <#
    .SYNOPSIS
        PowerShell script to document the configuration of Microsoft Windows Server in Word/HTML/Text formats
    .DESCRIPTION
        Documents the configuration of Microsoft Windows Server in Word/HTML/Text formats using PScribo.
    .NOTES
        Version: 0.5.6
        Author: Andrew Ramsay
        Editor: Jonathan Colon
        Twitter: @asbuiltreport
        Github: AsBuiltReport
        Credits: Iain Brighton (@iainbrighton) - PScribo module
 
    .LINK
        https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows
    #>


    # Do not remove or add to these parameters
    param (
        [String[]] $Target,
        [PSCredential] $Credential
    )

    Write-PScriboMessage -Plugin "Module" -IsWarning "Please refer to the AsBuiltReport.Microsoft.Windows github website for more detailed information about this project."
    Write-PScriboMessage -Plugin "Module" -IsWarning "Do not forget to update your report configuration file after each new release."
    Write-PScriboMessage -Plugin "Module" -IsWarning "Documentation: https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows"
    Write-PScriboMessage -Plugin "Module" -IsWarning "Issues or bug reporting: https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Windows/issues"

    Try {
        $InstalledVersion = Get-Module -ListAvailable -Name AsBuiltReport.Microsoft.Windows -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version

        if ($InstalledVersion) {
            Write-PScriboMessage -Plugin "Module" -IsWarning "AsBuiltReport.Microsoft.Windows $($InstalledVersion.ToString()) is currently installed."
            $LatestVersion = Find-Module -Name AsBuiltReport.Microsoft.Windows -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version
            if ($LatestVersion -gt $InstalledVersion) {
                Write-PScriboMessage -Plugin "Module" -IsWarning "AsBuiltReport.Microsoft.Windows $($LatestVersion.ToString()) is available."
                Write-PScriboMessage -Plugin "Module" -IsWarning "Run 'Update-Module -Name AsBuiltReport.Microsoft.Windows -Force' to install the latest version."
            }
        }
    } Catch {
        Write-PScriboMessage -IsWarning $_.Exception.Message
    }

    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())


    if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {

        throw "The requested operation requires elevation: Run PowerShell console as administrator"
    }

    # Import Report Configuration
    $script:Report = $ReportConfig.Report
    $script:InfoLevel = $ReportConfig.InfoLevel
    $script:Options = $ReportConfig.Options

    # Used to set values to TitleCase where required
    $script:TextInfo = (Get-Culture).TextInfo

    #region foreach loop
    foreach ($System in $Target) {
        Section -Style Heading1 $System {
            Paragraph "The following table details the Windows Host $System"
            BlankLine
            try {
                $script:TempPssSession = New-PSSession $System -Credential $Credential -Authentication Negotiate -ErrorAction stop
                $script:TempCimSession = New-CimSession $System -Credential $Credential -Authentication Negotiate -ErrorAction stop
            } catch {
                Write-PScriboMessage -IsWarning  "Unable to connect to $($System)"
                throw
            }

            $script:HostInfo = Invoke-Command -Session $TempPssSession { Get-ComputerInfo }

            #Validate Required Modules and Features
            $script:OSType = Invoke-Command -Session $TempPssSession { (Get-ComputerInfo).OsProductType }
            $script:HostCPU = Get-CimInstance -Class Win32_Processor -CimSession $TempCimSession
            $script:HostComputer = Get-CimInstance -Class Win32_ComputerSystem -CimSession $TempCimSession
            $script:HostBIOS = Get-CimInstance -Class Win32_Bios -CimSession $TempCimSession
            $script:HostLicense = Get-CimInstance -Query 'Select * from SoftwareLicensingProduct' -CimSession $TempCimSession | Where-Object { $_.LicenseStatus -eq 1 }
            #Host Hardware
            Get-AbrWinHostHWSummary
            #Host OS
            if ($InfoLevel.OperatingSystem -ge 1) {
                try {
                    Section -Style Heading2 'Host Operating System' {
                        Paragraph 'The following settings details host OS Settings'
                        BlankLine
                        #Host OS Configuration
                        Get-AbrWinOSConfig
                        #Host Hotfixes
                        Get-AbrWinOSHotfix
                        #Host Drivers
                        Get-AbrWinOSDriver
                        #Host Roles and Features
                        Get-AbrWinOSRoleFeature
                        #Host 3rd Party Applications
                        Get-AbrWinApplication
                        # Host Service Status
                        Get-AbrWinOSService
                    }
                } catch {
                    Write-PScriboMessage -IsWarning $_.Exception.Message
                }
            }
            #Local Users and Groups
            if ($InfoLevel.Account -ge 1) {
                try {
                    # Get the AsBuiltReport.Microsoft.Windows Shared Util Functions path and file
                    $AsBuiltWinModuleFolder = (Get-Module -ListAvailable -Name "AsBuiltReport.Microsoft.Windows" | Sort-Object Version -Descending | Select-Object -First 1).Path | Split-Path
                    $SharedFunctionPath = Join-Path -Path $AsBuiltWinModuleFolder -ChildPath "Src\Private\SharedUtilsFunctions.ps1"
                    # Dot-source the script from the latest version
                    . $SharedFunctionPath
                    # Read the Shared Util Function into a variable to pass through to a script block so that remote computers have this script available locally
                    $SharedFunctions = [System.IO.File]::ReadAllText($SharedFunctionPath)
                    # Get Local Users
                    $LocalUsers = Invoke-Command -Session $TempPssSession { Get-LocalUser | Where-Object { $_.PrincipalSource -ne "ActiveDirectory" } }

                    # Get Local Groups and their members
                    $LocalGroups = Invoke-Command -Session $TempPssSession -ScriptBlock {
                        param ($ScriptContent)

                        # Create and dot-source the script block so the remote computer can use our shared functions
                        . ([scriptblock]::Create($ScriptContent))

                        $Result = Get-LocalGroup | Where-Object { $_.PrincipalSource -ne "ActiveDirectory" } | ForEach-Object { [PSCustomObject]@{ GroupName = $_.Name; Description = $_.Description; Members = (Get-LocalGroupMembership -Group $_.Name -Depth 1).Name } }
                        Write-Output $Result
                    } -ArgumentList $SharedFunctions

                    # Get Local Administrators members
                    $LocalAdmins = Get-LocalGroupMembership -Group 'Administrators' -Computer $System -Depth 1 -ErrorAction Continue
                    # Remove empty or null elements
                    $LocalAdmins = $LocalAdmins | Where-Object { $_ }

                    if ($LocalUsers -or $LocalGroups -or $LocalAdmins) {
                        Section -Style Heading2 'Local Users and Groups' {
                            Paragraph 'The following section details local configured users and groups'
                            BlankLine
                            #Local Users
                            Get-AbrWinLocalUser
                            #Local Groups
                            Get-AbrWinLocalGroup
                            #Local Administrators
                            Get-AbrWinLocalAdmin
                        }
                    }
                } catch {
                    Write-PScriboMessage -IsWarning $_.Exception.Message
                }
            }
            #Host Firewall
            Get-AbrWinNetFirewall
            #Host Networking
            if ($InfoLevel.Networking -ge 1) {
                try {
                    Section -Style Heading2 'Host Networking' {
                        Paragraph 'The following section details Host Network Configuration'
                        BlankLine
                        #Host Network Adapter
                        Get-AbrWinNetAdapter
                        #Host Network IP Address
                        Get-AbrWinNetIPAddress
                        #Host DNS Client Setting
                        Get-AbrWinNetDNSClient
                        #Host DNS Server Setting
                        Get-AbrWinNetDNSServer
                        #Host Network Teaming
                        Get-AbrWinNetTeamInterface
                        #Host Network Adapter MTU
                        Get-AbrWinNetAdapterMTU
                    }
                } catch {
                    Write-PScriboMessage -IsWarning $_.Exception.Message
                }
            }
            #Host Storage
            if ($InfoLevel.Storage -ge 1) {
                try {
                    Section -Style Heading2 'Host Storage' {
                        Paragraph 'The following section details the storage configuration of the host'
                        #Local Disks
                        Get-AbrWinHostStorage
                        #Local Volumes
                        Get-AbrWinHostStorageVolume
                        #iSCSI Settings
                        Get-AbrWinHostStorageISCSI
                        #MPIO Setting
                        Get-AbrWinHostStorageMPIO
                    }
                } catch {
                    Write-PScriboMessage -IsWarning $_.Exception.Message
                }
            }
            #HyperV Configuration
            if ($InfoLevel.HyperV -ge 1) {
                $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'vmms' -ErrorAction SilentlyContinue }
                if ($Status) {
                    try {
                        if (Get-RequiredFeature -Name Hyper-V-PowerShell -OSType $OSType.Value -Status) {
                            Section -Style Heading2 "Hyper-V Configuration" {
                                Paragraph 'The following table details the Hyper-V server settings'
                                BlankLine
                                # Hyper-V Configuration
                                Get-AbrWinHyperVSummary
                                # Hyper-V Numa Information
                                Get-AbrWinHyperVNuma
                                # Hyper-V Networking
                                Get-AbrWinHyperVNetworking
                                # Hyper-V VM Information
                                Get-AbrWinHyperVHostVM
                            }
                        } else {
                            Get-RequiredFeature -Name Hyper-V-PowerShell -OSType $OSType.Value -Service "Hyper-V"
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning $_.Exception.Message
                    }
                } else {
                    Write-PScriboMessage "No HyperV service detected. Disabling HyperV server section"
                }
            }
            if ($InfoLevel.IIS -ge 1) {
                $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'W3SVC' -ErrorAction SilentlyContinue }
                if ($Status) {
                    try {
                        if (((Get-RequiredFeature -Name web-mgmt-console -OSType $OSType.Value -Status) -and (Get-RequiredFeature -Name Web-Scripting-Tools -OSType $OSType.Value -Status)) -or ((Get-RequiredFeature -Name IIS-WebServerRole -OSType $OSType.Value -Status) -and (Get-RequiredFeature -Name WebServerManagementTools -OSType $OSType.Value -Status) -and (Get-RequiredFeature -Name IIS-ManagementScriptingTools -OSType $OSType.Value -Status))) {
                            Section -Style Heading2 "IIS Configuration" {
                                Paragraph 'The following table details the IIS server settings'
                                BlankLine
                                # IIS Configuration
                                Get-AbrWinIISSummary
                                # IIS Web Application Pools
                                Get-AbrWinIISWebAppPool
                                # IIS Web Site
                                Get-AbrWinIISWebSite
                            }
                        } else {
                            If ($OSType -eq 'Server' -or $OSType -eq 'DomainController') {
                                Get-RequiredFeature -Name web-mgmt-console -OSType $OSType.Value -Service "IIS"
                                Get-RequiredFeature -Name Web-Scripting-Tools -OSType $OSType.Value -Service "IIS"
                            } else {
                                Get-RequiredFeature -Name IIS-WebServerRole -OSType $OSType.Value -Service "IIS"
                                Get-RequiredFeature -Name WebServerManagementTools -OSType $OSType.Value -Service "IIS"
                                Get-RequiredFeature -Name IIS-ManagementScriptingTools -OSType $OSType.Value -Service "IIS"
                            }
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning $_.Exception.Message
                    }
                } else {
                    Write-PScriboMessage "No W3SVC service detected. Disabling IIS server section"
                }
            }
            if ($InfoLevel.SMB -ge 1) {
                try {
                    $script:SMBShares = Invoke-Command -Session $TempPssSession { Get-SmbShare | Where-Object { $_.Special -like 'False' } }
                    if ($SMBShares) {
                        Section -Style Heading2 "File Server Configuration" {
                            Paragraph 'The following table details the File Server settings'
                            BlankLine
                            # SMB Server Configuration
                            Get-AbrWinSMBSummary
                            # SMB Server Network Interface
                            Get-AbrWinSMBNetworkInterface
                            # SMB Shares
                            Get-AbrWinSMBShare
                        }
                    }
                } catch {
                    Write-PScriboMessage -IsWarning $_.Exception.Message
                }
            }
            if ($InfoLevel.DHCP -ge 1 -and $OSType.Value -ne 'WorkStation') {
                $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'DHCPServer' -ErrorAction SilentlyContinue }
                if ($Status) {
                    try {
                        if (Get-RequiredFeature -Name RSAT-DHCP -OSType $OSType.Value -Status) {
                            Section -Style Heading2 "DHCP Server Configuration" {
                                Paragraph 'The following table details the DHCP server configurations'
                                BlankLine
                                # DHCP Server Configuration
                                Get-AbrWinDHCPInfrastructure
                                # DHCP Server Stats
                                Get-AbrWinDHCPv4Statistic
                                # DHCP Server Scope Info
                                Get-AbrWinDHCPv4Scope
                                # DHCP Server Scope Settings
                                Get-AbrWinDHCPv4ScopeServerSetting
                                # DHCP Server Per Scope Info
                                Get-AbrWinDHCPv4PerScopeSetting
                            }
                        } else {
                            Get-RequiredFeature -Name RSAT-DHCP -OSType $OSType.Value -Service "DHCP Server"
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning $_.Exception.Message
                    }
                } else {
                    Write-PScriboMessage "No DHCPServer service detected. Disabling Dhcp server section"
                }
            }
            if ($InfoLevel.DNS -ge 1 -and $OSType.Value -ne 'WorkStation') {
                $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'DNS' -ErrorAction SilentlyContinue }
                if ($Status) {
                    try {
                        if (Get-RequiredFeature -Name RSAT-DNS-Server -OSType $OSType.Value -Status) {
                            Section -Style Heading2 "DNS Server Configuration" {
                                Paragraph 'The following table details the DNS server settings'
                                BlankLine
                                # DNS Server Configuration
                                Get-AbrWinDNSInfrastructure
                                # DNS Zones Configuration
                                Get-AbrWinDNSZone
                            }
                        } else {
                            Get-RequiredFeature -Name RSAT-DNS-Server -OSType $OSType.Value -Service "DNS Server"
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning $_.Exception.Message
                    }
                } else {
                    Write-PScriboMessage "No DNS Server service detected. Disabling DNS server section"
                }
            }

            if ($InfoLevel.FailOverCluster -ge 1 -and $OSType.Value -ne 'WorkStation') {
                $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'ClusSvc' -ErrorAction SilentlyContinue }
                if ($Status.Status -eq "Running") {
                    try {
                        $script:Cluster = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Cluster }
                        if ((Get-RequiredFeature -Name RSAT-Clustering-PowerShell -OSType $OSType.Value -Status ) -and $Cluster) {
                            Section -Style Heading2 "Failover Cluster Configuration" {
                                Paragraph 'The following table details the Failover Cluster Settings'
                                BlankLine
                                # Failover Cluster Server Configuration
                                Get-AbrWinFOCluster
                                # Cluster Access Permission
                                Get-AbrWinFOClusterPermission
                                # Cluster Nodes
                                Get-AbrWinFOClusterNode
                                # Cluster Available Disks
                                Get-AbrWinFOClusterAvailableDisk
                                # Cluster Fault Domain
                                Get-AbrWinFOClusterFaultDomain
                                # Cluster Networks
                                Get-AbrWinFOClusterNetwork
                                # Cluser Quorum
                                Get-AbrWinFOClusterQuorum
                                #Cluster Resources
                                Get-AbrWinFOClusterResource
                                #Cluster Shared Volume
                                Get-AbrWinFOClusterSharedVolume

                            }
                        } else {
                            Get-RequiredFeature -Name RSAT-Clustering-PowerShell -OSType $OSType.Value -Service "FailOver Cluster"
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning $_.Exception.Message
                    }
                } else {
                    Write-PScriboMessage "No FailOver Cluster service detected. Disabling FailOver Cluster section"
                }
            }

            if ($InfoLevel.SQLServer -ge 1 -and $OSType.Value -ne 'WorkStation') {
                $Status = Invoke-Command -Session $TempPssSession -ScriptBlock { Get-Service 'MSSQL*' -ErrorAction SilentlyContinue }
                if ($Status.Status -eq "Running") {
                    try {
                        if ($Options.SQLLogin) {
                            $SQLCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Options.SQLUserName, (ConvertTo-SecureString -Force $Options.SQLSecurePassword)
                            $script:SQLServer = Connect-DbaInstance -SqlInstance $System -TrustServerCertificate -SqlCredential $SQLCredential
                        } else {
                            $script:SQLServer = Connect-DbaInstance -SqlInstance $System -TrustServerCertificate -SqlCredential $Credential
                        }
                        if ($SQLServer) {
                            Section -Style Heading2 "SQL Server Configuration" {
                                Paragraph "The following table details the SQL Server configuration from $($SQLServer.Name)."
                                BlankLine
                                # SQL Server Build Information
                                Get-AbrWinSQLBuild
                                # SQL Server Security Information
                                Section -Style Heading3 "Security" {
                                    Paragraph 'The following table details the SQL Server security settings'
                                    BlankLine
                                    # SQL Server Roles Information
                                    Get-AbrWinSQLRole
                                    # SQL Server Logins Information
                                    Get-AbrWinSQLLogin
                                }
                                # SQL Server Database Information
                                Get-AbrWinSQLDatabase
                                # SQL Server Server Objects Information
                                $BackupDevices = Get-AbrWinSQLBackupDevice
                                if ($BackupDevices) {
                                    Section -Style Heading3 "Server Objects" {
                                        Paragraph 'The following table details the SQL Server server objects settings'
                                        BlankLine
                                        # SQL Server Backup Devices Information
                                        $BackupDevices
                                    }
                                }
                            }
                            # Disconnect SQL Instance
                            Write-PScriboMessage "Disconnecting SQL Instance"
                            $SQLServer | Disconnect-DbaInstance | Out-Null
                        } else {
                            Write-PScriboMessage -IsWarning "Unable to connect to SQL Instance"
                        }
                    } catch {
                        Write-PScriboMessage -IsWarning $_.Exception.Message
                    }
                } else {
                    Write-PScriboMessage "No SQL Server service detected. Disabling SQL Server section"
                }
            }

        }
        Remove-PSSession $TempPssSession
        Remove-CimSession $TempCimSession
    }
    #endregion foreach loop
}