PSWinDocumentation.psm1
function Get-DocumentPath { [CmdletBinding()] param ([System.Collections.IDictionary] $Document, [string] $FinalDocumentLocation) if ($Document.Configuration.Prettify.UseBuiltinTemplate) { $WordDocument = Get-WordDocument -FilePath "$($MyInvocation.MyCommand.Module.ModuleBase)\Templates\WordTemplate.docx" } else { if ($Document.Configuration.Prettify.CustomTemplatePath) { if ($(Test-File -File $Document.Configuration.Prettify.CustomTemplatePath -FileName 'CustomTemplatePath') -eq 0) { $WordDocument = Get-WordDocument -FilePath $Document.Configuration.Prettify.CustomTemplatePath } else { $WordDocument = New-WordDocument -FilePath $FinalDocumentLocation } } else { $WordDocument = New-WordDocument -FilePath $FinalDocumentLocation } } if ($WordDocument -eq $null) { Write-Verbose ' Null' } return $WordDocument } function Get-TypesRequired { [CmdletBinding()] param ([hashtable[]] $Sections) $TypesRequired = New-ArrayList $Types = 'TableData', 'ListData', 'ChartData', 'SqlData', 'ExcelData', 'TextBasedData' foreach ($Section in $Sections) { $Keys = Get-ObjectKeys -Object $Section foreach ($Key in $Keys) { if ($Section.$Key.Use -eq $True) { foreach ($Type in $Types) { Add-ToArrayAdvanced -List $TypesRequired -Element $Section.$Key.$Type -SkipNull -RequireUnique -FullComparison } } } } Write-Verbose "Get-TypesRequired - FinalList: $($TypesRequired -join ', ')" return $TypesRequired } function Get-WinDataFromFile { [cmdletbinding()] param([string] $FilePath, [string] $Type, [string] $FileType = 'XML') try { if (Test-Path $FilePath) { if ($FileType -eq 'XML') { $Data = Import-Clixml -Path $FilePath -ErrorAction Stop } else { $File = Get-Content -Raw -Path $FilePath $Data = ConvertFrom-Json -InputObject $File } } else { Write-Warning "Couldn't load $FileType file from $FilePath for $Type data. File doesn't exists." } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning "Couldn't load $FileType file from $FilePath for $Type data. Error occured: $ErrorMessage" } return $Data } function Get-WinDataFromFileInChunks { [CmdletBinding()] param ([string] $FolderPath, [string] $FileType = 'XML', [Object] $Type) $DataInformation = @{ } if (Test-Path $FolderPath) { $Files = @(Get-ChildItem -Path "$FolderPath\*.$FileType" -ErrorAction SilentlyContinue -Recurse) foreach ($File in $Files) { $FilePath = $File.FullName $FieldName = $File.BaseName Write-Verbose -Message "Importing $FilePath as $FieldName" try { $DataInformation.$FieldName = Import-Clixml -Path $FilePath -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning "Couldn't load $FileType file from $FilePath for $Type data to match into $FieldName. Error occured: $ErrorMessage" } } } else { Write-Warning -Message "Couldn't load files ($FileType) from folder $FolderPath as it doesn't exists." } return $DataInformation } function Get-WinDocumentationData { [CmdletBinding()] param ([alias("Data")][Object] $DataToGet, [alias("Forest")][Object] $Object, [string] $Domain) if ($null -ne $DataToGet) { $Type = Get-ObjectType -Object $DataToGet -ObjectName 'Get-WinDocumentationData' if ($Type.ObjectTypeName -eq 'ActiveDirectory') { if ("$DataToGet" -like 'Forest*') { return $Object."$DataToGet" } elseif ($DataToGet.ToString() -like 'Domain*') { return $Object.FoundDomains.$Domain."$DataToGet" } } else { return $Object."$DataToGet" } } return } function Get-WinDocumentationText { [CmdletBinding()] param ([string[]] $Text, [hashtable] $Forest, [string] $Domain) $Array = foreach ($T in $Text) { $T = $T.Replace('<CompanyName>', $Document.Configuration.Prettify.CompanyName) $T = $T.Replace('<ForestName>', $Forest.ForestInformation.Name) $T = $T.Replace('<ForestNameDN>', $Forest.ForestInformation.'Forest Distingushed Name') $T = $T.Replace('<Domain>', $Domain) $T = $T.Replace('<DomainNetBios>', $Forest.FoundDomains.$Domain.DomainInformation.NetBIOSName) $T = $T.Replace('<DomainDN>', $Forest.FoundDomains.$Domain.DomainInformation.DistinguishedName) $T = $T.Replace('<DomainPasswordWeakPasswordList>', $Forest.FoundDomains.$Domain.DomainPasswordDataPasswords.DomainPasswordWeakPasswordList) $T } return $Array } function Get-WinServiceData { [CmdletBinding()] param ([Object] $Credentials, [Object] $Service, [string] $Type, [Object] $TypesRequired) $CommandOutput = Connect-WinService -Type $Type -Credentials $Credentials -Service $Service -Verbose if ($Service.Use) { if ($Service.OnlineMode) { switch ($Type) { 'ActiveDirectory' { if ($Service.PasswordTests.Use) { $PasswordClearText = $Service.PasswordTests.PasswordFilePathClearText } else { $PasswordClearText = '' } if ($Service.PasswordTests.UseHashDB) { $PasswordHashes = $Service.PasswordTests.PasswordFilePathHash } else { $PasswordHashes = '' } $DataInformation = Get-WinADForestInformation -TypesRequired $TypesRequired -PathToPasswords $PasswordClearText -PathToPasswordsHashes $PasswordHashes -Verbose } 'AWS' { $DataInformation = Get-WinAWSInformation -TypesRequired $TypesRequired -AWSAccessKey $Credentials.AccessKey -AWSSecretKey $Credentials.SecretKey -AWSRegion $Credentials.Region } 'Azure' { $DataInformation = Get-WinO365Azure -TypesRequired $TypesRequired } 'AzureAD' { } 'Exchange' { $DataInformation = Get-WinExchangeInformation -TypesRequired $TypesRequired -Prefix $Service.Prefix } 'ExchangeOnline' { $DataInformation = Get-WinO365Exchange -TypesRequired $TypesRequired -Prefix $Service.Prefix } 'Teams' { } 'SharePointOnline' { } 'SkypeOnline' { } } if ($Service.Export.Use) { $Time = Start-TimeLog if ($Service.Export.To -eq 'File' -or $Service.Export.To -eq 'Both') { Save-WinDataToFile -Export $Service.Export.Use -FilePath $Service.Export.FilePath -Data $DataInformation -Type $Type -IsOffline:$false -FileType 'XML' $TimeSummary = Stop-TimeLog -Time $Time -Option OneLiner Write-Verbose "Saving data for $Type to file $($Service.Export.FilePath) took: $TimeSummary" } if ($Service.Export.To -eq 'Folder' -or $Service.Export.To -eq 'Both') { $Time = Start-TimeLog Save-WinDataToFileInChunks -Export $Service.Export.Use -FolderPath $Service.Export.FolderPath -Data $DataInformation -Type $Type -IsOffline:$false -FileType 'XML' $TimeSummary = Stop-TimeLog -Time $Time -Option OneLiner Write-Verbose "Saving data for $Type to folder $($Service.Export.FolderPath) took: $TimeSummary" } } return $DataInformation } else { if ($Service.Import.Use) { $Time = Start-TimeLog if ($Service.Import.From -eq 'File') { Write-Verbose "Loading data for $Type in offline mode from XML File $($Service.Import.Path). Hang on..." $DataInformation = Get-WinDataFromFile -FilePath $Service.Import.Path -Type $Type -FileType 'XML' } elseif ($Service.Import.From -eq 'Folder') { Write-Verbose "Loading data for $Type in offline mode from XML File $($Service.Import.Path). Hang on..." $DataInformation = Get-WinDataFromFileInChunks -FolderPath $Service.Import.Path -Type $Type -FileType 'XML' } else { Write-Warning "Wrong option for Import.Use. Only Folder/File is supported." } $TimeSummary = Stop-TimeLog -Time $Time -Option OneLiner Write-Verbose "Loading data for $Type in offline mode from file took $TimeSummary" return $DataInformation } } } } function New-DataBlock { [CmdletBinding()] param([Container]$WordDocument, [Object] $Section, [alias('Object')][Object] $Forest, [string] $Domain, [OfficeOpenXml.ExcelPackage] $Excel, [string] $SectionName, [nullable[bool]] $Sql) if ($Section.Use) { if ($Domain) { $SectionDetails = "$Domain - $SectionName" } else { $SectionDetails = $SectionName } $TableData = Get-WinDocumentationData -DataToGet $Section.TableData -Object $Forest -Domain $Domain $ExcelData = Get-WinDocumentationData -DataToGet $Section.ExcelData -Object $Forest -Domain $Domain $ListData = Get-WinDocumentationData -DataToGet $Section.ListData -Object $Forest -Domain $Domain $SqlData = Get-WinDocumentationData -DataToGet $Section.SqlData -Object $Forest -Domain $Domain $TextBasedData = Get-WindocumentationData -DataToGet $Section.TextBasedData -Object $Forest -Domain $Domain $ChartData = (Get-WinDocumentationData -DataToGet $Section.ChartData -Object $Forest -Domain $Domain) if ($ChartData) { if ($Section.ChartKeys -is [string]) { if ($Section.ChartKeys -eq 'Keys' -and $Section.ChartValues -eq 'Values') { $ChartKeys = (Convert-KeyToKeyValue $ChartData).Keys $ChartValues = (Convert-KeyToKeyValue $ChartData).Values } else { $ChartKeys = (Convert-KeyToKeyValue $ChartData)."$($Section.ChartKeys)" $ChartValues = (Convert-KeyToKeyValue $ChartData)."$($Section.ChartValues)" } } elseif ($Section.ChartKeys -is [Array]) { $ChartKeys = (Convert-TwoArraysIntoOne -Object $ChartData.($Section.ChartKeys[0]) -ObjectToAdd $ChartData.($Section.ChartKeys[1])) $ChartValues = ($ChartData.($Section.ChartValues)) } else { } } $TocText = (Get-WinDocumentationText -Text $Section.TocText -Forest $Forest -Domain $Domain) $TableTitleText = (Get-WinDocumentationText -Text $Section.TableTitleText -Forest $Forest -Domain $Domain) $Text = (Get-WinDocumentationText -Text $Section.Text -Forest $Forest -Domain $Domain) $ChartTitle = (Get-WinDocumentationText -Text $Section.ChartTitle -Forest $Forest -Domain $Domain) $ListBuilderContent = (Get-WinDocumentationText -Text $Section.ListBuilderContent -Forest $Forest -Domain $Domain) $TextNoData = (Get-WinDocumentationText -Text $Section.TextNoData -Forest $Forest -Domain $Domain) if ($WordDocument -and (($null -eq $Section.WordExport -and $Section.Use -eq $true) -or ($Section.WordExport -eq $true))) { Write-Verbose "Generating WORD Section for [$SectionDetails]" New-WordBlock -WordDocument $WordDocument -TocGlobalDefinition $Section.TocGlobalDefinition-TocGlobalTitle $Section.TocGlobalTitle -TocGlobalSwitches $Section.TocGlobalSwitches -TocGlobalRightTabPos $Section.TocGlobalRightTabPos -TocEnable $Section.TocEnable -TocText $TocText -TocListLevel $Section.TocListLevel -TocListItemType $Section.TocListItemType -TocHeadingType $Section.TocHeadingType -TableData $TableData -TableDesign $Section.TableDesign -TableTitleMerge $Section.TableTitleMerge -TableTitleText $TableTitleText -TableMaximumColumns $Section.TableMaximumColumns -TableColumnWidths $Section.TableColumnWidths -Text $Text -TextNoData $TextNoData -EmptyParagraphsBefore $Section.EmptyParagraphsBefore -EmptyParagraphsAfter $Section.EmptyParagraphsAfter -PageBreaksBefore $Section.PageBreaksBefore -PageBreaksAfter $Section.PageBreaksAfter -TextAlignment $Section.TextAlignment -ListData $ListData -ListType $Section.ListType -ListTextEmpty $Section.ListTextEmpty -ChartEnable $Section.ChartEnable -ChartTitle $ChartTitle -ChartKeys $ChartKeys -ChartValues $ChartValues -ListBuilderContent $ListBuilderContent -ListBuilderType $Section.ListBuilderType -ListBuilderLevel $Section.ListBuilderLevel -TextBasedData $TextBasedData -TextBasedDataAlignment $Section.TextSpecialAlignment } if ($Excel -and $Section.ExcelExport) { if ($Section.ExcelWorkSheet -eq '') { $WorkSheetName = $SectionDetails } else { $WorkSheetName = (Get-WinDocumentationText -Text $Section.ExcelWorkSheet -Forest $Forest -Domain $Domain) } if ($ExcelData) { Write-Verbose "Generating EXCEL Section for [$SectionDetails]" $ExcelWorksheet = Add-ExcelWorksheetData -ExcelDocument $Excel -ExcelWorksheetName $WorkSheetName -DataTable $ExcelData -AutoFit -AutoFilter -PreScanHeaders } } if ($Sql -and $Section.SQLExport -and $SqlData) { Write-Verbose "Sending [$SectionDetails] to SQL Server" $SqlQuery = Send-SqlInsert -Object $SqlData -SqlSettings $Section -Verbose foreach ($Query in $SqlQuery) { Write-Color @script:WriteParameters -Text '[i] ', 'MS SQL Output: ', $Query -Color White, White, Yellow } } } if ($WordDocument) { return $WordDocument } else { return } } function Save-WinDataToFile { [cmdletbinding()] param([nullable[bool]] $Export, [string] $Type, [Object] $Data, [string] $FilePath, [switch] $IsOffline, [string] $FileType = 'XML') if ($IsOffline) { Write-Verbose "Save-WinDataToFile - Exporting $Type data to $FileType to path $FilePath skipped. Running in offline mode." return } if ($Export) { if ($FilePath) { $Split = Split-Path -Path $FilePath if (-not (Test-Path -Path $Split)) { New-Item -ItemType Directory -Force -Path $Split > $null } Write-Verbose "Save-WinDataToFile - Exporting $Type data to $FileType to path $FilePath" if ($FileType -eq 'XML') { try { $Data | Export-Clixml -Path $FilePath -ErrorAction Stop -Encoding UTF8 } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning "Couldn't save $FileType file to $FilePath for $Type data. Error occured: $ErrorMessage" } } else { try { $Data | ConvertTo-Json -ErrorAction Stop | Add-Content -Path $FilePath -Encoding UTF8 -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning "Couldn't save $FileType file to $FilePath for $Type data. Error occured: $ErrorMessage" } } } } } function Save-WinDataToFileInChunks { [CmdletBinding()] param([nullable[bool]] $Export, [string] $Type, [Object] $Data, [string] $FolderPath, [switch] $IsOffline, [string] $FileType = 'XML') foreach ($Key in $Data.Keys) { $FilePath = [IO.Path]::Combine($FolderPath, "$Key.xml") Save-WinDataToFile -Export $Export -Type $Type -IsOffline:$IsOffline -Data $Data.$Key -FilePath $FilePath -FileType $FileType } } $Script:DataBehaviorActiveDirectory = [ordered] @{ForestInformation = @{OnlineRequired = $true } ForestFSMO = @{OnlineRequired = $true } ForestGlobalCatalogs = @{OnlineRequired = $true } ForestOptionalFeatures = @{OnlineRequired = $true } ForestUPNSuffixes = @{OnlineRequired = $true } ForestSPNSuffixes = @{OnlineRequired = $true } ForestSites = @{OnlineRequired = $true } ForestSites1 = @{OnlineRequired = $false } ForestSites2 = @{OnlineRequired = $false } ForestSubnets = @{OnlineRequired = $true } ForestSubnets1 = @{OnlineRequired = $true } ForestSubnets2 = @{OnlineRequired = $true } ForestSiteLinks = @{OnlineRequired = $true } DomainRootDSE = @{OnlineRequired = $true } DomainRIDs = @{OnlineRequired = $true } DomainAuthenticationPolicies = @{OnlineRequired = $true } DomainAuthenticationPolicySilos = @{OnlineRequired = $true } DomainCentralAccessPolicies = @{OnlineRequired = $true } DomainCentralAccessRules = @{OnlineRequired = $true } DomainClaimTransformPolicies = @{OnlineRequired = $true } DomainClaimTypes = @{OnlineRequired = $true } DomainFineGrainedPolicies = @{OnlineRequired = $true } DomainFineGrainedPoliciesUsers = @{OnlineRequired = $true } DomainFineGrainedPoliciesUsersExtended = @{OnlineRequired = $true } DomainGUIDS = @{OnlineRequired = $true } DomainDNSSRV = @{OnlineRequired = $true } DomainDNSA = @{OnlineRequired = $true } DomainInformation = @{OnlineRequired = $true } DomainControllers = @{OnlineRequired = $true } DomainFSMO = @{OnlineRequired = $true } DomainDefaultPasswordPolicy = @{OnlineRequired = $true } DomainGroupPolicies = @{OnlineRequired = $true } DomainGroupPoliciesDetails = @{OnlineRequired = $true } DomainGroupPoliciesACL = @{OnlineRequired = $true } DomainOrganizationalUnits = @{OnlineRequired = $true } DomainOrganizationalUnitsBasicACL = @{OnlineRequired = $true } DomainOrganizationalUnitsExtended = @{OnlineRequired = $true } DomainContainers = @{OnlineRequired = $true } DomainTrusts = @{OnlineRequired = $true } DomainGroupsFullList = @{OnlineRequired = $true } DomainGroups = @{OnlineRequired = $true } DomainGroupsMembers = @{OnlineRequired = $true } DomainGroupsMembersRecursive = @{OnlineRequired = $true } DomainGroupsSpecial = @{OnlineRequired = $true } DomainGroupsSpecialMembers = @{OnlineRequired = $true } DomainGroupsSpecialMembersRecursive = @{OnlineRequired = $true } DomainGroupsPriviliged = @{OnlineRequired = $true } DomainGroupsPriviligedMembers = @{OnlineRequired = $true } DomainGroupsPriviligedMembersRecursive = @{OnlineRequired = $true } DomainUsersFullList = @{OnlineRequired = $true } DomainUsers = @{OnlineRequired = $true } DomainUsersCount = @{OnlineRequired = $true } DomainUsersAll = @{OnlineRequired = $true } DomainUsersSystemAccounts = @{OnlineRequired = $true } DomainUsersNeverExpiring = @{OnlineRequired = $true } DomainUsersNeverExpiringInclDisabled = @{OnlineRequired = $true } DomainUsersExpiredInclDisabled = @{OnlineRequired = $true } DomainUsersExpiredExclDisabled = @{OnlineRequired = $true } DomainAdministrators = @{OnlineRequired = $true } DomainAdministratorsRecursive = @{OnlineRequired = $true } DomainEnterpriseAdministrators = @{OnlineRequired = $true } DomainEnterpriseAdministratorsRecursive = @{OnlineRequired = $true } DomainComputersFullList = @{OnlineRequired = $true } DomainComputersAll = @{OnlineRequired = $true } DomainComputersAllCount = @{OnlineRequired = $true } DomainComputers = @{OnlineRequired = $true } DomainComputersCount = @{OnlineRequired = $true } DomainServers = @{OnlineRequired = $true } DomainServersCount = @{OnlineRequired = $true } DomainComputersUnknown = @{OnlineRequired = $true } DomainComputersUnknownCount = @{OnlineRequired = $true } DomainPasswordDataUsers = @{OnlineRequired = $true } DomainPasswordDataPasswords = @{OnlineRequired = $true } DomainPasswordDataPasswordsHashes = @{OnlineRequired = $true } DomainPasswordClearTextPassword = @{OnlineRequired = $true } DomainPasswordClearTextPasswordEnabled = @{OnlineRequired = $true } DomainPasswordClearTextPasswordDisabled = @{OnlineRequired = $true } DomainPasswordLMHash = @{OnlineRequired = $true } DomainPasswordEmptyPassword = @{OnlineRequired = $true } DomainPasswordWeakPassword = @{OnlineRequired = $true } DomainPasswordWeakPasswordEnabled = @{OnlineRequired = $true } DomainPasswordWeakPasswordDisabled = @{OnlineRequired = $true } DomainPasswordWeakPasswordList = @{OnlineRequired = $true } DomainPasswordDefaultComputerPassword = @{OnlineRequired = $true } DomainPasswordPasswordNotRequired = @{OnlineRequired = $true } DomainPasswordPasswordNeverExpires = @{OnlineRequired = $true } DomainPasswordAESKeysMissing = @{OnlineRequired = $true } DomainPasswordPreAuthNotRequired = @{OnlineRequired = $true } DomainPasswordDESEncryptionOnly = @{OnlineRequired = $true } DomainPasswordDelegatableAdmins = @{OnlineRequired = $true } DomainPasswordDuplicatePasswordGroups = @{OnlineRequired = $true } DomainPasswordHashesWeakPassword = @{OnlineRequired = $true } DomainPasswordHashesWeakPasswordEnabled = @{OnlineRequired = $true } DomainPasswordHashesWeakPasswordDisabled = @{OnlineRequired = $true } DomainPasswordStats = @{OnlineRequired = $true } } $Script:Document = [ordered]@{Configuration = [ordered] @{Prettify = @{CompanyName = 'Evotec' UseBuiltinTemplate = $true CustomTemplatePath = '' Language = 'en-US' } Options = @{OpenDocument = $false OpenExcel = $false } DisplayConsole = @{ShowTime = $false LogFile = "$ENV:TEMP\PSWinDocumentationTesting.log" TimeFormat = 'yyyy-MM-dd HH:mm:ss' } Debug = @{Verbose = $false } } DocumentAD = [ordered] @{Enable = $true ExportWord = $true ExportExcel = $true FilePathWord = "$Env:USERPROFILE\Desktop\PSWinDocumentation-Report.docx" FilePathExcel = "$Env:USERPROFILE\Desktop\PSWinDocumentation-Report.xlsx" Sections = [ordered] @{SectionForest = [ordered] @{SectionTOC = [ordered] @{Use = $true TocGlobalDefinition = $true TocGlobalTitle = 'Table of content' TocGlobalRightTabPos = 15 PageBreaksAfter = 1 } SectionForestIntroduction = [ordered] @{Use = $true TocEnable = $True TocText = 'Scope' TocListLevel = 0 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' Text = "This document provides a low-level design of roles and permissions for" + " the IT infrastructure team at <CompanyName> organization. This document utilizes knowledge from" + " AD General Concept document that should be delivered with this document. Having all the information" + " described in attached document one can start designing Active Directory with those principles in mind." + " It's important to know while best practices that were described are important in decision making they" + " should not be treated as final and only solution. Most important aspect is to make sure company has full" + " usability of Active Directory and is happy with how it works. Making things harder just for the sake of" + " implementation of best practices isn't always the best way to go." TextAlignment = 'Both' PageBreaksAfter = 1 } SectionForestSummary = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Forest Summary' TocListLevel = 0 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' TableData = [PSWinDocumentation.ActiveDirectory]::ForestInformation TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = "Forest Summary" Text = "Active Directory at <CompanyName> has a forest name <ForestName>." + " Following table contains forest summary with important information:" ExcelExport = $true ExcelWorkSheet = 'Forest Summary' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestInformation } SectionForestFSMO = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::ForestFSMO TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = 'FSMO Roles' Text = 'Following table contains FSMO servers' EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = 'Forest FSMO' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestFSMO } SectionForestOptionalFeatures = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::ForestOptionalFeatures TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = 'Optional Features' Text = 'Following table contains optional forest features' TextNoData = "Following section should have table containing forest features. However no data was provided." EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = 'Forest Optional Features' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestOptionalFeatures } SectionForestUPNSuffixes = [ordered] @{Use = $true Text = "Following UPN suffixes were created in this forest:" TextNoData = "No UPN suffixes were created in this forest." ListType = 'Bulleted' ListData = [PSWinDocumentation.ActiveDirectory]::ForestUPNSuffixes EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = 'Forest UPN Suffixes' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestUPNSuffixes } SectionForesSPNSuffixes = [ordered] @{Use = $true Text = "Following SPN suffixes were created in this forest:" TextNoData = "No SPN suffixes were created in this forest." ListType = 'Bulleted' ListData = [PSWinDocumentation.ActiveDirectory]::ForestSPNSuffixes EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = 'Forest SPN Suffixes' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSPNSuffixes } SectionForestSites1 = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Sites' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' TableData = [PSWinDocumentation.ActiveDirectory]::ForestSites1 TableDesign = 'ColorfulGridAccent5' Text = "Forest Sites list can be found below" ExcelExport = $false ExcelWorkSheet = 'Forest Sites 1' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSites1 } SectionForestSites2 = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::ForestSites2 TableDesign = 'ColorfulGridAccent5' Text = "Forest Sites list can be found below" EmptyParagraphsBefore = 1 ExcelExport = $false ExcelWorkSheet = 'Forest Sites 2' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSites2 } SectionForestSites = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = 'Forest Sites' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSites } SectionForestSubnets1 = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Subnets' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' TableData = [PSWinDocumentation.ActiveDirectory]::ForestSubnets1 TableDesign = 'ColorfulGridAccent5' Text = "Table below contains information regarding relation between Subnets and sites" EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = 'Forest Subnets 1' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSubnets1 } SectionForestSubnets2 = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::ForestSubnets2 TableDesign = 'ColorfulGridAccent5' Text = "Table below contains information regarding relation between Subnets and sites" EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = 'Forest Subnets 2' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSubnets2 } SectionForestSiteLinks = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Site Links' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' TableData = [PSWinDocumentation.ActiveDirectory]::ForestSiteLinks TableDesign = 'ColorfulGridAccent5' Text = "Forest Site Links information is available in table below" ExcelExport = $true ExcelWorkSheet = 'Forest Site Links' ExcelData = [PSWinDocumentation.ActiveDirectory]::ForestSiteLinks } } SectionDomain = [ordered] @{SectionPageBreak = [ordered] @{Use = $True PageBreaksBefore = 1 } SectionDomainStarter = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Domain <Domain>' TocListLevel = 0 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' } SectionDomainIntroduction = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Domain Summary' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' Text = "Following domain exists within forest <ForestName>:" ListBuilderContent = "Domain <DomainDN>", 'Name for fully qualified domain name (FQDN): <Domain>', 'Name for NetBIOS: <DomainNetBios>' ListBuilderLevel = 0, 1, 1 ListBuilderType = 'Bulleted', 'Bulleted', 'Bulleted' EmptyParagraphsBefore = 0 } SectionDomainControllers = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Domain Controllers' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainControllers TableDesign = 'ColorfulGridAccent5' TableMaximumColumns = 8 Text = 'Following table contains domain controllers' TextNoData = '' ExcelExport = $true ExcelWorkSheet = '<Domain> - DCs' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainControllers } SectionDomainFSMO = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::DomainFSMO TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = "FSMO Roles for <Domain>" Text = "Following table contains FSMO servers with roles for domain <Domain>" EmptyParagraphsBefore = 1 ExcelExport = $true ExcelWorkSheet = '<Domain> - FSMO' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainFSMO } SectionDomainDefaultPasswordPolicy = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Password Policies' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainDefaultPasswordPolicy TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $True TableTitleText = "Default Password Policy for <Domain>" Text = 'Following table contains password policies for all users within <Domain>' ExcelExport = $true ExcelWorkSheet = '<Domain> - DefaultPasswordPolicy' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainDefaultPasswordPolicy } SectionDomainFineGrainedPolicies = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Fine Grained Password Policies' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPolicies TableDesign = 'ColorfulGridAccent5' TableMaximumColumns = 8 TableTitleMerge = $false TableTitleText = "Fine Grained Password Policy for <Domain>" Text = 'Following table contains fine grained password policies' TextNoData = "Following section should cover fine grained password policies. " + "There were no fine grained password polices defined in <Domain>. There was no formal requirement to have " + "them set up." ExcelExport = $true ExcelWorkSheet = '<Domain> - Password Policy (Grained)' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPolicies } SectionDomainGroupPolicies = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Group Policies' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainGroupPolicies TableDesign = 'ColorfulGridAccent5' Text = "Following table contains group policies for <Domain>" ExcelExport = $true ExcelWorkSheet = '<Domain> - GroupPolicies' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupPolicies } SectionDomainGroupPoliciesDetails = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Group Policies Details' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesDetails TableMaximumColumns = 6 TableDesign = 'ColorfulGridAccent5' Text = "Following table contains group policies for <Domain>" ExcelExport = $true ExcelWorkSheet = '<Domain> - GroupPolicies Details' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesDetails } SectionDomainGroupPoliciesACL = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - GroupPoliciesACL' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesACL } SectionDomainDNSSrv = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - DNS A/SRV Records' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainDNSSRV TableMaximumColumns = 10 TableDesign = 'ColorfulGridAccent5' Text = "Following table contains SRV records for Kerberos and LDAP" EmptyParagraphsAfter = 1 ExcelExport = $true ExcelWorkSheet = '<Domain> - DNSSRV' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainDNSSRV } SectionDomainDNSA = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::DomainDNSA TableMaximumColumns = 10 TableDesign = 'ColorfulGridAccent5' Text = "Following table contains A records for Kerberos and LDAP" ExcelExport = $true ExcelWorkSheet = '<Domain> - DNSA' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainDNSA } SectionDomainTrusts = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Trusts' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainTrusts TableMaximumColumns = 6 TableDesign = 'ColorfulGridAccent5' Text = "Following table contains trusts established with domains..." ExcelExport = $true ExcelWorkSheet = '<Domain> - DomainTrusts' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainTrusts } SectionDomainOrganizationalUnits = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Organizational Units' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnits TableDesign = 'ColorfulGridAccent5' TableMaximumColumns = 4 Text = "Following table contains all OU's created in <Domain>" ExcelExport = $true ExcelWorkSheet = '<Domain> - OrganizationalUnits' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnits } SectionDomainPriviligedGroup = [ordered] @{Use = $False TocEnable = $True TocText = 'General Information - Priviliged Groups' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged TableDesign = 'ColorfulGridAccent5' Text = 'Following table contains list of priviliged groups and count of the members in it.' ChartEnable = $True ChartTitle = 'Priviliged Group Members' ChartData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged ChartKeys = 'Group Name', 'Members Count' ChartValues = 'Members Count' ExcelExport = $true ExcelWorkSheet = '<Domain> - PriviligedGroupMembers' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged } SectionDomainUsers = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Domain Users in <Domain>' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' PageBreaksBefore = 1 Text = 'Following section covers users information for domain <Domain>. ' } SectionDomainUsersCount = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Users Count' TocListLevel = 2 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainUsersCount TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = 'Users Count' Text = "Following table and chart shows number of users in its categories" ChartEnable = $True ChartTitle = 'Users Count' ChartData = [PSWinDocumentation.ActiveDirectory]::DomainUsersCount ChartKeys = 'Keys' ChartValues = 'Values' ExcelExport = $true ExcelWorkSheet = '<Domain> - UsersCount' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersCount } SectionDomainAdministrators = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Domain Administrators' TocListLevel = 2 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainAdministratorsRecursive TableDesign = 'ColorfulGridAccent5' Text = 'Following users have highest priviliges and are able to control a lot of Windows resources.' ExcelExport = $true ExcelWorkSheet = '<Domain> - DomainAdministrators' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainAdministratorsRecursive } SectionEnterpriseAdministrators = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Enterprise Administrators' TocListLevel = 2 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministratorsRecursive TableDesign = 'ColorfulGridAccent5' Text = 'Following users have highest priviliges across Forest and are able to control a lot of Windows resources.' TextNoData = 'No Enterprise Administrators users were defined for this domain.' ExcelExport = $true ExcelWorkSheet = '<Domain> - EnterpriseAdministrators' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministratorsRecursive } SectionDomainComputers = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Computer Objects in <Domain>' TocListLevel = 1 TocListItemType = 'Numbered' TocHeadingType = 'Heading1' PageBreaksBefore = 1 Text = 'Following section covers computers information for domain <Domain>. ' } DomainComputers = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Computers' TocListLevel = 2 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainComputers TableDesign = 'ColorfulGridAccent5' Text = 'Following client computers are created in <Domain>.' ExcelExport = $true ExcelWorkSheet = '<Domain> - DomainComputers' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainComputers } DomainComputersCount = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::DomainComputersCount TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = 'Computers Count' Text = "Following table and chart shows number of computers and their versions" ChartEnable = $True ChartTitle = 'Computers Count' ChartData = [PSWinDocumentation.ActiveDirectory]::DomainComputersCount ChartKeys = 'System Name', 'System Count' ChartValues = 'System Count' ExcelExport = $true ExcelWorkSheet = '<Domain> - DomainComputersCount' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainComputersCount EmptyParagraphsBefore = 1 } DomainServers = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Servers' TocListLevel = 2 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainServers TableDesign = 'ColorfulGridAccent5' Text = 'Following client computers are created in <Domain>.' ExcelExport = $true ExcelWorkSheet = '<Domain> - DomainComputers' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainServers } DomainServersCount = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::DomainServersCount TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = 'Servers Count' Text = "Following table and chart shows number of servers and their versions" ChartEnable = $True ChartTitle = 'Servers Count' ChartData = [PSWinDocumentation.ActiveDirectory]::DomainServersCount ChartKeys = 'System Name', 'System Count' ChartValues = 'System Count' ExcelExport = $true ExcelWorkSheet = '<Domain> - DomainServersCount' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainServersCount EmptyParagraphsBefore = 1 } DomainComputersUnknown = [ordered] @{Use = $true TocEnable = $True TocText = 'General Information - Unknown Computer Objects' TocListLevel = 2 TocListItemType = 'Numbered' TocHeadingType = 'Heading2' TableData = [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown TableDesign = 'ColorfulGridAccent5' Text = 'Following client computers are not asisgned to clients or computers in <Domain>.' ExcelExport = $true ExcelWorkSheet = '<Domain> - ComputersUnknown' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown } DomainComputersUnknownCount = [ordered] @{Use = $true TableData = [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount TableDesign = 'ColorfulGridAccent5' TableTitleMerge = $true TableTitleText = 'Unknown Computers Count' Text = "Following table and chart shows number of unknown object computers in domain." ExcelExport = $false ExcelWorkSheet = '<Domain> - ComputersUnknownCount' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount EmptyParagraphsBefore = 1 } SectionExcelDomainOrganizationalUnitsBasicACL = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - OU ACL Basic' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsBasicACL } SectionExcelDomainOrganizationalUnitsExtended = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - OU ACL Extended' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsExtended } SectionExcelDomainUsers = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Users' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsers } SectionExcelDomainUsersAll = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Users All' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersAll } SectionExcelDomainUsersSystemAccounts = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Users System' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersSystemAccounts } SectionExcelDomainUsersNeverExpiring = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Never Expiring' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiring } SectionExcelDomainUsersNeverExpiringInclDisabled = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Never Expiring incl Disabled' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiringInclDisabled } SectionExcelDomainUsersExpiredInclDisabled = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Expired incl Disabled' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredInclDisabled } SectionExcelDomainUsersExpiredExclDisabled = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Expired excl Disabled' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredExclDisabled } SectionExcelDomainUsersFullList = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Users List Full' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainUsersFullList } SectionExcelDomainComputersFullList = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Computers List' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainComputersFullList } SectionExcelDomainGroupsFullList = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Groups List' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsFullList } SectionExcelDomainGroupsRest = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Groups' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroups } SectionExcelDomainGroupsSpecial = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Groups Special' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecial } SectionExcelDomainGroupsPriviliged = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Groups Priv' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged } SectionExcelDomainGroupMembers = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Members' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembers } SectionExcelDomainGroupMembersSpecial = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Members Special' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecialMembers } SectionExcelDomainGroupMembersPriviliged = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Members Priv' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembers } SectionExcelDomainGroupMembersRecursive = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Members Rec' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembersRecursive } SectionExcelDomainGroupMembersSpecialRecursive = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Members RecSpecial' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecialMembersRecursive } SectionExcelDomainGroupMembersPriviligedRecursive = [ordered] @{Use = $true ExcelExport = $true ExcelWorkSheet = '<Domain> - Members RecPriv' ExcelData = [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembersRecursive } } } } } $Script:O365SKU = @{"O365_BUSINESS_ESSENTIALS" = "Office 365 Business Essentials" "O365_BUSINESS_PREMIUM" = "Office 365 Business Premium" "DESKLESSPACK" = "Office 365 (Plan K1)" "DESKLESSWOFFPACK" = "Office 365 (Plan K2)" "LITEPACK" = "Office 365 (Plan P1)" "EXCHANGESTANDARD" = "Office 365 Exchange Online Only" "STANDARDPACK" = "Enterprise Plan E1" "STANDARDWOFFPACK" = "Office 365 (Plan E2)" "ENTERPRISEPACK" = "Enterprise Plan E3" "ENTERPRISEPACKLRG" = "Enterprise Plan E3" "ENTERPRISEWITHSCAL" = "Enterprise Plan E4" "STANDARDPACK_STUDENT" = "Office 365 (Plan A1) for Students" "STANDARDWOFFPACKPACK_STUDENT" = "Office 365 (Plan A2) for Students" "ENTERPRISEPACK_STUDENT" = "Office 365 (Plan A3) for Students" "ENTERPRISEWITHSCAL_STUDENT" = "Office 365 (Plan A4) for Students" "STANDARDPACK_FACULTY" = "Office 365 (Plan A1) for Faculty" "STANDARDWOFFPACKPACK_FACULTY" = "Office 365 (Plan A2) for Faculty" "ENTERPRISEPACK_FACULTY" = "Office 365 (Plan A3) for Faculty" "ENTERPRISEWITHSCAL_FACULTY" = "Office 365 (Plan A4) for Faculty" "ENTERPRISEPACK_B_PILOT" = "Office 365 (Enterprise Preview)" "STANDARD_B_PILOT" = "Office 365 (Small Business Preview)" "VISIOCLIENT" = "Visio Pro Online" "POWER_BI_ADDON" = "Office 365 Power BI Addon" "POWER_BI_INDIVIDUAL_USE" = "Power BI Individual User" "POWER_BI_STANDALONE" = "Power BI Stand Alone" "POWER_BI_STANDARD" = "Power-BI Standard" "PROJECTESSENTIALS" = "Project Lite" "PROJECTCLIENT" = "Project Professional" "PROJECTONLINE_PLAN_1" = "Project Online" "PROJECTONLINE_PLAN_2" = "Project Online and PRO" "ProjectPremium" = "Project Online Premium" "ECAL_SERVICES" = "ECAL" "EMS" = "Enterprise Mobility Suite" "RIGHTSMANAGEMENT_ADHOC" = "Windows Azure Rights Management" "MCOMEETADV" = "PSTN conferencing" "SHAREPOINTSTORAGE" = "SharePoint storage" "PLANNERSTANDALONE" = "Planner Standalone" "CRMIUR" = "CMRIUR" "BI_AZURE_P1" = "Power BI Reporting and Analytics" "INTUNE_A" = "Windows Intune Plan A" "PROJECTWORKMANAGEMENT" = "Office 365 Planner Preview" "ATP_ENTERPRISE" = "Exchange Online Advanced Threat Protection" "EQUIVIO_ANALYTICS" = "Office 365 Advanced eDiscovery" "AAD_BASIC" = "Azure Active Directory Basic" "RMS_S_ENTERPRISE" = "Azure Active Directory Rights Management" "AAD_PREMIUM" = "Azure Active Directory Premium" "MFA_PREMIUM" = "Azure Multi-Factor Authentication" "STANDARDPACK_GOV" = "Microsoft Office 365 (Plan G1) for Government" "STANDARDWOFFPACK_GOV" = "Microsoft Office 365 (Plan G2) for Government" "ENTERPRISEPACK_GOV" = "Microsoft Office 365 (Plan G3) for Government" "ENTERPRISEWITHSCAL_GOV" = "Microsoft Office 365 (Plan G4) for Government" "DESKLESSPACK_GOV" = "Microsoft Office 365 (Plan K1) for Government" "ESKLESSWOFFPACK_GOV" = "Microsoft Office 365 (Plan K2) for Government" "EXCHANGESTANDARD_GOV" = "Microsoft Office 365 Exchange Online (Plan 1) only for Government" "EXCHANGEENTERPRISE_GOV" = "Microsoft Office 365 Exchange Online (Plan 2) only for Government" "SHAREPOINTDESKLESS_GOV" = "SharePoint Online Kiosk" "EXCHANGE_S_DESKLESS_GOV" = "Exchange Kiosk" "RMS_S_ENTERPRISE_GOV" = "Windows Azure Active Directory Rights Management" "OFFICESUBSCRIPTION_GOV" = "Office ProPlus" "MCOSTANDARD_GOV" = "Lync Plan 2G" "SHAREPOINTWAC_GOV" = "Office Online for Government" "SHAREPOINTENTERPRISE_GOV" = "SharePoint Plan 2G" "EXCHANGE_S_ENTERPRISE_GOV" = "Exchange Plan 2G" "EXCHANGE_S_ARCHIVE_ADDON_GOV" = "Exchange Online Archiving" "EXCHANGE_S_DESKLESS" = "Exchange Online Kiosk" "SHAREPOINTDESKLESS" = "SharePoint Online Kiosk" "SHAREPOINTWAC" = "Office Online" "YAMMER_ENTERPRISE" = "Yammer for the Starship Enterprise" "EXCHANGE_L_STANDARD" = "Exchange Online (Plan 1)" "MCOLITE" = "Lync Online (Plan 1)" "SHAREPOINTLITE" = "SharePoint Online (Plan 1)" "OFFICE_PRO_PLUS_SUBSCRIPTION_SMBIZ" = "Office ProPlus" "EXCHANGE_S_STANDARD_MIDMARKET" = "Exchange Online (Plan 1)" "MCOSTANDARD_MIDMARKET" = "Lync Online (Plan 1)" "SHAREPOINTENTERPRISE_MIDMARKET" = "SharePoint Online (Plan 1)" "OFFICESUBSCRIPTION" = "Office ProPlus" "YAMMER_MIDSIZE" = "Yammer" "DYN365_ENTERPRISE_PLAN1" = "Dynamics 365 Customer Engagement Plan Enterprise Edition" "ENTERPRISEPREMIUM_NOPSTNCONF" = "Enterprise E5 (without Audio Conferencing)" "ENTERPRISEPREMIUM" = "Enterprise E5 (with Audio Conferencing)" "MCOSTANDARD" = "Skype for Business Online Standalone Plan 2" "PROJECT_MADEIRA_PREVIEW_IW_SKU" = "Dynamics 365 for Financials for IWs" "STANDARDWOFFPACK_IW_STUDENT" = "Office 365 Education for Students" "STANDARDWOFFPACK_IW_FACULTY" = "Office 365 Education for Faculty" "EOP_ENTERPRISE_FACULTY" = "Exchange Online Protection for Faculty" "EXCHANGESTANDARD_STUDENT" = "Exchange Online (Plan 1) for Students" "OFFICESUBSCRIPTION_STUDENT" = "Office ProPlus Student Benefit" "STANDARDWOFFPACK_FACULTY" = "Office 365 Education E1 for Faculty" "STANDARDWOFFPACK_STUDENT" = "Microsoft Office 365 (Plan A2) for Students" "DYN365_FINANCIALS_BUSINESS_SKU" = "Dynamics 365 for Financials Business Edition" "DYN365_FINANCIALS_TEAM_MEMBERS_SKU" = "Dynamics 365 for Team Members Business Edition" "FLOW_FREE" = "Microsoft Flow Free" "POWER_BI_PRO" = "Power BI Pro" "O365_BUSINESS" = "Office 365 Business" "DYN365_ENTERPRISE_SALES" = "Dynamics Office 365 Enterprise Sales" "RIGHTSMANAGEMENT" = "Rights Management" "PROJECTPROFESSIONAL" = "Project Professional" "VISIOONLINE_PLAN1" = "Visio Online Plan 1" "EXCHANGEENTERPRISE" = "Exchange Online Plan 2" "DYN365_ENTERPRISE_P1_IW" = "Dynamics 365 P1 Trial for Information Workers" "DYN365_ENTERPRISE_TEAM_MEMBERS" = "Dynamics 365 For Team Members Enterprise Edition" "CRMSTANDARD" = "Microsoft Dynamics CRM Online Professional" "EXCHANGEARCHIVE_ADDON" = "Exchange Online Archiving For Exchange Online" "EXCHANGEDESKLESS" = "Exchange Online Kiosk" "SPZA_IW" = "App Connect" "WINDOWS_STORE" = "Windows Store for Business" "MCOEV" = "Microsoft Phone System" "VIDEO_INTEROP" = "Polycom Skype Meeting Video Interop for Skype for Business" "SPE_E5" = "Microsoft 365 E5" "SPE_E3" = "Microsoft 365 E3" "ATA" = "Advanced Threat Analytics" "MCOPSTN2" = "Domestic and International Calling Plan" "FLOW_P1" = "Microsoft Flow Plan 1" "FLOW_P2" = "Microsoft Flow Plan 2" "POWERAPPS_VIRAL" = "Microsoft PowerApps Plan 2" } $Script:Services = @{OnPremises = [ordered] @{Credentials = [ordered] @{Username = '' Password = '' PasswordAsSecure = $true PasswordFromFile = $true } ActiveDirectory = [ordered] @{Use = $true OnlineMode = $true Import = @{Use = $false From = 'Folder' Path = "$Env:USERPROFILE\Desktop\PSWinDocumentation" } Export = @{Use = $false To = 'Folder' FolderPath = "$Env:USERPROFILE\Desktop\PSWinDocumentation" FilePath = "$Env:USERPROFILE\Desktop\PSWinDocumentation\PSWinDocumentation.xml" } Prefix = '' SessionName = 'ActiveDirectory' PasswordTests = @{Use = $false PasswordFilePathClearText = 'C:\Support\GitHub\PSWinDocumentation\Ignore\Passwords.txt' UseHashDB = $false PasswordFilePathHash = 'C:\Support\GitHub\PSWinDocumentation\Ignore\Passwords-Hashes.txt' } } } } $Script:ServicesAWS = @{Amazon = [ordered] @{Credentials = [ordered] @{AccessKey = '' SecretKey = '' Region = 'eu-west-1' } AWS = [ordered] @{Use = $true OnlineMode = $true Import = @{Use = $false From = 'Folder' Path = "$Env:USERPROFILE\Desktop\PSWinDocumentation" } Export = @{Use = $false To = 'Folder' FolderPath = "$Env:USERPROFILE\Desktop\PSWinDocumentation" FilePath = "$Env:USERPROFILE\Desktop\PSWinDocumentation\PSWinDocumentation.xml" } Prefix = '' SessionName = 'AWS' } } } $Script:ServicesO365 = @{Office365 = [ordered] @{Credentials = [ordered] @{Username = 'przemyslaw.klys@evotec.pl' Password = 'C:\Support\Important\Password-O365-Evotec.txt' PasswordAsSecure = $true PasswordFromFile = $true } Azure = [ordered] @{Use = $true OnlineMode = $true Import = @{Use = $false From = 'Folder' Path = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365Azure" } Export = @{Use = $false To = 'Folder' FolderPath = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365Azure" FilePath = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365Azure\PSWinDocumentation.xml" } ExportXML = $false FilePathXML = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365Azure.xml" Prefix = '' SessionName = 'O365Azure' } AzureAD = [ordered] @{Use = $true OnlineMode = $true Import = @{Use = $false From = 'Folder' Path = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365AzureAD" } Export = @{Use = $false To = 'Folder' FolderPath = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365AzureAD" FilePath = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365AzureAD\PSWinDocumentation.xml" } ExportXML = $false FilePathXML = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365AzureAD.xml" SessionName = 'O365AzureAD' Prefix = '' } ExchangeOnline = [ordered] @{Use = $true OnlineMode = $true Import = @{Use = $false From = 'Folder' Path = "$Env:USERPROFILE\Desktop\PSWinDocumentation" } Export = @{Use = $false To = 'Folder' FolderPath = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365ExchangeOnline" FilePath = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365ExchangeOnline\PSWinDocumentation.xml" } ExportXML = $false FilePathXML = "$Env:USERPROFILE\Desktop\PSWinDocumentation-O365ExchangeOnline.xml" Authentication = 'Basic' ConnectionURI = 'https://outlook.office365.com/powershell-liveid/' Prefix = 'O365' SessionName = 'O365Exchange' } } } $script:WriteParameters = @{ShowTime = $true LogFile = "" TimeFormat = "yyyy-MM-dd HH:mm:ss" } function Start-Documentation { [CmdletBinding()] param ([System.Collections.IDictionary] $Document) $TimeTotal = [System.Diagnostics.Stopwatch]::StartNew() Test-Configuration -Document $Document if ($Document.DocumentAD.Enable) { if ($null -eq $Document.DocumentAD.Services) { $Document.DocumentAD.Services = ($Script:Services).Clone() $Document.DocumentAD.Services.OnPremises.ActiveDirectory.PasswordTests = @{Use = $Document.DocumentAD.Configuration.PasswordTests.Use PasswordFilePathClearText = $Document.DocumentAD.Configuration.PasswordTests.PasswordFilePathClearText UseHashDB = $Document.DocumentAD.Configuration.PasswordTests.UseHashDB PasswordFilePathHash = $Document.DocumentAD.Configuration.PasswordTests.PasswordFilePathHash } } Start-DocumentationAD -Document $Document } if ($Document.DocumentAWS.Enable) { if ($null -eq $Document.DocumentAWS.Services) { $Document.DocumentAWS.Services = ($Script:ServicesAWS).Clone() $Document.DocumentAWS.Services.Amazon.Credentials.AccessKey = $Document.DocumentAWS.Configuration.AWSAccessKey $Document.DocumentAWS.Services.Amazon.Credentials.SecretKey = $Document.DocumentAWS.Configuration.AWSSecretKey $Document.DocumentAWS.Services.Amazon.Credentials.Region = $Document.DocumentAWS.Configuration.AWSRegion } Start-DocumentationAWS -Document $Document } if ($Document.DocumentOffice365.Enable) { if ($null -eq $Document.DocumentOffice365.Services) { $Document.DocumentOffice365.Services = ($Script:ServicesO365).Clone() $Document.DocumentOffice365.Services.Office365.Credentials = [ordered] @{Username = $Document.DocumentOffice365.Configuration.O365Username Password = $Document.DocumentOffice365.Configuration.O365Password PasswordAsSecure = $Document.DocumentOffice365.Configuration.O365PasswordAsSecure PasswordFromFile = $Document.DocumentOffice365.Configuration.O365PasswordFromFile } $Document.DocumentOffice365.Services.Office365.Azure.Use = $Document.DocumentOffice365.Configuration.O365AzureADUse $Document.DocumentOffice365.Services.Office365.Azure.Prefix = '' $Document.DocumentOffice365.Services.Office365.Azure.SessionName = 'O365Azure' $Document.DocumentOffice365.Services.Office365.AzureAD.Use = $Document.DocumentOffice365.Configuration.O365AzureADUse $Document.DocumentOffice365.Services.Office365.AzureAD.SessionName = 'O365AzureAD' $Document.DocumentOffice365.Services.Office365.AzureAD.Prefix = '' $Document.DocumentOffice365.Services.Office365.ExchangeOnline.Use = $Document.DocumentOffice365.Configuration.O365ExchangeUse $Document.DocumentOffice365.Services.Office365.ExchangeOnline.Authentication = $Document.DocumentOffice365.Configuration.O365ExchangeAuthentication $Document.DocumentOffice365.Services.Office365.ExchangeOnline.ConnectionURI = $Document.DocumentOffice365.Configuration.O365ExchangeURI $Document.DocumentOffice365.Services.Office365.ExchangeOnline.Prefix = '' $Document.DocumentOffice365.Services.Office365.ExchangeOnline.SessionName = $Document.DocumentOffice365.Configuration.O365ExchangeSessionName } Start-DocumentationO365 -Document $Document } $TimeTotal.Stop() Write-Verbose "Time total: $($TimeTotal.Elapsed)" } function Start-DocumentationAD { [CmdletBinding()] param([System.Collections.IDictionary] $Document) $TimeDataOnly = [System.Diagnostics.Stopwatch]::StartNew() $TypesRequired = Get-TypesRequired -Sections $Document.DocumentAD.Sections.SectionForest, $Document.DocumentAD.Sections.SectionDomain $DataInformationAD = Get-WinServiceData -Credentials $Document.DocumentAD.Services.OnPremises.Credentials -Service $Document.DocumentAD.Services.OnPremises.ActiveDirectory -TypesRequired $TypesRequired -Type 'ActiveDirectory' $TimeDataOnly.Stop() $TimeDocuments = [System.Diagnostics.Stopwatch]::StartNew() if ($Document.DocumentAD.ExportExcel -or $Document.DocumentAD.ExportWord -or $Document.DocumentAD.ExportSQL) { if ($Document.DocumentAD.ExportWord) { $WordDocument = Get-DocumentPath -Document $Document -FinalDocumentLocation $Document.DocumentAD.FilePathWord } if ($Document.DocumentAD.ExportExcel) { $ExcelDocument = New-ExcelDocument } $ADSectionsForest = Get-ObjectKeys -Object $Document.DocumentAD.Sections.SectionForest $ADSectionsDomain = Get-ObjectKeys -Object $Document.DocumentAD.Sections.SectionDomain foreach ($DataInformation in $DataInformationAD) { foreach ($Section in $ADSectionsForest) { $WordDocument = New-DataBlock -WordDocument $WordDocument -Section $Document.DocumentAD.Sections.SectionForest.$Section -Object $DataInformationAD -Excel $ExcelDocument -SectionName $Section -Sql $Document.DocumentAD.ExportSQL } foreach ($Domain in $DataInformationAD.FoundDomains.Keys) { foreach ($Section in $ADSectionsDomain) { $WordDocument = New-DataBlock -WordDocument $WordDocument -Section $Document.DocumentAD.Sections.SectionDomain.$Section -Object $DataInformationAD -Domain $Domain -Excel $ExcelDocument -SectionName $Section -Sql $Document.DocumentAD.ExportSQL } } } if ($Document.DocumentAD.ExportWord) { $FilePath = Save-WordDocument -WordDocument $WordDocument -Language $Document.Configuration.Prettify.Language -FilePath $Document.DocumentAD.FilePathWord -Supress $True -OpenDocument:$Document.Configuration.Options.OpenDocument } if ($Document.DocumentAD.ExportExcel) { $ExcelData = Save-ExcelDocument -ExcelDocument $ExcelDocument -FilePath $Document.DocumentAD.FilePathExcel -OpenWorkBook:$Document.Configuration.Options.OpenExcel } } $TimeDocuments.Stop() Write-Verbose "Time to gather data: $($TimeDataOnly.Elapsed)" Write-Verbose "Time to create documents: $($TimeDocuments.Elapsed)" } function Start-DocumentationAWS { [CmdletBinding()] param([System.Collections.IDictionary] $Document) $TimeDataOnly = [System.Diagnostics.Stopwatch]::StartNew() $DataSections = Get-ObjectKeys -Object $Document.DocumentAWS.Sections $TypesRequired = Get-TypesRequired -Sections $Document.DocumentAWS.Sections $DataInformation = Get-WinServiceData -Credentials $Document.DocumentAWS.Services.Amazon.Credentials -Service $Document.DocumentAWS.Services.Amazon.AWS -TypesRequired $TypesRequired -Type 'AWS' $TimeDataOnly.Stop() $TimeDocuments = [System.Diagnostics.Stopwatch]::StartNew() if ($DataInformation.Count -gt 0) { if ($Document.DocumentAWS.ExportWord) { $WordDocument = Get-DocumentPath -Document $Document -FinalDocumentLocation $Document.DocumentAWS.FilePathWord } if ($Document.DocumentAWS.ExportExcel) { $ExcelDocument = New-ExcelDocument } foreach ($Section in $DataSections) { $WordDocument = New-DataBlock -WordDocument $WordDocument -Section $Document.DocumentAWS.Sections.$Section -Forest $DataInformation -Excel $ExcelDocument -SectionName $Section -Sql $Document.DocumentAWS.ExportSQL } if ($Document.DocumentAWS.ExportWord) { $FilePath = Save-WordDocument -WordDocument $WordDocument -Language $Document.Configuration.Prettify.Language -FilePath $Document.DocumentAWS.FilePathWord -Supress $True -OpenDocument:$Document.Configuration.Options.OpenDocument } if ($Document.DocumentAWS.ExportExcel) { $ExcelData = Save-ExcelDocument -ExcelDocument $ExcelDocument -FilePath $Document.DocumentAWS.FilePathExcel -OpenWorkBook:$Document.Configuration.Options.OpenExcel } } else { Write-Warning "There was no data to process AWS documentation. Check configuration." } $TimeDocuments.Stop() Write-Verbose "Time to gather data: $($TimeDataOnly.Elapsed)" Write-Verbose "Time to create documents: $($TimeDocuments.Elapsed)" } function Start-DocumentationExchange { [CmdletBinding()] param([System.Collections.IDictionary] $Document) $DataSections = Get-ObjectKeys -Object $Document.DocumentExchange.Sections $TypesRequired = Get-TypesRequired -Sections $Document.DocumentExchange.Sections $TimeDataOnly = [System.Diagnostics.Stopwatch]::StartNew() $DataInformation = Get-WinServiceData -Credentials $Document.DocumentExchange.Services.OnPremises.Credentials -Service $Document.DocumentExchange.Services.OnPremises.Exchange -TypesRequired $TypesRequired -Type 'Exchange' $TimeDataOnly.Stop() $TimeDocuments = [System.Diagnostics.Stopwatch]::StartNew() if ($DataInformation.Count -gt 0) { if ($Document.DocumentExchange.ExportWord) { $WordDocument = Get-DocumentPath -Document $Document -FinalDocumentLocation $Document.DocumentExchange.FilePathWord } if ($Document.DocumentExchange.ExportExcel) { $ExcelDocument = New-ExcelDocument } foreach ($Section in $DataSections) { $WordDocument = New-DataBlock -WordDocument $WordDocument -Section $Document.DocumentExchange.Sections.$Section -Forest $DataInformation -Excel $ExcelDocument -SectionName $Section -Sql $Document.DocumentExchange.ExportSQL } if ($Document.DocumentExchange.ExportWord) { $FilePath = Save-WordDocument -WordDocument $WordDocument -Language $Document.Configuration.Prettify.Language -FilePath $Document.DocumentExchange.FilePathWord -Supress $True -OpenDocument:$Document.Configuration.Options.OpenDocument } if ($Document.DocumentExchange.ExportExcel) { $ExcelData = Save-ExcelDocument -ExcelDocument $ExcelDocument -FilePath $Document.DocumentExchange.FilePathExcel -OpenWorkBook:$Document.Configuration.Options.OpenExcel } } else { Write-Warning "There was no data to process Exchange documentation. Check configuration." } $TimeDocuments.Stop() Write-Verbose "Time to gather data: $($TimeDataOnly.Elapsed)" Write-Verbose "Time to create documents: $($TimeDocuments.Elapsed)" } function Start-DocumentationO365 { [CmdletBinding()] param([System.Collections.IDictionary] $Document) $TypesRequired = Get-TypesRequired -Sections $Document.DocumentOffice365.Sections $DataSections = Get-ObjectKeys -Object $Document.DocumentOffice365.Sections $TimeDataOnly = [System.Diagnostics.Stopwatch]::StartNew() $DataAzure = Get-WinServiceData -Credentials $Document.DocumentOffice365.Services.Office365.Credentials -Service $Document.DocumentOffice365.Services.Office365.Azure -TypesRequired $TypesRequired -Type 'Azure' $DataExchangeOnline = Get-WinServiceData -Credentials $Document.DocumentOffice365.Services.Office365.Credentials -Service $Document.DocumentOffice365.Services.Office365.ExchangeOnline -TypesRequired $TypesRequired -Type 'ExchangeOnline' $DataInformation = [ordered]@{ } if ($null -ne $DataAzure -and $DataExchangeOnline.Count -gt 0) { $DataInformation += $DataAzure } if ($null -ne $DataExchangeOnline -and $DataExchangeOnline.Count -gt 0) { $DataInformation += $DataExchangeOnline } $TimeDataOnly.Stop() $TimeDocuments = [System.Diagnostics.Stopwatch]::StartNew() if ($DataInformation.Count -gt 0) { if ($Document.DocumentOffice365.ExportWord) { $WordDocument = Get-DocumentPath -Document $Document -FinalDocumentLocation $Document.DocumentOffice365.FilePathWord } if ($Document.DocumentOffice365.ExportExcel) { $ExcelDocument = New-ExcelDocument } foreach ($Section in $DataSections) { $WordDocument = New-DataBlock -WordDocument $WordDocument -Section $Document.DocumentOffice365.Sections.$Section -Forest $DataInformation -Excel $ExcelDocument -SectionName $Section -Sql $Document.DocumentOffice365.ExportSQL } if ($Document.DocumentOffice365.ExportWord) { $FilePath = Save-WordDocument -WordDocument $WordDocument -Language $Document.Configuration.Prettify.Language -FilePath $Document.DocumentOffice365.FilePathWord -Supress $True -OpenDocument:$Document.Configuration.Options.OpenDocument } if ($Document.DocumentOffice365.ExportExcel) { $ExcelData = Save-ExcelDocument -ExcelDocument $ExcelDocument -FilePath $Document.DocumentOffice365.FilePathExcel -OpenWorkBook:$Document.Configuration.Options.OpenExcel } } else { Write-Warning "There was no data to process Office 365 documentation. Check configuration." } $TimeDocuments.Stop() Write-Verbose "Time to gather data: $($TimeDataOnly.Elapsed)" Write-Verbose "Time to create documents: $($TimeDocuments.Elapsed)" } function Test-Configuration { [CmdletBinding()] param ([System.Collections.IDictionary] $Document) [int] $ErrorCount = 0 $Script:WriteParameters = $Document.Configuration.DisplayConsole $Keys = Get-ObjectKeys -Object $Document -Ignore 'Configuration' foreach ($Key in $Keys) { $ErrorCount += Test-File -File $Document.$Key.FilePathWord -FileName 'FilePathWord' -Skip:(-not $Document.$Key.ExportWord) $ErrorCount += Test-File -File $Document.$Key.FilePathExcel -FileName 'FilePathExcel' -Skip:(-not $Document.$Key.ExportExcel) } if ($ErrorCount -ne 0) { Exit } } function Test-File { [CmdletBinding()] param ([string] $File, [string] $FileName, [switch] $Require, [switch] $Skip) [int] $ErrorCount = 0 if ($Skip) { return $ErrorCount } if ($File -ne '') { if ($Require) { if (Test-Path $File) { return $ErrorCount } else { Write-Color @Script:WriteParameters '[e] ', $FileName, " doesn't exists (", $File, "). It's required if you want to use this feature." -Color Red, Yellow, Yellow, White $ErrorCount++ } } } else { $ErrorCount++ Write-Color @Script:WriteParameters '[e] ', $FileName, " was empty. It's required if you want to use this feature." -Color Red, Yellow, White } return $ErrorCount } Export-ModuleMember -Function @('Start-Documentation') -Alias @() |