From 5fcc7763ba9af8dd628d944a09acade97627e0a6 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Sun, 5 Apr 2026 13:18:04 -0400 Subject: [PATCH 01/11] Refactor error handling messages in various report scripts to utilize translation functions for improved localization and clarity. Updated messages in Get-AbrADInfrastructureService.ps1, Get-AbrADKerberosAudit.ps1, Get-AbrADOU.ps1, Get-AbrADReportBrief.ps1, Get-AbrADSCCM.ps1, Get-AbrADSecurityAssessment.ps1, Get-AbrADSite.ps1, Get-AbrADSiteReplication.ps1, Get-AbrADTrust.ps1, Get-AbrDHCPinAD.ps1, Get-AbrDNSSection.ps1, Get-AbrDomainSection.ps1, and Invoke-DcDiag.ps1. --- .../Language/en-US/MicrosoftAD.psd1 | 279 +++++++++++++- .../Language/es-ES/MicrosoftAD.psd1 | 347 ++++++++++++++++-- .../Src/Private/Diagram/Get-AbrDiagrammer.ps1 | 8 +- .../Private/Report/Get-ADExchangeServer.ps1 | 2 +- .../Report/Get-AbrADAuthenticationPolicy.ps1 | 30 +- .../Src/Private/Report/Get-AbrADDCDiag.ps1 | 4 +- .../Private/Report/Get-AbrADDCRoleFeature.ps1 | 6 +- .../Src/Private/Report/Get-AbrADDFSHealth.ps1 | 16 +- .../Report/Get-AbrADDNSInfrastructure.ps1 | 30 +- .../Src/Private/Report/Get-AbrADDNSZone.ps1 | 38 +- .../Src/Private/Report/Get-AbrADDomain.ps1 | 4 +- .../Report/Get-AbrADDomainController.ps1 | 92 ++--- .../Report/Get-AbrADDomainLastBackup.ps1 | 4 +- .../Private/Report/Get-AbrADDomainObject.ps1 | 94 ++--- .../Report/Get-AbrADDuplicateObject.ps1 | 4 +- .../Private/Report/Get-AbrADDuplicateSPN.ps1 | 4 +- .../Src/Private/Report/Get-AbrADExchange.ps1 | 6 +- .../Src/Private/Report/Get-AbrADFSMO.ps1 | 8 +- .../Src/Private/Report/Get-AbrADForest.ps1 | 16 +- .../Src/Private/Report/Get-AbrADGPO.ps1 | 42 +-- .../Src/Private/Report/Get-AbrADHardening.ps1 | 4 +- .../Report/Get-AbrADInfrastructureService.ps1 | 6 +- .../Private/Report/Get-AbrADKerberosAudit.ps1 | 12 +- .../Src/Private/Report/Get-AbrADOU.ps1 | 8 +- .../Private/Report/Get-AbrADReportBrief.ps1 | 12 +- .../Src/Private/Report/Get-AbrADSCCM.ps1 | 6 +- .../Report/Get-AbrADSecurityAssessment.ps1 | 26 +- .../Src/Private/Report/Get-AbrADSite.ps1 | 84 ++--- .../Report/Get-AbrADSiteReplication.ps1 | 14 +- .../Src/Private/Report/Get-AbrADTrust.ps1 | 12 +- .../Src/Private/Report/Get-AbrDHCPinAD.ps1 | 6 +- .../Src/Private/Report/Get-AbrDNSSection.ps1 | 2 +- .../Private/Report/Get-AbrDomainSection.ps1 | 4 +- .../Src/Private/Report/Invoke-DcDiag.ps1 | 2 +- 34 files changed, 902 insertions(+), 330 deletions(-) diff --git a/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 b/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 index a0c3154..298b7bf 100644 --- a/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 +++ b/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 @@ -24,10 +24,10 @@ IncludeDomainsEnabled = - Include.Domains option enabled: Including only the following domains in the report: {0} ExcludeDomainsEnabled = - Including all child domains in the report except the following excluded domains: {0} GettingForestInfo = - Retrieving forest information {0}. - DiscoveringChildDomains = - Discovering child domains of the forest {0}: {1} + DiscoveringChildDomains = - Discovering child domains of the forest {0}: {1}. DCAvailable = - Initial configuration: A DC is available in the domain {0}. Adding domain to the report. DCUnavailable = - Unable to obtain an available DC in the domain {0}. Removing domain from the report. - FinishingDomainList = - Finalizing the list of domains in the forest {0}: {1} + FinishingDomainList = - Finalizing the list of domains in the forest {0}: {1}. WorkingOnForest = - Working on the Forest section. WorkingOnDomain = - Working on the Domain section. WorkingOnDNS = - Working on the DNS section. @@ -84,6 +84,12 @@ ScopeEnabled = Enabled (Summary) ScopeAdvanced = Enabled (Advanced Summary) ScopeDetailed = Enabled (Detailed) + ErrorReportOverview = Report Brief - Report Overview + ErrorForestSummary = Report Brief - Forest Summary + ErrorDomainSummaryItem = Report Brief - Domain Summary Item + ErrorDomainSummary = Report Brief - Domain Summary + ErrorReportScope = Report Brief - Report Scope + ErrorReportBriefSection = Report Brief Section '@ # Get-AbrForestSection @@ -150,6 +156,14 @@ RecycleBinBP = Accidental deletion of Active Directory objects is a common issue for AD DS users. Enabling the Recycle Bin feature allows for the recovery of these accidentally deleted objects, helping to maintain the integrity and continuity of the Active Directory environment. RecycleBinRef = https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/the-ad-recycle-bin-understanding-implementing-best-practices-and/ba-p/396944 CADiagram = Certificate Authority Diagram + TableName = Forest Summary + ErrorForestDiagramGraph = Forest Diagram Graph: + ErrorForestDiagramSection = Forest Diagram Section: + NoCARootInfo = No Certificate Authority Root information found in {0}, Disabling this section. + NoCAIssuerInfo = No Certificate Authority Issuer information found, Disabling this section. + ErrorCADiagramGraph = Certificate Authority Diagram Graph: + ErrorCADiagramSection = Certificate Authority Diagram Section: + NoOptionalFeatureInfo = No Optional Feature information found in {0}, Disabling this section. '@ NewADDiagram = ConvertFrom-StringData @' @@ -272,9 +286,11 @@ DnsName = DNS Name ServerRoles = Server Roles Version = Version + ErrorExchangeItem = Exchange Item + NoExchangeInfo = No Exchange Infrastructure information found in {0}, Disabling this section. + ErrorExchangeTable = Exchange Table + ErrorExchangeServerItem = ExchangeServer: [{0}]. '@ - - # Get-AbrADSCCM GetAbrADSCCM = ConvertFrom-StringData @' Collecting = Collecting AD SCCM information of {0}. Heading = SCCM Infrastructure @@ -284,6 +300,9 @@ ManagementPoint = Management Point SiteCode = Site Code Version = Version + ErrorSCCMItem = SCCM Item + NoSCCMInfo = No SCCM Infrastructure information found in {0}, Disabling this section. + ErrorSCCMTable = SCCM Table '@ # Get-AbrDHCPinAD @@ -297,6 +316,9 @@ Yes = Yes No = No Unknown = Unknown + ErrorDHCPItem = DHCP Item + NoDHCPInfo = No DHCP Infrastructure information found in {0}, Disabling this section. + ErrorDHCPTable = DHCP Table '@ # Get-AbrADSite @@ -383,6 +405,41 @@ StatusUnknown = Unknown StatusOffline = Offline SysvolBP = SYSVOL is a special directory that resides on each domain controller (DC) within a domain. The directory comprises folders that store Group Policy objects (GPOs) and logon scripts that clients need to access and synchronize between DCs. For these logon scripts and GPOs to function properly, SYSVOL should be replicated accurately and rapidly throughout the domain. Ensure that proper SYSVOL replication is in place to ensure identical GPO/SYSVOL content for the domain controller across all Active Directory domains. + ErrorReplicationDiagramGraph = Replication Diagram Graph: + ErrorReplicationDiagramSection = Replication Diagram Section: + ErrorDomainSite = Domain Site + ErrorSiteReplicationConnectionItem = Site Replication Connection Item + NoConnectionObjectsInfo = No Connection Objects information found in {0}, Disabling this section. + ErrorConnectionObjects = Connection Objects + ErrorSiteSubnets = Site Subnets + UnableToRead = Unable to read {0} on {1} + ErrorMissingSubnetPSSession = Missing Subnet in AD Section: New-PSSession: Unable to connect to {0}: {1} + ErrorMissingSubnetItemTable = Missing Subnet in AD Item table: + NoMissingSubnetsInfo = No Missing Subnets in AD information found in {0}, Disabling this section. + ErrorMissingSubnetItemSection = Missing Subnet in AD Item Section: + NoSiteSubnetsInfo = No Site Subnets information found in {0}, Disabling this section. + ErrorSiteTopologyDiagramGraph = Site Topology Diagram Graph: + ErrorSiteTopologyDiagramSection = Site Topology Diagram Section: + ErrorInterSiteTransports = Inter-Site Transports section + ErrorIPSiteLinksTable = IP Site Links table + NoIPSiteLinksInfo = No IP Site Links information found in {0}, Disabling this section. + ErrorIPSiteLinksSection = IP Site Links Section + ErrorIPSiteLinksBridgesTable = IP Site Links Bridges table + NoIPSiteLinksBridgesInfo = No IP Site Links Bridges information found in {0}, Disabling this section. + ErrorIP = IP + ErrorSMTPSiteLinksTable = SMTP Site Links table + ErrorSMTPSiteLinksSection = SMTP Site Links Section + ErrorSMTPSiteLinksBridgesTable = SMTP Site Links Bridges table + NoSMTPSiteLinksBridgesInfo = No SMTP Site Links Bridges information found in {0}, Disabling this section. + NoSMTPSiteLinksInfo = No SMTP Site Links information found in {0}, Disabling this section. + ErrorSMTP = SMTP + ErrorSysvolReplicationItemSection = Sysvol Replication Item Section: + UnableToCollect = Unable to collect information from {0}. + ErrorDNSIPConfigItem = DNS IP Configuration Item + NoSysvolReplicationInfo = No Sysvol Replication information found in {0}, Disabling this section. + ErrorSysvolReplicationTableSection = Sysvol Replication Table Section: + NoSitesInfo = No Sites information found in {0}, Disabling this section. + ErrorDomainSiteGlobal = Domain Site Global '@ # Get-AbrDNSSection @@ -396,6 +453,7 @@ DefinitionParagraph = The Domain Name System (DNS) is a hierarchical and decentralized naming system for computers, services, or other resources connected to the Internet or a private network. It associates various information with domain names assigned to each of the participating entities. Most prominently, it translates more readily memorized domain names to the numerical IP addresses needed for locating and identifying computer services and devices with the underlying network protocols. Paragraph = The following section provides a detailed overview of the DNS infrastructure configuration and settings within the Active Directory environment. NoCIMSession = DNS infrastructure configuration data requires a CIM session and could not be collected. Verify that WinRM and CIM connectivity to the domain controllers is available. + ErrorDNSInfo = Domain Name System Information '@ # Get-AbrADDNSInfrastructure @@ -457,6 +515,21 @@ ForwarderMinBP = For redundancy reasons, more than one forwarding server should be configured. RootHintsMissingCA = A default installation of the DNS server role should have root hints unless the server has a root zone - .(root). If the server has a root zone then delete it. If the server doesn't have a root zone and there are no root servers listed on the Root Hints tab of the DNS server properties then the server may be missing the cache.dns file in the %systemroot%\\system32\\dns directory, which is where the list of root servers is loaded from. RootHintsDuplicateCA = Duplicate IP Address found in the table of the DNS root hints servers. The DNS console does not show the duplicate Root Hint servers; you can only see them using the DNS PowerShell cmdlets. While there is a dnscmd utility to replace the Root Hints file, Using PowerShell is the best way to remediate this issue. + ErrorInfrastructureSummarySection = DNS Infrastructure Summary Section: + ErrorDirectoryPartitionsItemSection = Directory Partitions Item Section: + ErrorDirectoryPartitionsTableSection = Directory Partitions Table Section: + ErrorDirectoryPartitionsSection = Directory Partitions Section: + ErrorRRLItem = Response Rate Limiting (RRL) Item + ErrorRRLTable = Response Rate Limiting (RRL) Table + ErrorScavengingItem = Scavenging Item + ErrorScavengingTable = Scavenging Table + ErrorForwarderItem = Forwarder Item + ErrorForwarderTable = Forwarder Table + ErrorRootHintsTable = Root Hints Table + ErrorRootHintsSection = Root Hints Section + ErrorZoneScopeRecursionItem = Zone Scope Recursion Item + ErrorZoneScopeRecursionTable = Zone Scope Recursion Table + ErrorDNSInfrastructureSection = DNS Infrastructure Section '@ # Get-AbrADDNSZone @@ -499,6 +572,25 @@ BestPractice = Best Practices: ZoneTransferBP = Configure all DNS zones to allow zone transfers only from trusted IP addresses. This ensures that only authorized DNS servers can receive zone data, reducing the risk of unauthorized access or data leakage. It is a best practice to specify the IP addresses of the secondary DNS servers that are allowed to receive zone transfers. ZoneAgingBP = Microsoft recommends enabling aging/scavenging on all DNS servers. However, with AD-integrated zones, ensure DNS scavenging is enabled on only one DC at the main site. The results will be replicated to other DCs. + ErrorDNSZoneItem = Domain Name System Zone Item + NoDelegationInfo = DNS Zones {0} Section: No Zone Delegation information found, Disabling this section. + ErrorZoneDelegationItem = Zone Delegation Item + NoDelegationInfoDC = DNS Zones Section: No Zone Delegation information found in {0}, Disabling this section. + ErrorZoneDelegationTable = Zone Delegation Table + ErrorZoneTransferPSSession = DNS Zones Transfers Section: New-PSSession: Unable to connect to {0}: {1} + ErrorZoneTransfersItem = Zone Transfers Item + NoZoneTransferInfo = DNS Zones Section: No Zone Transfer information found in {0}, Disabling this section. + ErrorZoneTransfersTable = Zone Transfers Table + ErrorReverseLookupZoneItem = Reverse Lookup Zone Configuration Item + NoReverseLookupZoneInfo = DNS Zones Section: No Reverse lookup zone information found in {0}, Disabling this section. + ErrorReverseLookupZoneTable = Reverse Lookup Zone Configuration Table + ErrorConditionalForwarderItem = Conditional Forwarder Item + NoConditionalForwarderInfo = DNS Zones Section: No Conditional forwarder zone information found in {0}, Disabling this section. + ErrorConditionalForwarderTable = Conditional Forwarder Table + ErrorZoneScopeAgingItem = Zone Scope Aging Item + NoZoneAgingInfo = DNS Zones Section: No Zone Aging property information found in {0}, Disabling this section. + ErrorZoneScopeAgingTable = Zone Scope Aging Table + ErrorGlobalDNSZoneInfo = Global DNS Zone Information '@ # Get-AbrPKISection @@ -516,6 +608,7 @@ # Get-AbrDomainSection GetAbrDomainSection = ConvertFrom-StringData @' Collecting = Collecting Domain information from {0}. + CollectingDomain = Collecting Domain information from {0}. Paragraph = This section provides an overview of the Active Directory domain configuration, including key settings and operational details. SectionTitle = AD Domain Configuration DefinitionText = An Active Directory domain is a collection of objects within a Microsoft Active Directory network. An object can be a single user, a group, or a hardware component such as a computer or printer. Each domain holds a database containing object identity information. Active Directory domains can be identified using a DNS name, which can be the same as an organization's public domain name, a sub-domain, or an alternate version (which may end in .local). @@ -539,6 +632,7 @@ ReplicationParagraph = The following section provides an overview of Active Directory replication connections and status between domain controllers in this domain. GPOSection = Group Policy GPOParagraph = The following section provides an overview of the Group Policy Objects (GPOs) configured and applied within this domain. + ErrorADDomain = Active Directory Domain '@ # Get-AbrADDomain @@ -570,6 +664,8 @@ Reference = Reference: RIDBestPractice = The RID Issued percentage exceeds 80%. It is recommended to evaluate the utilization of RIDs to prevent potential exhaustion and ensure the stability of the domain. The Relative Identifier (RID) is a crucial component in the SID (Security Identifier) for objects within the domain. Exhaustion of the RID pool can lead to the inability to create new security principals, such as user or computer accounts. Regular monitoring and proactive management of the RID pool are essential to maintain domain health and avoid disruptions. RIDReference = https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/managing-rid-pool-depletion/ba-p/399736 + TableName = Domain Summary + ErrorSection = AD Domain Summary Section: '@ # Get-AbrADFSMO @@ -586,6 +682,9 @@ Reference = Reference: InfraMasterBP = The infrastructure master role in the domain {0} should be held by a domain controller that is not a global catalog server. The infrastructure master is responsible for updating references from objects in its domain to objects in other domains. If the infrastructure master runs on a global catalog server, it will not function properly because the global catalog holds a partial replica of every object in the forest, and it will not update the references. This issue does not affect forests that have a single domain. InfraMasterRef = http://go.microsoft.com/fwlink/?LinkId=168841 + TableName = FSMO Roles + ErrorFSMOItem = Flexible Single Master Operations + ErrorPSSession = FSMO Roles Section: New-PSSession: Unable to connect to {0}: {1} '@ # Get-AbrADTrust @@ -627,6 +726,12 @@ BestPractice = Best Practice: AESBP = Ensure that AES Kerberos encryption is enabled on all Active Directory trusts. RC4 encryption is considered weak and vulnerable to various attacks. Enabling AES encryption on trusts enhances Kerberos security and aligns with modern security standards. Reference: https://techcommunity.microsoft.com/t5/itops-talk-blog/tough-questions-answered-can-i-disable-rc4-etype-for-kerberos-on/ba-p/382718 TrustDiagramSection = Domain and Trusts Diagram + ErrorTrustItem = Trust Item + ErrorTrustDiagramGraph = Domain and Trusts Diagram Graph: + ErrorTrustDiagramSection = Domain and Trusts Diagram Section: + NoTrustInfo = No Domain Trust information found in {0}, Disabling this section. + ErrorTrustTable = Trust Table + ErrorTrustSection = Trust Section '@ # Get-AbrADAuthenticationPolicy @@ -660,6 +765,20 @@ ServiceTGTLifetime = Service TGT Lifetime (mins) ComputerTGTLifetime = Computer TGT Lifetime (mins) PolicyBP = Authentication Policies should be set to Enforce mode to actively restrict Kerberos TGT lifetimes and account sign-in. Policies in audit mode only log events without enforcing restrictions. + ErrorSiloItem = Authentication Policy Silo Item + SiloTableName = Authentication Policy Silo + SilosTableName = Authentication Policy Silos + ErrorSiloMemberItem = Authentication Policy Silo Member Item + SiloMembersTableName = Authentication Policy Silo Members + ErrorSiloMembersTable = Authentication Policy Silo Members Table + ErrorSilosSectionA = Authentication Policy Silos Section + NoSiloInfo = No Authentication Policy Silo information found in {0}, Disabling this section. + ErrorPolicyItem = Authentication Policy Item + PolicyTableName = Authentication Policy + PoliciesTableName = Authentication Policies + ErrorPoliciesSection = Authentication Policies Section + NoPolicyInfo = No Authentication Policy information found in {0}, Disabling this section. + NoAuthPolicyOrSiloInfo = No Authentication Policy or Silo information found in {0}, Disabling this section. '@ # Get-AbrADDomainObject @@ -829,6 +948,45 @@ GMSAInactiveBP = *Regularly check for and remove inactive group managed service accounts from Active Directory. Inactive accounts can pose a security risk as they may be exploited by malicious actors. Ensuring that only active and necessary accounts exist helps maintain a secure environment and reduces the risk of unauthorized access or privilege escalation. GMSANoHostComputersBP = **No 'Host Computers' has been defined; please validate that the gMSA is currently in use. If not, it is recommended to remove these unused resources from Active Directory. GMSANoRetrieveManagedPasswordBP = ***No 'Retrieve Managed Password' has been defined; please validate that the gMSA is currently in use. If not, it is recommended to remove these unused resources from Active Directory. + PrivilegedGroupMembersTableName = Privileged Group Members: + GMSATableName = gMSA + MembersLabel = Members + TypeLabelUser = USER + TypeLabelComputer = COMPUTER + TypeLabelGroup = GROUP + TypeLabelFSP = FOREIGN SECURITY PRINCIPAL + ErrorDomainObjectStats = Domain Object Stats + ErrorUserObjectCountChart = User Object Count Chart + ErrorStatusOfUserAccounts = Status of User Accounts + ErrorStatusOfUsersAccountsChart = Status of Users Accounts Chart + ErrorUsersObjectsTable = Users Objects Table + ErrorUsersObjectsSection = Users Objects Section + ErrorGroupCategoryObjectChart = Group Category Object Chart + ErrorGroupScopesObjectChart = Group Scopes Object Chart + ErrorGroupsObjectsTable = Groups Objects Table + ErrorGroupsObjectsSection = Groups Objects Section + ErrorPrivilegedGroup = Privileged Group in Active Directory + ErrorPrivilegedGroupNonDefaultTable = Privileged Group (Non-Default) Table + ErrorPrivilegedGroupNonDefaultSection = Privileged Group (Non-Default) Section + ErrorEmptyGroupsObjectsTable = Empty Groups Objects Table + ErrorEmptyGroupsObjectsSection = Empty Groups Objects Section + ErrorCircularGroupMembershipTable = Circular Group Membership Table + ErrorCircularGroupMembershipSection = Circular Group Membership Section + ErrorPreWin2000 = Pre-Windows 2000 Compatible Access + ErrorComputersObjectCountChart = Computers Object Count Chart + ErrorStatusOfComputerAccounts = Status of Computer Accounts + ErrorStatusOfComputersAccountsChart = Status of Computers Accounts Chart + ErrorOperatingSystemsInAD = Operating Systems in Active Directory + ErrorComputersPasswordNotRequired = Computers with Password-Not-Required + ErrorComputersObjectsTable = Computers Objects Table + ErrorComputersObjectsSection = Computers Objects Section + ErrorDefaultDomainPasswordPolicy = Default Domain Password Policy + ErrorFGPP = Fine Grained Password Policies + ErrorWindowsLAPS = Windows LAPS + ErrorGMSAItem = Group Managed Service Accounts Item + ErrorGMSASection = Group Managed Service Accounts Section + ErrorFSPItem = Foreign Security Principals Item + ErrorFSPSection = Foreign Security Principals Section '@ # Get-AbrADHardening @@ -872,6 +1030,8 @@ LDAPSigningBP = LDAP signing enforcement is not configured on this domain controller. LDAP signing is a security feature that protects the integrity and confidentiality of LDAP communications by requiring data signing. Configure LDAP signing to require signing on all domain controllers. LDAPCBBindingBP = LDAP channel binding enforcement is not configured on this domain controller. LDAP channel binding is a security feature that protects against man-in-the-middle attacks by binding the LDAP session to the TLS channel, ensuring the authenticity and integrity of LDAP communications. Configure LDAP channel binding on all domain controllers. NTLMv1BP = NTLMv1 authentication is enabled on this domain controller. NTLMv1 is an outdated authentication protocol that is vulnerable to credential capture and relay attacks. Disable NTLMv1 on all systems; it has been superseded by NTLMv2, which offers significantly improved security protections. + ErrorADHardeningItem = ADHardening Item + ErrorADHardeningSection = ADHardening Section '@ # Get-AbrADDomainLastBackup @@ -890,6 +1050,8 @@ BackupBP1 = Ensure there is a recent (<180 days) Active Directory backup. BackupBP2 = Regular backups are crucial for disaster recovery and maintaining the integrity of your Active Directory environment. BackupBP3 = Consider setting up automated backup schedules and regularly verifying the backup status to prevent data loss. + ErrorDomainLastBackupItem = Domain Last Backup Item + ErrorDomainLastBackupTable = Domain Last Backup Table '@ # Get-AbrADDuplicateSPN @@ -905,6 +1067,8 @@ HealthCheck = Health Check: CorrectiveActions = Corrective Actions: SPNBP = Ensure there aren't any duplicate SPNs (other than krbtgt). Duplicate SPNs can cause authentication issues and should be resolved promptly. Use the `setspn -X` command to identify duplicate SPNs. Remove or reassign duplicate SPNs as necessary to maintain a healthy AD environment. + ErrorSPNItem = SPN Item + ErrorSPNTable = SPN Table '@ # Get-AbrADDuplicateObject @@ -921,6 +1085,8 @@ HealthCheck = Health Check: CorrectiveActions = Corrective Actions: DuplicateObjectBP = Ensure there are no duplicate objects in Active Directory. Duplicate objects can cause various issues such as authentication problems, replication conflicts, and administrative overhead. It is recommended to regularly audit and clean up any duplicate objects to maintain a healthy and efficient Active Directory environment. + ErrorDuplicateObjectItem = Duplicate Object Item + ErrorDuplicateObjectTable = Duplicate Object Table '@ # Get-AbrADDCRoleFeature @@ -933,6 +1099,9 @@ HealthCheck = Health Check: BestPractices = Best Practices: RoleBP = Domain Controllers should have limited software and agents installed including roles and services. Non-essential code running on Domain Controllers is a risk to the enterprise Active Directory environment. A Domain Controller should only run required software, services and roles critical to essential operation. + ErrorPSSession = Roles Section: New-PSSession: Unable to connect to {0}: {1} + ErrorRoleFeatureSection = Roles {0} Section: + ErrorRolesSection = Roles Section: '@ # Get-AbrADDCDiag @@ -944,6 +1113,9 @@ Description = Description TableName = DCDiag Test Status NoData = No DCDiag information found in {0}, Disabling this section. + ErrorDCDiagTestSection = Active Directory DCDiag {0} Section: + ErrorDCDiagSection = Active Directory DCDiag Section: + ErrorInvokeDcDiag = Invoke-DcDiag - Failed to get DCDiag for {0} with error: '@ # Get-AbrADInfrastructureService @@ -958,6 +1130,9 @@ CorrectiveActions = Corrective Actions: SpoolerBP = The Print Spooler service has known vulnerabilities that can be exploited by attackers to gain unauthorized access or execute malicious code. Disabling this service on Domain Controllers and other critical servers that do not require print services can reduce the attack surface and improve the overall security posture of your Active Directory environment. DHCPServerBP = Per security best practices, DHCP Server services should run on a dedicated server separate from domain controllers to minimize security risks, reduce resource contention, and ensure optimal performance of both DHCP and Active Directory services. + ErrorPSSession = Domain Controller Infrastructure Services Section: New-PSSession: Unable to connect to {0}: {1} + ErrorDCInfraServicesItem = Domain Controller Infrastructure Services Item + ErrorDCInfraServicesTable = Domain Controller Infrastructure Services Table '@ # Get-AbrADDFSHealth @@ -992,6 +1167,14 @@ ContentCorrectiveActions = Corrective Actions: ContentSysvolBP = Review the files and extensions listed above and ensure they are necessary for the operation of your domain. Remove any files that are not required or that appear suspicious. Regularly monitor the Sysvol folder to maintain a healthy and secure Active Directory environment. ContentNetlogonBP = Review the files and extensions listed above and ensure they are necessary for the operation of your domain. Remove any files that are not required or that appear suspicious. Regularly monitor the Netlogon folder to maintain a healthy and secure Active Directory environment. + ErrorSysvolReplicationStatusItemSection = Sysvol Replication Status Item Section: + ErrorSysvolReplicationStatusTableSection = Sysvol Replication Status Table Section: + ErrorSysvolContentPSSession = Sysvol Content Status Section: New-PSSession: Unable to connect to {0}: {1} + ErrorSysvolHealthSection = Sysvol Health {0} Section: + ErrorSysvolHealthTableSection = Sysvol Health Table Section: + ErrorNetlogonContentPSSession = Netlogon Content Status Section: New-PSSession: Unable to connect to {0}: {1} + ErrorNetlogonHealthSection = Netlogon Health {0} Section: + ErrorNetlogonContentStatusSection = Netlogon Content Status Section: '@ # Get-AbrADKerberosAudit @@ -1023,6 +1206,10 @@ AdminHealthCheck = Health Check: AdminBestPractice = Best Practice: AdminBP = Microsoft recommends using a unique, complex password for the built-in Administrator account and rotating it regularly (at least every 90 days). Consider renaming the account and disabling it when not actively in use to reduce the risk of brute-force or credential-stuffing attacks targeting this well-known account. + ErrorUnconstrainedKerberosItem = Unconstrained Kerberos delegation + ErrorKRBTGTAccountItem = KRBTGT account Item + ErrorAdminAccountItem = ADMIN account Item + ErrorUnconstrainedKerberosSection = Unconstrained Kerberos delegation Section '@ # Get-AbrADSiteReplication @@ -1055,6 +1242,15 @@ ReplicationStatusBestPractices = Best Practices: ReplicationStatusBP = Replication failures can lead to object inconsistencies, stale credentials, Group Policy application failures, and authentication issues across the environment. Investigate and resolve any replication errors promptly using tools such as repadmin /showrepl or the Active Directory Replication Status Tool to prevent further divergence between domain controllers. AutoGeneratedValue = + ErrorSiteReplicationConnectionItem = Site Replication Connection Item + ErrorSiteReplicationConnectionSection = Site Replication Connection Section + SiteLabel = Site: + FromLabel = From: + ToLabel = To: + ErrorReplicationConnection = Replication Connection + ErrorPSSession = Replication Status Section: New-PSSession: Unable to connect to {0}: {1} + ErrorReplicationStatus = Replication Status + ErrorSiteReplicationStatus = Site Replication Status '@ # Get-AbrADOU @@ -1079,6 +1275,10 @@ GPOBlockedHealthCheck = Health Check: GPOBlockedCorrectiveActions = Corrective Actions: GPOBlockedBP = Review the use of enforced policies and blocked policy inheritance in Active Directory. Enforced policies ensure that specific Group Policy Objects (GPOs) are applied and cannot be overridden by other GPOs. Blocked policy inheritance prevents GPOs from parent containers from being applied to the Organizational Unit (OU). While these settings can be useful for maintaining strict policy application, they can also lead to unexpected results and complicate troubleshooting. Ensure that the use of these settings aligns with your organization's policy management strategy and does not inadvertently cause issues. + ErrorOUItem = Organizational Unit Item + ErrorBlockedInheritanceGPOItem = Blocked Inheritance GPO Item + ErrorBlockedInheritanceGPOSection = Blocked Inheritance GPO Section + ErrorOUSection = Organizational Unit Section '@ # Get-AbrADSecurityAssessment @@ -1135,6 +1335,19 @@ PrivilegedUsersReference = Reference: PrivilegedUsersReferenceURL = https://www.stigviewer.com/stig/active_directory_domain/2017-12-15/finding/V-36435 ServiceAccountsAdminCountNote = ** Attackers are most interested in Service Accounts that are members of highly privileged groups like Domain Admins. A quick way to check for this is to enumerate all user accounts with the attribute AdminCount equal to 1. This means an attacker may just ask Active Directory for all user accounts with an SPN and with AdminCount=1. Ensure that there are no privileged accounts that have SPNs assigned to them. + ErrorAccountSecurityAssessmentItem = Account Security Assessment Item + ErrorUserAccountSecurityAssessmentChart = User Account Security Assessment Chart + NoUserInfo = No Domain users information found in {0}, Disabling this section. + ErrorAccountSecurityAssessmentTable = Account Security Assessment Table + ErrorPrivilegedUsersAssessmentItem = Privileged Users Assessment Item + NoPrivilegedUserInfo = No Privileged User Assessment information found in {0}, Disabling this section. + ErrorPrivilegedUsersTable = Privileged Users Table + ErrorInactivePrivilegedAccountsItem = Inactive Privileged Accounts Item + NoInactivePrivilegedInfo = No Inactive Privileged Accounts information found in {0}, Disabling this section. + ErrorInactivePrivilegedAccountsTable = Inactive Privileged Accounts Table + ErrorServiceAccountsAssessmentItem = Service Accounts Assessment Item + NoServiceAccountsInfo = No Service Accounts Assessment information found in {0}, Disabling this section. + ErrorServiceAccountsAssessmentTable = Service Accounts Assessment Table '@ # Get-AbrADGPO @@ -1232,6 +1445,23 @@ GPOSettingsParagraph = The following section provides details about Group Policy configuration resources, including WMI filters, the Central Store repository, and scripts attached to GPOs. GPOHealthTitle = GPO Health GPOHealthParagraph = The following section highlights Group Policy Objects that may require attention, including unlinked, empty, enforced, and orphaned GPOs. + ErrorGPOItem = Group Policy Objects + ErrorWMIFiltersItem = WMI Filters + ErrorWMIFiltersPSSession = WMI Filters Section: New-PSSession: Unable to connect to {0}: {1} + ErrorGPOCentralStore = GPO Central Store + ErrorGPOLogonLogoffItem = GPO with Logon/Logoff Script Item + ErrorGPOLogonLogoffSection = GPO with Logon/Logoff Script Section + ErrorGPOStartupShutdownItem = GPO with Computer Startup/Shutdown Item + ErrorGPOStartupShutdownSection = GPO with Computer Startup/Shutdown Section + ErrorUnlinkedGPOItem = Unlinked Group Policy Objects Item + ErrorUnlinkedGPOSection = Unlinked Group Policy Objects Section + ErrorEmptyGPOItem = Empty Group Policy Objects Item + ErrorEmptyGPOSection = Empty Group Policy Objects Section + ErrorEnforcedGPOItem = Enforced Group Policy Objects Item + ErrorEnforcedGPOTable = Enforced Group Policy Objects Table + ErrorOrphanedGPOPSSession = Orphaned GPO Section: New-PSSession: Unable to connect to {0}: {1} + ErrorOrphanedGPOItem = Orphaned GPO + ErrorGPOSection = Group Policy Objects Section '@ # Get-AbrADDomainController GetAbrADDomainController = ConvertFrom-StringData @' @@ -1347,6 +1577,47 @@ MissingUpdatesParagraph = The following table provides a summary of pending or missing Windows updates detected on Domain Controllers in the {0} domain. MissingUpdatesBestPractice = It is critical to install security updates to protect your systems from malicious attacks. Regularly applying updates ensures that your systems are safeguarded against newly discovered vulnerabilities. Additionally, installing software updates provides access to new features and improvements, enhancing overall system performance and stability. Neglecting updates can leave your systems exposed to potential threats and exploitation. Therefore, it is in your best interest to maintain an up-to-date environment by promptly installing all recommended updates. DCObjectChart = Domain Controller Object - Chart + ErrorNetworkInterfacesInfo = Unable to get {0} network interfaces information + ErrorDCNetSettingsPSSession = DC Net Settings Section: New-PSSession: Unable to connect to {0}: {1} + ErrorDCItem = Domain Controller Item + UnableToCollect = Unable to collect information from {0}. + ErrorDCTable = Domain Controller Table + ErrorGeneralInfoSection = General Information Section + ErrorPartitionsSection = Partitions Section + ErrorNetworkingSettingsSection = Networking Settings Section + ErrorHardwareInventoryTable = Hardware Inventory Table + ErrorDCHardwareSection = Domain Controller Hardware Section + ErrorDCSection = Domain Controller Section + ErrorDNSIPConfigPSSession = DNS IP Configuration Section: New-PSSession: Unable to connect to {0}: {1} + ErrorDNSIPConfigTableSection = Domain Controller DNS IP Configuration Table Section: + ErrorDNSIPConfigItem = DNS IP Configuration Item + ErrorDNSIPConfigSection = Domain Controller DNS IP Configuration Section: + ErrorNTDSPSSession = NTDS Section: New-PSSession: Unable to connect to {0}: {1} + ErrorNTDSItem = NTDS Item + ErrorNTDSSection = NTDS section + ErrorTimeSourcePSSession = Time Source Section: New-PSSession: Unable to connect to {0}: {1} + ErrorTimeSourceItem = Time Source Item + ErrorTimeSourceTable = Time Source Table + ErrorTimeSource = Time Source + ErrorSRVRecordsStatusItem = SRV Records Status Item + ErrorSRVRecordsStatusTable = SRV Records Status Table + ErrorSRVRecordsStatus = SRV Records Status + ErrorFileSharesPSSession = Domain Controllers File Shares Section: New-PSSession: Unable to connect to {0}: {1} + ErrorFileSharesItem = File Shares Item + ErrorFileSharesTable = File Shares Table + ErrorInstalledSoftwarePSSession = Domain Controller Installed Software Section: New-PSSession: Unable to connect to {0}: {1} + ErrorInstalledSoftwareTable = Installed Software Table + ErrorInstalledSoftwareSection = Installed Software Section + ErrorMissingPatchPSSession = Domain Controller Pending Missing Patch Section: New-PSSession: Unable to connect to {0}: {1} + ErrorMissingPatchTable = Installed Software Table + ErrorMissingPatchSection = Domain Controller Section +'@ + + # Get-AbrDiagrammer + GetAbrDiagrammer = ConvertFrom-StringData @' + GettingDiagram = Getting {0} diagram from {1}. + ErrorExportDiagram = Unable to export the {0} Diagram: + ErrorGetDiagram = Unable to get the {0} Diagram: '@ } \ No newline at end of file diff --git a/AsBuiltReport.Microsoft.AD/Language/es-ES/MicrosoftAD.psd1 b/AsBuiltReport.Microsoft.AD/Language/es-ES/MicrosoftAD.psd1 index bae0268..8e9ceb4 100644 --- a/AsBuiltReport.Microsoft.AD/Language/es-ES/MicrosoftAD.psd1 +++ b/AsBuiltReport.Microsoft.AD/Language/es-ES/MicrosoftAD.psd1 @@ -2,17 +2,45 @@ @{ # InvokeAsBuiltReportMicrosoftAD InvokeAsBuiltReportMicrosoftAD = ConvertFrom-StringData @' - PwshISE = Este script no se puede ejecutar dentro del ISE de PowerShell. Por favor, ejecútalo desde la ventana de comandos de PowerShell. + PwshISE = Este script no se puede ejecutar dentro de PowerShell ISE. Por favor, ejecútalo desde la ventana de comandos de PowerShell. ReportModuleInfo3 = - Documentación: https://github.com/AsBuiltReport/AsBuiltReport.{0} ReportModuleInfo2 = - Informes de problemas o errores: https://github.com/AsBuiltReport/AsBuiltReport.{0}/issues - ReportModuleInfo1 = - No olvides actualizar tu archivo de configuración de informe después de cada nueva versión: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ + ReportModuleInfo1 = - No olvides actualizar tu archivo de configuración de informe después de cada nuevo lanzamiento de versión: https://www.asbuiltreport.com/user-guide/new-asbuiltreportconfig/ ReportModuleInfo4 = - Para patrocinar este proyecto, por favor visita: ReportModuleInfo5 = https://ko-fi.com/F1F8DEV80 ReportModuleInfo6 = - Obteniendo información de dependencias: ProjectWebsite = - Por favor consulta el sitio web de GitHub de AsBuiltReport.Microsoft.AD para obtener información más detallada sobre este proyecto. CommunityProject = - AsBuiltReport es un proyecto de código abierto mantenido por la comunidad. No tiene patrocinio, respaldo o afiliación con ningún proveedor de tecnología, sus empleados o afiliados. - DISCLAIMER = Este informe combina análisis de datos automatizado con observaciones profesionales. Aunque estos hallazgos ofrecen información experta, esta evaluación no es exhaustiva. Todas las recomendaciones deben ser revisadas e implementadas por personal calificado. Los autores no asumen responsabilidad alguna por daños, incluidas pérdidas de ganancias, interrupciones comerciales o pérdidas financieras, derivadas del uso de este informe o sus recomendaciones. - DisclaimerSection = AVISO LEGAL + DISCLAIMER = Este informe combina análisis de datos automatizado con observaciones profesionales. Aunque estos hallazgos ofrecen información experta, esta evaluación no es exhaustiva. Todas las recomendaciones deben ser revisadas e implementadas por personal calificado. Los autores no asumen ninguna responsabilidad por daños, incluyendo pérdidas de ganancias, interrupciones comerciales o pérdidas financieras, derivados del uso de este informe o sus recomendaciones. + DisclaimerSection = DESCARGO DE RESPONSABILIDAD + ModuleInstalled = - El módulo {0} v{1} está actualmente instalado. + ModuleAvailable = - El módulo {0} v{1} está disponible. + ModuleUpdate = - Ejecuta 'Update-Module -Name {0} -Force' para instalar la versión más reciente. + IPAddressError = Por favor, usa el Nombre de Dominio Completamente Calificado (FQDN) en lugar de una dirección IP al conectar con el Controlador de Dominio: {0} + PSSessionError = Error al establecer una PSSession ({0}) con el Controlador de Dominio '{1}': {2} + CIMSessionError = Error al establecer una sesión CIM ({0}) con el Controlador de Dominio '{1}'. + ConnectingForest = Conectando para recuperar información del bosque desde el Controlador de Dominio '{0}'. + ForestError = Error al recuperar información del bosque desde el Controlador de Dominio '{0}'. Asegúrate de que el sistema proporcionado sea un Controlador de Dominio y que las credenciales proporcionadas tengan permisos suficientes para consultar información del bosque de Active Directory. Detalles del error: {1} + IncludeDomainsEnabled = - Opción Include.Domains habilitada: Incluyendo solo los siguientes dominios en el informe: {0} + ExcludeDomainsEnabled = - Incluyendo todos los dominios secundarios en el informe excepto los siguientes dominios excluidos: {0} + GettingForestInfo = - Recuperando información del bosque {0}. + DiscoveringChildDomains = - Descubriendo dominios secundarios del bosque {0}: {1}. + DCAvailable = - Configuración inicial: Un DC está disponible en el dominio {0}. Agregando dominio al informe. + DCUnavailable = - No se puede obtener un DC disponible en el dominio {0}. Removiendo dominio del informe. + FinishingDomainList = - Finalizando la lista de dominios en el bosque {0}: {1}. + WorkingOnForest = - Trabajando en la sección del Bosque. + WorkingOnDomain = - Trabajando en la sección del Dominio. + WorkingOnDNS = - Trabajando en la sección de DNS. + WorkingOnPKI = - Trabajando en la sección de PKI. + ExportDiagramsEnabled = - Opción ExportDiagrams habilitada: Exportando diagramas: + TrustsDiagramError = No se puede generar el diagrama de 'Confianzas' para el dominio '{0}': {1} + DiagramExportError = No se puede exportar el diagrama {0}: {1} + ClearPSSession = Limpiando PSSession con ID {0} + ClearCIMSession = Limpiando sesión CIM con ID {0} + FinishedReport = - Se ha terminado de generar el informe para el bosque {0}: + SystemsUnreachable = Los siguientes sistemas no pudieron ser contactados: + DomainControllers = Controladores de Dominio + Domains = Dominios '@ # ConvertToTextYN @@ -56,6 +84,12 @@ ScopeEnabled = Habilitado (Resumen) ScopeAdvanced = Habilitado (Resumen Avanzado) ScopeDetailed = Habilitado (Detallado) + ErrorReportOverview = Report Brief - Report Overview + ErrorForestSummary = Report Brief - Forest Summary + ErrorDomainSummaryItem = Report Brief - Domain Summary Item + ErrorDomainSummary = Report Brief - Domain Summary + ErrorReportScope = Report Brief - Report Scope + ErrorReportBriefSection = Report Brief Section '@ # Get-AbrForestSection @@ -122,6 +156,14 @@ RecycleBinBP = La eliminación accidental de objetos de Active Directory es un problema común para usuarios de AD DS. Habilitar la función Papelera de Reciclaje permite la recuperación de estos objetos eliminados accidentalmente, ayudando a mantener la integridad y continuidad del entorno de Active Directory. RecycleBinRef = https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/the-ad-recycle-bin-understanding-implementing-best-practices-and/ba-p/396944 CADiagram = Diagrama de Autoridad de Certificación + TableName = Resumen del Bosque + ErrorForestDiagramGraph = Forest Diagram Graph: + ErrorForestDiagramSection = Forest Diagram Section: + NoCARootInfo = No se encontró información de Autoridad de Certificación raíz en {0}, deshabilitando esta sección. + NoCAIssuerInfo = No se encontró información de Autoridad de Certificación emisora, deshabilitando esta sección. + ErrorCADiagramGraph = Certificate Authority Diagram Graph: + ErrorCADiagramSection = Certificate Authority Diagram Section: + NoOptionalFeatureInfo = No se encontró información de Características Opcionales en {0}, deshabilitando esta sección. '@ NewADDiagram = ConvertFrom-StringData @' @@ -245,6 +287,10 @@ DnsName = Nombre DNS ServerRoles = Roles del Servidor Version = Versión + ErrorExchangeItem = Exchange Item + NoExchangeInfo = No se encontró información de infraestructura de Exchange en {0}, deshabilitando esta sección. + ErrorExchangeTable = Exchange Table + ErrorExchangeServerItem = ExchangeServer: [{0}]. '@ # Get-AbrADSCCM @@ -257,6 +303,9 @@ ManagementPoint = Punto de Gestión SiteCode = Código de Sitio Version = Versión + ErrorSCCMItem = SCCM Item + NoSCCMInfo = No se encontró información de infraestructura de SCCM en {0}, deshabilitando esta sección. + ErrorSCCMTable = SCCM Table '@ # Get-AbrDHCPinAD @@ -270,6 +319,9 @@ Yes = Sí No = No Unknown = Desconocido + ErrorDHCPItem = DHCP Item + NoDHCPInfo = No se encontró información de infraestructura de DHCP en {0}, deshabilitando esta sección. + ErrorDHCPTable = DHCP Table '@ # Get-AbrADSite @@ -306,7 +358,7 @@ MissingSubnets = Subredes Faltantes en AD MissingSubnetsTable = Subredes Faltantes MissingSubnetsParagraph = La siguiente tabla lista las entradas NO_CLIENT_SITE encontradas en el archivo netlogon.log en cada Controlador de Dominio del bosque. Estas entradas indican direcciones IP de clientes que no pudieron ser mapeadas a un sitio de Active Directory. - DC = CD + DC = DC IP = IP MissingSubnetsBP = Asegúrate de que todas las subredes en cada sitio estén correctamente definidas. Las definiciones de subred faltantes pueden impedir que los clientes usen sus Controladores de Dominio más cercanos, resultando en mayor latencia de autenticación. InterSiteTransports = Transportes Entre Sitios @@ -343,7 +395,7 @@ SMTPParagraph = La replicación SMTP se usa para sitios que no pueden usar otros protocolos de replicación, pero como regla general, nunca debe usarse. Se reserva para escenarios donde las conexiones de red no siempre están disponibles, permitiendo que la replicación se programe en intervalos específicos. SMTPChangeNotifBP = Habilitar la notificación de cambio trata una conexión de replicación entre sitios como si fuera una conexión dentro de un sitio. La replicación entre sitios con notificación de cambio es casi instantánea. Microsoft recomienda usar un valor de Opción de 5 (Notificación de Cambio Habilitada sin Compresión). SysvolReplication = Replicación de Sysvol - DCName = Nombre del CD + DCName = Nombre del DC ReplicationStatus = Estado de Replicación Domain = Dominio StatusUninitialized = No Inicializado @@ -355,7 +407,42 @@ StatusDisabled = Deshabilitado StatusUnknown = Desconocido StatusOffline = Fuera de Línea - SysvolBP = SYSVOL es un directorio especial que reside en cada controlador de dominio (CD) dentro de un dominio. El directorio comprende carpetas que almacenan objetos de Política de Grupo (GPO) y scripts de inicio de sesión que los clientes necesitan acceder y sincronizar entre CDs. Para que estos scripts de inicio de sesión y GPO funcionen correctamente, SYSVOL debe replicarse con precisión y rapidez en todo el dominio. Asegúrate de que se implemente una replicación correcta de SYSVOL para asegurar contenido idéntico de GPO/SYSVOL para el controlador de dominio en todos los dominios de Active Directory. + SysvolBP = SYSVOL es un directorio especial que reside en cada controlador de dominio (DC) dentro de un dominio. El directorio comprende carpetas que almacenan objetos de Política de Grupo (GPO) y scripts de inicio de sesión que los clientes necesitan acceder y sincronizar entre DCs. Para que estos scripts de inicio de sesión y GPO funcionen correctamente, SYSVOL debe replicarse con precisión y rapidez en todo el dominio. Asegúrate de que se implemente una replicación correcta de SYSVOL para asegurar contenido idéntico de GPO/SYSVOL para el controlador de dominio en todos los dominios de Active Directory. + ErrorReplicationDiagramGraph = Replication Diagram Graph: + ErrorReplicationDiagramSection = Replication Diagram Section: + ErrorDomainSite = Domain Site + ErrorSiteReplicationConnectionItem = Site Replication Connection Item + NoConnectionObjectsInfo = No se encontró información de Objetos de Conexión en {0}, deshabilitando esta sección. + ErrorConnectionObjects = Connection Objects + ErrorSiteSubnets = Site Subnets + UnableToRead = No se puede leer {0} en {1} + ErrorMissingSubnetPSSession = Missing Subnet in AD Section: New-PSSession: Unable to connect to {0}: {1} + ErrorMissingSubnetItemTable = Missing Subnet in AD Item table: + NoMissingSubnetsInfo = No se encontró información de Subredes Faltantes en {0}, deshabilitando esta sección. + ErrorMissingSubnetItemSection = Missing Subnet in AD Item Section: + NoSiteSubnetsInfo = No se encontró información de Subredes de Sitio en {0}, deshabilitando esta sección. + ErrorSiteTopologyDiagramGraph = Site Topology Diagram Graph: + ErrorSiteTopologyDiagramSection = Site Topology Diagram Section: + ErrorInterSiteTransports = Inter-Site Transports section + ErrorIPSiteLinksTable = IP Site Links table + NoIPSiteLinksInfo = No se encontró información de Vínculos de Sitio IP en {0}, deshabilitando esta sección. + ErrorIPSiteLinksSection = IP Site Links Section + ErrorIPSiteLinksBridgesTable = IP Site Links Bridges table + NoIPSiteLinksBridgesInfo = No se encontró información de Puentes de Vínculos de Sitio IP en {0}, deshabilitando esta sección. + ErrorIP = IP + ErrorSMTPSiteLinksTable = SMTP Site Links table + ErrorSMTPSiteLinksSection = SMTP Site Links Section + ErrorSMTPSiteLinksBridgesTable = SMTP Site Links Bridges table + NoSMTPSiteLinksBridgesInfo = No se encontró información de Puentes de Vínculos de Sitio SMTP en {0}, deshabilitando esta sección. + NoSMTPSiteLinksInfo = No se encontró información de Vínculos de Sitio SMTP en {0}, deshabilitando esta sección. + ErrorSMTP = SMTP + ErrorSysvolReplicationItemSection = Sysvol Replication Item Section: + UnableToCollect = No se puede recopilar información de {0}. + ErrorDNSIPConfigItem = DNS IP Configuration Item + NoSysvolReplicationInfo = No se encontró información de Replicación Sysvol en {0}, deshabilitando esta sección. + ErrorSysvolReplicationTableSection = Sysvol Replication Table Section: + NoSitesInfo = No se encontró información de Sitios en {0}, deshabilitando esta sección. + ErrorDomainSiteGlobal = Domain Site Global '@ # Get-AbrDNSSection @@ -364,11 +451,12 @@ CollectingDomain = Recopilando información de DNS desde {0}. DomainParagraph = La siguiente sección proporciona una descripción general detallada de la configuración del servicio DNS y su configuración para este dominio. ExcludedDomain = {0} deshabilitado en variable Exclude.Domain - NoDCAvailable = No se puede obtener un CD disponible en el dominio {0}. Removiendo dominio de la sección DNS. + NoDCAvailable = No se puede obtener un DC disponible en el dominio {0}. Removiendo dominio de la sección DNS. Heading = Configuración de DNS DefinitionParagraph = El Sistema de Nombres de Dominio (DNS) es un sistema de nomenclatura jerárquico y descentralizado para computadoras, servicios u otros recursos conectados a Internet o a una red privada. Asocia varios tipos de información con nombres de dominio asignados a cada una de las entidades participantes. Más prominentemente, traduce nombres de dominio más fáciles de recordar a direcciones IP numéricas necesarias para localizar e identificar servicios y dispositivos de computadora dentro de los protocolos de red subyacentes. Paragraph = La siguiente sección proporciona una descripción general detallada de la configuración de infraestructura de DNS y su configuración dentro del entorno de Active Directory. NoCIMSession = La configuración de la infraestructura de DNS requiere una sesión CIM y no pudo ser recopilada. Verifica que la conectividad WinRM y CIM a los controladores de dominio esté disponible. + ErrorDNSInfo = Domain Name System Information '@ # Get-AbrADDNSInfrastructure - Continue with the rest of the translations... @@ -389,11 +477,11 @@ RootHintsParagraph = La siguiente sección proporciona información detallada sobre la configuración de Sugerencias de Raíz para cada servidor DNS en el dominio {0}. ZoneScopeRecursion = Recursión de Alcance de Zona DirectoryPartitions = Particiones de Directorio - DCName = Nombre del CD + DCName = Nombre del DC BuildNumber = Número de Compilación IPv6 = IPv6 DnsSec = DnsSec - ReadOnlyDC = CD de Solo Lectura + ReadOnlyDC = DC de Solo Lectura ListeningIP = IP de Escucha Name = Nombre State = Estado @@ -425,12 +513,27 @@ BestPractice = Mejores Prácticas: CorrectiveActions = Acciones Correctivas: Reference = Referencia: - ScavengingBP = Microsoft recomienda habilitar envejecimiento/limpieza en todos los servidores DNS. Sin embargo, con zonas integradas en AD, asegúrate de que la limpieza de DNS esté habilitada solo en un CD del sitio principal. Los resultados se replicarán a otros CDs. + ScavengingBP = Microsoft recomienda habilitar envejecimiento/limpieza en todos los servidores DNS. Sin embargo, con zonas integradas en AD, asegúrate de que la limpieza de DNS esté habilitada solo en un DC del sitio principal. Los resultados se replicarán a otros DCs. ForwarderMaxBP = Configura los servidores para usar no más de dos servidores DNS externos como Reenviadores. Usar más de dos reenviadores puede llevar a tiempos de resolución aumentados y problemas potenciales con el equilibrio de carga de consultas DNS. Se recomienda usar dos servidores DNS confiables y geográficamente diversos para asegurar redundancia y rendimiento óptimo. ForwarderRefURL = https://learn.microsoft.com/es-es/troubleshoot/windows-server/networking/forwarders-resolution-timeouts ForwarderMinBP = Por razones de redundancia, se debe configurar más de un servidor de reenvío. RootHintsMissingCA = Una instalación predeterminada del rol de servidor DNS debe tener sugerencias de raíz a menos que el servidor tenga una zona raíz - .(raíz). Si el servidor tiene una zona raíz, elimínala. Si el servidor no tiene una zona raíz y no hay servidores raíz listados en la pestaña Sugerencias de Raíz de las propiedades del servidor DNS, el servidor puede estar perdiendo el archivo cache.dns en el directorio %systemroot%\\system32\\dns, desde donde se carga la lista de servidores raíz. RootHintsDuplicateCA = Se encontró dirección IP duplicada en la tabla de servidores de sugerencias de raíz de DNS. La consola de DNS no muestra los servidores de Sugerencias de Raíz duplicados; solo puedes verlos usando cmdlets de PowerShell de DNS. Aunque existe una utilidad dnscmd para reemplazar el archivo de Sugerencias de Raíz, usar PowerShell es la mejor forma de remediar este problema. + ErrorInfrastructureSummarySection = DNS Infrastructure Summary Section: + ErrorDirectoryPartitionsItemSection = Directory Partitions Item Section: + ErrorDirectoryPartitionsTableSection = Directory Partitions Table Section: + ErrorDirectoryPartitionsSection = Directory Partitions Section: + ErrorRRLItem = Response Rate Limiting (RRL) Item + ErrorRRLTable = Response Rate Limiting (RRL) Table + ErrorScavengingItem = Scavenging Item + ErrorScavengingTable = Scavenging Table + ErrorForwarderItem = Forwarder Item + ErrorForwarderTable = Forwarder Table + ErrorRootHintsTable = Root Hints Table + ErrorRootHintsSection = Root Hints Section + ErrorZoneScopeRecursionItem = Zone Scope Recursion Item + ErrorZoneScopeRecursionTable = Zone Scope Recursion Table + ErrorDNSInfrastructureSection = DNS Infrastructure Section '@ # Get-AbrADDNSZone @@ -472,7 +575,26 @@ HealthCheck = Verificación de Salud: BestPractice = Mejores Prácticas: ZoneTransferBP = Configura todas las zonas de DNS para permitir transferencias de zona solo desde direcciones IP de confianza. Esto asegura que solo servidores DNS autorizados puedan recibir datos de zona, reduciendo el riesgo de acceso no autorizado o fuga de datos. Es una mejor práctica especificar las direcciones IP de los servidores DNS secundarios autorizados a recibir transferencias de zona. - ZoneAgingBP = Microsoft recomienda habilitar envejecimiento/limpieza en todos los servidores DNS. Sin embargo, con zonas integradas en AD, asegúrate de que la limpieza de DNS esté habilitada solo en un CD del sitio principal. Los resultados se replicarán a otros CDs. + ZoneAgingBP = Microsoft recomienda habilitar envejecimiento/limpieza en todos los servidores DNS. Sin embargo, con zonas integradas en AD, asegúrate de que la limpieza de DNS esté habilitada solo en un DC del sitio principal. Los resultados se replicarán a otros DCs. + ErrorDNSZoneItem = Domain Name System Zone Item + NoDelegationInfo = Sección de Zonas DNS {0}: No se encontró información de Delegación de Zona, deshabilitando esta sección. + ErrorZoneDelegationItem = Zone Delegation Item + NoDelegationInfoDC = Sección de Zonas DNS: No se encontró información de Delegación de Zona en {0}, deshabilitando esta sección. + ErrorZoneDelegationTable = Zone Delegation Table + ErrorZoneTransferPSSession = DNS Zones Transfers Section: New-PSSession: Unable to connect to {0}: {1} + ErrorZoneTransfersItem = Zone Transfers Item + NoZoneTransferInfo = Sección de Zonas DNS: No se encontró información de Transferencia de Zona en {0}, deshabilitando esta sección. + ErrorZoneTransfersTable = Zone Transfers Table + ErrorReverseLookupZoneItem = Reverse Lookup Zone Configuration Item + NoReverseLookupZoneInfo = Sección de Zonas DNS: No se encontró información de zona de búsqueda inversa en {0}, deshabilitando esta sección. + ErrorReverseLookupZoneTable = Reverse Lookup Zone Configuration Table + ErrorConditionalForwarderItem = Conditional Forwarder Item + NoConditionalForwarderInfo = Sección de Zonas DNS: No se encontró información de zona de reenviador condicional en {0}, deshabilitando esta sección. + ErrorConditionalForwarderTable = Conditional Forwarder Table + ErrorZoneScopeAgingItem = Zone Scope Aging Item + NoZoneAgingInfo = Sección de Zonas DNS: No se encontró información de propiedad de envejecimiento de zona en {0}, deshabilitando esta sección. + ErrorZoneScopeAgingTable = Zone Scope Aging Table + ErrorGlobalDNSZoneInfo = Global DNS Zone Information '@ # Continuing with remaining sections... @@ -563,7 +685,7 @@ ValidityPeriod = Período de Validez ACL = Lista de Control de Acceso (ACL) ACLTable = Lista de Control de Acceso - DCName = Nombre del CD + DCName = Nombre del DC Owner = Propietario Group = Grupo AccessRights = Derechos de Acceso @@ -672,22 +794,23 @@ # Get-AbrDomainSection GetAbrDomainSection = ConvertFrom-StringData @' Collecting = Recopilando información de Dominio desde {0}. + CollectingDomain = Recopilando información de Dominio desde {0}. Paragraph = Esta sección proporciona una descripción general de la configuración del dominio de Active Directory, incluyendo configuraciones clave y detalles operacionales. SectionTitle = Configuración del Dominio de AD DefinitionText = Un dominio de Active Directory es una colección de objetos dentro de una red de Microsoft Active Directory. Un objeto puede ser un usuario individual, un grupo o un componente de hardware como una computadora o impresora. Cada dominio contiene una base de datos con información de identidad de objetos. Los dominios de Active Directory se pueden identificar usando un nombre DNS, que puede ser el mismo que el nombre de dominio público de una organización, un subdominio o una versión alternativa (que puede terminar en .local). ParagraphDetail = La siguiente tabla proporciona un desglose detallado de los atributos de configuración del dominio de Active Directory. HealthChecks = Verificaciones de Salud DomainControllersSection = Controladores de Dominio - DCDefinitionText = Un controlador de dominio (CD) es una computadora servidor que responde solicitudes de autenticación de seguridad dentro de un dominio de red de computadoras. Es un servidor de red responsable de permitir el acceso del anfitrión a recursos del dominio. Autentica usuarios, almacena información de cuenta de usuario e implementa la política de seguridad para un dominio. + DCDefinitionText = Un controlador de dominio (DC) es una computadora servidor que responde solicitudes de autenticación de seguridad dentro de un dominio de red de computadoras. Es un servidor de red responsable de permitir el acceso del anfitrión a recursos del dominio. Autentica usuarios, almacena información de cuenta de usuario e implementa la política de seguridad para un dominio. DCParagraphDetail = La siguiente sección presenta una descripción general profunda de los controladores de dominio de Active Directory, incluyendo su configuración y detalles clave. DCParagraphSummary = La siguiente sección proporciona un resumen de la configuración y detalles clave de los controladores de dominio de Active Directory. RolesSection = Roles RolesParagraph = La siguiente sección proporciona una descripción general detallada de los roles y funciones instalados en controladores de dominio en {0}. - DCDiagSection = Diagnóstico de CD - DCDiagParagraph = La siguiente sección proporciona un resumen del Diagnóstico de CD de Active Directory. + DCDiagSection = Diagnóstico de DC + DCDiagParagraph = La siguiente sección proporciona un resumen del Diagnóstico de DC de Active Directory. InfraServicesSection = Servicios de Infraestructura InfraServicesParagraph = La siguiente sección proporciona una descripción general detallada del estado y configuración de servicios de infraestructura en los controladores de dominio. - NoDCAvailable = No se puede obtener un CD disponible en el dominio {0}. Removiendo dominio de la sección de Dominio. + NoDCAvailable = No se puede obtener un DC disponible en el dominio {0}. Removiendo dominio de la sección de Dominio. WinRMErrorDCDiag = Error: La conexión al servidor remoto {0} falló: WinRM no puede completar la operación. (Información de DCDiag) WinRMErrorInfraService = Error: La conexión al servidor remoto {0} falló: WinRM no puede completar la operación. (ADInfrastructureService) DomainExcluded = {0} deshabilitado en variable Exclude.Domain @@ -695,6 +818,7 @@ ReplicationParagraph = La siguiente sección proporciona una descripción general de las conexiones de replicación de Active Directory y estado entre controladores de dominio en este dominio. GPOSection = Política de Grupo GPOParagraph = La siguiente sección proporciona una descripción general de los Objetos de Política de Grupo (GPO) configurados y aplicados dentro de este dominio. + ErrorADDomain = Active Directory Domain '@ # Get-AbrADDomain @@ -726,6 +850,8 @@ Reference = Referencia: RIDBestPractice = El porcentaje de RID Emitido excede el 80%. Se recomienda evaluar la utilización de RID para prevenir posible agotamiento y asegurar la estabilidad del dominio. El Identificador Relativo (RID) es un componente crucial en el SID (Identificador de Seguridad) para objetos dentro del dominio. El agotamiento del grupo de RID puede llevar a la incapacidad de crear nuevos principales de seguridad, como cuentas de usuario o computadora. El monitoreo regular y la gestión proactiva del grupo de RID son esenciales para mantener la salud del dominio y evitar disrupciones. RIDReference = https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/managing-rid-pool-depletion/ba-p/399736 + TableName = Resumen del Dominio + ErrorSection = Sección de Resumen del Dominio de AD: '@ # Get-AbrADFSMO @@ -742,6 +868,9 @@ Reference = Referencia: InfraMasterBP = El rol maestro de infraestructura en el dominio {0} debe ser mantenido por un controlador de dominio que no sea un servidor de catálogo global. El maestro de infraestructura es responsable de actualizar referencias de objetos en su dominio a objetos en otros dominios. Si el maestro de infraestructura se ejecuta en un servidor de catálogo global, no funcionará correctamente porque el catálogo global contiene una réplica parcial de cada objeto en el bosque, y no actualizará las referencias. Este problema no afecta bosques que tienen un único dominio. InfraMasterRef = http://go.microsoft.com/fwlink/?LinkId=168841 + TableName = Roles FSMO + ErrorFSMOItem = Flexible Single Master Operations + ErrorPSSession = FSMO Roles Section: New-PSSession: Unable to connect to {0}: {1} '@ # Get-AbrADTrust @@ -783,6 +912,12 @@ BestPractice = Mejor Práctica: AESBP = Asegúrate de que la encriptación Kerberos AES esté habilitada en todas las confianzas de Active Directory. La encriptación RC4 se considera débil y vulnerable a varios ataques. Habilitar la encriptación AES en confianzas mejora la seguridad de Kerberos y se alinea con estándares de seguridad modernos. Referencia: https://techcommunity.microsoft.com/t5/itops-talk-blog/tough-questions-answered-can-i-disable-rc4-etype-for-kerberos-on/ba-p/382718 TrustDiagramSection = Diagrama de Dominios y Confianzas + ErrorTrustItem = Trust Item + ErrorTrustDiagramGraph = Domain and Trusts Diagram Graph: + ErrorTrustDiagramSection = Domain and Trusts Diagram Section: + NoTrustInfo = No se encontró información de confianza de dominio en {0}, deshabilitando esta sección. + ErrorTrustTable = Trust Table + ErrorTrustSection = Trust Section '@ # Continue with remaining sections... @@ -816,6 +951,20 @@ ServiceTGTLifetime = Tiempo de Vida de TGT del Servicio (mins) ComputerTGTLifetime = Tiempo de Vida de TGT de la Computadora (mins) PolicyBP = Las Políticas de Autenticación deben estar configuradas en modo Aplicar para restringir activamente los tiempos de vida de TGT de Kerberos e inicio de sesión de cuenta. Las políticas en modo auditoría solo registran eventos sin aplicar restricciones. + ErrorSiloItem = Authentication Policy Silo Item + SiloTableName = Silo de Política de Autenticación + SilosTableName = Silos de Políticas de Autenticación + ErrorSiloMemberItem = Authentication Policy Silo Member Item + SiloMembersTableName = Miembros del Silo de Política de Autenticación + ErrorSiloMembersTable = Authentication Policy Silo Members Table + ErrorSilosSectionA = Authentication Policy Silos Section + NoSiloInfo = No se encontró información de Silos de Política de Autenticación en {0}, deshabilitando esta sección. + ErrorPolicyItem = Authentication Policy Item + PolicyTableName = Política de Autenticación + PoliciesTableName = Políticas de Autenticación + ErrorPoliciesSection = Authentication Policies Section + NoPolicyInfo = No se encontró información de Políticas de Autenticación en {0}, deshabilitando esta sección. + NoAuthPolicyOrSiloInfo = No se encontró información de Política de Autenticación o Silo en {0}, deshabilitando esta sección. '@ # Get-AbrADDomainObject @@ -985,6 +1134,45 @@ GMSAInactiveBP = *Verifica regularmente y elimina cuentas de servicio administradas grupales inactivas de Active Directory. Las cuentas inactivas pueden ser un riesgo de seguridad ya que pueden ser explotadas por actores maliciosos. Asegurar que solo cuentas activas y necesarias existan ayuda a mantener un entorno seguro y reduce el riesgo de acceso no autorizado o escalada de privilegios. GMSANoHostComputersBP = **No se ha definido "Computadoras Anfitrión"; por favor valida que gMSA esté actualmente en uso. Si no, se recomienda eliminar estos recursos no utilizados de Active Directory. GMSANoRetrieveManagedPasswordBP = ***No se ha definido "Recuperar Contraseña Administrada"; por favor valida que gMSA esté actualmente en uso. Si no, se recomienda eliminar estos recursos no utilizados de Active Directory. + PrivilegedGroupMembersTableName = Miembros del Grupo Privilegiado: + GMSATableName = gMSA + MembersLabel = Miembros + TypeLabelUser = USUARIO + TypeLabelComputer = COMPUTADORA + TypeLabelGroup = GRUPO + TypeLabelFSP = ENTIDAD DE SEGURIDAD EXTERNA + ErrorDomainObjectStats = Domain Object Stats + ErrorUserObjectCountChart = User Object Count Chart + ErrorStatusOfUserAccounts = Status of User Accounts + ErrorStatusOfUsersAccountsChart = Status of Users Accounts Chart + ErrorUsersObjectsTable = Users Objects Table + ErrorUsersObjectsSection = Users Objects Section + ErrorGroupCategoryObjectChart = Group Category Object Chart + ErrorGroupScopesObjectChart = Group Scopes Object Chart + ErrorGroupsObjectsTable = Groups Objects Table + ErrorGroupsObjectsSection = Groups Objects Section + ErrorPrivilegedGroup = Privileged Group in Active Directory + ErrorPrivilegedGroupNonDefaultTable = Privileged Group (Non-Default) Table + ErrorPrivilegedGroupNonDefaultSection = Privileged Group (Non-Default) Section + ErrorEmptyGroupsObjectsTable = Empty Groups Objects Table + ErrorEmptyGroupsObjectsSection = Empty Groups Objects Section + ErrorCircularGroupMembershipTable = Circular Group Membership Table + ErrorCircularGroupMembershipSection = Circular Group Membership Section + ErrorPreWin2000 = Pre-Windows 2000 Compatible Access + ErrorComputersObjectCountChart = Computers Object Count Chart + ErrorStatusOfComputerAccounts = Status of Computer Accounts + ErrorStatusOfComputersAccountsChart = Status of Computers Accounts Chart + ErrorOperatingSystemsInAD = Operating Systems in Active Directory + ErrorComputersPasswordNotRequired = Computers with Password-Not-Required + ErrorComputersObjectsTable = Computers Objects Table + ErrorComputersObjectsSection = Computers Objects Section + ErrorDefaultDomainPasswordPolicy = Default Domain Password Policy + ErrorFGPP = Fine Grained Password Policies + ErrorWindowsLAPS = Windows LAPS + ErrorGMSAItem = Group Managed Service Accounts Item + ErrorGMSASection = Group Managed Service Accounts Section + ErrorFSPItem = Foreign Security Principals Item + ErrorFSPSection = Foreign Security Principals Section '@ # Get-AbrADHardening @@ -1028,6 +1216,8 @@ LDAPSigningBP = La aplicación de firmas LDAP no se configura en este controlador de dominio. La firma LDAP es una función de seguridad que protege la integridad y confidencialidad de las comunicaciones LDAP requiriendo firma de datos. Configura la firma LDAP para requerir firma en todos los controladores de dominio. LDAPCBBindingBP = La aplicación de vinculación de canal de LDAP no se configura en este controlador de dominio. La vinculación de canal de LDAP es una función de seguridad que protege contra ataques de intermediario vinculando la sesión LDAP al canal TLS, asegurando la autenticidad e integridad de las comunicaciones LDAP. Configura la vinculación de canal de LDAP en todos los controladores de dominio. NTLMv1BP = La autenticación NTLMv1 está habilitada en este controlador de dominio. NTLMv1 es un protocolo de autenticación obsoleto que es vulnerable a ataques de captura y retransmisión de credenciales. Deshabilita NTLMv1 en todos los sistemas; ha sido superado por NTLMv2, que ofrece protecciones de seguridad significativamente mejoradas. + ErrorADHardeningItem = ADHardening Item + ErrorADHardeningSection = ADHardening Section '@ # Get-AbrADDomainLastBackup @@ -1046,6 +1236,8 @@ BackupBP1 = Asegúrate de que haya un respaldo reciente de Active Directory (<180 días). BackupBP2 = Los respaldos regulares son cruciales para la recuperación ante desastres y el mantenimiento de la integridad de tu entorno de Active Directory. BackupBP3 = Considera configurar cronogramas de respaldo automatizados y verifica regularmente el estado del respaldo para prevenir pérdida de datos. + ErrorDomainLastBackupItem = Domain Last Backup Item + ErrorDomainLastBackupTable = Domain Last Backup Table '@ # Get-AbrADDuplicateSPN @@ -1061,6 +1253,8 @@ HealthCheck = Verificación de Salud: CorrectiveActions = Acciones Correctivas: SPNBP = Asegúrate de que no haya SPN duplicados (otros que krbtgt). Los SPN duplicados pueden causar problemas de autenticación y deben resolverse rápidamente. Usa el comando `setspn -X` para identificar SPN duplicados. Elimina o reasigna SPN duplicados según sea necesario para mantener un entorno de AD saludable. + ErrorSPNItem = SPN Item + ErrorSPNTable = SPN Table '@ # Get-AbrADDuplicateObject @@ -1077,11 +1271,13 @@ HealthCheck = Verificación de Salud: CorrectiveActions = Acciones Correctivas: DuplicateObjectBP = Asegúrate de que no haya objetos duplicados en Active Directory. Los objetos duplicados pueden causar varios problemas tales como problemas de autenticación, conflictos de replicación y gastos administrativos adicionales. Se recomienda auditar y limpiar regularmente cualquier objeto duplicado para mantener un entorno de Active Directory saludable y eficiente. + ErrorDuplicateObjectItem = Duplicate Object Item + ErrorDuplicateObjectTable = Duplicate Object Table '@ # Get-AbrADDCRoleFeature GetAbrADDCRoleFeature = ConvertFrom-StringData @' - Collecting = Recopilando información de Rol y Características de CD de Active Directory de {0}. + Collecting = Recopilando información de Rol y Características de DC de Active Directory de {0}. Name = Nombre Parent = Padre Description = Descripción @@ -1089,6 +1285,9 @@ HealthCheck = Verificación de Salud: BestPractices = Mejores Prácticas: RoleBP = Los Controladores de Dominio deben tener software y agentes limitados instalados incluyendo roles y servicios. El código no esencial ejecutándose en Controladores de Dominio es un riesgo para el entorno empresarial de Active Directory. Un Controlador de Dominio debe ejecutar solo software requerido, servicios y roles críticos para la operación esencial. + ErrorPSSession = Roles Section: New-PSSession: Unable to connect to {0}: {1} + ErrorRoleFeatureSection = Roles {0} Section: + ErrorRolesSection = Roles Section: '@ # Get-AbrADDCDiag @@ -1100,11 +1299,14 @@ Description = Descripción TableName = Estado de Prueba de DCDiag NoData = No se encontró información de DCDiag en {0}, deshabilitando esta sección. + ErrorDCDiagTestSection = Active Directory DCDiag {0} Section: + ErrorDCDiagSection = Active Directory DCDiag Section: + ErrorInvokeDcDiag = Invoke-DcDiag - Failed to get DCDiag for {0} with error: '@ # Get-AbrADInfrastructureService GetAbrADInfrastructureService = ConvertFrom-StringData @' - Collecting = Recopilando información de Servicios de Infraestructura de CD de Active Directory de {0}. + Collecting = Recopilando información de Servicios de Infraestructura de DC de Active Directory de {0}. DisplayName = Nombre Mostrado ShortName = Nombre Corto Status = Estado @@ -1114,6 +1316,9 @@ CorrectiveActions = Acciones Correctivas: SpoolerBP = El servicio Print Spooler tiene vulnerabilidades conocidas que pueden ser explotadas por atacantes para obtener acceso no autorizado o ejecutar código malicioso. Deshabilitar este servicio en Controladores de Dominio y otros servidores críticos que no requieren servicios de impresión puede reducir la superficie de ataque y mejorar la postura de seguridad general de tu entorno de Active Directory. DHCPServerBP = De acuerdo con las mejores prácticas de seguridad, los servicios de Servidor DHCP deben ejecutarse en un servidor dedicado separado de los controladores de dominio para minimizar riesgos de seguridad, reducir contención de recursos y asegurar rendimiento óptimo de ambos servicios DHCP y Active Directory. + ErrorPSSession = Domain Controller Infrastructure Services Section: New-PSSession: Unable to connect to {0}: {1} + ErrorDCInfraServicesItem = Domain Controller Infrastructure Services Item + ErrorDCInfraServicesTable = Domain Controller Infrastructure Services Table '@ # Get-AbrADDFSHealth @@ -1121,7 +1326,7 @@ Collecting = Recopilando información de Salud de DFS de Dominio de AD en {0}. SysvolReplicationTitle = Estado de Replicación de Sysvol SysvolReplicationParagraph = La siguiente sección proporciona el estado de replicación de la carpeta SYSVOL para el dominio {0}. - DCName = Nombre del CD + DCName = Nombre del DC ReplicationStatus = Estado de Replicación GPOCount = Conteo de GPO SysvolCount = Conteo de Sysvol @@ -1132,7 +1337,7 @@ SysvolReplicationNoData = No se encontró información de DFS en {0}, deshabilitando esta sección. SysvolReplicationHealthCheck = Verificación de Salud: SysvolReplicationCorrectiveActions = Acciones Correctivas: - SysvolReplicationBP = SYSVOL es un directorio especial que reside en cada controlador de dominio (CD) dentro de un dominio. El directorio comprende carpetas que almacenan objetos de Política de Grupo (GPO) y scripts de inicio de sesión que los clientes necesitan acceder y sincronizar entre CDs. Para que estos scripts de inicio de sesión y GPO funcionen correctamente, SYSVOL debe replicarse con precisión y rapidez en todo el dominio. Asegúrate de que se implemente una replicación correcta de SYSVOL para asegurar contenido idéntico de GPO/SYSVOL para el controlador de dominio en todos los dominios de Active Directory. + SysvolReplicationBP = SYSVOL es un directorio especial que reside en cada controlador de dominio (DC) dentro de un dominio. El directorio comprende carpetas que almacenan objetos de Política de Grupo (GPO) y scripts de inicio de sesión que los clientes necesitan acceder y sincronizar entre DCs. Para que estos scripts de inicio de sesión y GPO funcionen correctamente, SYSVOL debe replicarse con precisión y rapidez en todo el dominio. Asegúrate de que se implemente una replicación correcta de SYSVOL para asegurar contenido idéntico de GPO/SYSVOL para el controlador de dominio en todos los dominios de Active Directory. SysvolContentTitle = Estado de Contenido de Sysvol SysvolContentParagraph = La siguiente sección proporciona el estado de salud de SYSVOL para el dominio {0}. SysvolContentNoData = No se encontró información de carpeta SYSVOL en {0}, deshabilitando esta sección. @@ -1148,6 +1353,14 @@ ContentCorrectiveActions = Acciones Correctivas: ContentSysvolBP = Revisa los archivos y extensiones listados arriba y asegúrate de que sean necesarios para la operación de tu dominio. Elimina cualquier archivo que no sea requerido o que parezca sospechoso. Monitorea regularmente la carpeta Sysvol para mantener un entorno de Active Directory saludable y seguro. ContentNetlogonBP = Revisa los archivos y extensiones listados arriba y asegúrate de que sean necesarios para la operación de tu dominio. Elimina cualquier archivo que no sea requerido o que parezca sospechoso. Monitorea regularmente la carpeta Netlogon para mantener un entorno de Active Directory saludable y seguro. + ErrorSysvolReplicationStatusItemSection = Sysvol Replication Status Item Section: + ErrorSysvolReplicationStatusTableSection = Sysvol Replication Status Table Section: + ErrorSysvolContentPSSession = Sysvol Content Status Section: New-PSSession: Unable to connect to {0}: {1} + ErrorSysvolHealthSection = Sysvol Health {0} Section: + ErrorSysvolHealthTableSection = Sysvol Health Table Section: + ErrorNetlogonContentPSSession = Netlogon Content Status Section: New-PSSession: Unable to connect to {0}: {1} + ErrorNetlogonHealthSection = Netlogon Health {0} Section: + ErrorNetlogonContentStatusSection = Netlogon Content Status Section: '@ # Get-AbrADKerberosAudit @@ -1179,6 +1392,10 @@ AdminHealthCheck = Verificación de Salud: AdminBestPractice = Mejor Práctica: AdminBP = Microsoft recomienda usar una contraseña única y compleja para la cuenta de Administrador integrada y rotarla regularmente (al menos cada 90 días). Considera renombrar la cuenta y deshabilitarla cuando no esté activamente en uso para reducir el riesgo de ataques de fuerza bruta o relleno de credenciales dirigidos a esta cuenta bien conocida. + ErrorUnconstrainedKerberosItem = Unconstrained Kerberos delegation + ErrorKRBTGTAccountItem = KRBTGT account Item + ErrorAdminAccountItem = ADMIN account Item + ErrorUnconstrainedKerberosSection = Unconstrained Kerberos delegation Section '@ # Get-AbrADSiteReplication @@ -1211,6 +1428,15 @@ ReplicationStatusBestPractices = Mejores Prácticas: ReplicationStatusBP = Los fallos de replicación pueden llevar a inconsistencias de objetos, credenciales obsoletas, fallos en la aplicación de Política de Grupo e problemas de autenticación en todo el entorno. Investiga y resuelve cualquier error de replicación rápidamente usando herramientas como repadmin /showrepl o la Herramienta de Estado de Replicación de Active Directory para prevenir mayor divergencia entre controladores de dominio. AutoGeneratedValue = + ErrorSiteReplicationConnectionItem = Site Replication Connection Item + ErrorSiteReplicationConnectionSection = Site Replication Connection Section + SiteLabel = Sitio: + FromLabel = Desde: + ToLabel = Hacia: + ErrorReplicationConnection = Replication Connection + ErrorPSSession = Replication Status Section: New-PSSession: Unable to connect to {0}: {1} + ErrorReplicationStatus = Replication Status + ErrorSiteReplicationStatus = Site Replication Status '@ # Get-AbrADOU @@ -1235,6 +1461,10 @@ GPOBlockedHealthCheck = Verificación de Salud: GPOBlockedCorrectiveActions = Acciones Correctivas: GPOBlockedBP = Revisa el uso de políticas aplicadas y herencia de política bloqueada en Active Directory. Las políticas aplicadas aseguran que Objetos de Política de Grupo (GPO) específicos se apliquen y no puedan ser anulados por otros GPO. La herencia de política bloqueada previene que GPO de contenedores padres se apliquen a la Unidad Organizativa (OU). Aunque estas configuraciones pueden ser útiles para mantener la aplicación de política estricta, también pueden llevar a resultados inesperados y complicar la solución de problemas. Asegúrate de que el uso de estas configuraciones se alinee con la estrategia de gestión de políticas de tu organización y no cause inadvertidamente problemas. + ErrorOUItem = Organizational Unit Item + ErrorBlockedInheritanceGPOItem = Blocked Inheritance GPO Item + ErrorBlockedInheritanceGPOSection = Blocked Inheritance GPO Section + ErrorOUSection = Organizational Unit Section '@ # Get-AbrADSecurityAssessment @@ -1291,6 +1521,19 @@ PrivilegedUsersReference = Referencia: PrivilegedUsersReferenceURL = https://www.stigviewer.com/stig/active_directory_domain/2017-12-15/finding/V-36435 ServiceAccountsAdminCountNote = ** Los Atacantes están más interesados en Cuentas de Servicio que son miembros de grupos altamente privilegiados como Domain Admins. Una forma rápida de verificar esto es enumerar todas las cuentas de usuario con el atributo AdminCount igual a 1. Esto significa que un atacante puede simplemente pedir al Active Directory todas las cuentas de usuario con un SPN y con AdminCount=1. Asegúrate de que no haya cuentas privilegiadas que tengan SPN asignado a ellas. + ErrorAccountSecurityAssessmentItem = Account Security Assessment Item + ErrorUserAccountSecurityAssessmentChart = User Account Security Assessment Chart + NoUserInfo = No se encontró información de usuarios del dominio en {0}, deshabilitando esta sección. + ErrorAccountSecurityAssessmentTable = Account Security Assessment Table + ErrorPrivilegedUsersAssessmentItem = Privileged Users Assessment Item + NoPrivilegedUserInfo = No se encontró información de Evaluación de Usuarios Privilegiados en {0}, deshabilitando esta sección. + ErrorPrivilegedUsersTable = Privileged Users Table + ErrorInactivePrivilegedAccountsItem = Inactive Privileged Accounts Item + NoInactivePrivilegedInfo = No se encontró información de Cuentas Privilegiadas Inactivas en {0}, deshabilitando esta sección. + ErrorInactivePrivilegedAccountsTable = Inactive Privileged Accounts Table + ErrorServiceAccountsAssessmentItem = Service Accounts Assessment Item + NoServiceAccountsInfo = No se encontró información de Evaluación de Cuentas de Servicio en {0}, deshabilitando esta sección. + ErrorServiceAccountsAssessmentTable = Service Accounts Assessment Table '@ # Get-AbrADGPO @@ -1388,6 +1631,23 @@ GPOSettingsParagraph = La siguiente sección proporciona detalles sobre recursos de configuración de Política de Grupo, incluyendo filtros WMI, el repositorio de Almacenamiento Central y scripts anexados a GPO. GPOHealthTitle = Salud de GPO GPOHealthParagraph = La siguiente sección destaca Objetos de Política de Grupo que pueden requerir atención, incluyendo GPO sin vincular, vacíos, aplicados y huérfanos. + ErrorGPOItem = Group Policy Objects + ErrorWMIFiltersItem = WMI Filters + ErrorWMIFiltersPSSession = WMI Filters Section: New-PSSession: Unable to connect to {0}: {1} + ErrorGPOCentralStore = GPO Central Store + ErrorGPOLogonLogoffItem = GPO with Logon/Logoff Script Item + ErrorGPOLogonLogoffSection = GPO with Logon/Logoff Script Section + ErrorGPOStartupShutdownItem = GPO with Computer Startup/Shutdown Item + ErrorGPOStartupShutdownSection = GPO with Computer Startup/Shutdown Section + ErrorUnlinkedGPOItem = Unlinked Group Policy Objects Item + ErrorUnlinkedGPOSection = Unlinked Group Policy Objects Section + ErrorEmptyGPOItem = Empty Group Policy Objects Item + ErrorEmptyGPOSection = Empty Group Policy Objects Section + ErrorEnforcedGPOItem = Enforced Group Policy Objects Item + ErrorEnforcedGPOTable = Enforced Group Policy Objects Table + ErrorOrphanedGPOPSSession = Orphaned GPO Section: New-PSSession: Unable to connect to {0}: {1} + ErrorOrphanedGPOItem = Orphaned GPO + ErrorGPOSection = Group Policy Objects Section '@ # Get-AbrADDomainController GetAbrADDomainController = ConvertFrom-StringData @' @@ -1397,7 +1657,7 @@ BestPractices = Mejores Prácticas: CorrectiveActions = Acciones Correctivas: SecurityBestPractices = Mejores Prácticas de Seguridad: - DCName = Nombre del CD + DCName = Nombre del DC Status = Estado Online = En Línea Offline = Fuera de Línea @@ -1503,6 +1763,47 @@ MissingUpdatesParagraph = La siguiente tabla proporciona un resumen de actualizaciones de Windows pendientes o faltantes detectadas en Controladores de Dominio en el dominio {0}. MissingUpdatesBestPractice = Es crítico instalar actualizaciones de seguridad para proteger tus sistemas de ataques maliciosos. Aplicar regularmente actualizaciones asegura que tus sistemas estén protegidos contra vulnerabilidades recién descubiertos. Además, instalar actualizaciones de software proporciona acceso a nuevas características y mejoras, mejorando el rendimiento y estabilidad general del sistema. Descuidar las actualizaciones puede dejar tus sistemas expuestos a amenazas potenciales y explotación. Por lo tanto, es en tu mejor interés mantener un entorno actualizado instalando rápidamente todas las actualizaciones recomendadas. DCObjectChart = Gráfico de Objeto de Controlador de Dominio + ErrorNetworkInterfacesInfo = No se puede obtener información de interfaces de red de {0} + ErrorDCNetSettingsPSSession = DC Net Settings Section: New-PSSession: Unable to connect to {0}: {1} + ErrorDCItem = Domain Controller Item + UnableToCollect = No se puede recopilar información de {0}. + ErrorDCTable = Domain Controller Table + ErrorGeneralInfoSection = General Information Section + ErrorPartitionsSection = Partitions Section + ErrorNetworkingSettingsSection = Networking Settings Section + ErrorHardwareInventoryTable = Hardware Inventory Table + ErrorDCHardwareSection = Domain Controller Hardware Section + ErrorDCSection = Domain Controller Section + ErrorDNSIPConfigPSSession = DNS IP Configuration Section: New-PSSession: Unable to connect to {0}: {1} + ErrorDNSIPConfigTableSection = Domain Controller DNS IP Configuration Table Section: + ErrorDNSIPConfigItem = DNS IP Configuration Item + ErrorDNSIPConfigSection = Domain Controller DNS IP Configuration Section: + ErrorNTDSPSSession = NTDS Section: New-PSSession: Unable to connect to {0}: {1} + ErrorNTDSItem = NTDS Item + ErrorNTDSSection = NTDS section + ErrorTimeSourcePSSession = Time Source Section: New-PSSession: Unable to connect to {0}: {1} + ErrorTimeSourceItem = Time Source Item + ErrorTimeSourceTable = Time Source Table + ErrorTimeSource = Time Source + ErrorSRVRecordsStatusItem = SRV Records Status Item + ErrorSRVRecordsStatusTable = SRV Records Status Table + ErrorSRVRecordsStatus = SRV Records Status + ErrorFileSharesPSSession = Domain Controllers File Shares Section: New-PSSession: Unable to connect to {0}: {1} + ErrorFileSharesItem = File Shares Item + ErrorFileSharesTable = File Shares Table + ErrorInstalledSoftwarePSSession = Domain Controller Installed Software Section: New-PSSession: Unable to connect to {0}: {1} + ErrorInstalledSoftwareTable = Installed Software Table + ErrorInstalledSoftwareSection = Installed Software Section + ErrorMissingPatchPSSession = Domain Controller Pending Missing Patch Section: New-PSSession: Unable to connect to {0}: {1} + ErrorMissingPatchTable = Installed Software Table + ErrorMissingPatchSection = Domain Controller Section +'@ + + # Get-AbrDiagrammer + GetAbrDiagrammer = ConvertFrom-StringData @' + GettingDiagram = Getting {0} diagram from {1}. + ErrorExportDiagram = Unable to export the {0} Diagram: + ErrorGetDiagram = Unable to get the {0} Diagram: '@ -} \ No newline at end of file +} diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagrammer.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagrammer.ps1 index 4885b3a..ee7bca4 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagrammer.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagrammer.ps1 @@ -61,7 +61,7 @@ function Get-AbrDiagrammer { ) begin { - Write-PScriboMessage -Message "Getting $($DiagramType) diagram from $DomainController ." + Write-PScriboMessage -Message ($reportTranslate.GetAbrDiagrammer.GettingDiagram -f $DiagramType, $DomainController) } process { @@ -136,7 +136,7 @@ function Get-AbrDiagrammer { if (Test-Path -Path $FilePath -PathType Leaf) { $FilePath } else { - Write-PScriboMessage -IsWarning -Message "Unable to export the $DiagramType Diagram: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrDiagrammer.ErrorExportDiagram -f $DiagramType) $($_.Exception.Message)" } } else { Write-Information "Saved '$FileName' diagram to '$($OutputFolderPath)'." -InformationAction Continue @@ -145,10 +145,10 @@ function Get-AbrDiagrammer { } } } catch { - Write-PScriboMessage -IsWarning -Message "Unable to export the $DiagramType Diagram: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrDiagrammer.ErrorExportDiagram -f $DiagramType) $($_.Exception.Message)" } } catch { - Write-PScriboMessage -IsWarning -Message "Unable to get the $DiagramType Diagram: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrDiagrammer.ErrorGetDiagram -f $DiagramType) $($_.Exception.Message)" } } end {} diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-ADExchangeServer.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-ADExchangeServer.ps1 index 51d3171..d12c181 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-ADExchangeServer.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-ADExchangeServer.ps1 @@ -59,7 +59,7 @@ function Get-ADExchangeServer { ServerRoles = $roles; } } catch { - Write-PScriboMessage -IsWarning -Message "ExchangeServer: [$($server.Name)]. $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADExchange.ErrorExchangeServerItem -f $server.Name) $($_.Exception.Message)" } } } \ No newline at end of file diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADAuthenticationPolicy.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADAuthenticationPolicy.ps1 index 1d255b6..b2f1625 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADAuthenticationPolicy.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADAuthenticationPolicy.ps1 @@ -61,7 +61,7 @@ function Get-AbrADAuthenticationPolicy { } $SiloInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silo Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorSiloItem) $($_.Exception.Message)" } } @@ -73,7 +73,7 @@ function Get-AbrADAuthenticationPolicy { foreach ($Silo in $SiloInfo) { Section -Style NOTOCHeading5 -ExcludeFromTOC "$($Silo.Name)" { $TableParams = @{ - Name = "Authentication Policy Silo - $($Silo.Name)" + Name = "$($reportTranslate.GetAbrADAuthenticationPolicy.SiloTableName) - $($Silo.Name)" List = $true ColumnWidths = 40, 60 } @@ -85,7 +85,7 @@ function Get-AbrADAuthenticationPolicy { } } else { $TableParams = @{ - Name = "Authentication Policy Silos - $($Domain.DNSRoot.ToString().ToUpper())" + Name = "$($reportTranslate.GetAbrADAuthenticationPolicy.SilosTableName) - $($Domain.DNSRoot.ToString().ToUpper())" List = $false Columns = $reportTranslate.GetAbrADAuthenticationPolicy.SiloName, $reportTranslate.GetAbrADAuthenticationPolicy.SiloEnforce, $reportTranslate.GetAbrADAuthenticationPolicy.UserAuthPolicy, $reportTranslate.GetAbrADAuthenticationPolicy.ServiceAuthPolicy, $reportTranslate.GetAbrADAuthenticationPolicy.ComputerAuthPolicy ColumnWidths = 20, 12, 23, 23, 22 @@ -126,7 +126,7 @@ function Get-AbrADAuthenticationPolicy { $SiloMemberInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silo Member Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorSiloMemberItem) $($_.Exception.Message)" } } } @@ -135,7 +135,7 @@ function Get-AbrADAuthenticationPolicy { Paragraph ($reportTranslate.GetAbrADAuthenticationPolicy.SiloMembersParagraph -f $Domain.DNSRoot.ToString().ToUpper()) BlankLine $TableParams = @{ - Name = "Authentication Policy Silo Members - $($Domain.DNSRoot.ToString().ToUpper())" + Name = "$($reportTranslate.GetAbrADAuthenticationPolicy.SiloMembersTableName) - $($Domain.DNSRoot.ToString().ToUpper())" List = $false ColumnWidths = 20, 20, 15, 45 } @@ -146,14 +146,14 @@ function Get-AbrADAuthenticationPolicy { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silo Members Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorSiloMembersTable) $($_.Exception.Message)" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silos Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorSilosSectionA) $($_.Exception.Message)" } } else { - Write-PScriboMessage -Message "No Authentication Policy Silo information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADAuthenticationPolicy.NoSiloInfo -f $Domain.DNSRoot) } if ($AuthPolicies) { try { @@ -181,7 +181,7 @@ function Get-AbrADAuthenticationPolicy { } $PolicyInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorPolicyItem) $($_.Exception.Message)" } } @@ -193,7 +193,7 @@ function Get-AbrADAuthenticationPolicy { foreach ($Policy in $PolicyInfo) { Section -Style NOTOCHeading5 -ExcludeFromTOC "$($Policy.Name)" { $TableParams = @{ - Name = "Authentication Policy - $($Policy.Name)" + Name = "$($reportTranslate.GetAbrADAuthenticationPolicy.PolicyTableName) - $($Policy.Name)" List = $true ColumnWidths = 40, 60 } @@ -205,7 +205,7 @@ function Get-AbrADAuthenticationPolicy { } } else { $TableParams = @{ - Name = "Authentication Policies - $($Domain.DNSRoot.ToString().ToUpper())" + Name = "$($reportTranslate.GetAbrADAuthenticationPolicy.PoliciesTableName) - $($Domain.DNSRoot.ToString().ToUpper())" List = $false Columns = $reportTranslate.GetAbrADAuthenticationPolicy.PolicyName, $reportTranslate.GetAbrADAuthenticationPolicy.PolicyEnforce, $reportTranslate.GetAbrADAuthenticationPolicy.UserTGTLifetime, $reportTranslate.GetAbrADAuthenticationPolicy.ServiceTGTLifetime, $reportTranslate.GetAbrADAuthenticationPolicy.ComputerTGTLifetime ColumnWidths = 20, 12, 23, 23, 22 @@ -227,17 +227,17 @@ function Get-AbrADAuthenticationPolicy { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policies Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorPoliciesSection) $($_.Exception.Message)" } } else { - Write-PScriboMessage -Message "No Authentication Policy information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADAuthenticationPolicy.NoPolicyInfo -f $Domain.DNSRoot) } } } else { - Write-PScriboMessage -Message "No Authentication Policy or Silo information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADAuthenticationPolicy.NoAuthPolicyOrSiloInfo -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silos Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADAuthenticationPolicy.ErrorSilosSectionA) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCDiag.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCDiag.ps1 index a116853..117783c 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCDiag.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCDiag.ps1 @@ -69,7 +69,7 @@ function Get-AbrADDCDiag { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Active Directory DCDiag $($Result.TestName) Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDCDiag.ErrorDCDiagTestSection -f $Result.TestName) $($_.Exception.Message)" } } if ($HealthCheck.DomainController.Diagnostic) { @@ -89,7 +89,7 @@ function Get-AbrADDCDiag { Write-PScriboMessage -Message ($reportTranslate.GetAbrADDCDiag.NoData -f $DC) } } catch { - Write-PScriboMessage -IsWarning -Message "Active Directory DCDiag Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDCDiag.ErrorDCDiagSection) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCRoleFeature.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCRoleFeature.ps1 index c827c01..e6aefea 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCRoleFeature.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDCRoleFeature.ps1 @@ -33,7 +33,7 @@ function Get-AbrADDCRoleFeature { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Roles Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDCRoleFeature.ErrorPSSession -f $DC, $ErrorMessage) } if ($Features) { Section -ExcludeFromTOC -Style NOTOCHeading5 $($DC.ToString().ToUpper().Split('.')[0]) { @@ -47,7 +47,7 @@ function Get-AbrADDCRoleFeature { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Roles $($Feature.DisplayName) Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDCRoleFeature.ErrorRoleFeatureSection -f $Feature.DisplayName) $($_.Exception.Message)" } } @@ -78,7 +78,7 @@ function Get-AbrADDCRoleFeature { } } } catch { - Write-PScriboMessage -IsWarning -Message "Roles Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDCRoleFeature.ErrorRolesSection) $($_.Exception.Message)" } } end { diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDFSHealth.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDFSHealth.ps1 index c270c2e..1c1a924 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDFSHealth.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDFSHealth.ps1 @@ -71,7 +71,7 @@ } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Sysvol Replication Status Iten Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDFSHealth.ErrorSysvolReplicationStatusItemSection) $($_.Exception.Message)" } } @@ -117,7 +117,7 @@ Write-PScriboMessage -Message ($reportTranslate.GetAbrADDFSHealth.SysvolReplicationNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "Sysvol Replication Status Table Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDFSHealth.ErrorSysvolReplicationStatusTableSection) $($_.Exception.Message)" } try { @@ -134,7 +134,7 @@ if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Sysvol Content Status Section: New-PSSession: Unable to connect to $($ValidDcFromDomain): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDFSHealth.ErrorSysvolContentPSSession -f $ValidDcFromDomain, $ErrorMessage) } if ($SYSVOLFolder) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADDFSHealth.SysvolContentTitle { @@ -150,7 +150,7 @@ } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Sysvol Health $($Extension.Extension) Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDFSHealth.ErrorSysvolHealthSection -f $Extension.Extension) $($_.Exception.Message)" } } @@ -181,7 +181,7 @@ Write-PScriboMessage -Message ($reportTranslate.GetAbrADDFSHealth.SysvolContentNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "Sysvol Health Table Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDFSHealth.ErrorSysvolHealthTableSection) $($_.Exception.Message)" } try { $DCPssSession = Get-ValidPSSession -ComputerName $ValidDcFromDomain -SessionName $($ValidDcFromDomain) -PSSTable ([ref]$PSSTable) @@ -197,7 +197,7 @@ if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Netlogon Content Status Section: New-PSSession: Unable to connect to $($ValidDcFromDomain): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDFSHealth.ErrorNetlogonContentPSSession -f $ValidDcFromDomain, $ErrorMessage) } if ($NetlogonFolder) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADDFSHealth.NetlogonContentTitle { @@ -213,7 +213,7 @@ } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Netlogon Health $($Extension.Extension) Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDFSHealth.ErrorNetlogonHealthSection -f $Extension.Extension) $($_.Exception.Message)" } } @@ -244,7 +244,7 @@ Write-PScriboMessage -Message ($reportTranslate.GetAbrADDFSHealth.NetlogonContentNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "Netlogon Content Status Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDFSHealth.ErrorNetlogonContentStatusSection) $($_.Exception.Message)" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSInfrastructure.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSInfrastructure.ps1 index 8681b6f..c47f808 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSInfrastructure.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSInfrastructure.ps1 @@ -47,7 +47,7 @@ function Get-AbrADDNSInfrastructure { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "DNS Infrastructure Summary Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorInfrastructureSummarySection) $($_.Exception.Message)" } } } @@ -93,7 +93,7 @@ function Get-AbrADDNSInfrastructure { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Directory Partitions Item Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorDirectoryPartitionsItemSection) $($_.Exception.Message)" } } $TableParams = @{ @@ -107,13 +107,13 @@ function Get-AbrADDNSInfrastructure { $OutObj | Sort-Object -Property $reportTranslate.GetAbrADDNSInfrastructure.Name | Table @TableParams } } catch { - Write-PScriboMessage -IsWarning -Message "Directory Partitions Table Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorDirectoryPartitionsTableSection) $($_.Exception.Message)" } } } } } catch { - Write-PScriboMessage -IsWarning -Message "Directory Partitions Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorDirectoryPartitionsSection) $($_.Exception.Message)" } } #---------------------------------------------------------------------------------------------# @@ -140,7 +140,7 @@ function Get-AbrADDNSInfrastructure { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Response Rate Limiting (RRL) Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorRRLItem) $($_.Exception.Message)" } } } @@ -156,7 +156,7 @@ function Get-AbrADDNSInfrastructure { $OutObj | Sort-Object -Property $reportTranslate.GetAbrADDNSInfrastructure.DCName | Table @TableParams } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Response Rate Limiting (RRL) Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorRRLTable) $($_.Exception.Message)" } } #---------------------------------------------------------------------------------------------# @@ -189,7 +189,7 @@ function Get-AbrADDNSInfrastructure { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Scavenging Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorScavengingItem) $($_.Exception.Message)" } } } @@ -217,7 +217,7 @@ function Get-AbrADDNSInfrastructure { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Scavenging Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorScavengingTable) $($_.Exception.Message)" } } #---------------------------------------------------------------------------------------------# @@ -241,7 +241,7 @@ function Get-AbrADDNSInfrastructure { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Forwarder Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorForwarderItem) $($_.Exception.Message)" } } } @@ -285,7 +285,7 @@ function Get-AbrADDNSInfrastructure { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Forwarder Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorForwarderTable) $($_.Exception.Message)" } #---------------------------------------------------------------------------------------------# # DNS Root Hints Section # @@ -383,13 +383,13 @@ function Get-AbrADDNSInfrastructure { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Root Hints Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorRootHintsTable) $($_.Exception.Message)" } } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Root Hints Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorRootHintsSection) $($_.Exception.Message)" } } #---------------------------------------------------------------------------------------------# @@ -415,7 +415,7 @@ function Get-AbrADDNSInfrastructure { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Scope Recursion Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorZoneScopeRecursionItem) $($_.Exception.Message)" } } } @@ -431,13 +431,13 @@ function Get-AbrADDNSInfrastructure { $OutObj | Sort-Object -Property $reportTranslate.GetAbrADDNSInfrastructure.DCName | Table @TableParams } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Scope Recursion Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorZoneScopeRecursionTable) $($_.Exception.Message)" } } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (DNS Infrastructure Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSInfrastructure.ErrorDNSInfrastructureSection) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSZone.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSZone.ps1 index f055409..dfb5221 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSZone.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDNSZone.ps1 @@ -47,7 +47,7 @@ function Get-AbrADDNSZone { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Name System Zone Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorDNSZoneItem) $($_.Exception.Message)" } } @@ -83,14 +83,14 @@ function Get-AbrADDNSZone { } } } else { - Write-PScriboMessage -Message "DNS Zones $($Zone) Section: No Zone Delegation information found, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDNSZone.NoDelegationInfo -f $Zone) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Delegation Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorZoneDelegationItem) $($_.Exception.Message)" } } } else { - Write-PScriboMessage -Message "DNS Zones Section: No Zone Delegation information found in $DC, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDNSZone.NoDelegationInfoDC -f $DC) } if ($OutObj) { @@ -108,7 +108,7 @@ function Get-AbrADDNSZone { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Delegation Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorZoneDelegationTable) $($_.Exception.Message)" } } @@ -122,7 +122,7 @@ function Get-AbrADDNSZone { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "DNS Zones Transfers Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDNSZone.ErrorZoneTransferPSSession -f $DC, $ErrorMessage) } if ($DNSSetting) { Section -Style Heading4 $reportTranslate.GetAbrADDNSZone.ZoneTransfers { @@ -147,7 +147,7 @@ function Get-AbrADDNSZone { $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADDNSZone.SecureSecondaries) -eq $reportTranslate.GetAbrADDNSZone.SecureSecondariesAll } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADDNSZone.SecureSecondaries } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Transfers Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorZoneTransfersItem) $($_.Exception.Message)" } } @@ -170,10 +170,10 @@ function Get-AbrADDNSZone { } } } else { - Write-PScriboMessage -Message "DNS Zones Section: No Zone Transfer information found in $DC, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDNSZone.NoZoneTransferInfo -f $DC) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Transfers Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorZoneTransfersTable) $($_.Exception.Message)" } } try { @@ -194,7 +194,7 @@ function Get-AbrADDNSZone { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Reverse Lookup Zone Configuration Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorReverseLookupZoneItem) $($_.Exception.Message)" } } @@ -209,10 +209,10 @@ function Get-AbrADDNSZone { $OutObj | Sort-Object -Property $reportTranslate.GetAbrADDNSZone.ZoneName | Table @TableParams } } else { - Write-PScriboMessage -Message "DNS Zones Section: No Reverse lookup zone information found in $DC, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDNSZone.NoReverseLookupZoneInfo -f $DC) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Reverse Lookup Zone Configuration Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorReverseLookupZoneTable) $($_.Exception.Message)" } try { $DNSSetting = Get-DnsServerZone -CimSession $TempCIMSession -ComputerName $DC | Where-Object { $_.IsReverseLookupZone -like 'False' -and $_.ZoneType -like 'Forwarder' } @@ -230,7 +230,7 @@ function Get-AbrADDNSZone { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Conditional Forwarder Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorConditionalForwarderItem) $($_.Exception.Message)" } } @@ -245,10 +245,10 @@ function Get-AbrADDNSZone { $OutObj | Sort-Object -Property $reportTranslate.GetAbrADDNSZone.ZoneName | Table @TableParams } } else { - Write-PScriboMessage -Message "DNS Zones Section: No Conditional forwarder zone information found in $DC, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDNSZone.NoConditionalForwarderInfo -f $DC) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Conditional Forwarder Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorConditionalForwarderTable) $($_.Exception.Message)" } if ($InfoLevel.DNS -ge 2) { try { @@ -272,7 +272,7 @@ function Get-AbrADDNSZone { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Scope Aging Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorZoneScopeAgingItem) $($_.Exception.Message)" } } @@ -299,16 +299,16 @@ function Get-AbrADDNSZone { } } } else { - Write-PScriboMessage -Message "DNS Zones Section: No Zone Aging property information found in $DC, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDNSZone.NoZoneAgingInfo -f $DC) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Zone Scope Aging Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorZoneScopeAgingTable) $($_.Exception.Message)" } } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Global DNS Zone Information)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDNSZone.ErrorGlobalDNSZoneInfo) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomain.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomain.ps1 index 22880a7..c866ea4 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomain.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomain.ps1 @@ -68,7 +68,7 @@ function Get-AbrADDomain { } $TableParams = @{ - Name = "Domain Summary - $($Domain.DNSRoot.ToString().ToUpper())" + Name = "$($reportTranslate.GetAbrADDomain.TableName) - $($Domain.DNSRoot.ToString().ToUpper())" List = $true ColumnWidths = 40, 60 } @@ -91,7 +91,7 @@ function Get-AbrADDomain { } } } catch { - Write-PScriboMessage -IsWarning -Message "AD Domain Summary Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomain.ErrorSection) $($_.Exception.Message)" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainController.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainController.ps1 index 0cd679d..3180504 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainController.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainController.ps1 @@ -1,4 +1,4 @@ -function Get-AbrADDomainController { +function Get-AbrADDomainController { <# .SYNOPSIS Used by As Built Report to retrieve Microsoft AD Domain Controller information. @@ -34,12 +34,12 @@ function Get-AbrADDomainController { $DCPssSession = Get-ValidPSSession -ComputerName $DC -SessionName $($DC) -PSSTable ([ref]$PSSTable) if ($DCPssSession ) { - $DCNetSettings = try { Invoke-CommandWithTimeout -Session $DCPssSession -ScriptBlock { Get-NetIPAddress } } catch { Write-PScriboMessage -IsWarning -Message "Unable to get $DC network interfaces information" } + $DCNetSettings = try { Invoke-CommandWithTimeout -Session $DCPssSession -ScriptBlock { Get-NetIPAddress } } catch { Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorNetworkInterfacesInfo -f $DC) } } else { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "DC Net Settings Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorDCNetSettingsPSSession -f $DC, $ErrorMessage) } try { $inObj = [ordered] @{ @@ -60,11 +60,11 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCItem) $($_.Exception.Message)" } } else { try { - Write-PScriboMessage -Message "Unable to collect infromation from $DC." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDomainController.UnableToCollect -f $DC) $inObj = [ordered] @{ $($reportTranslate.GetAbrADDomainController.DCName) = $DC.ToString().ToUpper().Split('.')[0] $($reportTranslate.GetAbrADDomainController.Status) = $reportTranslate.GetAbrADDomainController.Offline @@ -75,7 +75,7 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCItem) $($_.Exception.Message)" } } } @@ -103,7 +103,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCTable) $($_.Exception.Message)" } try { $OutObj = [System.Collections.Generic.List[object]]::new() @@ -151,7 +151,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "DC Net Settings Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorDCNetSettingsPSSession -f $DC, $ErrorMessage) } try { Section -Style Heading5 $DCInfo.Name { @@ -204,7 +204,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (General Information Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorGeneralInfoSection) $($_.Exception.Message)" } try { Section -ExcludeFromTOC -Style NOTOCHeading6 $reportTranslate.GetAbrADDomainController.PartitionsTitle { @@ -227,7 +227,7 @@ function Get-AbrADDomainController { $OutObj | Table @TableParams } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Partitions Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorPartitionsSection) $($_.Exception.Message)" } try { if ($DCNetSettings) { @@ -274,7 +274,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Networking Settings Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorNetworkingSettingsSection) $($_.Exception.Message)" } try { $DCHWInfo = [System.Collections.Generic.List[object]]::new() @@ -343,14 +343,14 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Hardware Inventory Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorHardwareInventoryTable) $($_.Exception.Message)" } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Hardware Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCHardwareSection) $($_.Exception.Message)" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCSection) $($_.Exception.Message)" } } } @@ -360,7 +360,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCSection) $($_.Exception.Message)" } } #---------------------------------------------------------------------------------------------# @@ -381,7 +381,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "DNS IP Configuration Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorDNSIPConfigPSSession -f $DC, $ErrorMessage) } foreach ($DNSServer in $DNSSettings.ServerAddresses) { if ($DCPssSession) { @@ -403,15 +403,15 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($DC.ToString().ToUpper().Split('.')[0]) DNS IP Configuration Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDNSIPConfigItem) $($_.Exception.Message)" } } } catch { - Write-PScriboMessage -IsWarning -Message "Domain Controller DNS IP Configuration Table Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDNSIPConfigTableSection) $($_.Exception.Message)" } } else { try { - Write-PScriboMessage -Message "Unable to collect infromation from $DC." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDomainController.UnableToCollect -f $DC) $inObj = [ordered] @{ $($reportTranslate.GetAbrADDomainController.DCName) = $DC.ToString().ToUpper().Split('.')[0] $($reportTranslate.GetAbrADDomainController.Interface) = '--' @@ -422,7 +422,7 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (DNS IP Configuration Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDNSIPConfigItem) $($_.Exception.Message)" } } } @@ -482,7 +482,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "Domain Controller DNS IP Configuration Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDNSIPConfigSection) $($_.Exception.Message)" } try { @@ -501,7 +501,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "NTDS Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorNTDSPSSession -f $DC, $ErrorMessage) } if ( $NTDS -and $size ) { $inObj = [ordered] @{ @@ -514,11 +514,11 @@ function Get-AbrADDomainController { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (NTDS Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorNTDSItem) $($_.Exception.Message)" } } else { try { - Write-PScriboMessage -Message "Unable to collect infromation from $DC." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDomainController.UnableToCollect -f $DC) $inObj = [ordered] @{ $($reportTranslate.GetAbrADDomainController.DCName) = $DC.ToString().ToUpper().Split('.')[0] $($reportTranslate.GetAbrADDomainController.DatabaseFile) = '--' @@ -528,7 +528,7 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (NTDS Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorNTDSItem) $($_.Exception.Message)" } } } @@ -547,7 +547,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (NTDS section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorNTDSSection) $($_.Exception.Message)" } try { $OutObj = [System.Collections.Generic.List[object]]::new() @@ -563,7 +563,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Time Source Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorTimeSourcePSSession -f $DC, $ErrorMessage) } if ( $NtpServer -and $SourceType ) { try { @@ -583,15 +583,15 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning "$($_.Exception.Message) (Time Source Item)" + Write-PScriboMessage -IsWarning "$($reportTranslate.GetAbrADDomainController.ErrorTimeSourceItem) $($_.Exception.Message)" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Time Source Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorTimeSourceTable) $($_.Exception.Message)" } } else { try { - Write-PScriboMessage -Message "Unable to collect infromation from $DC." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDomainController.UnableToCollect -f $DC) $inObj = [ordered] @{ $($reportTranslate.GetAbrADDomainController.Name) = $DC.ToString().ToUpper().Split('.')[0] $($reportTranslate.GetAbrADDomainController.TimeServer) = '--' @@ -599,7 +599,7 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (NTDS Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorNTDSItem) $($_.Exception.Message)" } } } @@ -619,7 +619,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Time Source)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorTimeSource) $($_.Exception.Message)" } if ($HealthCheck.DomainController.Diagnostic) { try { @@ -691,7 +691,7 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning "$($_.Exception.Message) (SRV Records Status Item)" + Write-PScriboMessage -IsWarning "$($reportTranslate.GetAbrADDomainController.ErrorSRVRecordsStatusItem) $($_.Exception.Message)" } if ($HealthCheck.DomainController.Diagnostic) { $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADDomainController.ARecord) -eq $reportTranslate.GetAbrADDomainController.Fail } | Set-Style -Style Critical -Property $reportTranslate.GetAbrADDomainController.ARecord @@ -703,11 +703,11 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SRV Records Status Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorSRVRecordsStatusTable) $($_.Exception.Message)" } } else { try { - Write-PScriboMessage -Message "Unable to collect infromation from $DC." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADDomainController.UnableToCollect -f $DC) $inObj = [ordered] @{ $($reportTranslate.GetAbrADDomainController.Name) = $DC.ToString().ToUpper().Split('.')[0] $($reportTranslate.GetAbrADDomainController.ARecord) = '--' @@ -718,7 +718,7 @@ function Get-AbrADDomainController { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (NTDS Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorNTDSItem) $($_.Exception.Message)" } } } @@ -746,7 +746,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SRV Records Status)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorSRVRecordsStatus) $($_.Exception.Message)" } } try { @@ -763,7 +763,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Domain Controllers File Shares Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorFileSharesPSSession -f $DC, $ErrorMessage) } if ($Shares) { Section -ExcludeFromTOC -Style NOTOCHeading5 $($DC.ToString().ToUpper().Split('.')[0]) { @@ -794,7 +794,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (File Shares Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorFileSharesItem) $($_.Exception.Message)" } } } @@ -813,7 +813,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (File Shares Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorFileSharesTable) $($_.Exception.Message)" } if ($HealthCheck.DomainController.Software) { try { @@ -832,7 +832,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Domain Controller Installed Software Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorInstalledSoftwarePSSession -f $DC, $ErrorMessage) } if ($SoftwareX64) { @@ -897,7 +897,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Installed Software Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorInstalledSoftwareTable) $($_.Exception.Message)" } } } @@ -909,7 +909,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Installed Software Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorInstalledSoftwareSection) $($_.Exception.Message)" } try { # Todo: Fix arraylist issue with foreach @@ -926,7 +926,7 @@ function Get-AbrADDomainController { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Domain Controller Pending Missing Patch Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADDomainController.ErrorMissingPatchPSSession -f $DC, $ErrorMessage) } if ( $Updates ) { @@ -967,7 +967,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Installed Software Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorInstalledSoftwareTable) $($_.Exception.Message)" } } } @@ -979,7 +979,7 @@ function Get-AbrADDomainController { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainController.ErrorDCSection) $($_.Exception.Message)" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainLastBackup.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainLastBackup.ps1 index ac50a68..d78e2d9 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainLastBackup.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainLastBackup.ps1 @@ -49,7 +49,7 @@ function Get-AbrADDomainLastBackup { $OutObj | Where-Object { [int]$_.$($reportTranslate.GetAbrADDomainLastBackup.LastBackupInDays) -gt 180 } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADDomainLastBackup.LastBackupInDays } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Last Backup Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADDomainLastBackup.ErrorDomainLastBackupItem))" } } @@ -78,7 +78,7 @@ function Get-AbrADDomainLastBackup { Write-PScriboMessage -Message ($reportTranslate.GetAbrADDomainLastBackup.NoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Last Backup Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADDomainLastBackup.ErrorDomainLastBackupTable))" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainObject.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainObject.ps1 index dea976f..f70662a 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainObject.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDomainObject.ps1 @@ -65,10 +65,10 @@ function Get-AbrADDomainObject { $ADObjects = $Users + $GroupObj } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Object Stats)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorDomainObjectStats) $($_.Exception.Message)" } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Object Stats)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorDomainObjectStats) $($_.Exception.Message)" } try { Section -Style Heading4 $reportTranslate.GetAbrADDomainObject.UserObjectsSection { @@ -94,7 +94,7 @@ function Get-AbrADDomainObject { $sampleData = $inObj.GetEnumerator() | Select-Object @{ Name = 'Name'; Expression = { $_.key } }, @{ Name = 'Value'; Expression = { $_.value } } | Sort-Object -Property 'Category' $Chart = New-PieChart -Values $sampleData.Value -Labels $sampleData.Name -Title "$($reportTranslate.GetAbrADDomainObject.UserObjectsSection)" -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 400 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (User Object Count Chart)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorUserObjectCountChart) $($_.Exception.Message)" } if ($OutObj) { @@ -170,7 +170,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Status of User Accounts)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorStatusOfUserAccounts) $($_.Exception.Message)" } } @@ -186,7 +186,7 @@ function Get-AbrADDomainObject { $sampleData = $OutObj $Chart = New-PieChart -Values $sampleData.$($reportTranslate.GetAbrADDomainObject.Total) -Labels $sampleData.$($reportTranslate.GetAbrADDomainObject.Category) -Title "$($reportTranslate.GetAbrADDomainObject.StatusOfUsersSection)" -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 800 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Status of Users Accounts Chart)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorStatusOfUsersAccountsChart) $($_.Exception.Message)" } } if ($OutObj) { @@ -223,7 +223,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Users Objects Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorUsersObjectsTable) $($_.Exception.Message)" } } @@ -241,7 +241,7 @@ function Get-AbrADDomainObject { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Users Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorUsersObjectsSection) $($_.Exception.Message)" } } Show-AbrDebugExecutionTime -End -TitleMessage 'User Objects' @@ -272,7 +272,7 @@ function Get-AbrADDomainObject { $sampleData = $inObj.GetEnumerator() | Select-Object @{ Name = 'Name'; Expression = { $_.key } }, @{ Name = 'Value'; Expression = { $_.value } } | Sort-Object -Property 'Name' $Chart = New-PieChart -Values $sampleData.Value -Labels $sampleData.Name -Title $reportTranslate.GetAbrADDomainObject.GroupCategoriesSubSection -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 400 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Category Object Chart)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorGroupCategoryObjectChart) $($_.Exception.Message)" } if ($OutObj) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADDomainObject.GroupCategoriesSubSection { @@ -306,7 +306,7 @@ function Get-AbrADDomainObject { $sampleData = $inObj.GetEnumerator() | Select-Object @{ Name = 'Name'; Expression = { $_.key } }, @{ Name = 'Value'; Expression = { $_.value } } | Sort-Object -Property 'Name' $Chart = New-PieChart -Values $sampleData.Value -Labels $sampleData.Name -Title $reportTranslate.GetAbrADDomainObject.GroupScopesSubSection -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 400 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Scopes Object Chart)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorGroupScopesObjectChart) $($_.Exception.Message)" } if ($OutObj) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADDomainObject.GroupScopesSubSection { @@ -335,7 +335,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Groups Objects Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorGroupsObjectsTable) $($_.Exception.Message)" } } @@ -353,7 +353,7 @@ function Get-AbrADDomainObject { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Groups Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorGroupsObjectsSection) $($_.Exception.Message)" } } if ($GroupOBj) { @@ -379,7 +379,7 @@ function Get-AbrADDomainObject { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Group in Active Directory item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPrivilegedGroup) $($_.Exception.Message)" } } @@ -438,7 +438,7 @@ function Get-AbrADDomainObject { if ($Group = ($GroupOBj | Where-Object { $_.SID -like $GroupSID })) { $GroupObjects = $Group.Members if ($GroupObjFilter = $ADObjects | Where-Object { $_.distinguishedName -in $GroupObjects }) { - Section -ExcludeFromTOC -Style NOTOCHeading4 "$($Group.Name) ($(($GroupObjects | Measure-Object).count) Members)" { + Section -ExcludeFromTOC -Style NOTOCHeading4 "$($Group.Name) ($(($GroupObjects | Measure-Object).count) $($reportTranslate.GetAbrADDomainObject.MembersLabel))" { $OutObj = [System.Collections.Generic.List[object]]::new() foreach ($GroupObject in $GroupObjFilter) { try { @@ -454,7 +454,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Group in Active Directory item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPrivilegedGroup) $($_.Exception.Message)" } } @@ -472,7 +472,7 @@ function Get-AbrADDomainObject { } $TableParams = @{ - Name = "$($Group.Name) - $($Domain.DNSRoot.ToString().ToUpper())" + Name = "$($reportTranslate.GetAbrADDomainObject.PrivilegedGroupMembersTableName) $($Group.Name) - $($Domain.DNSRoot.ToString().ToUpper())" List = $false ColumnWidths = 50, 20, 15, 15 } @@ -520,13 +520,13 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Group in Active Directory item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPrivilegedGroup) $($_.Exception.Message)" } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Group in Active Directory)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPrivilegedGroup) $($_.Exception.Message)" } Show-AbrDebugExecutionTime -End -TitleMessage 'Privileged Groups (Built-in)' } @@ -545,7 +545,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Group (Non-Default) Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPrivilegedGroupNonDefaultTable) $($_.Exception.Message)" } } } @@ -576,7 +576,7 @@ function Get-AbrADDomainObject { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Group (Non-Default) Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPrivilegedGroupNonDefaultSection) $($_.Exception.Message)" } } if ($HealthCheck.Domain.BestPractice -and ($EmptyGroupOBj)) { @@ -594,7 +594,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Empty Groups Objects Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorEmptyGroupsObjectsTable) $($_.Exception.Message)" } } } @@ -620,7 +620,7 @@ function Get-AbrADDomainObject { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Empty Groups Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorEmptyGroupsObjectsSection) $($_.Exception.Message)" } } if ($HealthCheck.Domain.BestPractice -and $InfoLevel.Domain -ge 2) { @@ -648,7 +648,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Circular Group Membership Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorCircularGroupMembershipTable) $($_.Exception.Message)" } } } @@ -686,7 +686,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Circular Group Membership Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorCircularGroupMembershipSection) $($_.Exception.Message)" } } if ($HealthCheck.Domain.Security) { @@ -699,15 +699,15 @@ function Get-AbrADDomainObject { foreach ($MemberDN in $GroupMembers) { try { if ($MemberUser = $Users | Where-Object { $_.DistinguishedName -eq $MemberDN }) { - $MemberName = "$($MemberUser.SamAccountName) (USER)" + $MemberName = "$($MemberUser.SamAccountName) ($($reportTranslate.GetAbrADDomainObject.TypeLabelUser))" } elseif ($MemberComputer = $Computers | Where-Object { $_.DistinguishedName -eq $MemberDN }) { - $MemberName = "$($MemberComputer.Name) (COMPUTER)" + $MemberName = "$($MemberComputer.Name) ($($reportTranslate.GetAbrADDomainObject.TypeLabelComputer))" } elseif ($MemberGroup = $GroupOBj | Where-Object { $_.DistinguishedName -eq $MemberDN }) { - $MemberName = "$($MemberGroup.Name) (GROUP)" + $MemberName = "$($MemberGroup.Name) ($($reportTranslate.GetAbrADDomainObject.TypeLabelGroup))" } elseif ($MemberFSP = $FSP | Where-Object { $_.DistinguishedName -eq $MemberDN }) { - $MemberName = "$($MemberFSP.'msds-principalname') (FOREIGN SECURITY PRINCIPAL)" + $MemberName = "$($MemberFSP.'msds-principalname') ($($reportTranslate.GetAbrADDomainObject.TypeLabelFSP))" } elseif ($MemberDN -match 'ForeignSecurityPrincipals') { - $MemberName = "$(($MemberDN -split ',')[0] -replace '^CN=') (FOREIGN SECURITY PRINCIPAL)" + $MemberName = "$(($MemberDN -split ',')[0] -replace '^CN=') ($($reportTranslate.GetAbrADDomainObject.TypeLabelFSP))" } else { $MemberName = ($MemberDN -split ',')[0] -replace '^CN=' } @@ -717,7 +717,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Pre-Windows 2000 Compatible Access Group Member)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPreWin2000) $($_.Exception.Message)" } } if ($OutObj) { @@ -745,7 +745,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Pre-Windows 2000 Compatible Access Group Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorPreWin2000) $($_.Exception.Message)" } Show-AbrDebugExecutionTime -End -TitleMessage 'Pre-Windows 2000 Compatible Access Group' } @@ -776,7 +776,7 @@ function Get-AbrADDomainObject { $sampleData = $inObj.GetEnumerator() | Select-Object @{ Name = 'Name'; Expression = { $_.key } }, @{ Name = 'Value'; Expression = { $_.value } } | Sort-Object -Property 'Name' $Chart = New-PieChart -Values $sampleData.Value -Labels $sampleData.Name -Title "$($reportTranslate.GetAbrADDomainObject.ComputersCount)" -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 400 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Computers Object Count Chart)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorComputersObjectCountChart) $($_.Exception.Message)" } if ($OutObj) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADDomainObject.ComputersSubSection { @@ -838,7 +838,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Status of Computer Accounts)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorStatusOfComputerAccounts) $($_.Exception.Message)" } } @@ -854,7 +854,7 @@ function Get-AbrADDomainObject { $sampleData = $OutObj $Chart = New-PieChart -Values $sampleData.$($reportTranslate.GetAbrADDomainObject.Total) -Labels $sampleData.$($reportTranslate.GetAbrADDomainObject.Category) -Title "$($reportTranslate.GetAbrADDomainObject.StatusOfComputerAccountsSection)" -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 400 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Status of Computers Accounts Chart)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorStatusOfComputersAccountsChart) $($_.Exception.Message)" } if ($OutObj) { @@ -910,7 +910,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Operating Systems in Active Directory)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorOperatingSystemsInAD) $($_.Exception.Message)" } Show-AbrDebugExecutionTime -End -TitleMessage 'Operating Systems Count' } @@ -951,14 +951,14 @@ function Get-AbrADDomainObject { Text $reportTranslate.GetAbrADDomainObject.PasswordNotRequiredBP } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Computers with Password-Not-Required table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorComputersPasswordNotRequired) $($_.Exception.Message)" } } Show-AbrDebugExecutionTime -End -TitleMessage 'Computers with Password-Not-Required Attribute Set' } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Computers with Password-Not-Required section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorComputersPasswordNotRequired) $($_.Exception.Message)" } if ($InfoLevel.Domain -ge 4) { try { @@ -979,7 +979,7 @@ function Get-AbrADDomainObject { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Computers Objects Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorComputersObjectsTable) $($_.Exception.Message)" } } @@ -997,7 +997,7 @@ function Get-AbrADDomainObject { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Computers Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorComputersObjectsSection) $($_.Exception.Message)" } } Show-AbrDebugExecutionTime -End -TitleMessage 'Computer Objects' @@ -1051,7 +1051,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Default Domain Password Policy)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorDefaultDomainPasswordPolicy) $($_.Exception.Message)" } Show-AbrDebugExecutionTime -End -TitleMessage 'Default Domain Password Policy' } @@ -1123,7 +1123,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Fined Grained Password Policies)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorFGPP) $($_.Exception.Message)" } try { @@ -1192,7 +1192,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Windows LAPS)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorWindowsLAPS) $($_.Exception.Message)" } try { @@ -1231,7 +1231,7 @@ function Get-AbrADDomainObject { $GMSAInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Managed Service Accounts Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorGMSAItem) $($_.Exception.Message)" } } @@ -1264,7 +1264,7 @@ function Get-AbrADDomainObject { foreach ($Account in $GMSAInfo) { Section -Style NOTOCHeading4 -ExcludeFromTOC "$($Account.$($reportTranslate.GetAbrADDomainObject.GMSAName))" { $TableParams = @{ - Name = "gMSA - $($Account.$($reportTranslate.GetAbrADDomainObject.GMSAName))" + Name = "$($reportTranslate.GetAbrADDomainObject.GMSATableName) - $($Account.$($reportTranslate.GetAbrADDomainObject.GMSAName))" List = $true ColumnWidths = 40, 60 } @@ -1299,7 +1299,7 @@ function Get-AbrADDomainObject { } } else { $TableParams = @{ - Name = "gMSA - $($Domain.DNSRoot.ToString().ToUpper())" + Name = "$($reportTranslate.GetAbrADDomainObject.GMSATableName) - $($Domain.DNSRoot.ToString().ToUpper())" List = $false Columns = $reportTranslate.GetAbrADDomainObject.GMSAName, $reportTranslate.GetAbrADDomainObject.GMSALogonCount, $reportTranslate.GetAbrADDomainObject.GMSALockedOut, $reportTranslate.GetAbrADDomainObject.GMSALastLogonDate, $reportTranslate.GetAbrADDomainObject.GMSAPasswordLastSet, $reportTranslate.GetAbrADDomainObject.GMSAEnabled ColumnWidths = 25, 15, 15, 15, 15, 15 @@ -1323,7 +1323,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Managed Service Accounts Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorGMSASection) $($_.Exception.Message)" } } catch { Write-PScriboMessage -IsWarning $($_.Exception.Message) @@ -1349,7 +1349,7 @@ function Get-AbrADDomainObject { $FSPInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Foreign Security Principals Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorFSPItem) $($_.Exception.Message)" } } @@ -1366,7 +1366,7 @@ function Get-AbrADDomainObject { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Foreign Security Principals Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADDomainObject.ErrorFSPSection) $($_.Exception.Message)" } } catch { Write-PScriboMessage -IsWarning $($_.Exception.Message) diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateObject.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateObject.ps1 index e1b7660..d13417c 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateObject.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateObject.ps1 @@ -47,7 +47,7 @@ function Get-AbrADDuplicateObject { $OutObj | Set-Style -Style Warning } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Duplicate Object Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADDuplicateObject.ErrorDuplicateObjectItem))" } } @@ -72,7 +72,7 @@ function Get-AbrADDuplicateObject { Write-PScriboMessage -Message ($reportTranslate.GetAbrADDuplicateObject.NoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Duplicate Object Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADDuplicateObject.ErrorDuplicateObjectTable))" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateSPN.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateSPN.ps1 index f0306c5..4389cf8 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateSPN.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADDuplicateSPN.ps1 @@ -46,7 +46,7 @@ function Get-AbrADDuplicateSPN { $OutObj | Set-Style -Style Warning } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SPN Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADDuplicateSPN.ErrorSPNItem))" } } @@ -73,7 +73,7 @@ function Get-AbrADDuplicateSPN { Write-PScriboMessage -Message ($reportTranslate.GetAbrADDuplicateSPN.NoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SPN Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADDuplicateSPN.ErrorSPNTable))" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADExchange.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADExchange.ps1 index fea6e8d..8a8c723 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADExchange.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADExchange.ps1 @@ -41,7 +41,7 @@ function Get-AbrADExchange { } $EXInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Exchange Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADExchange.ErrorExchangeItem))" } } @@ -73,12 +73,12 @@ function Get-AbrADExchange { } } } else { - Write-PScriboMessage -Message "No Exchange Infrastructure information found in $($ForestInfo.toUpper()), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADExchange.NoExchangeInfo -f $ForestInfo.toUpper()) Paragraph $reportTranslate.GetAbrADExchange.NotFound BlankLine } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Exchabge Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADExchange.ErrorExchangeTable))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADFSMO.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADFSMO.ps1 index 48efead..dcb2a2c 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADFSMO.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADFSMO.ps1 @@ -45,7 +45,7 @@ function Get-AbrADFSMO { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Flexible Single Master Operations)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADFSMO.ErrorFSMOItem))" } if ($HealthCheck.Domain.BestPractice) { @@ -55,7 +55,7 @@ function Get-AbrADFSMO { } $TableParams = @{ - Name = "FSMO Roles - $($Domain.DNSRoot)" + Name = "$($reportTranslate.GetAbrADFSMO.TableName) - $($Domain.DNSRoot)" List = $true ColumnWidths = 40, 60 } @@ -81,12 +81,12 @@ function Get-AbrADFSMO { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "FSMO Roles Section: New-PSSession: Unable to connect to $($Domain.DNSRoot): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADFSMO.ErrorPSSession -f $Domain.DNSRoot, $ErrorMessage) } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Flexible Single Master Operations)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADFSMO.ErrorFSMOItem))" } } end { diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADForest.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADForest.ps1 index 76d07c6..81d81ef 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADForest.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADForest.ps1 @@ -79,7 +79,7 @@ function Get-AbrADForest { } $TableParams = @{ - Name = "Forest Summary - $($ForestInfo)" + Name = "$($reportTranslate.GetAbrADForest.TableName) - $($ForestInfo)" List = $true ColumnWidths = 40, 60 } @@ -112,7 +112,7 @@ function Get-AbrADForest { try { $Graph = Get-AbrDiagrammer -DiagramType 'Forest' -DiagramOutput base64 -PSSessionObject $TempPssSession } catch { - Write-PScriboMessage -IsWarning -Message "Forest Diagram Graph: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADForest.ErrorForestDiagramGraph) $($_.Exception.Message)" } if ($Graph) { @@ -124,7 +124,7 @@ function Get-AbrADForest { } } } catch { - Write-PScriboMessage -IsWarning -Message "Forest Diagram Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADForest.ErrorForestDiagramSection) $($_.Exception.Message)" } } } @@ -183,7 +183,7 @@ function Get-AbrADForest { } } } else { - Write-PScriboMessage -Message "No Certificate Authority Root information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADForest.NoCARootInfo -f $ForestInfo) } if ($subordinateCA) { @@ -212,7 +212,7 @@ function Get-AbrADForest { $OutObj | Sort-Object -Property $reportTranslate.GetAbrADForest.CAName | Table @TableParams } } else { - Write-PScriboMessage -Message 'No Certificate Authority Issuer information found, Disabling this section.' + Write-PScriboMessage -Message $reportTranslate.GetAbrADForest.NoCAIssuerInfo } } if ($Options.EnableDiagrams) { @@ -220,7 +220,7 @@ function Get-AbrADForest { try { $Graph = Get-AbrDiagrammer -DiagramType 'CertificateAuthority' -DiagramOutput base64 -PSSessionObject $TempPssSession } catch { - Write-PScriboMessage -IsWarning -Message "Certificate Authority Diagram Graph: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADForest.ErrorCADiagramGraph) $($_.Exception.Message)" } if ($Graph) { @@ -232,7 +232,7 @@ function Get-AbrADForest { } } } catch { - Write-PScriboMessage -IsWarning -Message "Certificate Authority Diagram Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADForest.ErrorCADiagramSection) $($_.Exception.Message)" } } } @@ -289,7 +289,7 @@ function Get-AbrADForest { } } } else { - Write-PScriboMessage -Message "No Optional Feature information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADForest.NoOptionalFeatureInfo -f $ForestInfo) } } } catch { diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADGPO.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADGPO.ps1 index 02d228c..11829a4 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADGPO.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADGPO.ps1 @@ -56,7 +56,7 @@ function Get-AbrADGPO { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Policy Objects)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOItem) $($_.Exception.Message)" } } @@ -102,7 +102,7 @@ function Get-AbrADGPO { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Policy Objects)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOItem) $($_.Exception.Message)" } } if ($InfoLevel.Domain -ge 2) { @@ -187,12 +187,12 @@ function Get-AbrADGPO { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Policy Objects)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOItem) $($_.Exception.Message)" } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (WMI Filters)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorWMIFiltersItem) $($_.Exception.Message)" } } } @@ -210,7 +210,7 @@ function Get-AbrADGPO { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Wmi Filters Section: New-PSSession: Unable to connect to $($ValidDCFromDomain): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADGPO.ErrorWMIFiltersPSSession -f $ValidDCFromDomain, $ErrorMessage) } if ($WmiFilters) { @@ -245,7 +245,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.WMINoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (WMI Filters)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorWMIFiltersItem) $($_.Exception.Message)" } } try { @@ -288,7 +288,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.CentralStoreNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (GPO Central Store)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOCentralStore) $($_.Exception.Message)" } try { if ($GPOs) { @@ -313,7 +313,7 @@ function Get-AbrADGPO { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (GPO with Logon/Logoff Script Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOLogonLogoffItem) $($_.Exception.Message)" } } } @@ -338,7 +338,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.LogonLogoffNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (GPO with Logon/Logoff Script Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOLogonLogoffSection) $($_.Exception.Message)" } try { if ($GPOs) { @@ -358,12 +358,12 @@ function Get-AbrADGPO { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (GPO with Computer Startup/Shutdown Script Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOStartupShutdownItem) $($_.Exception.Message)" } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (GPO with Computer Startup/Shutdown Script)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOStartupShutdownItem) $($_.Exception.Message)" } } } @@ -389,7 +389,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.StartupShutdownNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (GPO with Computer Startup/Shutdown Script Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOStartupShutdownSection) $($_.Exception.Message)" } } } @@ -414,7 +414,7 @@ function Get-AbrADGPO { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Unlinked Group Policy Objects Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorUnlinkedGPOItem) $($_.Exception.Message)" } } } @@ -445,7 +445,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.UnlinkedGPONoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Unlinked Group Policy Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorUnlinkedGPOSection) $($_.Exception.Message)" } try { $OutObj = [System.Collections.Generic.List[object]]::new() @@ -463,7 +463,7 @@ function Get-AbrADGPO { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Empty Group Policy Objects Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorEmptyGPOItem) $($_.Exception.Message)" } } } @@ -494,7 +494,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.EmptyGPONoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Empty Group Policy Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorEmptyGPOSection) $($_.Exception.Message)" } try { $OutObj = [System.Collections.Generic.List[object]]::new() @@ -518,7 +518,7 @@ function Get-AbrADGPO { } } } catch { - Write-PScriboMessage -IsWarning -Message "OU: $($OU): $($_.Exception.Message) (Enforced Group Policy Objects Item)" + Write-PScriboMessage -IsWarning -Message "OU: $($OU): $($reportTranslate.GetAbrADGPO.ErrorEnforcedGPOItem) $($_.Exception.Message)" } } } @@ -551,7 +551,7 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.EnforcedGPONoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Enforced Group Policy Objects Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorEnforcedGPOTable) $($_.Exception.Message)" } # Code taken from Jeremy Saunders # https://github.com/jeremyts/ActiveDirectoryDomainServices/blob/master/Audit/FindOrphanedGPOs.ps1 @@ -564,7 +564,7 @@ function Get-AbrADGPO { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Orphaned GPO Section: New-PSSession: Unable to connect to $($ValidDCFromDomain): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADGPO.ErrorOrphanedGPOPSSession -f $ValidDCFromDomain, $ErrorMessage) } $GPOPoliciesSYSVOLUNC = "\\$($Domain.DNSRoot)\SYSVOL\$($Domain.DNSRoot)\Policies" $OrphanGPOs = [System.Collections.Generic.List[object]]::new() @@ -658,13 +658,13 @@ function Get-AbrADGPO { Write-PScriboMessage -Message ($reportTranslate.GetAbrADGPO.OrphanedGPONoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Orphaned GPO)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorOrphanedGPOItem) $($_.Exception.Message)" } } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Group Policy Objects Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADGPO.ErrorGPOSection) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADHardening.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADHardening.ps1 index 1fd7668..7494f08 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADHardening.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADHardening.ps1 @@ -175,11 +175,11 @@ function Get-AbrADHardening { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (ADHardening Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADHardening.ErrorADHardeningItem))" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (ADHardening Section)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADHardening.ErrorADHardeningSection))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADInfrastructureService.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADInfrastructureService.ps1 index a0fd536..72304e6 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADInfrastructureService.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADInfrastructureService.ps1 @@ -33,7 +33,7 @@ function Get-AbrADInfrastructureService { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Domain Controller Infrastructure Services Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADInfrastructureService.ErrorPSSession -f $DC, $ErrorMessage) } if ($Available) { $OutObj = [System.Collections.Generic.List[object]]::new() @@ -50,7 +50,7 @@ function Get-AbrADInfrastructureService { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Infrastructure Services Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADInfrastructureService.ErrorDCInfraServicesItem))" } } @@ -96,7 +96,7 @@ function Get-AbrADInfrastructureService { Write-PScriboMessage -Message ($reportTranslate.GetAbrADInfrastructureService.NoData -f $DC) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Controller Infrastructure Services Section)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADInfrastructureService.ErrorDCInfraServicesTable))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADKerberosAudit.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADKerberosAudit.ps1 index 6ffe642..44080e1 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADKerberosAudit.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADKerberosAudit.ps1 @@ -42,7 +42,7 @@ function Get-AbrADKerberosAudit { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Unconstrained Kerberos delegation Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADKerberosAudit.ErrorUnconstrainedKerberosItem))" } } @@ -86,7 +86,7 @@ function Get-AbrADKerberosAudit { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (KRBTGT account Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADKerberosAudit.ErrorKRBTGTAccountItem))" } if ($HealthCheck.Domain.Security) { @@ -114,7 +114,7 @@ function Get-AbrADKerberosAudit { Write-PScriboMessage -Message ($reportTranslate.GetAbrADKerberosAudit.KRBTGTNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Unconstrained Kerberos delegation Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADKerberosAudit.ErrorUnconstrainedKerberosItem))" } try { $SID = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { "$($($using:Domain).domainsid.ToString())-500" } @@ -134,7 +134,7 @@ function Get-AbrADKerberosAudit { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (ADMIN account Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADKerberosAudit.ErrorAdminAccountItem))" } if ($HealthCheck.Domain.Security) { @@ -162,10 +162,10 @@ function Get-AbrADKerberosAudit { Write-PScriboMessage -Message ($reportTranslate.GetAbrADKerberosAudit.AdminNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Unconstrained Kerberos delegation Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADKerberosAudit.ErrorUnconstrainedKerberosItem))" } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Unconstrained Kerberos delegation Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADKerberosAudit.ErrorUnconstrainedKerberosSection))" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADOU.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADOU.ps1 index eb33870..f1eb319 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADOU.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADOU.ps1 @@ -52,7 +52,7 @@ function Get-AbrADOU { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Organizational Unit Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADOU.ErrorOUItem))" } } @@ -94,7 +94,7 @@ function Get-AbrADOU { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Blocked Inheritance GPO Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADOU.ErrorBlockedInheritanceGPOItem))" } } } @@ -124,7 +124,7 @@ function Get-AbrADOU { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Blocked Inheritance GPO Section)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADOU.ErrorBlockedInheritanceGPOSection))" } } } @@ -132,7 +132,7 @@ function Get-AbrADOU { Write-PScriboMessage -Message ($reportTranslate.GetAbrADOU.OUNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Organizational Unit Section)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADOU.ErrorOUSection))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADReportBrief.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADReportBrief.ps1 index fe11695..899ffd1 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADReportBrief.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADReportBrief.ps1 @@ -51,7 +51,7 @@ function Get-AbrADReportBrief { } $OutObj | Table @TableParams } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Report Brief - Report Overview)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADReportBrief.ErrorReportOverview))" } BlankLine @@ -79,7 +79,7 @@ function Get-AbrADReportBrief { } $OutObj | Table @TableParams } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Report Brief - Forest Summary)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADReportBrief.ErrorForestSummary))" } BlankLine @@ -103,7 +103,7 @@ function Get-AbrADReportBrief { } $OutObj.Add([pscustomobject]$inObj) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Report Brief - Domain Summary - $Domain)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADReportBrief.ErrorDomainSummaryItem))" } } @@ -121,7 +121,7 @@ function Get-AbrADReportBrief { $OutObj | Table @TableParams } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Report Brief - Domain Summary)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADReportBrief.ErrorDomainSummary))" } BlankLine @@ -162,12 +162,12 @@ function Get-AbrADReportBrief { } $OutObj | Table @TableParams } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Report Brief - Report Scope)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADReportBrief.ErrorReportScope))" } } PageBreak } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Report Brief Section)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADReportBrief.ErrorReportBriefSection))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSCCM.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSCCM.ps1 index 375886c..cf9604f 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSCCM.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSCCM.ps1 @@ -42,7 +42,7 @@ function Get-AbrADSCCM { } $SCCMInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.SCCMception.Message) (SCCM Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSCCM.ErrorSCCMItem) $($_.Exception.Message)" } } @@ -74,12 +74,12 @@ function Get-AbrADSCCM { } } } else { - Write-PScriboMessage -Message "No SCCM Infrastructure information found in $($ForestInfo.toUpper()), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSCCM.NoSCCMInfo -f $ForestInfo.toUpper()) Paragraph $reportTranslate.GetAbrADSCCM.NotFound BlankLine } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.SCCMception.Message) (SCCM Table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSCCM.ErrorSCCMTable) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSecurityAssessment.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSecurityAssessment.ps1 index 99789ea..9e6f2df 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSecurityAssessment.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSecurityAssessment.ps1 @@ -56,7 +56,7 @@ function Get-AbrADSecurityAssessment { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Account Security Assessment Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorAccountSecurityAssessmentItem))" } if ($HealthCheck.Domain.Security) { @@ -83,7 +83,7 @@ function Get-AbrADSecurityAssessment { $sampleData = $inObj.GetEnumerator() | Select-Object @{ Name = 'Category'; Expression = { $_.key } }, @{ Name = 'Value'; Expression = { $_.value } } $Chart = New-PieChart -Values $sampleData.Value -Labels $sampleData.Category -Title $reportTranslate.GetAbrADSecurityAssessment.UserAccountTitle -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 600 -Format base64 -TitleFontSize 20 -TitleFontBold -EnableCustomColorPalette -CustomColorPalette $AbrCustomPalette -EnableChartBorder -ChartBorderStyle DenselyDashed -ChartBorderColor DarkBlue } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (User Account Security Assessment Chart)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorUserAccountSecurityAssessmentChart))" } if ($OutObj) { Section -ExcludeFromTOC -Style NOTOCHeading4 $reportTranslate.GetAbrADSecurityAssessment.UserAccountTitle { @@ -101,10 +101,10 @@ function Get-AbrADSecurityAssessment { } } } else { - Write-PScriboMessage -Message "No Domain users information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSecurityAssessment.NoUserInfo -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Account Security Assessment Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorAccountSecurityAssessmentTable))" } if ($InfoLevel.Domain -ge 2) { try { @@ -139,7 +139,7 @@ function Get-AbrADSecurityAssessment { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Users Assessment Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorPrivilegedUsersAssessmentItem))" } } @@ -186,10 +186,10 @@ function Get-AbrADSecurityAssessment { } } } else { - Write-PScriboMessage -Message "No Privileged User Assessment information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSecurityAssessment.NoPrivilegedUserInfo -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Privileged Users Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorPrivilegedUsersTable))" } try { $InactivePrivilegedUsers = $PrivilegedUsers | Where-Object { ($_.LastLogonDate -le (Get-Date).AddDays(-30)) -and ($_.PasswordLastSet -le (Get-Date).AddDays(-365)) -and ($_.SamAccountName -ne 'krbtgt') -and ($_.SamAccountName -ne 'Administrator') } @@ -217,7 +217,7 @@ function Get-AbrADSecurityAssessment { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Inactive Privileged Accounts Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorInactivePrivilegedAccountsItem))" } } @@ -243,10 +243,10 @@ function Get-AbrADSecurityAssessment { } } } else { - Write-PScriboMessage -Message "No Inactive Privileged Accounts information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSecurityAssessment.NoInactivePrivilegedInfo -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Inactive Privileged Accounts Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorInactivePrivilegedAccountsTable))" } try { $UserSPNs = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADUser -ResultPageSize 1000 -Server ($using:Domain).DNSRoot -Filter { ServicePrincipalName -like '*' } -Properties AdminCount, PasswordLastSet, LastLogonDate, ServicePrincipalName, TrustedForDelegation, TrustedtoAuthForDelegation } @@ -273,7 +273,7 @@ function Get-AbrADSecurityAssessment { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Service Accounts Assessment Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorServiceAccountsAssessmentItem))" } } @@ -305,10 +305,10 @@ function Get-AbrADSecurityAssessment { } } } else { - Write-PScriboMessage -Message "No Service Accounts Assessment information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSecurityAssessment.NoServiceAccountsInfo -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Service Accounts Assessment Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADSecurityAssessment.ErrorServiceAccountsAssessmentTable))" } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSite.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSite.ps1 index 9cfc160..3064a6f 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSite.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSite.ps1 @@ -36,7 +36,7 @@ function Get-AbrADSite { try { $Graph = Get-AbrDiagrammer -DiagramType 'Replication' -DiagramOutput base64 -PSSessionObject $TempPssSession } catch { - Write-PScriboMessage -IsWarning -Message "Replication Diagram Graph: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorReplicationDiagramGraph) $($_.Exception.Message)" } if ($Graph) { @@ -48,7 +48,7 @@ function Get-AbrADSite { } } } catch { - Write-PScriboMessage -IsWarning -Message "Replication Diagram Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorReplicationDiagramSection) $($_.Exception.Message)" } } Section -Style Heading4 $reportTranslate.GetAbrADSite.Sites { @@ -82,7 +82,7 @@ function Get-AbrADSite { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Site)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorDomainSite) $($_.Exception.Message)" } } @@ -154,12 +154,12 @@ function Get-AbrADSite { $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADSite.Name) -ne $reportTranslate.GetAbrADSite.AutoGenerated } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADSite.Name } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Replication Connection Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSiteReplicationConnectionItem) $($_.Exception.Message)" } } $TableParams = @{ - Name = "$($reportTranslate.GetAbrADSite.ConnectionObjects) - $($ForestInfo)" + Name = "$($reportTranslate.GetAbrADSite.ConnectionObjects)- $($ForestInfo)" List = $false ColumnWidths = 25, 25, 25, 25 } @@ -179,10 +179,10 @@ function Get-AbrADSite { } } } else { - Write-PScriboMessage -Message "No Connection Objects information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoConnectionObjectsInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Connection Objects)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorConnectionObjects) $($_.Exception.Message)" } try { $Subnet = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADReplicationSubnet -Filter * -Properties * } @@ -207,7 +207,7 @@ function Get-AbrADSite { $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADSite.Sites) -eq $reportTranslate.GetAbrADSite.NoSiteAssigned } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADSite.Sites } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Subnets)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSiteSubnets) $($_.Exception.Message)" } } @@ -222,7 +222,7 @@ function Get-AbrADSite { } $List.Add($reportTranslate.GetAbrADSite.DescBP) } - if ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADSite.Sites) -eq $reportTranslate.GetAbrADSite.NoSiteAssigned }) { + if ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADSite.Sites) -eq $reportTranslate.GetAbrADSite.NoSiteAssigned }){ $OutObj | Where-Object { $_.$($reportTranslate.GetAbrADSite.Sites) -eq $reportTranslate.GetAbrADSite.NoSiteAssigned } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADSite.Sites $Num++ foreach ( $OBJ in ($OutObj | Where-Object { $_.$($reportTranslate.GetAbrADSite.Sites) -eq $reportTranslate.GetAbrADSite.NoSiteAssigned }) ) { @@ -273,16 +273,16 @@ function Get-AbrADSite { } } } else { - Write-PScriboMessage -Message "Unable to read $Path on $DC" + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.UnableToRead -f $Path, $DC) } } else { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Missing Subnet in AD Section: New-PSSession: Unable to connect to $($DC): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADSite.ErrorMissingSubnetPSSession -f $DC, $ErrorMessage) } } catch { - Write-PScriboMessage -IsWarning -Message "Missing Subnet in AD Item table: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorMissingSubnetItemTable) $($_.Exception.Message)" } } } @@ -313,25 +313,25 @@ function Get-AbrADSite { } } } else { - Write-PScriboMessage -Message "No Missing Subnets in AD information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoMissingSubnetsInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "Missing Subnet in AD Item Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorMissingSubnetItemSection) $($_.Exception.Message)" } } } } else { - Write-PScriboMessage -Message "No Site Subnets information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoSiteSubnetsInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Subnets)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSiteSubnets) $($_.Exception.Message)" } if ($Options.EnableDiagrams) { try { try { $Graph = Get-AbrDiagrammer -DiagramType 'Sites' -DiagramOutput base64 -PSSessionObject $TempPssSession } catch { - Write-PScriboMessage -IsWarning -Message "Site Topology Diagram Graph: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSiteTopologyDiagramGraph) $($_.Exception.Message)" } if ($Graph) { @@ -343,7 +343,7 @@ function Get-AbrADSite { } } } catch { - Write-PScriboMessage -IsWarning -Message "Site Topology Diagram Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSiteTopologyDiagramSection) $($_.Exception.Message)" } } try { @@ -402,7 +402,7 @@ function Get-AbrADSite { } $OutObj | Sort-Object -Property $reportTranslate.GetAbrADSite.Name | Table @TableParams } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Inter-Site Transports section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorInterSiteTransports) $($_.Exception.Message)" } try { Section -Style Heading4 $reportTranslate.GetAbrADSite.IPSection { @@ -484,15 +484,15 @@ function Get-AbrADSite { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (IP Site Links table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorIPSiteLinksTable) $($_.Exception.Message)" } } } } else { - Write-PScriboMessage -Message "No IP Site Links information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoIPSiteLinksInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (IP Site Links Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorIPSiteLinksSection) $($_.Exception.Message)" } try { $IPLinkBridges = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADReplicationSiteLinkBridge -Filter * -Properties * | Where-Object { $_.InterSiteTransportProtocol -eq 'IP' } } @@ -550,19 +550,19 @@ function Get-AbrADSite { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (IP Site Links Bridges table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorIPSiteLinksBridgesTable) $($_.Exception.Message)" } } } } else { - Write-PScriboMessage -Message "No IP Site Links Bridges information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoIPSiteLinksBridgesInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (IP Site Links Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorIPSiteLinksSection) $($_.Exception.Message)" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (IP)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorIP) $($_.Exception.Message)" } try { $IPLink = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADReplicationSiteLink -Filter * -Properties * | Where-Object { $_.InterSiteTransportProtocol -eq 'SMTP' } } @@ -645,12 +645,12 @@ function Get-AbrADSite { } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SMTP Site Links table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSMTPSiteLinksTable) $($_.Exception.Message)" } } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SMTP Site Links Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSMTPSiteLinksSection) $($_.Exception.Message)" } try { $IPLinkBridges = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADReplicationSiteLinkBridge -Filter * -Properties * | Where-Object { $_.InterSiteTransportProtocol -eq 'SMTP' } } @@ -707,29 +707,29 @@ function Get-AbrADSite { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SMTP Site Links Bridges table)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSMTPSiteLinksBridgesTable) $($_.Exception.Message)" } } } } else { - Write-PScriboMessage -Message "No SMTP Site Links Bridges information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoSMTPSiteLinksBridgesInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SMTP Site Links Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSMTPSiteLinksSection) $($_.Exception.Message)" } } } else { - Write-PScriboMessage -Message "No SMTP Site Links information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoSMTPSiteLinksInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (SMTP)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSMTP) $($_.Exception.Message)" } } } else { - Write-PScriboMessage -Message "No SMTP Site Links information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoSMTPSiteLinksInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Subnets)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSiteSubnets) $($_.Exception.Message)" } try { $OutObj = [System.Collections.Generic.List[object]]::new() @@ -760,7 +760,7 @@ function Get-AbrADSite { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "Sysvol Replication Item Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSysvolReplicationItemSection) $($_.Exception.Message)" } if ($HealthCheck.Site.BestPractice) { @@ -782,7 +782,7 @@ function Get-AbrADSite { } } else { try { - Write-PScriboMessage -Message "Unable to collect infromation from $DC." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.UnableToCollect -f $DC) $inObj = [ordered] @{ $reportTranslate.GetAbrADSite.DCName = $DC.split('.', 2)[0] $reportTranslate.GetAbrADSite.ReplicationStatus = $reportTranslate.GetAbrADSite.StatusUnknown @@ -790,7 +790,7 @@ function Get-AbrADSite { } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (DNS IP Configuration Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorDNSIPConfigItem) $($_.Exception.Message)" } } } @@ -819,17 +819,17 @@ function Get-AbrADSite { } } } else { - Write-PScriboMessage -Message "No Sysvol Replication information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoSysvolReplicationInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "Sysvol Replication Table Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorSysvolReplicationTableSection) $($_.Exception.Message)" } } } else { - Write-PScriboMessage -Message "No Sites information found in $ForestInfo, Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADSite.NoSitesInfo -f $ForestInfo) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Site Global)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSite.ErrorDomainSiteGlobal) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSiteReplication.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSiteReplication.ps1 index 10443eb..f743e9c 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSiteReplication.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADSiteReplication.ps1 @@ -64,11 +64,11 @@ function Get-AbrADSiteReplication { $ReplInfo | Where-Object { $_.$($reportTranslate.GetAbrADSiteReplication.AutoGenerated) -ne 'Yes' } | Set-Style -Style Warning -Property $reportTranslate.GetAbrADSiteReplication.AutoGenerated } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Replication Connection Item)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSiteReplication.ErrorSiteReplicationConnectionItem) $($_.Exception.Message)" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Replication Connection Section)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSiteReplication.ErrorSiteReplicationConnectionSection) $($_.Exception.Message)" } } } @@ -79,7 +79,7 @@ function Get-AbrADSiteReplication { Paragraph $reportTranslate.GetAbrADSiteReplication.ReplicationConnectionParagraph BlankLine foreach ($Repl in ($ReplInfo | Sort-Object -Property 'Replicate From Directory Server')) { - Section -Style NOTOCHeading4 -ExcludeFromTOC "Site: $($Repl.$($reportTranslate.GetAbrADSiteReplication.FromSite)): From: $($Repl.$($reportTranslate.GetAbrADSiteReplication.FromServer)) To: $($Repl.$($reportTranslate.GetAbrADSiteReplication.ToServer))" { + Section -Style NOTOCHeading4 -ExcludeFromTOC "$($reportTranslate.GetAbrADSiteReplication.SiteLabel) $($Repl.$($reportTranslate.GetAbrADSiteReplication.FromSite)): $($reportTranslate.GetAbrADSiteReplication.FromLabel) $($Repl.$($reportTranslate.GetAbrADSiteReplication.FromServer)) $($reportTranslate.GetAbrADSiteReplication.ToLabel) $($Repl.$($reportTranslate.GetAbrADSiteReplication.ToServer))" { $TableParams = @{ Name = "$($reportTranslate.GetAbrADSiteReplication.ReplicationConnectionTableName) - $($Repl.$($reportTranslate.GetAbrADSiteReplication.ToServer))" List = $true @@ -112,7 +112,7 @@ function Get-AbrADSiteReplication { Write-PScriboMessage -Message ($reportTranslate.GetAbrADSiteReplication.ReplicationConnectionNoData -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Replication Connection)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSiteReplication.ErrorReplicationConnection) $($_.Exception.Message)" } } try { @@ -125,7 +125,7 @@ function Get-AbrADSiteReplication { if (-not $_.Exception.MessageId) { $ErrorMessage = $_.FullyQualifiedErrorId } else { $ErrorMessage = $_.Exception.MessageId } - Write-PScriboMessage -IsWarning -Message "Replication Status Section: New-PSSession: Unable to connect to $($ValidDCFromDomain): $ErrorMessage" + Write-PScriboMessage -IsWarning -Message ($reportTranslate.GetAbrADSiteReplication.ErrorPSSession -f $ValidDCFromDomain, $ErrorMessage) } if ($RepStatus) { Section -Style Heading4 $reportTranslate.GetAbrADSiteReplication.ReplicationStatusTitle { @@ -144,7 +144,7 @@ function Get-AbrADSiteReplication { $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Replication Status)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSiteReplication.ErrorReplicationStatus) $($_.Exception.Message)" } } if ($HealthCheck.Site.Replication) { @@ -175,7 +175,7 @@ function Get-AbrADSiteReplication { } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Site Replication Status)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADSiteReplication.ErrorSiteReplicationStatus) $($_.Exception.Message)" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADTrust.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADTrust.ps1 index fa7e28f..69b7715 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADTrust.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrADTrust.ps1 @@ -75,7 +75,7 @@ function Get-AbrADTrust { } $TrustInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Trust Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADTrust.ErrorTrustItem))" } } @@ -123,7 +123,7 @@ function Get-AbrADTrust { try { $Graph = Get-AbrDiagrammer -DiagramType 'Trusts' -DiagramOutput base64 -DomainController $ValidDCFromDomain } catch { - Write-PScriboMessage -IsWarning -Message "Domain and Trusts Diagram Graph: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADTrust.ErrorTrustDiagramGraph) $($_.Exception.Message)" } if ($Graph) { @@ -135,19 +135,19 @@ function Get-AbrADTrust { } } } catch { - Write-PScriboMessage -IsWarning -Message "Domain and Trusts Diagram Section: $($_.Exception.Message)" + Write-PScriboMessage -IsWarning -Message "$($reportTranslate.GetAbrADTrust.ErrorTrustDiagramSection) $($_.Exception.Message)" } } } } else { - Write-PScriboMessage -Message "No Domain Trust information found in $($Domain.DNSRoot), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrADTrust.NoTrustInfo -f $Domain.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Trust Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADTrust.ErrorTrustTable))" } } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Trust Section)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrADTrust.ErrorTrustSection))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDHCPinAD.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDHCPinAD.ps1 index 581bec5..4ae7023 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDHCPinAD.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDHCPinAD.ps1 @@ -60,7 +60,7 @@ function Get-AbrDHCPinAD { } $DCHPInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (DHCP Item)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrDHCPinAD.ErrorDHCPItem))" } } @@ -75,12 +75,12 @@ function Get-AbrDHCPinAD { $DCHPInfo | Sort-Object -Property $reportTranslate.GetAbrDHCPinAD.ServerName | Table @TableParams } } else { - Write-PScriboMessage -Message "No DHCP Infrastructure information found in $($ForestInfo.toUpper()), Disabling this section." + Write-PScriboMessage -Message ($reportTranslate.GetAbrDHCPinAD.NoDHCPInfo -f $ForestInfo.toUpper()) Paragraph $reportTranslate.GetAbrDHCPinAD.NotFound BlankLine } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (DHCP Table)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrDHCPinAD.ErrorDHCPTable))" } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDNSSection.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDNSSection.ps1 index 7899718..c442e15 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDNSSection.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDNSSection.ps1 @@ -54,7 +54,7 @@ function Get-AbrDNSSection { Write-PScriboMessage -Message ([string]::Format($reportTranslate.GetAbrDNSSection.ExcludedDomain, $DomainInfo.DNSRoot)) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Domain Name System Information)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrDNSSection.ErrorDNSInfo))" } } else { Write-PScriboMessage -IsWarning -Message ([string]::Format($reportTranslate.GetAbrDNSSection.NoDCAvailable, $DomainInfo.DNSRoot)) diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 index 127a644..7567ca9 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 @@ -32,7 +32,7 @@ function Get-AbrDomainSection { # Define Filter option for Domain variable try { if ($DomainInfo = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADDomain -Identity $using:Domain }) { - Write-Host " - Collecting Domain information from $Domain." + Write-Host ([string]::Format(" - $($reportTranslate.GetAbrDomainSection.CollectingDomain)", $Domain)) $DCs = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADDomain -Identity $using:Domain | Select-Object -ExpandProperty ReplicaDirectoryServers | Where-Object { $_ -notin ($using:Options).Exclude.DCs } } | Sort-Object Section -Style Heading2 "$($DomainInfo.DNSRoot.ToString().ToUpper())" { Paragraph $reportTranslate.GetAbrDomainSection.Paragraph @@ -140,7 +140,7 @@ function Get-AbrDomainSection { Write-PScriboMessage -Message ($reportTranslate.GetAbrDomainSection.DomainExcluded -f $DomainInfo.DNSRoot) } } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Active Directory Domain)" + Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) ($($reportTranslate.GetAbrDomainSection.ErrorADDomain))" } } else { $DomainStatus.Value.Add( diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Invoke-DcDiag.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Invoke-DcDiag.ps1 index 0cfdaa3..8249bf8 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Invoke-DcDiag.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Invoke-DcDiag.ps1 @@ -25,7 +25,7 @@ function Invoke-DcDiag { try { $result = Invoke-CommandWithTimeout -Session $DCPssSessionDCDiag -ScriptBlock { dcdiag /c /s:$using:DomainController } } catch { - Write-PScriboMessage -Message "Invoke-DcDiag - Failed to get DCDiag for $DomainController with error: $($_.Exception.Message)" + Write-PScriboMessage -Message "$($reportTranslate.GetAbrADDCDiag.ErrorInvokeDcDiag -f $DomainController) $($_.Exception.Message)" return } From d49307db443099c6530212495e64921ed55c25a2 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Sun, 5 Apr 2026 13:48:34 -0400 Subject: [PATCH 02/11] Refactor output formatting in domain and report functions for improved readability and consistency --- .../Language/en-US/MicrosoftAD.psd1 | 10 +++++----- .../Src/Private/Report/Get-AbrDomainSection.ps1 | 2 +- .../Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 b/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 index 298b7bf..01b82cb 100644 --- a/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 +++ b/AsBuiltReport.Microsoft.AD/Language/en-US/MicrosoftAD.psd1 @@ -21,13 +21,13 @@ CIMSessionError = Failed to establish a CimSession ({0}) with the Domain Controller '{1}'. ConnectingForest = Connecting to retrieve forest information from the Domain Controller '{0}'. ForestError = Failed to retrieve forest information from the Domain Controller '{0}'. Ensure the provided system is a Domain Controller and the provided credentials have sufficient permissions to query Active Directory forest information. Error details: {1} - IncludeDomainsEnabled = - Include.Domains option enabled: Including only the following domains in the report: {0} - ExcludeDomainsEnabled = - Including all child domains in the report except the following excluded domains: {0} + IncludeDomainsEnabled = - Include.Domains option enabled: Including only the following domains in the report: {0} + ExcludeDomainsEnabled = - Including all child domains in the report except the following excluded domains: {0} GettingForestInfo = - Retrieving forest information {0}. - DiscoveringChildDomains = - Discovering child domains of the forest {0}: {1}. + DiscoveringChildDomains = - Discovering child domains of the forest {0}: {1}. DCAvailable = - Initial configuration: A DC is available in the domain {0}. Adding domain to the report. - DCUnavailable = - Unable to obtain an available DC in the domain {0}. Removing domain from the report. - FinishingDomainList = - Finalizing the list of domains in the forest {0}: {1}. + DCUnavailable = - Unable to obtain an available DC in the domain {0}. Removing domain from the report. + FinishingDomainList = - Finalizing the list of domains in the forest {0}: {1}. WorkingOnForest = - Working on the Forest section. WorkingOnDomain = - Working on the Domain section. WorkingOnDNS = - Working on the DNS section. diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 index 7567ca9..f39c071 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 @@ -78,7 +78,7 @@ function Get-AbrDomainSection { try { $DCDiagObj = foreach ($DC in $DCs) { if (Get-DCWinRMState -ComputerName $DC -DCStatus ([ref]$DCStatus)) { - # Get-AbrADDCDiag -Domain $Domain -DC $DC + Get-AbrADDCDiag -Domain $Domain -DC $DC } } if ($DCDiagObj) { diff --git a/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 b/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 index 78c02a6..f8c26fb 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 @@ -44,11 +44,11 @@ function Invoke-AsBuiltReport.Microsoft.AD { $InstalledVersion = Get-Module -ListAvailable -Name $Module -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version if ($InstalledVersion) { - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.ModuleInstalled -f $Module, $InstalledVersion.ToString()) + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.ModuleInstalled)" -f $Module, $InstalledVersion.ToString()) $LatestVersion = Find-Module -Name $Module -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version if ($InstalledVersion -lt $LatestVersion) { - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.ModuleAvailable -f $Module, $LatestVersion.ToString()) -ForegroundColor Red - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.ModuleUpdate -f $Module) -ForegroundColor Red + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.ModuleAvailable)" -f $Module, $LatestVersion.ToString()) -ForegroundColor Red + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.ModuleUpdate)" -f $Module) -ForegroundColor Red } } } catch { @@ -163,16 +163,16 @@ function Invoke-AsBuiltReport.Microsoft.AD { if ($ChildDomains) { $OrderedDomains.Add($ChildDomains) - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.DiscoveringChildDomains -f $RootDomains, ($OrderedDomains -join ', ')) + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.DiscoveringChildDomains)" -f $RootDomains, ($OrderedDomains -join ', ')) } # Set initial connection to childs domains to find out if there is an available DC to fulfill the requests foreach ($Domain in $OrderedDomains) { try { if (Get-ValidDCfromDomain -Domain $Domain -DCStatus ([ref]$DCStatus)) { - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.DCAvailable -f $Domain) + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.DCAvailable)" -f $Domain) } else { - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.DCUnavailable -f $Domain) + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.DCUnavailable)" -f $Domain) $DomainStatus.Add( @{ Name = $Domain @@ -183,7 +183,7 @@ function Invoke-AsBuiltReport.Microsoft.AD { } } catch { $null } } - Write-Host ($reportTranslate.InvokeAsBuiltReportMicrosoftAD.FinishingDomainList -f $RootDomains, ($OrderedDomains -join ', ')) + Write-Host (" $($reportTranslate.InvokeAsBuiltReportMicrosoftAD.FinishingDomainList)" -f $RootDomains, ($OrderedDomains -join ', ')) # Report Overview Get-AbrADReportBrief From ad2060cada1016b7278c453248f785dbd7b1b3a9 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Sun, 5 Apr 2026 13:53:05 -0400 Subject: [PATCH 03/11] Bump module version to 1.0.0 and update CHANGELOG for improved localization and documentation clarity --- .../AsBuiltReport.Microsoft.AD.psd1 | 2 +- .../Src/Private/Report/Get-AbrDomainSection.ps1 | 2 +- .../Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 | 2 +- CHANGELOG.md | 8 ++++++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 index bdeab47..43a98fa 100644 --- a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 +++ b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 @@ -12,7 +12,7 @@ RootModule = 'AsBuiltReport.Microsoft.AD.psm1' # Version number of this module. - ModuleVersion = '0.9.12' + ModuleVersion = '1.0.0' # Supported PSEditions CompatiblePSEditions = @('Core') diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 index f39c071..c791f57 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Report/Get-AbrDomainSection.ps1 @@ -5,7 +5,7 @@ function Get-AbrDomainSection { .DESCRIPTION .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux diff --git a/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 b/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 index f8c26fb..b943c1a 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1 @@ -5,7 +5,7 @@ function Invoke-AsBuiltReport.Microsoft.AD { .DESCRIPTION Documents the configuration of Microsoft AD in Word/HTML/Text formats using PScribo. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a9708..01ea05f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ##### This project is community maintained and has no sponsorship from Microsoft, its employees or any of its affiliates. +## [1.0.0] - 2026-04-?? + +### :arrows_clockwise: Changed + +- Improved multi-language support by refactoring localization strings and enhancing documentation clarity in MicrosoftAD.psd1 for English and Spanish languages. + This includes improved grammar, punctuation, and readability across various best practice descriptions related to Active Directory configurations +- Bump module version to `1.0.0` + ## [0.9.12] - 2026-04-02 ### :toolbox: Added From 797eeebdb3d3c8dbb47780f4a9d9316b9cf78734 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 14:16:57 -0400 Subject: [PATCH 04/11] Update module versions for AsBuiltReport.Chart and AsBuiltReport.Diagram in CHANGELOG and module manifest --- AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 | 4 ++-- CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 index 43a98fa..24fc28f 100644 --- a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 +++ b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 @@ -58,11 +58,11 @@ }, @{ ModuleName = 'AsBuiltReport.Chart'; - ModuleVersion = '0.3.0' + ModuleVersion = '0.3.1' }, @{ ModuleName = 'AsBuiltReport.Diagram'; - ModuleVersion = '1.0.5' + ModuleVersion = '1.0.6' } ) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ea05f..e9c2836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved multi-language support by refactoring localization strings and enhancing documentation clarity in MicrosoftAD.psd1 for English and Spanish languages. This includes improved grammar, punctuation, and readability across various best practice descriptions related to Active Directory configurations - Bump module version to `1.0.0` +- Upgrade AsBuiltReport.Diagram module to version `1.0.6` +- Upgrade AsBuiltReport.Chart module to version `0.3.1` ## [0.9.12] - 2026-04-02 From 36a6bb3bba23352aba1c81157e9924cd51f5d614 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 14:30:04 -0400 Subject: [PATCH 05/11] Implement feature X to enhance user experience and optimize performance --- .github/copilot-instructions.md | 983 ++++++++++++++++++++++++-------- 1 file changed, 751 insertions(+), 232 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 4093fa2..558cea0 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,352 +1,871 @@ -# Copilot Instructions for AsBuiltReport.Microsoft.AD +# AsBuiltReport.Microsoft.AD - Copilot Instructions -## What This Project Does +**Project Overview:** AsBuiltReport.Microsoft.AD is a PowerShell module that generates comprehensive as-built documentation for Microsoft Active Directory (AD) infrastructure in Word/HTML/Text formats. It's part of the larger AsBuiltReport ecosystem and works in conjunction with AsBuiltReport.Core. -A PowerShell module that generates As-Built documentation reports for Microsoft Active Directory environments (Forest, Domains, Domain Controllers, DNS, PKI/CA). It produces HTML/Word/Text output via the **PScribo** library, with optional network topology diagrams via **Diagrammer.Core**. +--- + +## 1. PROJECT STRUCTURE + +### Top-Level Directory Layout +``` +AsBuiltReport.Microsoft.AD/ +├── .github/ # CI/CD workflows and PR templates +│ ├── workflows/ # GitHub Actions workflows +│ │ ├── Pester.yml # Unit testing pipeline +│ │ ├── PSScriptAnalyzer.yml # Linting/code analysis +│ │ ├── CodeQL.yml # Security scanning +│ │ ├── Release.yml # Publishing to PSGallery + social media +│ │ └── Stale.yml # Issue/PR housekeeping +│ └── PULL_REQUEST_TEMPLATE.md +├── .vscode/ # VS Code settings for PowerShell formatting +│ └── settings.json # Formatting rules, rulers @ 115 chars +├── AsBuiltReport.Microsoft.AD/ # MAIN MODULE DIRECTORY +│ ├── AsBuiltReport.Microsoft.AD.psm1 # Module manifest (14 lines - loads all functions) +│ ├── AsBuiltReport.Microsoft.AD.psd1 # Module declaration (v0.9.11) +│ ├── AsBuiltReport.Microsoft.AD.json # Default report config (InfoLevels, HealthChecks) +│ ├── AsBuiltReport.Microsoft.AD.Style.ps1 # Document styling (20.8 KB) +│ ├── Src/ +│ │ ├── Public/ +│ │ │ └── Invoke-AsBuiltReport.Microsoft.AD.ps1 # ENTRY POINT (291 lines) +│ │ └── Private/ +│ │ ├── Get-Abr*.ps1 # 52x data gathering functions +│ │ ├── ConvertTo-*.ps1 # Format/conversion helpers +│ │ ├── Convert-*.ps1 # Data transformation utilities +│ │ ├── Get-*Diagram.ps1 # Visualization generation +│ │ └── Utility functions # Session management, timeout handling, etc. +│ ├── Language/ # Localization files +│ │ ├── en-US/MicrosoftAD.psd1 # English strings (hash of all messages) +│ │ └── es-ES/MicrosoftAD.psd1 # Spanish localization +│ └── icons/ # Image assets for reports +├── Tests/ +│ ├── Invoke-Tests.ps1 # Test runner script (204 lines) +│ ├── AsBuiltReport.Microsoft.AD.Tests.ps1 # Pester unit tests +│ ├── LocalizationData.Tests.ps1 # Localization validation +│ └── README.md +├── Samples/ # Example HTML reports +├── README.md # Project documentation +├── CONTRIBUTING.md # Contribution guidelines +├── CODE_OF_CONDUCT.md # Community standards +├── LICENSE # License file +├── CHANGELOG.md # Version history +├── SECURITY.md # Security policy +└── Todo.md # Development roadmap +``` -## Runtime Requirements +### Key Directories +- **Src/Public**: Only `Invoke-AsBuiltReport.Microsoft.AD` - the single exported public function +- **Src/Private**: 88 total functions (52 Get-Abr* for data gathering, rest are utilities) +- **Language**: Localization for multi-language support (en-US, es-ES) +- **Tests**: Pester tests + custom test runner supporting code coverage -- **Must run as Administrator** — `#Requires -RunAsAdministrator` is enforced in the entry point. -- **Target must be an FQDN** — IP addresses are explicitly rejected; always pass a fully-qualified domain name for `-Target`. -- **Cannot run in PowerShell ISE** — detected and blocked at startup; use the PowerShell console or terminal. -- **PowerShell 7+ recommended** — required for tests; the module itself targets Windows PowerShell 5.1+ on Windows only. -- **Reporting machine must be domain-joined** — required for the PKI/CA section (`Get-ComputerADDomain` check). -- **WinRM must be enabled on DCs** — all remote data collection goes through WinRM; CIMSession is supplementary. +### File Count Summary +- **Total .ps1 files**: 94 +- **Public functions**: 1 (exported) +- **Private functions**: ~88 + utilities +- **Data gathering functions (Get-Abr*)**: 52 -## Testing +--- + +## 2. BUILD, TEST, LINT COMMANDS + +### Test Execution -Run all Pester tests (requires PowerShell 7+, Windows): +**Local Test Execution:** ```powershell -cd Tests -.\Invoke-Tests.ps1 +.\Tests\Invoke-Tests.ps1 # Basic run +.\Tests\Invoke-Tests.ps1 -CodeCoverage -OutputFormat NUnitXml # With coverage +``` + +**Test Runner Details** (`Tests/Invoke-Tests.ps1`): +- Uses **Pester 5.0.0+** for testing framework +- Supports output formats: Console, NUnitXml, JUnitXml +- Includes code coverage analysis (JaCoCo format) +- Code coverage threshold: 50% minimum (warning at <50%) +- Coverage files tracked: `*.psm1`, `Src/Public/*.ps1`, `Src/Private/*.ps1` +- Test results: `Tests/testResults.xml` +- Coverage output: `Tests/coverage.xml` + +### Code Analysis + +**PSScriptAnalyzer** (`PSScriptAnalyzerSettings.psd1`): +- Linting tool configured in CI/CD +- Custom rules enforced: + - `PSAvoidExclaimOperator` - no `!` operator + - `AvoidUsingDoubleQuotesForConstantString` - use single quotes for constants + - `UseCorrectCasing` - enforce proper case + - `PSAvoidUsingCmdletAliases` - no aliases + - `PSUseConsistentWhitespace` - whitespace consistency +- Excluded rules: + - `PSUseToExportFieldsInManifest` + - `PSAvoidUsingWriteHost` (needed for reports) + +### CI/CD Pipelines + +**Pester Tests Workflow** (`.github/workflows/Pester.yml`): +- Triggers: push (main/dev/master), PR, manual +- Runs on: Windows (pwsh + powershell 5.1) +- Auto-installs: Pester 5.0.0+, PScribo 0.11.1+, PSScriptAnalyzer 1.0.0+, AsBuiltReport.Core 1.6.2+ +- Uploads test results as artifacts +- Uploads code coverage to Codecov + +**PSScriptAnalyzer Workflow** (`.github/workflows/PSScriptAnalyzer.yml`): +- Uses external action: `alagoutte/github-action-psscriptanalyzer@master` +- Fails on errors, comments inline +- Settings: `.github/workflows/PSScriptAnalyzerSettings.psd1` + +**CodeQL Workflow** (`.github/workflows/CodeQL.yml`): +- Security scanning for PowerShell + +**Release Workflow** (`.github/workflows/Release.yml`): +- Triggers on release published +- Tests module manifest +- Publishes to PowerShell Gallery (`Publish-Module`) +- Posts release announcements to Twitter & Bluesky + +**No Build/Invoke-Build found**: This is a pure PowerShell module (no compilation). + +--- + +## 3. ARCHITECTURE + +### High-Level Data Flow + +``` +Invoke-AsBuiltReport.Microsoft.AD (Entry Point) + ↓ + [Input: Target DC, Credentials] + ↓ + [Validate: Requirements, Features, Modules] + ↓ + [Connection: PSSession + CIMSession to DC] + ↓ + [Process Per Forest/Domain] + ├── Get-AbrForestSection (Forest-level data) + ├── Get-AbrDomainSection (Per-domain data) + ├── Get-AbrDnsSection (DNS configuration) + └── Get-AbrPKISection (Certificate Authority) + ↓ + [Diagram Generation: Forest, Replication, Trusts, Sites, CA] + ↓ + [Session Cleanup: Remove PSSession, CIMSession] + ↓ + [Output: HTML/Word/Text Report] ``` -Run with code coverage: +### Main Entry Point + +**File**: `AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1` (291 lines) + +**Signature**: ```powershell -.\Invoke-Tests.ps1 -CodeCoverage +function Invoke-AsBuiltReport.Microsoft.AD { + [CmdletBinding()] + param ( + [String[]] $Target, # Domain controller(s) FQDN + [PSCredential] $Credential # Credentials for remote session + ) + #Requires -RunAsAdministrator +} +``` + +**Key Responsibilities**: +1. Validate prerequisites (Windows PS >= 5.1, admin rights, not ISE) +2. Check installed modules & warn on outdated versions +3. Validate OS features (RSAT tools on workstation, features on server) +4. Load report config (JSON), InfoLevels, HealthChecks, Options +5. Establish PSSession + CIMSession to DC via WinRM +6. Collect forest/domain/DNS/PKI data via section functions +7. Generate diagrams (if enabled) +8. Build report using PScribo +9. Cleanup sessions + +**Critical Design Pattern**: +- **$Target** must be FQDN (not IP) - WinRM limitation +- Must run **-RunAsAdministrator** +- Must run from PowerShell 7+, **NOT** PowerShell ISE +- WinRM must be enabled on DC +- Uses **$Options** hash from config for behavior control + +### Core Section Builders + +These functions call data gatherers and structure output via PScribo's **Section** cmdlet: + +1. **Get-AbrForestSection**: Forest topology, schema, tombstone lifetime, global catalogs +2. **Get-AbrDomainSection**: Per-domain configuration, trusts, replication, GPOs, OUs +3. **Get-AbrDnsSection**: DNS zones, scavenging, delegation +4. **Get-AbrPKISection**: Certificate authorities, templates, security + +### Data Gathering Functions (Get-Abr*) + +**Pattern**: Each function collects specific AD object data via remote PSSession: + +Example: `Get-AbrADForest` (80 lines) +- Uses `Invoke-CommandWithTimeout` to run remote cmdlets +- Parses schema version to determine Windows Server version +- Detects anonymous access via dsHeuristics +- Returns object with translated property names +- Applies HealthCheck styling if enabled + +**All 52 Get-Abr* functions follow this pattern:** +- Accept parameters (Domain, ValidDcFromDomain, etc.) +- Start: Log collection message, start timing +- Process: Remote invocation via session, data transformation +- Output: `[System.Collections.ArrayList]` of objects +- HealthCheck: Conditionally apply styling (Warning/Critical) +- Return: Table/list output via PScribo's **Table** cmdlet + +### InfoLevel Architecture + +**Default Config** (`AsBuiltReport.Microsoft.AD.json`): +```json +"InfoLevel": { + "_comment_": "0 = Disabled, 1 = Enabled, 2 = Adv Summary, 3 = Detailed", + "Forest": 2, + "Domain": 2, + "DNS": 1, + "CA": 0 +} ``` -Run a single test file directly: +**Usage Pattern**: ```powershell -Invoke-Pester -Path .\Tests\AsBuiltReport.Microsoft.AD.Tests.ps1 -Output Detailed +if ($InfoLevel.Forest -ge 1) { ... show basic info } +if ($InfoLevel.Forest -ge 2) { ... show advanced details } +if ($InfoLevel.Forest -ge 3) { ... show comprehensive tables } ``` -Run PSScriptAnalyzer lint locally: +Enables **progressive disclosure** - users control report verbosity. + +### HealthCheck Architecture + +**Default Config**: +```json +"HealthCheck": { + "Domain": { + "GMSA": true, # Group Managed Service Accounts + "GPO": true, # Group Policy Objects + "Backup": true, # Domain backup status + "DFS": true, # DFS health + "SPN": true, # Service Principal Names + "DuplicateObject": true, + "Security": true, + "BestPractice": true + }, + "DomainController": { ... }, + "Site": { ... }, + "DNS": { ... }, + "CA": { ... } +} +``` + +**Styling Application**: ```powershell -Invoke-ScriptAnalyzer -Path .\AsBuiltReport.Microsoft.AD\Src -Settings .\.github\workflows\PSScriptAnalyzerSettings.psd1 -Recurse +if ($HealthCheck.Domain.Security) { + $OutObj | Where-Object { $_.AnonymousAccess -eq 'Enabled' } | + Set-Style -Style Critical -Property AnonymousAccess + $OutObj | Where-Object { $_.TombstoneLifetime -lt 180 } | + Set-Style -Style Warning -Property TombstoneLifetime +} ``` -PSScriptAnalyzer enforces: `UseCorrectCasing`, `PSUseConsistentWhitespace`, `PSAvoidUsingCmdletAliases`, `AvoidUsingDoubleQuotesForConstantString`, `PSAvoidExclaimOperator`. Errors fail CI; warnings do not. +Objects marked as Warning/Critical get colored highlighting in reports. -## Architecture +### Connection Management -### Module Layout +**Session Establishment** (in main entry point): +```powershell +$TempPssSession = Get-ValidPSSession -ComputerName $System -SessionName $System +$TempCIMSession = Get-ValidCIMSession -ComputerName $System -SessionName $System +``` +**Remote Command Execution**: +```powershell +Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADForest } ``` -AsBuiltReport.Microsoft.AD/ - AsBuiltReport.Microsoft.AD.psm1 # Dot-sources all Src/Public and Src/Private *.ps1 files - AsBuiltReport.Microsoft.AD.json # Default report config (InfoLevel, HealthCheck, Options) - AsBuiltReport.Microsoft.AD.psd1 # Module manifest - AsBuiltReport.Microsoft.AD.Style.ps1 # PScribo document styling - Src/ - Public/ - Invoke-AsBuiltReport.Microsoft.AD.ps1 # Entry point; sets up sessions, calls Section functions - Private/ - Get-Abr*Section.ps1 # Top-level section orchestrators - Get-AbrAD*.ps1 # Report content generators (one per AD topic) - Get-AbrDiag*.ps1 # Diagram generators - ConvertTo-*.ps1 # Data conversion helpers - Get-Valid*.ps1 # Session/DC validation helpers - Language/ - en-US/MicrosoftAD.psd1 # English string resources - es-ES/MicrosoftAD.psd1 # Spanish string resources + +**Cleanup**: +```powershell +foreach ($PSSession in $PSSTable | Where { $_.Status -ne 'Offline' }) { + Remove-PSSession -Id $PSSession.id +} ``` -### Data Flow +### Diagram Generation + +**Diagrammer Integration**: +- Uses `Diagrammer.Core` module for topology visualization +- Types: Forest, Replication, Sites, SitesInventory, Trusts, CertificateAuthority +- Controlled by `$Options.EnableDiagrams`, `$Options.DiagramType.*` +- Outputs: PDF/PNG (configurable via `$Options.ExportDiagramsFormat`) +- Theme: White/Dark (via `$Options.DiagramTheme`) -1. `Invoke-AsBuiltReport.Microsoft.AD` (Public) connects via PSSession/CIMSession to a target DC, discovers the forest/domain topology, then calls each `Get-Abr*Section` function. -2. Section functions (e.g., `Get-AbrDomainSection`, `Get-AbrForestSection`, `Get-AbrDNSSection`, `Get-AbrPKISection`) gate execution with `$InfoLevel.*` checks and iterate over domains/DCs. -3. Content functions (e.g., `Get-AbrADDomain`, `Get-AbrADDomainController`) collect AD data via `Invoke-CommandWithTimeout` (remote PSSession) and write output using PScribo DSL (`Section`, `Table`, `Paragraph`, `BlankLine`). -4. The PScribo document is assembled in memory and exported to the requested format by the AsBuiltReport.Core framework. +--- -### Key Script-Scoped Variables +## 4. KEY CONVENTIONS AND PATTERNS -These are set by `Invoke-AsBuiltReport.Microsoft.AD` and used across all Private functions: +### Function Naming Convention -| Variable | Purpose | -|---|---| -| `$script:TempPssSession` | Primary PSSession to initial target DC | -| `$script:TempCIMSession` | CIMSession to initial DC | -| `$script:InfoLevel` | Hash from JSON config — controls section depth (0–3) | -| `$script:Options` | Hash from JSON config — WinRM, exclusions, diagram settings | -| `$script:ADSystem` | `Get-ADForest` result for the target forest | -| `$script:ForestInfo` | Root domain FQDN (uppercased) | -| `$script:OrderedDomains` | Root domain first, then child domains | -| `$script:DCStatus` | ArrayList tracking reachability status per DC | -| `$reportTranslate` | Localized string resources loaded from `Language/` | +**Public Functions**: +- `Invoke-AsBuiltReport.Microsoft.AD` - single entry point (uses dot notation) -## Key Conventions +**Private Functions** - Three categories: -### Function Naming +1. **Data Gatherers** (`Get-Abr*`): + - `Get-AbrADForest` - retrieves Forest info + - `Get-AbrADDomain` - retrieves Domain info + - `Get-AbrADDomainController` - DC inventory + - `Get-AbrADCA*` - CA-specific data + - Pattern: Get-Abr[Section][Subsection] -- `Get-AbrAD*` — collects and renders a specific AD topic (domain info, DC info, GPO, trust, etc.) -- `Get-Abr*Section` — top-level orchestrators that call multiple `Get-AbrAD*` functions inside `Section {}` blocks -- `Get-AbrDiag*` — generate infrastructure diagrams -- `ConvertTo-*` — data transformation helpers (e.g., `ConvertTo-TextYN`, `ConvertTo-HashToYN`, `ConvertTo-FileSizeString`) -- `Get-Valid*` — session/connectivity helpers (`Get-ValidDCfromDomain`, `Get-ValidPSSession`, `Get-ValidCIMSession`) +2. **Section Builders** (`Get-Abr*Section`): + - `Get-AbrForestSection` - orchestrates Forest section + - `Get-AbrDomainSection` - orchestrates Domain section + - `Get-AbrDnsSection` - orchestrates DNS section + - `Get-AbrPKISection` - orchestrates PKI section + - Pattern: Get-Abr[Section]Section -### Building Report Tables +3. **Diagram Builders** (`Get-AbrDiag*`): + - `Get-AbrDiagrammer` - main diagram orchestration + - `Get-AbrDiagForest`, `Get-AbrDiagReplication`, etc. + - Pattern: Get-AbrDiag[DiagramType] -Every content function uses this pattern: +4. **Utility Functions** (various): + - `Convert-IpAddressToMaskLength` - IP/CIDR conversion + - `ConvertTo-HashToYN` - bool → Yes/No conversion + - `Invoke-CommandWithTimeout` - remote execution with timeout + - `Get-ValidPSSession` - session validation/creation + - `Test-WinRM` - WinRM connectivity check + +### Data Structure Patterns + +**Standard Data Object**: ```powershell -$OutObj = [System.Collections.ArrayList]::new() $inObj = [ordered] @{ - $reportTranslate.FunctionName.FieldKey = $value - # ... + 'Property Name' = $Value + 'Health Check Property' = $CheckResult } $OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) | Out-Null - -$TableParams = @{ - Name = "Table Title - $Domain" - List = $true # or $false for horizontal tables - ColumnWidths = 40, 60 -} -if ($Report.ShowTableCaptions) { - $TableParams['Caption'] = "- $($TableParams.Name)" -} -$OutObj | Table @TableParams ``` -### Localized Strings +**Conversion Helper Usage**: +```powershell +# ConvertTo-HashToYN: Converts boolean $true/$false → "Yes"/"No" +$inObj | ConvertTo-HashToYN +``` -All user-visible strings — table column headers, section headings, paragraph text, health check messages — must come from `$reportTranslate..`. Add new strings to both `Language/en-US/MicrosoftAD.psd1` and `Language/es-ES/MicrosoftAD.psd1`. String keys use PascalCase and match the function name as a top-level key. +**Style Application**: +```powershell +$OutObj | Set-Style -Style Critical -Property $PropertyName +$OutObj | Set-Style -Style Warning -Property $PropertyName +``` -### InfoLevel and HealthCheck Gating +### Report Section Structure -- `$InfoLevel.Domain` (0=Disabled, 1=Enabled, 2=Adv Summary, 3=Detailed) controls whether a section runs and how much detail it shows. -- `$HealthCheck.Domain.BestPractice` (boolean) controls whether health check styling/paragraphs are added to existing tables. -- Pattern for health checks: +**PScribo Section Hierarchy**: ```powershell -if ($HealthCheck.Domain.BestPractice) { - $OutObj | Set-Style -Style Warning -Property $reportTranslate.FunctionName.FieldKey +Section -Style Heading1 "Forest Name" { + Paragraph "Introduction..." + BlankLine + + Section -Style Heading2 "Subsection Title" { + if ($Options.ShowDefinitionInfo) { + Paragraph "Definition text..." + } + + # Call data gatherer + Get-AbrADForest + + if ($InfoLevel.Forest -ge 2) { + # Advanced details + Get-AbrADSite + } + } } ``` -### Remote Execution +**PScribo Elements Used**: +- `Section` - create section with heading levels (Heading1-Heading4) +- `Table` - display data in tabular format +- `Paragraph` - text with styling (Bold, Underline, Colors) +- `BlankLine` - spacing +- `PageBreak` - force page break in Word/PDF -Always use `Invoke-CommandWithTimeout` (not `Invoke-Command` directly) for remote PSSession calls. This respects `$Options.JobsTimeOut`: +### Translation/Localization Pattern + +**Property Names Use Translated Strings**: ```powershell -$Result = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { - Get-ADDomain -Identity $using:Domain +# From Language/en-US/MicrosoftAD.psd1 +@{ + GetAbrADForest = @{ + Collecting = 'Collecting Active Directory forest information.' + ForestName = 'Forest Name' + ForestFunctionalLevel = 'Forest Functional Level' + ... + } } + +# In function: +$reportTranslate.GetAbrADForest.Collecting # Loaded at module init ``` -### Error Handling Pattern +**Multi-Language Support**: +- Each culture has its own .psd1 file (en-US, es-ES, etc.) +- Strings loaded into `$reportTranslate` hash at module load +- Property names in output tables are localized +### HealthCheck Patterns + +**Pre-Check Pattern** (e.g., RID Pool): ```powershell -begin { - Write-PScriboMessage -Message ($reportTranslate.FunctionName.Collecting -f $Domain) - Show-AbrDebugExecutionTime -Start -TitleMessage 'Section Title' -} -process { - try { - # ... collect and render ... - } catch { - Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Context Description)" +if ($HealthCheck.Domain.BestPractice) { + if ([math]::Truncate($CompleteSIDS / $RIDsRemaining) -gt 80) { + $OutObj | Set-Style -Style Warning -Property RIDProperty + Paragraph "Health check message about RID pool..." } } -end { - Show-AbrDebugExecutionTime -End -TitleMessage 'Section Title' +``` + +**28 Functions Use HealthCheck** out of 52 data gatherers (~54%): +- Focus on security, best practices, service health +- Each check compares values against thresholds +- Styling applied: Warning, Critical, or Success + +### Configuration-Driven Behavior + +**Options Hash Controls**: +```json +"Options": { + "ShowExecutionTime": false, # Show timing info + "ShowDefinitionInfo": false, # Show definition text + "PSDefaultAuthentication": "Negotiate", + "Exclude": { "Domains": [], "DCs": [] }, + "Include": { "Domains": [] }, # Only these domains + "WinRMSSL": false, + "WinRMFallbackToNoSSL": true, + "WinRMSSLPort": 5986, + "WinRMPort": 5985, + "EnableDiagrams": true, + "DiagramTheme": "White", + "JobsTimeOut": 900 # 15-minute timeout } ``` -Use `Write-PScriboMessage` (not `Write-Host`) for module logging. `Write-Host` is only allowed in the Public entry point (`Invoke-AsBuiltReport.Microsoft.AD.ps1`) for top-level user-facing progress messages. +**Usage Example**: +```powershell +if ($Options.ShowDefinitionInfo) { + Paragraph $reportTranslate.GetAbrForestSection.DefinitionText +} + +$TimeoutSeconds = $Options.JobsTimeOut +``` -### DC Connectivity Check +### Error Handling & Timeouts -Before running per-DC logic, always check WinRM reachability: +**Invoke-CommandWithTimeout Pattern**: ```powershell -if (Get-DCWinRMState -ComputerName $DC -DCStatus ([ref]$DCStatus)) { - # ... per-DC work ... +function Invoke-CommandWithTimeout { + param( + [System.Management.Automation.Runspaces.PSSession]$Session, + [scriptblock]$ScriptBlock, + [int]$TimeoutSeconds = $Options.JobsTimeOut + ) + + # Run as background job with timeout + $job = Invoke-Command -Session $Session -AsJob -ScriptBlock $ScriptBlock + Wait-Job $job -Timeout $TimeoutSeconds + Receive-Job $job } ``` -### Configuration JSON +**Try-Catch in Data Gatherers**: +```powershell +try { + Get-AbrADForest +} catch { + Write-PScriboMessage -IsWarning $_.Exception.Message +} +``` -`AsBuiltReport.Microsoft.AD.json` defines defaults for `Report`, `Options`, `InfoLevel`, and `HealthCheck`. New configurable options must be added here with sensible defaults. +### Sensitive Data Handling ---- +**No explicit redaction observed**, but patterns suggest: +- Credentials passed via `$PSCredential` object (not stored) +- Session-based execution (no inline secrets) +- Remote execution prevents data capture on local disk +- Output tables contain parsed, non-sensitive data -## Session Management +**Recommendation**: Follow AD best practices - restrict report access, don't email to untrusted parties. -### Three Parallel Session Tables +--- -All remote connectivity is tracked in three `[System.Collections.ArrayList]` caches (passed as `[ref]` throughout): +## 5. CONFIGURATION + +### Primary Config File + +**File**: `AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.json` + +**Structure**: +```json +{ + "Report": { + "Name": "Microsoft Active Directory As Built Report", + "Version": "1.0", + "Status": "Released", + "ShowCoverPageImage": true, + "ShowTableOfContents": true, + "ShowHeaderFooter": true, + "ShowTableCaptions": true + }, + "Options": { ... }, // Execution behavior + "InfoLevel": { ... }, // Report verbosity + "HealthCheck": { ... } // Health check toggles +} +``` -| Variable | Cache Contents | Helper | -|---|---|---| -| `$DCStatus` | WinRM reachability per DC | `Get-DCWinRMState` | -| `$PSSTable` | PSSession objects per DC | `Get-ValidPSSession` | -| `$CIMTable` | CIMSession objects per DC | `Get-ValidCIMSession` | +### Configuration Usage -Each entry in these lists is a hashtable with at minimum: `DCName`, `Status` (`Online`/`Offline`), `Protocol`, and `Id`. +Users provide config via **-ReportConfig parameter** to AsBuiltReport.Core: -### `Get-DCWinRMState` — Reachability Gate +```powershell +$ReportConfig = Get-Content 'config.json' | ConvertFrom-Json -Always called **before** establishing a PSSession or CIMSession. It: -1. Checks `$DCStatus` cache first (avoids repeated Test-WSMan calls). -2. Falls back to `Test-WSMan` if not cached, respecting `$Options.WinRMSSL`, `$Options.WinRMSSLPort`, and `$Options.WinRMFallbackToNoSSL`. -3. Records result in `$DCStatus` and returns `$true`/`$false`. -4. Ping count controlled by `$Options.DCStatusPingCount` (default: 2). +New-AsBuiltReport -Report Microsoft.AD ` + -Target 'DC01.contoso.com' ` + -ReportConfig $ReportConfig ` + -Credential $cred ` + -Format HTML +``` +**Module Loads**: ```powershell -# Always gate DC-specific work: -if (Get-DCWinRMState -ComputerName $DC -DCStatus ([ref]$DCStatus)) { - # safe to proceed -} +$script:Report = $ReportConfig.Report +$script:InfoLevel = $ReportConfig.InfoLevel +$script:Options = $ReportConfig.Options ``` -### `Get-ValidPSSession` — PSSession Pool +### Module Manifest -Manages a pool of reusable PSSessions. Behaviour: -- If a cached `Online` session exists for the DC, returns it immediately without creating a new one. -- If `$Options.WinRMSSL` is set, tries SSL first (`$Options.WinRMSSLPort`); if it fails and `$Options.WinRMFallbackToNoSSL` is `$true`, retries on plain WinRM (`$Options.WinRMPort`). -- For the **initial forest connection** (`-InitialForrestConnection $true`), failure throws a terminating error. For per-DC connections, failure is non-terminating (logged as a warning). -- Authentication method is `$Options.PSDefaultAuthentication` (default: `Negotiate`). +**File**: `AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1` -```powershell -$DCPssSession = Get-ValidPSSession -ComputerName $DC -SessionName $DC -PSSTable ([ref]$PSSTable) -``` +**Key Settings**: +- **Version**: 0.9.11 +- **PowerShellVersion**: 5.1 (minimum, actually PS7 required) +- **CompatiblePSEditions**: Desktop, Core +- **GUID**: 0a3e1c04-13b8-418f-89bc-a5a18da07394 -### `Get-ValidCIMSession` — CIMSession Pool +**Required Modules**: +- AsBuiltReport.Core (v1.6.2+) +- AsBuiltReport.Chart (v0.2.0+) +- Diagrammer.Core (v0.2.38+) +- PSPKI (v4.3.0+) -Mirrors `Get-ValidPSSession` but for CIM. SSL uses `New-CimSessionOption -UseSsl`; plain uses `New-CimSession` with `$Options.PSDefaultAuthentication`. CIMSession entries carry an additional `InstanceId` field. +--- -### `Get-ValidDCfromDomain` — Domain DC Discovery +## 6. EXISTING AI CONFIGS -Queries `Get-ADDomain` (via the primary `$TempPssSession`) to get `ReplicaDirectoryServers`, then iterates them through `Get-DCWinRMState` and returns the first reachable DC's FQDN. Used at the start of each domain loop to obtain the `$ValidDC` variable passed to all content functions. +**None Found**. No existing files: +- `.cursorrules` ✗ +- `.clinerules` ✗ +- `.windsurfrules` ✗ +- `CLAUDE.md` ✗ +- `AGENTS.md` ✗ +- `CONVENTIONS.md` ✗ -```powershell -if ($ValidDC = Get-ValidDCfromDomain -Domain $Domain -DCStatus ([ref]$DCStatus)) { - # use $ValidDC as the -Server parameter for AD cmdlets -} -``` +--- + +## 7. README AND CONTRIBUTING + +### README Key Points + +**Project Purpose**: +- Community-maintained, no Microsoft sponsorship +- Generates as-built documentation for AD (Word/HTML/Text) +- Supports AD 2012/2016/2019/2022/2025 +- **PowerShell 7+ required** (not PS 5.1!) +- Windows only (RSAT dependency) + +**Supported Features**: +- Forest topology & schema info +- Domain configuration & replication +- DNS zones & scavenging +- PKI/Certificate Authority details +- Diagrams (Forest, Replication, Trusts, Sites, CA) +- Health checks for security/best practices +- Multi-language support (en-US, es-ES) + +**Key Disclaimer**: +> This assessment is not exhaustive. All recommendations should be reviewed and implemented by qualified personnel. The author(s) assume no liability for any damages. + +### CONTRIBUTING Guidelines + +**Process**: +1. Fork repo, clone, add remote upstream +2. Create topic branch off dev/main +3. Make changes following project conventions +4. Commit with clear messages +5. Pull upstream dev before pushing +6. Open PR with clear description + +**Requirements**: +- Follow existing code conventions (indentation, comments) +- Include test coverage (reference Pester tests) +- Respect git commit message guidelines +- No copyrighted content +- Agree to project license + +**Key Restriction**: +- Ask before embarking on large features/refactoring +- Don't use issue tracker for personal support --- -## Diagram Generation +## 8. CODE CONVENTIONS SUMMARY + +### PowerShell Code Style + +**Enforced via VSCode + PSScriptAnalyzer**: + +**Formatting** (`.vscode/settings.json`): +- Tab size: 4 spaces (insert spaces, not tabs) +- Line length: 115 characters (ruler configured) +- Trim trailing whitespace: enabled +- Code folding: enabled +- Brace style: + - Opening brace on same line: `if (...) {` + - New line after opening brace: `{\n ...` + - New line after closing brace: disabled +- Whitespace: + - Before open brace: enabled + - Before open paren: enabled + - Around operators: enabled + - After separator (;): enabled + - Around pipe: enabled + +**Linting** (`PSScriptAnalyzerSettings.psd1`): +- No single-character variable names +- No double quotes for constant strings +- Case sensitivity enforced +- No aliases (full cmdlet names) +- Consistent whitespace + +### Naming Conventions + +**Variables**: +- PascalCase for scripts/function names: `$ValidDcFromDomain` +- $script: prefix for module-level vars: `$script:Report`, `$script:InfoLevel` +- Hungarian notation for collections: `$PSSTable`, `$DCStatus` (plural hint) + +**Functions**: +- Verb-Noun format: `Get-AbrADForest`, `Invoke-CommandWithTimeout` +- Approved verbs: Get, New, Invoke, Test, Convert +- Hierarchy: `Get-[Abr][Component][Action]` + +**Constants**: +- `[ordered]` for hash ordering +- `[System.Collections.ArrayList]` for dynamic arrays (preferred over `@()`) +- `[pscustomobject]` for object creation + +### Error Handling + +- Use **try-catch** blocks +- Write warnings via `Write-PScriboMessage -IsWarning` +- Write errors via `Write-Error` or `throw` +- Log activity via `Write-PScriboMessage` +- Show timing via `Show-AbrDebugExecutionTime` + +### Documentation + +- SYNOPSIS, DESCRIPTION, NOTES (version, author, twitter, github) +- .EXAMPLE, .LINK for help +- Inline comments for complex logic +- Parameter documentation with `[Parameter(...)]` attributes -### Overview +--- -Diagrams are generated via the **Diagrammer.Core** / **Diagrammer.Microsoft.AD** ecosystem (PSGraph + Graphviz). The pipeline is: +## 9. CRITICAL DEVELOPMENT NOTES -``` -Get-AbrDiagrammer # thin wrapper, reads $Options, calls New-AbrADDiagram - └─ New-AbrADDiagram # builds Graphviz DOT graph, exports to file or base64 - └─ Get-AbrDiag* # per-diagram-type data collectors (called inside New-AbrADDiagram) -``` +### Must-Know Limitations -### Diagram Types +1. **WinRM Requirements**: + - Target must be FQDN (not IP) + - WinRM must be enabled on DC + - Domain-joined machine required to run module + - PowerShell 7+ on Windows only -Six types are supported (controlled by `$Options.DiagramType.*` booleans in the JSON config): +2. **Execution Context**: + - Must run `-RunAsAdministrator` + - Cannot run inside PowerShell ISE + - Remote execution via PSSession (not local cmdlets) -| Type | JSON Key | What it shows | -|---|---|---| -| `Forest` | `DiagramType.Forest` | Forest topology with domains | -| `Sites` | `DiagramType.Sites` | AD site links and connections | -| `SitesInventory` | `DiagramType.SitesInventory` | Sites with DC inventory per site | -| `Trusts` | `DiagramType.Trusts` | Domain trust relationships | -| `CertificateAuthority` | `DiagramType.CertificateAuthority` | PKI CA hierarchy | -| `Replication` | `DiagramType.Replication` | DC replication topology | +3. **Session Timeout**: + - Default timeout: 900 seconds (15 minutes) + - Configurable via `$Options.JobsTimeOut` + - Long operations may timeout on slow links -### How `Get-AbrDiagrammer` Works +### Development Workflow -1. Reads `$Options.DiagramTheme` (`White`/`Black`/`Neon`) and `$Options.ExportDiagramsFormat` (array: `pdf`, `png`, `svg`, `jpg`, `base64`). -2. Passes an existing `$TempPssSession` as `-PSSessionObject` (no credential re-prompt). -3. For `base64` format: returns the base64 string directly (used to embed diagrams inline in HTML reports). -4. For file formats: saves to `$OutputFolderPath` as `AsBuiltReport.Microsoft.AD-().` and returns the file path when `-ExportPath` is set. -5. Optional features toggled via `$Options`: `EnableDiagramDebug` (red edge/subgraph outlines), `EnableDiagramSignature` (footer with `SignatureAuthorName`/`SignatureCompanyName`), `DiagramWaterMark`. +1. **Make changes** to `.ps1` files in `Src/Public` or `Src/Private` +2. **Run tests** locally: `.\Tests\Invoke-Tests.ps1` +3. **Check linting**: PSScriptAnalyzer via VSCode +4. **Push to dev branch** (not master) +5. **CI/CD runs** Pester + PSScriptAnalyzer +6. **Create PR** to merge into master -### Embedding a Diagram in the Report +### Debugging Tips -The typical pattern in a Section function: +**Execution Timing**: ```powershell -if ($Options.EnableDiagrams -and $Options.DiagramType.Forest) { - $DiagramFile = Get-AbrDiagrammer -DiagramType 'Forest' -DiagramOutput 'base64' -PSSessionObject $TempPssSession - if ($DiagramFile) { - Image -Base64 $DiagramFile -Text 'Forest Diagram' -Percent 100 -Align 'Center' - BlankLine - } +if ($Options.ShowExecutionTime) { + Show-AbrDebugExecutionTime -Start/Stop -TitleMessage 'Section Name' } ``` -### `New-AbrADDiagram` Internals +**Logging Messages**: +```powershell +Write-PScriboMessage -Message "Collecting..." +Write-PScriboMessage -IsWarning "Warning message" +``` -- Requires **admin** privileges (checks `WindowsPrincipal` role). -- Builds a `Graph {}` block (PSGraph DSL) with node/edge default styles derived from `$DiagramTheme`. -- Icon images are loaded from `AsBuiltReport.Microsoft.AD/icons/` via `$script:IconPath`. -- The `$reportTranslate.NewADDiagram.*` keys supply graph label strings (supports `en-US`/`es-ES`). -- `$Options.DiagramObjDebug` enables verbose object-level debug output. -- Does **not** use `$TempPssSession` directly — it creates its own internal `$DiagramTempPssSession` or accepts one via `-PSSessionObject`. +**Remote Session Debugging**: +```powershell +$session = Get-PSSession -Name 'DC01.contoso.com' +Invoke-Command -Session $session -ScriptBlock { Get-ADForest } +``` -### Adding a New Diagram Type +### Performance Considerations -1. Add a new `Get-AbrDiag.ps1` in `Src/Private/` following the existing `Get-AbrDiagForest.ps1` / `Get-AbrDiagSite.ps1` pattern. -2. Add the type string to the `ValidateSet` in both `Get-AbrDiagrammer` and `New-AbrADDiagram`. -3. Add a `$MainGraphLabel` switch case in `New-AbrADDiagram`'s `begin` block. -4. Add the corresponding boolean key to `Options.DiagramType` in `AsBuiltReport.Microsoft.AD.json`. -5. Add localized label strings to both `Language/` psd1 files under the `NewADDiagram` key. +- Remote data collection happens sequentially (per domain) +- Large forests (100+ domains) may take 30+ minutes +- CPU-intensive: Schema analysis, trust enumeration +- Network: WinRM traffic, potentially large XML responses +- Disk: HTML/DOCX output can be 50+ MB with diagrams ---- +### Testing Strategy -## PKI / Certificate Authority Section +**Unit Tests** (`Tests/AsBuiltReport.Microsoft.AD.Tests.ps1`): +- Module manifest validation +- Function availability +- Module dependency versions +- Export validation -### Prerequisites +**Integration Tests** (Not present): +- Would require live AD environment +- Manual testing against test domains recommended -The PKI section only runs when **all** of the following are true: -- `$InfoLevel.CA -ge 1` -- The machine running the report is joined to a domain that is **part of the target forest** (`Get-ComputerADDomain` result must be in `$ADSystem.Domains`) -- `Get-CertificationAuthority -Enterprise` returns at least one CA (uses the **PSPKI** module) +**Code Coverage**: +- Current: Unknown (50% threshold enforced) +- Recommendation: Add more tests for edge cases -If the reporting machine's domain is not in the forest, a warning is logged and the section is skipped entirely. +--- -### CA Data Source +## 10. PROJECT-SPECIFIC GUIDANCE FOR AI ASSISTANTS + +### When Making Code Changes + +1. **Respect InfoLevel checks**: Wrap new sections with `if ($InfoLevel.Component -ge N)` +2. **Add HealthCheck conditionals**: Wrap checks with `if ($HealthCheck.Component.Feature)` +3. **Use localization strings**: Reference `$reportTranslate.FunctionName.PropertyName` +4. **Follow try-catch pattern**: Every data gatherer in try-catch with `-IsWarning` +5. **Apply Set-Style**: Mark warning/critical objects for report highlighting +6. **Use OrderedDictionary**: `[ordered] @{}` for property ordering +7. **Pass sessions as parameters**: Don't assume `$TempPssSession` global exists +8. **Document with `.SYNOPSIS`**: All functions need help documentation +9. **Return objects not strings**: Build arrays of `[pscustomobject]` for Table output +10. **Test with `-CodeCoverage`**: Ensure new code is covered by tests + +### Common Tasks + +**Add a new health check:** +1. Add boolean to `AsBuiltReport.Microsoft.AD.json` under `HealthCheck.Component.NewCheck` +2. In Get-Abr* function: `if ($HealthCheck.Component.NewCheck) { ... Set-Style ... }` +3. Add test case to `Tests/AsBuiltReport.Microsoft.AD.Tests.ps1` + +**Add new report section:** +1. Create `Get-AbrNewSection` function in `Src/Private/` +2. Create `Get-AbrNewSectionData` data gatherer +3. Call from main entry point: `if ($InfoLevel.NewComponent -ge 1) { Get-AbrNewSection }` +4. Add InfoLevel config: `"NewComponent": 1` to JSON +5. Add translations to `Language/en-US/MicrosoftAD.psd1` and `es-ES/` + +**Fix a timeout issue:** +1. Increase `$Options.JobsTimeOut` in JSON (default 900) +2. Or reduce data scope (disable HealthChecks or lower InfoLevel) +3. Or optimize remote query (use `-Filter` with better conditions) + +### Module Dependencies to Understand + +- **AsBuiltReport.Core**: Framework for report generation, parameter validation +- **PScribo**: Document markup (Section, Table, Paragraph, Set-Style) +- **ActiveDirectory**: AD cmdlets (Get-ADForest, Get-ADDomain, etc.) - Microsoft module +- **PSPKI**: PKI cmdlets (Get-CertificationAuthority) - community module +- **Diagrammer.Core**: Diagram generation for topology visualization +- **GroupPolicy**: GPO retrieval (Get-GPO, Get-GPOReport) +- **DnsServer**: DNS zone enumeration -The PKI section does **not** use PSSession/CIMSession for CA data. It uses **PSPKI** module cmdlets directly on the machine running the report: -- `Get-CertificationAuthority -Enterprise` — discovers all enterprise CAs -- `Get-CertificationAuthority -Enterprise -ComputerName $CA` — per-CA object -- `Get-CACryptographyConfig -CertificationAuthority $CA` -- `Get-CATemplate`, `Get-CARoleServiceStatus`, `Get-CRLDistributionPoint`, `Get-AuthorityInformationAccess` +--- -The `$script:CAs` variable is set in `Get-AbrPKISection` and used by all CA sub-functions. +## 11. QUICK REFERENCE + +### Module Entry Point +- **Location**: `AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1` +- **Exports**: Single public function (dot-notation name) +- **Parameters**: `$Target` (FQDN array), `$Credential` (PSCredential) +- **Returns**: Report file (HTML/Word/Text) via PScribo + +### Main Directories +| Directory | Purpose | Files | +|-----------|---------|-------| +| `Src/Public` | Exported functions | 1 file (entry point) | +| `Src/Private` | Internal functions | 88 functions | +| `Language` | Localization | .psd1 per culture | +| `Tests` | Unit/integration tests | Pester framework | +| `.github/workflows` | CI/CD pipelines | 5 YAML files | + +### Key Files +| File | Purpose | Size | +|------|---------|------| +| `AsBuiltReport.Microsoft.AD.psm1` | Module loader | 14 lines | +| `AsBuiltReport.Microsoft.AD.psd1` | Manifest | ~100 lines | +| `AsBuiltReport.Microsoft.AD.json` | Config template | 89 lines | +| `AsBuiltReport.Microsoft.AD.Style.ps1` | Report styling | 20 KB | + +### Test Commands +```powershell +# Basic test run +.\Tests\Invoke-Tests.ps1 -### Section Structure (`Get-AbrPKISection`) +# With coverage +.\Tests\Invoke-Tests.ps1 -CodeCoverage -OutputFormat NUnitXml -``` -PKI (Heading1) ← only when $InfoLevel.CA -ge 1 - Get-AbrADCASummary ← always (CA name, server, type, service status) - Get-AbrADCARoot ← InfoLevel.CA -ge 2 - Get-AbrADCASubordinate ← InfoLevel.CA -ge 2 - foreach accessible CA: - Details (Heading2) - Get-AbrADCASecurity ← always - Get-AbrADCACryptographyConfig ← always - Get-AbrADCAAIA ← InfoLevel.CA -ge 2 - Get-AbrADCACRLSetting ← InfoLevel.CA -ge 2 - Get-AbrADCATemplate ← InfoLevel.CA -ge 2 - Get-AbrADCAKeyRecoveryAgent ← always +# Output formats +.\Tests\Invoke-Tests.ps1 -OutputFormat JUnitXml +.\Tests\Invoke-Tests.ps1 -OutputFormat Console ``` -### HealthCheck Styles for CA +### Required Modules (Minimum Versions) +```powershell +AsBuiltReport.Core 1.6.2+ +AsBuiltReport.Chart 0.2.0+ +Diagrammer.Core 0.2.38+ +PSPKI 4.3.0+ +Pester 5.0.0+ +PScribo 0.11.1+ +PSScriptAnalyzer 1.0.0+ +``` -| Check | Config Key | Style Applied | -|---|---|---| -| CA service not Running | `HealthCheck.CA.Status` | `Critical` on Status column | -| CA statistics thresholds | `HealthCheck.CA.Statistics` | `Warning` | -| Best practice settings | `HealthCheck.CA.BestPractice` | `Warning` | +### Function Categories +| Category | Count | Examples | +|----------|-------|----------| +| Get-Abr* (data gathering) | 52 | Get-AbrADForest, Get-AbrADDomain | +| Get-Abr*Section (orchestration) | 4 | Get-AbrForestSection, Get-AbrDNSSection | +| Get-AbrDiag* (diagrams) | 8 | Get-AbrDiagrammer, Get-AbrDiagForest | +| Utility (conversion, helpers) | 24+ | ConvertTo-HashToYN, Invoke-CommandWithTimeout | -Style values are `Warning` (yellow), `Critical` (red), and `Info` (blue) — passed to `Set-Style -Style -Property `. +--- -### Adding New CA Content +**Document Version**: 1.0 +**Last Updated**: 2024 +**Project Version**: 0.9.11 +**Target PowerShell**: 7+ +**Platform**: Windows Only -CA functions receive `$CA` (a PSPKI `CertificationAuthority` object) as their only parameter. The `$ForestInfo` script variable provides the forest name for table naming. Follow the same `$inObj` → `ConvertTo-HashToYN` → `Table` pattern as all other content functions. From 4eabd2dcd1ebec054dc16746fbe8a22108b5f5ac Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 14:30:16 -0400 Subject: [PATCH 06/11] Remove copilot instructions document to streamline project documentation --- copilot-instructions.md | 871 ---------------------------------------- 1 file changed, 871 deletions(-) delete mode 100644 copilot-instructions.md diff --git a/copilot-instructions.md b/copilot-instructions.md deleted file mode 100644 index 558cea0..0000000 --- a/copilot-instructions.md +++ /dev/null @@ -1,871 +0,0 @@ -# AsBuiltReport.Microsoft.AD - Copilot Instructions - -**Project Overview:** AsBuiltReport.Microsoft.AD is a PowerShell module that generates comprehensive as-built documentation for Microsoft Active Directory (AD) infrastructure in Word/HTML/Text formats. It's part of the larger AsBuiltReport ecosystem and works in conjunction with AsBuiltReport.Core. - ---- - -## 1. PROJECT STRUCTURE - -### Top-Level Directory Layout -``` -AsBuiltReport.Microsoft.AD/ -├── .github/ # CI/CD workflows and PR templates -│ ├── workflows/ # GitHub Actions workflows -│ │ ├── Pester.yml # Unit testing pipeline -│ │ ├── PSScriptAnalyzer.yml # Linting/code analysis -│ │ ├── CodeQL.yml # Security scanning -│ │ ├── Release.yml # Publishing to PSGallery + social media -│ │ └── Stale.yml # Issue/PR housekeeping -│ └── PULL_REQUEST_TEMPLATE.md -├── .vscode/ # VS Code settings for PowerShell formatting -│ └── settings.json # Formatting rules, rulers @ 115 chars -├── AsBuiltReport.Microsoft.AD/ # MAIN MODULE DIRECTORY -│ ├── AsBuiltReport.Microsoft.AD.psm1 # Module manifest (14 lines - loads all functions) -│ ├── AsBuiltReport.Microsoft.AD.psd1 # Module declaration (v0.9.11) -│ ├── AsBuiltReport.Microsoft.AD.json # Default report config (InfoLevels, HealthChecks) -│ ├── AsBuiltReport.Microsoft.AD.Style.ps1 # Document styling (20.8 KB) -│ ├── Src/ -│ │ ├── Public/ -│ │ │ └── Invoke-AsBuiltReport.Microsoft.AD.ps1 # ENTRY POINT (291 lines) -│ │ └── Private/ -│ │ ├── Get-Abr*.ps1 # 52x data gathering functions -│ │ ├── ConvertTo-*.ps1 # Format/conversion helpers -│ │ ├── Convert-*.ps1 # Data transformation utilities -│ │ ├── Get-*Diagram.ps1 # Visualization generation -│ │ └── Utility functions # Session management, timeout handling, etc. -│ ├── Language/ # Localization files -│ │ ├── en-US/MicrosoftAD.psd1 # English strings (hash of all messages) -│ │ └── es-ES/MicrosoftAD.psd1 # Spanish localization -│ └── icons/ # Image assets for reports -├── Tests/ -│ ├── Invoke-Tests.ps1 # Test runner script (204 lines) -│ ├── AsBuiltReport.Microsoft.AD.Tests.ps1 # Pester unit tests -│ ├── LocalizationData.Tests.ps1 # Localization validation -│ └── README.md -├── Samples/ # Example HTML reports -├── README.md # Project documentation -├── CONTRIBUTING.md # Contribution guidelines -├── CODE_OF_CONDUCT.md # Community standards -├── LICENSE # License file -├── CHANGELOG.md # Version history -├── SECURITY.md # Security policy -└── Todo.md # Development roadmap -``` - -### Key Directories -- **Src/Public**: Only `Invoke-AsBuiltReport.Microsoft.AD` - the single exported public function -- **Src/Private**: 88 total functions (52 Get-Abr* for data gathering, rest are utilities) -- **Language**: Localization for multi-language support (en-US, es-ES) -- **Tests**: Pester tests + custom test runner supporting code coverage - -### File Count Summary -- **Total .ps1 files**: 94 -- **Public functions**: 1 (exported) -- **Private functions**: ~88 + utilities -- **Data gathering functions (Get-Abr*)**: 52 - ---- - -## 2. BUILD, TEST, LINT COMMANDS - -### Test Execution - -**Local Test Execution:** -```powershell -.\Tests\Invoke-Tests.ps1 # Basic run -.\Tests\Invoke-Tests.ps1 -CodeCoverage -OutputFormat NUnitXml # With coverage -``` - -**Test Runner Details** (`Tests/Invoke-Tests.ps1`): -- Uses **Pester 5.0.0+** for testing framework -- Supports output formats: Console, NUnitXml, JUnitXml -- Includes code coverage analysis (JaCoCo format) -- Code coverage threshold: 50% minimum (warning at <50%) -- Coverage files tracked: `*.psm1`, `Src/Public/*.ps1`, `Src/Private/*.ps1` -- Test results: `Tests/testResults.xml` -- Coverage output: `Tests/coverage.xml` - -### Code Analysis - -**PSScriptAnalyzer** (`PSScriptAnalyzerSettings.psd1`): -- Linting tool configured in CI/CD -- Custom rules enforced: - - `PSAvoidExclaimOperator` - no `!` operator - - `AvoidUsingDoubleQuotesForConstantString` - use single quotes for constants - - `UseCorrectCasing` - enforce proper case - - `PSAvoidUsingCmdletAliases` - no aliases - - `PSUseConsistentWhitespace` - whitespace consistency -- Excluded rules: - - `PSUseToExportFieldsInManifest` - - `PSAvoidUsingWriteHost` (needed for reports) - -### CI/CD Pipelines - -**Pester Tests Workflow** (`.github/workflows/Pester.yml`): -- Triggers: push (main/dev/master), PR, manual -- Runs on: Windows (pwsh + powershell 5.1) -- Auto-installs: Pester 5.0.0+, PScribo 0.11.1+, PSScriptAnalyzer 1.0.0+, AsBuiltReport.Core 1.6.2+ -- Uploads test results as artifacts -- Uploads code coverage to Codecov - -**PSScriptAnalyzer Workflow** (`.github/workflows/PSScriptAnalyzer.yml`): -- Uses external action: `alagoutte/github-action-psscriptanalyzer@master` -- Fails on errors, comments inline -- Settings: `.github/workflows/PSScriptAnalyzerSettings.psd1` - -**CodeQL Workflow** (`.github/workflows/CodeQL.yml`): -- Security scanning for PowerShell - -**Release Workflow** (`.github/workflows/Release.yml`): -- Triggers on release published -- Tests module manifest -- Publishes to PowerShell Gallery (`Publish-Module`) -- Posts release announcements to Twitter & Bluesky - -**No Build/Invoke-Build found**: This is a pure PowerShell module (no compilation). - ---- - -## 3. ARCHITECTURE - -### High-Level Data Flow - -``` -Invoke-AsBuiltReport.Microsoft.AD (Entry Point) - ↓ - [Input: Target DC, Credentials] - ↓ - [Validate: Requirements, Features, Modules] - ↓ - [Connection: PSSession + CIMSession to DC] - ↓ - [Process Per Forest/Domain] - ├── Get-AbrForestSection (Forest-level data) - ├── Get-AbrDomainSection (Per-domain data) - ├── Get-AbrDnsSection (DNS configuration) - └── Get-AbrPKISection (Certificate Authority) - ↓ - [Diagram Generation: Forest, Replication, Trusts, Sites, CA] - ↓ - [Session Cleanup: Remove PSSession, CIMSession] - ↓ - [Output: HTML/Word/Text Report] -``` - -### Main Entry Point - -**File**: `AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1` (291 lines) - -**Signature**: -```powershell -function Invoke-AsBuiltReport.Microsoft.AD { - [CmdletBinding()] - param ( - [String[]] $Target, # Domain controller(s) FQDN - [PSCredential] $Credential # Credentials for remote session - ) - #Requires -RunAsAdministrator -} -``` - -**Key Responsibilities**: -1. Validate prerequisites (Windows PS >= 5.1, admin rights, not ISE) -2. Check installed modules & warn on outdated versions -3. Validate OS features (RSAT tools on workstation, features on server) -4. Load report config (JSON), InfoLevels, HealthChecks, Options -5. Establish PSSession + CIMSession to DC via WinRM -6. Collect forest/domain/DNS/PKI data via section functions -7. Generate diagrams (if enabled) -8. Build report using PScribo -9. Cleanup sessions - -**Critical Design Pattern**: -- **$Target** must be FQDN (not IP) - WinRM limitation -- Must run **-RunAsAdministrator** -- Must run from PowerShell 7+, **NOT** PowerShell ISE -- WinRM must be enabled on DC -- Uses **$Options** hash from config for behavior control - -### Core Section Builders - -These functions call data gatherers and structure output via PScribo's **Section** cmdlet: - -1. **Get-AbrForestSection**: Forest topology, schema, tombstone lifetime, global catalogs -2. **Get-AbrDomainSection**: Per-domain configuration, trusts, replication, GPOs, OUs -3. **Get-AbrDnsSection**: DNS zones, scavenging, delegation -4. **Get-AbrPKISection**: Certificate authorities, templates, security - -### Data Gathering Functions (Get-Abr*) - -**Pattern**: Each function collects specific AD object data via remote PSSession: - -Example: `Get-AbrADForest` (80 lines) -- Uses `Invoke-CommandWithTimeout` to run remote cmdlets -- Parses schema version to determine Windows Server version -- Detects anonymous access via dsHeuristics -- Returns object with translated property names -- Applies HealthCheck styling if enabled - -**All 52 Get-Abr* functions follow this pattern:** -- Accept parameters (Domain, ValidDcFromDomain, etc.) -- Start: Log collection message, start timing -- Process: Remote invocation via session, data transformation -- Output: `[System.Collections.ArrayList]` of objects -- HealthCheck: Conditionally apply styling (Warning/Critical) -- Return: Table/list output via PScribo's **Table** cmdlet - -### InfoLevel Architecture - -**Default Config** (`AsBuiltReport.Microsoft.AD.json`): -```json -"InfoLevel": { - "_comment_": "0 = Disabled, 1 = Enabled, 2 = Adv Summary, 3 = Detailed", - "Forest": 2, - "Domain": 2, - "DNS": 1, - "CA": 0 -} -``` - -**Usage Pattern**: -```powershell -if ($InfoLevel.Forest -ge 1) { ... show basic info } -if ($InfoLevel.Forest -ge 2) { ... show advanced details } -if ($InfoLevel.Forest -ge 3) { ... show comprehensive tables } -``` - -Enables **progressive disclosure** - users control report verbosity. - -### HealthCheck Architecture - -**Default Config**: -```json -"HealthCheck": { - "Domain": { - "GMSA": true, # Group Managed Service Accounts - "GPO": true, # Group Policy Objects - "Backup": true, # Domain backup status - "DFS": true, # DFS health - "SPN": true, # Service Principal Names - "DuplicateObject": true, - "Security": true, - "BestPractice": true - }, - "DomainController": { ... }, - "Site": { ... }, - "DNS": { ... }, - "CA": { ... } -} -``` - -**Styling Application**: -```powershell -if ($HealthCheck.Domain.Security) { - $OutObj | Where-Object { $_.AnonymousAccess -eq 'Enabled' } | - Set-Style -Style Critical -Property AnonymousAccess - $OutObj | Where-Object { $_.TombstoneLifetime -lt 180 } | - Set-Style -Style Warning -Property TombstoneLifetime -} -``` - -Objects marked as Warning/Critical get colored highlighting in reports. - -### Connection Management - -**Session Establishment** (in main entry point): -```powershell -$TempPssSession = Get-ValidPSSession -ComputerName $System -SessionName $System -$TempCIMSession = Get-ValidCIMSession -ComputerName $System -SessionName $System -``` - -**Remote Command Execution**: -```powershell -Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADForest } -``` - -**Cleanup**: -```powershell -foreach ($PSSession in $PSSTable | Where { $_.Status -ne 'Offline' }) { - Remove-PSSession -Id $PSSession.id -} -``` - -### Diagram Generation - -**Diagrammer Integration**: -- Uses `Diagrammer.Core` module for topology visualization -- Types: Forest, Replication, Sites, SitesInventory, Trusts, CertificateAuthority -- Controlled by `$Options.EnableDiagrams`, `$Options.DiagramType.*` -- Outputs: PDF/PNG (configurable via `$Options.ExportDiagramsFormat`) -- Theme: White/Dark (via `$Options.DiagramTheme`) - ---- - -## 4. KEY CONVENTIONS AND PATTERNS - -### Function Naming Convention - -**Public Functions**: -- `Invoke-AsBuiltReport.Microsoft.AD` - single entry point (uses dot notation) - -**Private Functions** - Three categories: - -1. **Data Gatherers** (`Get-Abr*`): - - `Get-AbrADForest` - retrieves Forest info - - `Get-AbrADDomain` - retrieves Domain info - - `Get-AbrADDomainController` - DC inventory - - `Get-AbrADCA*` - CA-specific data - - Pattern: Get-Abr[Section][Subsection] - -2. **Section Builders** (`Get-Abr*Section`): - - `Get-AbrForestSection` - orchestrates Forest section - - `Get-AbrDomainSection` - orchestrates Domain section - - `Get-AbrDnsSection` - orchestrates DNS section - - `Get-AbrPKISection` - orchestrates PKI section - - Pattern: Get-Abr[Section]Section - -3. **Diagram Builders** (`Get-AbrDiag*`): - - `Get-AbrDiagrammer` - main diagram orchestration - - `Get-AbrDiagForest`, `Get-AbrDiagReplication`, etc. - - Pattern: Get-AbrDiag[DiagramType] - -4. **Utility Functions** (various): - - `Convert-IpAddressToMaskLength` - IP/CIDR conversion - - `ConvertTo-HashToYN` - bool → Yes/No conversion - - `Invoke-CommandWithTimeout` - remote execution with timeout - - `Get-ValidPSSession` - session validation/creation - - `Test-WinRM` - WinRM connectivity check - -### Data Structure Patterns - -**Standard Data Object**: -```powershell -$inObj = [ordered] @{ - 'Property Name' = $Value - 'Health Check Property' = $CheckResult -} -$OutObj.Add([pscustomobject](ConvertTo-HashToYN $inObj)) | Out-Null -``` - -**Conversion Helper Usage**: -```powershell -# ConvertTo-HashToYN: Converts boolean $true/$false → "Yes"/"No" -$inObj | ConvertTo-HashToYN -``` - -**Style Application**: -```powershell -$OutObj | Set-Style -Style Critical -Property $PropertyName -$OutObj | Set-Style -Style Warning -Property $PropertyName -``` - -### Report Section Structure - -**PScribo Section Hierarchy**: -```powershell -Section -Style Heading1 "Forest Name" { - Paragraph "Introduction..." - BlankLine - - Section -Style Heading2 "Subsection Title" { - if ($Options.ShowDefinitionInfo) { - Paragraph "Definition text..." - } - - # Call data gatherer - Get-AbrADForest - - if ($InfoLevel.Forest -ge 2) { - # Advanced details - Get-AbrADSite - } - } -} -``` - -**PScribo Elements Used**: -- `Section` - create section with heading levels (Heading1-Heading4) -- `Table` - display data in tabular format -- `Paragraph` - text with styling (Bold, Underline, Colors) -- `BlankLine` - spacing -- `PageBreak` - force page break in Word/PDF - -### Translation/Localization Pattern - -**Property Names Use Translated Strings**: -```powershell -# From Language/en-US/MicrosoftAD.psd1 -@{ - GetAbrADForest = @{ - Collecting = 'Collecting Active Directory forest information.' - ForestName = 'Forest Name' - ForestFunctionalLevel = 'Forest Functional Level' - ... - } -} - -# In function: -$reportTranslate.GetAbrADForest.Collecting # Loaded at module init -``` - -**Multi-Language Support**: -- Each culture has its own .psd1 file (en-US, es-ES, etc.) -- Strings loaded into `$reportTranslate` hash at module load -- Property names in output tables are localized - -### HealthCheck Patterns - -**Pre-Check Pattern** (e.g., RID Pool): -```powershell -if ($HealthCheck.Domain.BestPractice) { - if ([math]::Truncate($CompleteSIDS / $RIDsRemaining) -gt 80) { - $OutObj | Set-Style -Style Warning -Property RIDProperty - Paragraph "Health check message about RID pool..." - } -} -``` - -**28 Functions Use HealthCheck** out of 52 data gatherers (~54%): -- Focus on security, best practices, service health -- Each check compares values against thresholds -- Styling applied: Warning, Critical, or Success - -### Configuration-Driven Behavior - -**Options Hash Controls**: -```json -"Options": { - "ShowExecutionTime": false, # Show timing info - "ShowDefinitionInfo": false, # Show definition text - "PSDefaultAuthentication": "Negotiate", - "Exclude": { "Domains": [], "DCs": [] }, - "Include": { "Domains": [] }, # Only these domains - "WinRMSSL": false, - "WinRMFallbackToNoSSL": true, - "WinRMSSLPort": 5986, - "WinRMPort": 5985, - "EnableDiagrams": true, - "DiagramTheme": "White", - "JobsTimeOut": 900 # 15-minute timeout -} -``` - -**Usage Example**: -```powershell -if ($Options.ShowDefinitionInfo) { - Paragraph $reportTranslate.GetAbrForestSection.DefinitionText -} - -$TimeoutSeconds = $Options.JobsTimeOut -``` - -### Error Handling & Timeouts - -**Invoke-CommandWithTimeout Pattern**: -```powershell -function Invoke-CommandWithTimeout { - param( - [System.Management.Automation.Runspaces.PSSession]$Session, - [scriptblock]$ScriptBlock, - [int]$TimeoutSeconds = $Options.JobsTimeOut - ) - - # Run as background job with timeout - $job = Invoke-Command -Session $Session -AsJob -ScriptBlock $ScriptBlock - Wait-Job $job -Timeout $TimeoutSeconds - Receive-Job $job -} -``` - -**Try-Catch in Data Gatherers**: -```powershell -try { - Get-AbrADForest -} catch { - Write-PScriboMessage -IsWarning $_.Exception.Message -} -``` - -### Sensitive Data Handling - -**No explicit redaction observed**, but patterns suggest: -- Credentials passed via `$PSCredential` object (not stored) -- Session-based execution (no inline secrets) -- Remote execution prevents data capture on local disk -- Output tables contain parsed, non-sensitive data - -**Recommendation**: Follow AD best practices - restrict report access, don't email to untrusted parties. - ---- - -## 5. CONFIGURATION - -### Primary Config File - -**File**: `AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.json` - -**Structure**: -```json -{ - "Report": { - "Name": "Microsoft Active Directory As Built Report", - "Version": "1.0", - "Status": "Released", - "ShowCoverPageImage": true, - "ShowTableOfContents": true, - "ShowHeaderFooter": true, - "ShowTableCaptions": true - }, - "Options": { ... }, // Execution behavior - "InfoLevel": { ... }, // Report verbosity - "HealthCheck": { ... } // Health check toggles -} -``` - -### Configuration Usage - -Users provide config via **-ReportConfig parameter** to AsBuiltReport.Core: - -```powershell -$ReportConfig = Get-Content 'config.json' | ConvertFrom-Json - -New-AsBuiltReport -Report Microsoft.AD ` - -Target 'DC01.contoso.com' ` - -ReportConfig $ReportConfig ` - -Credential $cred ` - -Format HTML -``` - -**Module Loads**: -```powershell -$script:Report = $ReportConfig.Report -$script:InfoLevel = $ReportConfig.InfoLevel -$script:Options = $ReportConfig.Options -``` - -### Module Manifest - -**File**: `AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1` - -**Key Settings**: -- **Version**: 0.9.11 -- **PowerShellVersion**: 5.1 (minimum, actually PS7 required) -- **CompatiblePSEditions**: Desktop, Core -- **GUID**: 0a3e1c04-13b8-418f-89bc-a5a18da07394 - -**Required Modules**: -- AsBuiltReport.Core (v1.6.2+) -- AsBuiltReport.Chart (v0.2.0+) -- Diagrammer.Core (v0.2.38+) -- PSPKI (v4.3.0+) - ---- - -## 6. EXISTING AI CONFIGS - -**None Found**. No existing files: -- `.cursorrules` ✗ -- `.clinerules` ✗ -- `.windsurfrules` ✗ -- `CLAUDE.md` ✗ -- `AGENTS.md` ✗ -- `CONVENTIONS.md` ✗ - ---- - -## 7. README AND CONTRIBUTING - -### README Key Points - -**Project Purpose**: -- Community-maintained, no Microsoft sponsorship -- Generates as-built documentation for AD (Word/HTML/Text) -- Supports AD 2012/2016/2019/2022/2025 -- **PowerShell 7+ required** (not PS 5.1!) -- Windows only (RSAT dependency) - -**Supported Features**: -- Forest topology & schema info -- Domain configuration & replication -- DNS zones & scavenging -- PKI/Certificate Authority details -- Diagrams (Forest, Replication, Trusts, Sites, CA) -- Health checks for security/best practices -- Multi-language support (en-US, es-ES) - -**Key Disclaimer**: -> This assessment is not exhaustive. All recommendations should be reviewed and implemented by qualified personnel. The author(s) assume no liability for any damages. - -### CONTRIBUTING Guidelines - -**Process**: -1. Fork repo, clone, add remote upstream -2. Create topic branch off dev/main -3. Make changes following project conventions -4. Commit with clear messages -5. Pull upstream dev before pushing -6. Open PR with clear description - -**Requirements**: -- Follow existing code conventions (indentation, comments) -- Include test coverage (reference Pester tests) -- Respect git commit message guidelines -- No copyrighted content -- Agree to project license - -**Key Restriction**: -- Ask before embarking on large features/refactoring -- Don't use issue tracker for personal support - ---- - -## 8. CODE CONVENTIONS SUMMARY - -### PowerShell Code Style - -**Enforced via VSCode + PSScriptAnalyzer**: - -**Formatting** (`.vscode/settings.json`): -- Tab size: 4 spaces (insert spaces, not tabs) -- Line length: 115 characters (ruler configured) -- Trim trailing whitespace: enabled -- Code folding: enabled -- Brace style: - - Opening brace on same line: `if (...) {` - - New line after opening brace: `{\n ...` - - New line after closing brace: disabled -- Whitespace: - - Before open brace: enabled - - Before open paren: enabled - - Around operators: enabled - - After separator (;): enabled - - Around pipe: enabled - -**Linting** (`PSScriptAnalyzerSettings.psd1`): -- No single-character variable names -- No double quotes for constant strings -- Case sensitivity enforced -- No aliases (full cmdlet names) -- Consistent whitespace - -### Naming Conventions - -**Variables**: -- PascalCase for scripts/function names: `$ValidDcFromDomain` -- $script: prefix for module-level vars: `$script:Report`, `$script:InfoLevel` -- Hungarian notation for collections: `$PSSTable`, `$DCStatus` (plural hint) - -**Functions**: -- Verb-Noun format: `Get-AbrADForest`, `Invoke-CommandWithTimeout` -- Approved verbs: Get, New, Invoke, Test, Convert -- Hierarchy: `Get-[Abr][Component][Action]` - -**Constants**: -- `[ordered]` for hash ordering -- `[System.Collections.ArrayList]` for dynamic arrays (preferred over `@()`) -- `[pscustomobject]` for object creation - -### Error Handling - -- Use **try-catch** blocks -- Write warnings via `Write-PScriboMessage -IsWarning` -- Write errors via `Write-Error` or `throw` -- Log activity via `Write-PScriboMessage` -- Show timing via `Show-AbrDebugExecutionTime` - -### Documentation - -- SYNOPSIS, DESCRIPTION, NOTES (version, author, twitter, github) -- .EXAMPLE, .LINK for help -- Inline comments for complex logic -- Parameter documentation with `[Parameter(...)]` attributes - ---- - -## 9. CRITICAL DEVELOPMENT NOTES - -### Must-Know Limitations - -1. **WinRM Requirements**: - - Target must be FQDN (not IP) - - WinRM must be enabled on DC - - Domain-joined machine required to run module - - PowerShell 7+ on Windows only - -2. **Execution Context**: - - Must run `-RunAsAdministrator` - - Cannot run inside PowerShell ISE - - Remote execution via PSSession (not local cmdlets) - -3. **Session Timeout**: - - Default timeout: 900 seconds (15 minutes) - - Configurable via `$Options.JobsTimeOut` - - Long operations may timeout on slow links - -### Development Workflow - -1. **Make changes** to `.ps1` files in `Src/Public` or `Src/Private` -2. **Run tests** locally: `.\Tests\Invoke-Tests.ps1` -3. **Check linting**: PSScriptAnalyzer via VSCode -4. **Push to dev branch** (not master) -5. **CI/CD runs** Pester + PSScriptAnalyzer -6. **Create PR** to merge into master - -### Debugging Tips - -**Execution Timing**: -```powershell -if ($Options.ShowExecutionTime) { - Show-AbrDebugExecutionTime -Start/Stop -TitleMessage 'Section Name' -} -``` - -**Logging Messages**: -```powershell -Write-PScriboMessage -Message "Collecting..." -Write-PScriboMessage -IsWarning "Warning message" -``` - -**Remote Session Debugging**: -```powershell -$session = Get-PSSession -Name 'DC01.contoso.com' -Invoke-Command -Session $session -ScriptBlock { Get-ADForest } -``` - -### Performance Considerations - -- Remote data collection happens sequentially (per domain) -- Large forests (100+ domains) may take 30+ minutes -- CPU-intensive: Schema analysis, trust enumeration -- Network: WinRM traffic, potentially large XML responses -- Disk: HTML/DOCX output can be 50+ MB with diagrams - -### Testing Strategy - -**Unit Tests** (`Tests/AsBuiltReport.Microsoft.AD.Tests.ps1`): -- Module manifest validation -- Function availability -- Module dependency versions -- Export validation - -**Integration Tests** (Not present): -- Would require live AD environment -- Manual testing against test domains recommended - -**Code Coverage**: -- Current: Unknown (50% threshold enforced) -- Recommendation: Add more tests for edge cases - ---- - -## 10. PROJECT-SPECIFIC GUIDANCE FOR AI ASSISTANTS - -### When Making Code Changes - -1. **Respect InfoLevel checks**: Wrap new sections with `if ($InfoLevel.Component -ge N)` -2. **Add HealthCheck conditionals**: Wrap checks with `if ($HealthCheck.Component.Feature)` -3. **Use localization strings**: Reference `$reportTranslate.FunctionName.PropertyName` -4. **Follow try-catch pattern**: Every data gatherer in try-catch with `-IsWarning` -5. **Apply Set-Style**: Mark warning/critical objects for report highlighting -6. **Use OrderedDictionary**: `[ordered] @{}` for property ordering -7. **Pass sessions as parameters**: Don't assume `$TempPssSession` global exists -8. **Document with `.SYNOPSIS`**: All functions need help documentation -9. **Return objects not strings**: Build arrays of `[pscustomobject]` for Table output -10. **Test with `-CodeCoverage`**: Ensure new code is covered by tests - -### Common Tasks - -**Add a new health check:** -1. Add boolean to `AsBuiltReport.Microsoft.AD.json` under `HealthCheck.Component.NewCheck` -2. In Get-Abr* function: `if ($HealthCheck.Component.NewCheck) { ... Set-Style ... }` -3. Add test case to `Tests/AsBuiltReport.Microsoft.AD.Tests.ps1` - -**Add new report section:** -1. Create `Get-AbrNewSection` function in `Src/Private/` -2. Create `Get-AbrNewSectionData` data gatherer -3. Call from main entry point: `if ($InfoLevel.NewComponent -ge 1) { Get-AbrNewSection }` -4. Add InfoLevel config: `"NewComponent": 1` to JSON -5. Add translations to `Language/en-US/MicrosoftAD.psd1` and `es-ES/` - -**Fix a timeout issue:** -1. Increase `$Options.JobsTimeOut` in JSON (default 900) -2. Or reduce data scope (disable HealthChecks or lower InfoLevel) -3. Or optimize remote query (use `-Filter` with better conditions) - -### Module Dependencies to Understand - -- **AsBuiltReport.Core**: Framework for report generation, parameter validation -- **PScribo**: Document markup (Section, Table, Paragraph, Set-Style) -- **ActiveDirectory**: AD cmdlets (Get-ADForest, Get-ADDomain, etc.) - Microsoft module -- **PSPKI**: PKI cmdlets (Get-CertificationAuthority) - community module -- **Diagrammer.Core**: Diagram generation for topology visualization -- **GroupPolicy**: GPO retrieval (Get-GPO, Get-GPOReport) -- **DnsServer**: DNS zone enumeration - ---- - -## 11. QUICK REFERENCE - -### Module Entry Point -- **Location**: `AsBuiltReport.Microsoft.AD/Src/Public/Invoke-AsBuiltReport.Microsoft.AD.ps1` -- **Exports**: Single public function (dot-notation name) -- **Parameters**: `$Target` (FQDN array), `$Credential` (PSCredential) -- **Returns**: Report file (HTML/Word/Text) via PScribo - -### Main Directories -| Directory | Purpose | Files | -|-----------|---------|-------| -| `Src/Public` | Exported functions | 1 file (entry point) | -| `Src/Private` | Internal functions | 88 functions | -| `Language` | Localization | .psd1 per culture | -| `Tests` | Unit/integration tests | Pester framework | -| `.github/workflows` | CI/CD pipelines | 5 YAML files | - -### Key Files -| File | Purpose | Size | -|------|---------|------| -| `AsBuiltReport.Microsoft.AD.psm1` | Module loader | 14 lines | -| `AsBuiltReport.Microsoft.AD.psd1` | Manifest | ~100 lines | -| `AsBuiltReport.Microsoft.AD.json` | Config template | 89 lines | -| `AsBuiltReport.Microsoft.AD.Style.ps1` | Report styling | 20 KB | - -### Test Commands -```powershell -# Basic test run -.\Tests\Invoke-Tests.ps1 - -# With coverage -.\Tests\Invoke-Tests.ps1 -CodeCoverage -OutputFormat NUnitXml - -# Output formats -.\Tests\Invoke-Tests.ps1 -OutputFormat JUnitXml -.\Tests\Invoke-Tests.ps1 -OutputFormat Console -``` - -### Required Modules (Minimum Versions) -```powershell -AsBuiltReport.Core 1.6.2+ -AsBuiltReport.Chart 0.2.0+ -Diagrammer.Core 0.2.38+ -PSPKI 4.3.0+ -Pester 5.0.0+ -PScribo 0.11.1+ -PSScriptAnalyzer 1.0.0+ -``` - -### Function Categories -| Category | Count | Examples | -|----------|-------|----------| -| Get-Abr* (data gathering) | 52 | Get-AbrADForest, Get-AbrADDomain | -| Get-Abr*Section (orchestration) | 4 | Get-AbrForestSection, Get-AbrDNSSection | -| Get-AbrDiag* (diagrams) | 8 | Get-AbrDiagrammer, Get-AbrDiagForest | -| Utility (conversion, helpers) | 24+ | ConvertTo-HashToYN, Invoke-CommandWithTimeout | - ---- - -**Document Version**: 1.0 -**Last Updated**: 2024 -**Project Version**: 0.9.11 -**Target PowerShell**: 7+ -**Platform**: Windows Only - From aa1b8d6033ff83026cfe4c7d9b311efd5705f6c1 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 16:33:58 -0400 Subject: [PATCH 07/11] feat: Add GliderUI support for report generation with a graphical interface fix: Ensure diagram theme generation respects user-selected themes in configuration refactor: Improve multi-language support and documentation clarity for MicrosoftAD.psd1 --- .../AsBuiltReport.Microsoft.AD.json | 5 - .../AsBuiltReport.Microsoft.AD.psd1 | 2 +- .../AsBuiltReport.Microsoft.AD.psm1 | 6 +- .../Src/Private/Diagram/Get-AbrADCaInfo.ps1 | 8 +- .../Private/Diagram/Get-AbrADForestInfo.ps1 | 8 +- .../Private/Diagram/Get-AbrADTrustInfo.ps1 | 6 +- .../Get-AbrDiagCertificateAuthority.ps1 | 12 +- .../Src/Private/Diagram/Get-AbrDiagForest.ps1 | 4 +- .../Diagram/Get-AbrDiagReplication.ps1 | 14 +- .../Src/Private/Diagram/Get-AbrDiagSite.ps1 | 6 +- .../Diagram/Get-AbrDiagSiteInventory.ps1 | 20 +- .../Src/Private/Diagram/Get-AbrDiagTrust.ps1 | 6 +- .../Src/Private/Diagram/New-AbrADDiagram.ps1 | 4 +- .../Private/Gui/Start-AsBuiltReportMSAD.ps1 | 1408 +++++++++++++++++ CHANGELOG.md | 8 + 15 files changed, 1465 insertions(+), 52 deletions(-) create mode 100644 AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 diff --git a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.json b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.json index 88f5b32..4a34316 100644 --- a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.json +++ b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.json @@ -79,11 +79,6 @@ "DP": true, "Zones": true, "BestPractice": true - }, - "CA": { - "Status": true, - "Statistics": true, - "BestPractice": true } } } \ No newline at end of file diff --git a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 index 24fc28f..58e336b 100644 --- a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 +++ b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psd1 @@ -82,7 +82,7 @@ # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. - FunctionsToExport = @('Invoke-AsBuiltReport.Microsoft.AD') + FunctionsToExport = @('Invoke-AsBuiltReport.Microsoft.AD', 'Start-AsBuiltReportMSAD') # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. # CmdletsToExport = '*' diff --git a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psm1 b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psm1 index c27469d..2b78072 100644 --- a/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psm1 +++ b/AsBuiltReport.Microsoft.AD/AsBuiltReport.Microsoft.AD.psm1 @@ -3,8 +3,9 @@ $Public = @(Get-ChildItem -Path $PSScriptRoot\Src\Public\*.ps1 -ErrorAction Sile $Diagram = @(Get-ChildItem -Path $PSScriptRoot\Src\Private\Diagram\*.ps1 -ErrorAction SilentlyContinue) $Report = @(Get-ChildItem -Path $PSScriptRoot\Src\Private\Report\*.ps1 -ErrorAction SilentlyContinue) $Tools = @(Get-ChildItem -Path $PSScriptRoot\Src\Private\Tools\*.ps1 -ErrorAction SilentlyContinue) +$Gui = @(Get-ChildItem -Path $PSScriptRoot\Src\Private\Gui\*.ps1 -ErrorAction SilentlyContinue) -foreach ($Module in @($Public + $Report + $Diagram + $Tools)) { +foreach ($Module in @($Public + $Report + $Diagram + $Tools + $Gui)) { try { . $Module.FullName } catch { @@ -15,4 +16,5 @@ foreach ($Module in @($Public + $Report + $Diagram + $Tools)) { Export-ModuleMember -Function $Public.BaseName Export-ModuleMember -Function $Report.BaseName Export-ModuleMember -Function $Diagram.BaseName -Export-ModuleMember -Function $Tools.BaseName \ No newline at end of file +Export-ModuleMember -Function $Tools.BaseName +Export-ModuleMember -Function $Gui.BaseName \ No newline at end of file diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADCaInfo.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADCaInfo.ps1 index 014d8ea..399e2b9 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADCaInfo.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADCaInfo.ps1 @@ -5,7 +5,7 @@ function Get-AbrADCAInfo { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -43,7 +43,7 @@ function Get-AbrADCAInfo { $TempCAInfo = [PSCustomObject]@{ Name = Remove-SpecialCharacter -String "$($rootCA.Name)RootCA" -SpecialChars '\-. ' CAName = $rootCA.Name - Label = Add-NodeIcon -Name $rootCA.Name -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -Rows $AditionalInfo + Label = Add-NodeIcon -Name $rootCA.Name -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -Rows $AditionalInfo -FontColor $Fontcolor AditionalInfo = $AditionalInfo IsRoot = $true } @@ -64,7 +64,7 @@ function Get-AbrADCAInfo { $TempCAInfo = [PSCustomObject]@{ Name = Remove-SpecialCharacter -String $RootCAName -SpecialChars '\-. ' CAName = $RootCAName - Label = Add-NodeIcon -Name $RootCAName -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -Rows $AditionalInfo + Label = Add-NodeIcon -Name $RootCAName -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -Rows $AditionalInfo -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor AditionalInfo = $AditionalInfo IsRoot = $true } @@ -86,7 +86,7 @@ function Get-AbrADCAInfo { $TempCAInfo = [PSCustomObject]@{ Name = Remove-SpecialCharacter -String $subordinateCA.Name -SpecialChars '\-. ' CAName = $subordinateCA.Name - Label = Add-NodeIcon -Name $subordinateCA.dNSHostName -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -Rows $AditionalInfo + Label = Add-NodeIcon -Name $subordinateCA.dNSHostName -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -Rows $AditionalInfo -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor AditionalInfo = $AditionalInfo IsRoot = $false } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADForestInfo.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADForestInfo.ps1 index f830c5e..41c1595 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADForestInfo.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADForestInfo.ps1 @@ -5,7 +5,7 @@ function Get-AbrADForestInfo { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -131,9 +131,9 @@ function Get-AbrADForestInfo { $TempForestInfo = [PSCustomObject]@{ Name = Remove-SpecialCharacter -String "$($ChildDomain)ChildDomain" -SpecialChars '\-. ' ChildDomainLabel = $ChildDomain - Label = Add-NodeIcon -Name $ChildDomain -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -AditionalInfo $AditionalDomainInfo -FontSize 18 + Label = Add-NodeIcon -Name $ChildDomain -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -AditionalInfo $AditionalDomainInfo -FontSize 18 -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor RootDomain = $ForestObj.RootDomain - RootDomainLabel = Add-NodeIcon -Name $ForestObj.RootDomain -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -AditionalInfo $AditionalForestInfo -FontSize 18 + RootDomainLabel = Add-NodeIcon -Name $ForestObj.RootDomain -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -AditionalInfo $AditionalForestInfo -FontSize 18 -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor ChildDomain = $ChildDomain ParentDomain = Remove-SpecialCharacter -String "$($Childs.Parent)ChildDomain" -SpecialChars '\-. ' AditionalInfo = $AditionalDomainInfo @@ -181,7 +181,7 @@ function Get-AbrADForestInfo { $TempForestInfo = [PSCustomObject]@{ Name = Remove-SpecialCharacter -String "$($ForestObj.Name)RootDomain" -SpecialChars '\-. ' - Label = Add-NodeIcon -Name $ForestObj.RootDomain -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -AditionalInfo $AditionalForestInfo -FontSize 18 + Label = Add-NodeIcon -Name $ForestObj.RootDomain -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -AditionalInfo $AditionalForestInfo -FontSize 18 -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor AditionalInfo = $AditionalForestInfo } $ForestInfo.Add($TempForestInfo) diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADTrustInfo.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADTrustInfo.ps1 index 7d4e407..5b37274 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADTrustInfo.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrADTrustInfo.ps1 @@ -5,7 +5,7 @@ function Get-AbrADTrustsInfo { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -71,9 +71,9 @@ function Get-AbrADTrustsInfo { } $TempTrustsInfo = [PSCustomObject]@{ Name = Remove-SpecialCharacter -String "$($Trust.Target)Trusts" -SpecialChars '\-. ' - Label = Add-NodeIcon -Name $Trust.Target -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -RowsOrdered $AditionalInfo + Label = Add-NodeIcon -Name $Trust.Target -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -RowsOrdered $AditionalInfo -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor Source = $Trust.CanonicalName.split('/')[0] - SourceLabel = Add-NodeIcon -Name $Trust.CanonicalName.split('/')[0] -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug + SourceLabel = Add-NodeIcon -Name $Trust.CanonicalName.split('/')[0] -IconType 'AD_Domain' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor Direction = $TrustDirectionID[[int]$Trust.TrustDirection] } $TrustsInfo.Add($TempTrustsInfo) diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagCertificateAuthority.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagCertificateAuthority.ps1 index 20d5e9f..e8e96b5 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagCertificateAuthority.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagCertificateAuthority.ps1 @@ -5,7 +5,7 @@ function Get-AbrDiagCertificateAuthority { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -32,7 +32,7 @@ function Get-AbrDiagCertificateAuthority { $CAInfo = Get-AbrADCAInfo if ($CAInfo) { - SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { + SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { SubGraph MainSubGraph -Attributes @{Label = ' ' ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { if ($CAInfo | Where-Object { $_.IsRoot }) { @@ -42,16 +42,16 @@ function Get-AbrDiagCertificateAuthority { $CALabel = $reportTranslate.NewADDiagram.caEntRootCA } - $CARootNodes = Add-HtmlNodeTable -Name CARootNodes -ImagesObj $Images -inputObject ($CAInfo | Where-Object { $_.IsRoot }).CAName -Align 'Center' -iconType 'AD_Certificate' -ColumnSize 4 -IconDebug $IconDebug -MultiIcon -AditionalInfo ($CAInfo | Where-Object { $_.IsRoot }).AditionalInfo -FontSize 18 -TableBorderColor $Edgecolor + $CARootNodes = Add-HtmlNodeTable -Name CARootNodes -ImagesObj $Images -inputObject ($CAInfo | Where-Object { $_.IsRoot }).CAName -Align 'Center' -iconType 'AD_Certificate' -ColumnSize 4 -IconDebug $IconDebug -MultiIcon -AditionalInfo ($CAInfo | Where-Object { $_.IsRoot }).AditionalInfo -FontSize 18 -TableBorderColor $Edgecolor -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor - Node -Name 'RootCA' -Attributes @{Label = (Add-HtmlSubGraph -Name RootCA -ImagesObj $Images -TableArray $CARootNodes -Align 'Center' -IconDebug $IconDebug -Label $CALabel -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -IconType 'AD_PKI_Logo' -FontColor $Fontcolor -FontSize 24 -FontBold -TableBorderColor $Edgecolor); shape = 'plain'; fillColor = 'transparent'; fontsize = 18; fontname = 'Segoe Ui' } + Node -Name 'RootCA' -Attributes @{Label = (Add-HtmlSubGraph -Name RootCA -ImagesObj $Images -TableArray $CARootNodes -Align 'Center' -IconDebug $IconDebug -Label $CALabel -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -IconType 'AD_PKI_Logo' -FontColor $Fontcolor -FontSize 24 -FontBold -TableBorderColor $Edgecolor -TableBackgroundColor $MainGraphBGColor); shape = 'plain'; fillColor = 'transparent'; fontsize = 18; fontname = 'Segoe Ui' } } if ($CAInfo | Where-Object { -not $_.IsRoot }) { - $CASubordinateNodes = Add-HtmlNodeTable -Name CASubordinateNodes -ImagesObj $Images -inputObject ($CAInfo | Where-Object { -not $_.IsRoot }).CAName -Align 'Center' -iconType 'AD_Certificate' -ColumnSize 4 -IconDebug $IconDebug -MultiIcon -AditionalInfo ($CAInfo | Where-Object { -not $_.IsRoot }).AditionalInfo -FontSize 18 -TableBorderColor $Edgecolor + $CASubordinateNodes = Add-HtmlNodeTable -Name CASubordinateNodes -ImagesObj $Images -inputObject ($CAInfo | Where-Object { -not $_.IsRoot }).CAName -Align 'Center' -iconType 'AD_Certificate' -ColumnSize 4 -IconDebug $IconDebug -MultiIcon -AditionalInfo ($CAInfo | Where-Object { -not $_.IsRoot }).AditionalInfo -FontSize 18 -TableBorderColor $Edgecolor -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor - Node -Name 'SubordinateCA' -Attributes @{Label = (Add-HtmlSubGraph -Name SubordinateCA -ImagesObj $Images -TableArray $CASubordinateNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.caEntSubCA -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -IconType 'AD_PKI_Logo' -FontColor $Fontcolor -FontSize 24 -FontBold -TableBorderColor $Edgecolor); shape = 'plain'; fillColor = 'transparent'; fontsize = 18; fontname = 'Segoe Ui' } + Node -Name 'SubordinateCA' -Attributes @{Label = (Add-HtmlSubGraph -Name SubordinateCA -ImagesObj $Images -TableArray $CASubordinateNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.caEntSubCA -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -IconType 'AD_PKI_Logo' -FontColor $Fontcolor -FontSize 24 -FontBold -TableBorderColor $Edgecolor -TableBackgroundColor $MainGraphBGColor); shape = 'plain'; fillColor = 'transparent'; fontsize = 18; fontname = 'Segoe Ui' } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagForest.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagForest.ps1 index a44e6bc..8c3c83c 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagForest.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagForest.ps1 @@ -5,7 +5,7 @@ function Get-AbrDiagForest { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -32,7 +32,7 @@ function Get-AbrDiagForest { $ForestInfo = Get-AbrADForestInfo if ($ForestInfo) { - SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { + SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { SubGraph MainSubGraph -Attributes @{Label = ' ' ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { if ($ForestInfo.ChildDomain ) { diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagReplication.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagReplication.ps1 index bcf6b9a..af21f1e 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagReplication.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagReplication.ps1 @@ -5,7 +5,7 @@ function Get-AbrDiagReplication { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -33,7 +33,7 @@ function Get-AbrDiagReplication { Write-Verbose -Message ($reportTranslate.NewADDiagram.buildingReplication -f $($ForestRoot)) $HTMLLegend = ('
{0} {1}
' -f $reportTranslate.NewADDiagram.replIntraSite, $reportTranslate.NewADDiagram.replInterSite) if ($ReplInfo) { - SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { + SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { SubGraph MainSubGraph -Attributes @{Label = $HTMLLegend ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { # Collect unique sites and DCs from replication data $Sites = ($ReplInfo | Select-Object -ExpandProperty FromSite) + ($ReplInfo | Select-Object -ExpandProperty ToSite) | Select-Object -Unique | Where-Object { $_ -ne 'Unknown' } @@ -49,10 +49,10 @@ function Get-AbrDiagReplication { ($ReplInfo | Where-Object { ($_.FromServer -eq $DC -and $_.FromSite -eq $Site) -or ($_.ToServer -eq $DC -and $_.ToSite -eq $Site) }) } | Select-Object -Unique - SubGraph $SiteNodeName -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $Site -IconType 'AD_Site' -IconDebug $IconDebug -SubgraphLabel -IconWidth 35 -IconHeight 35 -Fontsize 18 -FontName 'Segoe UI' -FontColor $Fontcolor); fontsize = 18; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray' } { + SubGraph $SiteNodeName -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $Site -IconType 'AD_Site' -IconDebug $IconDebug -SubgraphLabel -IconWidth 35 -IconHeight 35 -Fontsize 18 -FontName 'Segoe UI' -FontColor $Fontcolor -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor); fontsize = 18; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray' } { foreach ($DC in $SiteDCs) { $DCNodeName = Remove-SpecialCharacter -String $DC -SpecialChars '\-. ' - Node -Name $DCNodeName -Attributes @{Label = (Add-NodeIcon -Name ($DC.Split('.')[0].ToUpper()) -IconType 'AD_DC' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -FontSize 18); shape = 'plain'; fillColor = 'transparent' } + Node -Name $DCNodeName -Attributes @{Label = (Add-NodeIcon -Name ($DC.Split('.')[0].ToUpper()) -IconType 'AD_DC' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -FontSize 18 -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor); shape = 'plain'; fillColor = 'transparent' } } } } @@ -63,10 +63,10 @@ function Get-AbrDiagReplication { -not ($ReplInfo | Where-Object { ($_.FromServer -eq $DC -and $_.FromSite -ne 'Unknown') -or ($_.ToServer -eq $DC -and $_.ToSite -ne 'Unknown') }) } if ($UnknownSiteDCs) { - SubGraph UnknownSite -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $reportTranslate.NewADDiagram.replUnknownSite -IconType 'AD_Site' -IconDebug $IconDebug -SubgraphLabel -IconWidth 35 -IconHeight 35 -Fontsize 18 -FontName 'Segoe UI' -FontColor $Fontcolor); fontsize = 18; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray' } { + SubGraph UnknownSite -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $reportTranslate.NewADDiagram.replUnknownSite -IconType 'AD_Site' -IconDebug $IconDebug -SubgraphLabel -IconWidth 35 -IconHeight 35 -Fontsize 18 -FontName 'Segoe UI' -FontColor $Fontcolor -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor); fontsize = 18; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray' } { foreach ($DC in $UnknownSiteDCs) { $DCNodeName = Remove-SpecialCharacter -String $DC -SpecialChars '\-. ' - Node -Name $DCNodeName -Attributes @{Label = (Add-NodeIcon -Name ($DC.Split('.')[0].ToUpper()) -IconType 'AD_DC' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -FontSize 18); shape = 'plain'; fillColor = 'transparent' } + Node -Name $DCNodeName -Attributes @{Label = (Add-NodeIcon -Name ($DC.Split('.')[0].ToUpper()) -IconType 'AD_DC' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -FontSize 18 -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor); shape = 'plain'; fillColor = 'transparent' } } } } @@ -74,7 +74,7 @@ function Get-AbrDiagReplication { # No site information - draw all DCs without grouping foreach ($DC in $AllDCs) { $DCNodeName = Remove-SpecialCharacter -String $DC -SpecialChars '\-. ' - Node -Name $DCNodeName -Attributes @{Label = (Add-NodeIcon -Name ($DC.Split('.')[0].ToUpper()) -IconType 'AD_DC' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -FontSize 18); shape = 'plain'; fillColor = 'transparent' } + Node -Name $DCNodeName -Attributes @{Label = (Add-NodeIcon -Name ($DC.Split('.')[0].ToUpper()) -IconType 'AD_DC' -Align 'Center' -ImagesObj $Images -IconDebug $IconDebug -FontSize 18 -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor -FontColor $Fontcolor); shape = 'plain'; fillColor = 'transparent' } } } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSite.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSite.ps1 index 36bd60f..bd88d2b 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSite.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSite.ps1 @@ -5,7 +5,7 @@ function Get-AbrDiagSite { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -32,7 +32,7 @@ function Get-AbrDiagSite { $SitesInfo = Get-AbrADSitesInfo if ($SitesInfo) { - SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { + SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { SubGraph MainSubGraph -Attributes @{Label = ' ' ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { if ($SitesInfo.Site) { foreach ($SitesObj in $SitesInfo) { @@ -41,7 +41,7 @@ function Get-AbrDiagSite { foreach ($Link in $SitesObj.SiteLink) { # Start - Information for each SiteLink. Example: "Name: (Pharmax-to-Acad) SiteLink (Cost: 10) (Frequency: 15 minutes)" $SiteLink = Remove-SpecialCharacter -String $Link.Name -SpecialChars '\-. ' - Node -Name $SiteLink -Attributes @{Label = (Add-HtmlTable -Name SiteLink -ALIGN 'Center' -IconDebug $IconDebug -Rows ($Link.AditionalInfo.GetEnumerator() | ForEach-Object { "$($_.key): $($_.value)" }) -ColumnSize 1 -FontSize 12); shape = 'plain'; fillColor = 'transparent' } + Node -Name $SiteLink -Attributes @{Label = (Add-HtmlTable -Name SiteLink -ALIGN 'Center' -IconDebug $IconDebug -Rows ($Link.AditionalInfo.GetEnumerator() | ForEach-Object { "$($_.key): $($_.value)" }) -ColumnSize 1 -FontSize 12 -FontColor $Fontcolor -TableBackgroundColor $MainGraphBGColor); shape = 'plain'; fillColor = 'transparent' } Edge -From $Site -To $SiteLink @{minlen = 2; arrowtail = 'none'; arrowhead = 'none' } # End - Information for each SiteLink foreach ($SiteLinkSite in $Link.Sites) { diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSiteInventory.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSiteInventory.ps1 index 21ae9a7..2f9f905 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSiteInventory.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagSiteInventory.ps1 @@ -5,7 +5,7 @@ function Get-AbrDiagSiteInventory { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -32,7 +32,7 @@ function Get-AbrDiagSiteInventory { $SitesGroups = Get-AbrADSitesInventoryInfo if ($SitesGroups) { - SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { + SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor) ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { SubGraph MainSubGraph -Attributes @{Label = ' ' ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { if (($SitesGroups | Measure-Object).Count -ge 1) { $ChildSiteSubgraphArray = [System.Collections.Generic.List[object]]::new() @@ -40,23 +40,23 @@ function Get-AbrDiagSiteInventory { if ($SiteGroupOBJ.DomainControllers.DCsArray) { - $ChildDCsNodes = Add-HtmlTable -Name ChildDCsNodes -ImagesObj $Images -Rows $SiteGroupOBJ.DomainControllers.DCsArray -ALIGN 'Center' -ColumnSize 3 -IconDebug $IconDebug -TableStyle 'dashed,rounded' -NoFontBold -FontSize 18 + $ChildDCsNodes = Add-HtmlTable -Name ChildDCsNodes -ImagesObj $Images -Rows $SiteGroupOBJ.DomainControllers.DCsArray -ALIGN 'Center' -ColumnSize 3 -IconDebug $IconDebug -TableStyle 'dashed,rounded' -NoFontBold -FontSize 18 -TableBackgroundColor $MainGraphBGColor -FontColor $Fontcolor - $ChildDCsNodesSubgraph = Add-HtmlSubGraph -Name ChildDCsNodesSubgraph -ImagesObj $Images -TableArray $ChildDCsNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.DomainControllers -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_DC' -FontSize 18 + $ChildDCsNodesSubgraph = Add-HtmlSubGraph -Name ChildDCsNodesSubgraph -ImagesObj $Images -TableArray $ChildDCsNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.DomainControllers -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_DC' -FontSize 18 -TableBackgroundColor $MainGraphBGColor } else { - $ChildDCsNodesSubgraph = Add-HtmlSubGraph -Name ChildDCsNodesSubgraph -ImagesObj $Images -TableArray $reportTranslate.NewADDiagram.NoSiteDC -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.DomainControllers -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_DC' -FontSize 22 + $ChildDCsNodesSubgraph = Add-HtmlSubGraph -Name ChildDCsNodesSubgraph -ImagesObj $Images -TableArray $reportTranslate.NewADDiagram.NoSiteDC -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.DomainControllers -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_DC' -FontSize 22 -TableBackgroundColor $MainGraphBGColor } if ($SiteGroupOBJ.Subnets.SubnetArray) { - $ChildSubnetsNodes = Add-HtmlTable -Name ChildSubnetsNodes -ImagesObj $Images -Rows $SiteGroupOBJ.Subnets.SubnetArray -ALIGN 'Center' -ColumnSize 3 -IconDebug $IconDebug -TableStyle 'dashed,rounded' -NoFontBold -FontSize 18 + $ChildSubnetsNodes = Add-HtmlTable -Name ChildSubnetsNodes -ImagesObj $Images -Rows $SiteGroupOBJ.Subnets.SubnetArray -ALIGN 'Center' -ColumnSize 3 -IconDebug $IconDebug -TableStyle 'dashed,rounded' -NoFontBold -FontSize 18 -TableBackgroundColor $MainGraphBGColor -FontColor $Fontcolor - $ChildSubnetsNodesSubgraph = Add-HtmlSubGraph -Name ChildSubnetsNodesSubgraph -ImagesObj $Images -TableArray $ChildSubnetsNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.Subnets -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_Site_Subnet' -FontSize 22 + $ChildSubnetsNodesSubgraph = Add-HtmlSubGraph -Name ChildSubnetsNodesSubgraph -ImagesObj $Images -TableArray $ChildSubnetsNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.Subnets -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_Site_Subnet' -FontSize 22 -TableBackgroundColor $MainGraphBGColor } else { - $ChildSubnetsNodesSubgraph = Add-HtmlSubGraph -Name ChildSubnetsNodesSubgraph -ImagesObj $Images -TableArray $reportTranslate.NewADDiagram.NoSiteSubnet -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.Subnets -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_Site_Subnet' -FontSize 22 + $ChildSubnetsNodesSubgraph = Add-HtmlSubGraph -Name ChildSubnetsNodesSubgraph -ImagesObj $Images -TableArray $reportTranslate.NewADDiagram.NoSiteSubnet -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.Subnets -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -IconType 'AD_Site_Subnet' -FontSize 22 -TableBackgroundColor $MainGraphBGColor } $ChildSiteSubgraph = [System.Collections.Generic.List[object]]::new() @@ -65,11 +65,11 @@ function Get-AbrDiagSiteInventory { $ChildSiteSubgraph.Add($ChildSubnetsNodesSubgraph) $ChildSiteSubgraphArray.Add( - (Add-HtmlSubGraph -Name ChildSiteSubgraphArray -ImagesObj $Images -TableArray $ChildSiteSubgraph -Align 'Center' -IconType 'AD_Site' -IconDebug $IconDebug -Label $SiteGroupOBJ.Name -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -FontSize 22) + (Add-HtmlSubGraph -Name ChildSiteSubgraphArray -ImagesObj $Images -TableArray $ChildSiteSubgraph -Align 'Center' -IconType 'AD_Site' -IconDebug $IconDebug -Label $SiteGroupOBJ.Name -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -FontSize 22 -TableBackgroundColor $MainGraphBGColor) ) } - Node -Name 'SitesTopology' -Attributes @{Label = (Add-HtmlSubGraph -Name SitesTopology -ImagesObj $Images -TableArray $ChildSiteSubgraphArray -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.Sites -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -FontSize 22); shape = 'plain'; fillColor = 'transparent'; fontsize = 14; fontname = 'Segoe Ui' } + Node -Name 'SitesTopology' -Attributes @{Label = (Add-HtmlSubGraph -Name SitesTopology -ImagesObj $Images -TableArray $ChildSiteSubgraphArray -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.Sites -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -TableBorderColor 'gray' -FontColor $Fontcolor -FontSize 22 -TableBackgroundColor $MainGraphBGColor); shape = 'plain'; fillColor = 'transparent'; fontsize = 14; fontname = 'Segoe Ui' } } else { Node -Name NoSites -Attributes @{Label = $reportTranslate.NewADDiagram.NoSites; shape = 'rectangle'; labelloc = 'c'; fixedsize = $true; width = '3'; height = '2'; fillColor = 'transparent'; penwidth = 0 } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagTrust.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagTrust.ps1 index 6cbc704..d623288 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagTrust.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/Get-AbrDiagTrust.ps1 @@ -5,7 +5,7 @@ function Get-AbrDiagTrust { .DESCRIPTION Build a diagram of the configuration of Microsoft Active Directory to a supported formats using Psgraph. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author: Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -32,13 +32,13 @@ function Get-AbrDiagTrust { $TrustsInfo = Get-AbrADTrustsInfo if ($TrustsInfo) { - SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold); fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { + SubGraph ForestSubGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $ForestRoot -IconType 'ForestRoot' -IconDebug $IconDebug -SubgraphLabel -IconWidth 50 -IconHeight 50 -Fontsize 22 -FontName 'Segoe UI' -FontColor $Fontcolor -FontBold -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor); fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style ; color = $SubGraphDebug.color } { SubGraph MainSubGraph -Attributes @{Label = ' ' ; fontsize = 24; penwidth = 1.5; labelloc = 't'; style = $SubGraphDebug.style; color = $SubGraphDebug.color } { if (($TrustsInfo.Name | Measure-Object).count -gt 10) { $ChildDomainsNodes = $TrustsInfo.Label - Node -Name 'TrustDestinations' -Attributes @{Label = (Add-HtmlSubGraph -Name TrustDestinations -ImagesObj $Images -TableArray $ChildDomainsNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.TrustRelationships -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -FontSize 22 -FontName 'Segoe UI' -TableBorderColor $Edgecolor -FontColor $Fontcolor); shape = 'plain'; fillColor = 'transparent'; fontsize = 18; fontname = 'Segoe Ui' } + Node -Name 'TrustDestinations' -Attributes @{Label = (Add-HtmlSubGraph -Name TrustDestinations -ImagesObj $Images -TableArray $ChildDomainsNodes -Align 'Center' -IconDebug $IconDebug -Label $reportTranslate.NewADDiagram.TrustRelationships -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorder '1' -ColumnSize 3 -FontSize 22 -FontName 'Segoe UI' -TableBorderColor $Edgecolor -FontColor $Fontcolor -TableBackgroundColor $MainGraphBGColor); shape = 'plain'; fillColor = 'transparent'; fontsize = 18; fontname = 'Segoe Ui' } $ForestRootDomain = Remove-SpecialCharacter -String "$($TrustsInfo.Source[0])ForestRoot" -SpecialChars '\-. ' Node -Name $ForestRootDomain -Attributes @{Label = $TrustsInfo.SourceLabel[0]; shape = 'plain'; fillColor = 'transparent' } diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/New-AbrADDiagram.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/New-AbrADDiagram.ps1 index c8e9aa8..3896270 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/New-AbrADDiagram.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Diagram/New-AbrADDiagram.ps1 @@ -71,7 +71,7 @@ function New-AbrADDiagram { .PARAMETER WatermarkColor Allow to specified the color used for the watermark text. Default: #565656. .NOTES - Version: 0.9.12 + Version: 1.0.0 Author(s): Jonathan Colon Twitter: @jcolonfzenpr Github: rebelinux @@ -511,7 +511,7 @@ function New-AbrADDiagram { Write-Verbose $reportTranslate.NewADDiagram.genDiagramSignature # Main Graph SubGraph - SubGraph MainGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $MainGraphLabel -IconType $CustomLogo -IconDebug $IconDebug -IconWidth 250 -IconHeight 80 -Fontsize 24 -FontName 'Segoe UI Bold' -FontColor $Fontcolor ); fontsize = 22; penwidth = 0; labelloc = 't'; labeljust = 'c' } { + SubGraph MainGraph -Attributes @{Label = (Add-HtmlLabel -ImagesObj $Images -Label $MainGraphLabel -IconType $CustomLogo -IconDebug $IconDebug -IconWidth 250 -IconHeight 80 -Fontsize 24 -FontName 'Segoe UI Bold' -FontColor $Fontcolor -TableBackgroundColor $MainGraphBGColor -CellBackgroundColor $MainGraphBGColor); fontsize = 22; penwidth = 0; labelloc = 't'; labeljust = 'c' } { Write-Verbose $reportTranslate.NewADDiagram.genDiagramMain $script:ForestRoot = $ADSystem.Name.ToString().ToUpper() diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 new file mode 100644 index 0000000..b7ddb6a --- /dev/null +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 @@ -0,0 +1,1408 @@ +#Requires -RunAsAdministrator + +using namespace GliderUI +using namespace GliderUI.Avalonia +using namespace GliderUI.Avalonia.Controls +using namespace GliderUI.Avalonia.Platform.Storage +using namespace GliderUI.Avalonia.Media + +function Start-AsBuiltReportMSAD { + <# + .SYNOPSIS + GUI launcher for AsBuiltReport.Microsoft.AD — runs entirely in PowerShell 7. + .DESCRIPTION + A PowerShell 7.4+ desktop GUI (GliderUI / Avalonia) that collects connection, + output and report options, then generates the Microsoft AD As-Built Report by + calling New-AsBuiltReport directly — no child PS5.1 process required. + .NOTES + Requirements: + PowerShell 7.4+ — to run this script + GliderUI 0.2.0+ (auto-installed on first run) — Install-PSResource -Name GliderUI -Version 0.2.0 -Scope CurrentUser -TrustRepository + AsBuiltReport.Core — Install-PSResource -Name AsBuiltReport.Core + AsBuiltReport.Microsoft.AD — Install-PSResource -Name AsBuiltReport.Microsoft.AD + #> + + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope = 'Function')] + + [CmdletBinding()] + param() + + if ($PSVersionTable.PSVersion.Major -lt 7 -or ($PSVersionTable.PSVersion.Major -eq 7 -and $PSVersionTable.PSVersion.Minor -lt 4)) { + throw "Start-AsBuiltReportMSAD requires PowerShell 7.4+. Current version: $($PSVersionTable.PSVersion)" + } + + # ── Bootstrap GliderUI ────────────────────────────────────────────────────── + $requiredGliderUIVersion = [version]'0.2.0' + + if (-not (Get-Module -ListAvailable -Name GliderUI)) { + Write-Host 'GliderUI not found — installing from PSGallery…' -ForegroundColor Cyan + Install-PSResource -Name GliderUI -Version $requiredGliderUIVersion -Scope CurrentUser -TrustRepository + } + + $gliderMod = Get-Module -ListAvailable -Name GliderUI | + Sort-Object Version -Descending | + Select-Object -First 1 + + if ($null -eq $gliderMod -or $gliderMod.Version -lt $requiredGliderUIVersion) { + $found = if ($null -eq $gliderMod) { 'not installed' } else { "v$($gliderMod.Version)" } + Write-Error ("GliderUI v{0} or later is required (found: {1}).`nInstall with: Install-PSResource -Name GliderUI -Version {0} -Scope CurrentUser -TrustRepository`nThen restart PowerShell." -f $requiredGliderUIVersion, $found) + return + } + + Import-Module GliderUI -Force + + # Thread-safe store shared between the main runspace and the report runspace + $syncHash = [Hashtable]::Synchronized(@{ + CancelRequested = $false + IsBusy = $false + }) + + # ── UI Helper Functions ───────────────────────────────────────────────────── + function New-SectionTitle ([string]$Text) { + $tb = [TextBlock]::new() + $tb.Text = $Text + $tb.FontSize = 13 + $tb.FontWeight = 'SemiBold' + $tb.Margin = '0,18,0,6' + return $tb + } + + function New-FormRow ([string]$Label, $Control, [int]$LabelWidth = 185) { + $row = [StackPanel]::new() + $row.Orientation = 'Horizontal' + $row.Spacing = 10 + $row.Margin = '0,3,0,3' + + $lbl = [TextBlock]::new() + $lbl.Text = $Label + $lbl.Width = $LabelWidth + $lbl.VerticalAlignment = 'Center' + $lbl.FontSize = 12 + + $row.Children.Add($lbl) + $row.Children.Add($Control) + return $row + } + + function New-InlineLabel ([string]$Text) { + $tb = [TextBlock]::new() + $tb.Text = $Text + $tb.VerticalAlignment = 'Center' + $tb.Margin = '8,0,0,0' + $tb.FontSize = 12 + return $tb + } + + # Wraps a password TextBox with an eye-toggle button. + function New-PasswordRow ($PasswordTextBox) { + $btn = [Button]::new() + $btn.Content = '👁' + $btn.Padding = '6,2,6,2' + $btn.VerticalAlignment = 'Center' + $btn.AddClick({ + if ($PasswordTextBox.PasswordChar -eq [char]0) { + $PasswordTextBox.PasswordChar = [char]'●' + } else { + $PasswordTextBox.PasswordChar = [char]0 + } + }.GetNewClosure()) + + $row = [StackPanel]::new() + $row.Orientation = 'Horizontal' + $row.Spacing = 6 + $row.Children.Add($PasswordTextBox) + $row.Children.Add($btn) + return $row + } + + function New-DrawerMenuItem ([string]$Title, [string]$IconGeometry, $Page, $NavigationPage) { + $icon = [PathIcon]::new() + $icon.Data = [Geometry]::Parse($IconGeometry) + + $textBlock = [TextBlock]::new() + $textBlock.Text = $Title + $textBlock.VerticalAlignment = 'Center' + + $panel = [StackPanel]::new() + $panel.Orientation = 'Horizontal' + $panel.Spacing = 8 + $panel.Children.Add($icon) + $panel.Children.Add($textBlock) + + $button = [Button]::new() + $button.HorizontalAlignment = 'Stretch' + $button.Padding = 12 + $button.Background = [SolidColorBrush]::new([Colors]::Transparent, 1) + $button.Content = $panel + $button.AddClick({ + param($argumentList) + $targetPage, $navPage = $argumentList + $navPage.ReplaceAsync($targetPage) | Out-Null + }, @($Page, $NavigationPage)) + return $button + } + + # ── Connection Controls ───────────────────────────────────────────────────── + $txtServer = [TextBox]::new() + $txtServer.Width = 240 + $txtServer.Watermark = 'dc01.contoso.com' + + $txtUser = [TextBox]::new() + $txtUser.Width = 200 + $txtUser.Watermark = 'DOMAIN\username or user@domain' + + $txtPass = [TextBox]::new() + $txtPass.Width = 200 + $txtPass.Watermark = 'Password' + try { $txtPass.PasswordChar = [char]'●' } catch { Out-Null } + + # ── Saved Connections ─────────────────────────────────────────────────────── + $savedConnPath = if ($IsWindows) { + [System.IO.Path]::Combine($env:USERPROFILE, 'AsBuiltReport', 'MSAD-SavedConnections.json') + } else { + [System.IO.Path]::Combine($env:HOME, 'AsBuiltReport', 'MSAD-SavedConnections.json') + } + + $loadSavedConns = { + if (Test-Path $savedConnPath) { + try { + $raw = Get-Content -Path $savedConnPath -Raw -Encoding UTF8 | ConvertFrom-Json + if ($null -eq $raw) { return @() } + return @($raw) + } catch { return @() } + } + return @() + }.GetNewClosure() + + $saveSavedConns = { + param ([array]$Connections) + $dir = Split-Path $savedConnPath -Parent + if (-not (Test-Path $dir)) { New-Item -Path $dir -ItemType Directory -Force | Out-Null } + if ($Connections.Count -eq 0) { + '[]' | Set-Content -Path $savedConnPath -Encoding UTF8 + } else { + $Connections | ConvertTo-Json -Depth 3 | Set-Content -Path $savedConnPath -Encoding UTF8 + } + }.GetNewClosure() + + $cboSavedConn = [ComboBox]::new() + $cboSavedConn.Width = 262 + + $refreshSavedConnCombo = { + $cboSavedConn.Items.Clear() + foreach ($c in (& $loadSavedConns)) { + $cboSavedConn.Items.Add("$($c.Server) ($($c.Username))") | Out-Null + } + }.GetNewClosure() + & $refreshSavedConnCombo + + $cboSavedConn.AddSelectionChanged({ + $idx = $cboSavedConn.SelectedIndex + if ($idx -lt 0) { return } + $conns = & $loadSavedConns + if ($idx -ge $conns.Count) { return } + $sel = $conns[$idx] + $txtServer.Text = $sel.Server + $txtUser.Text = $sel.Username + $txtPass.Text = '' + }) + + $btnSaveConn = [Button]::new() + $btnSaveConn.Content = '💾 Save Connection' + $btnSaveConn.AddClick({ + $srv = $txtServer.Text.Trim() + $usr = $txtUser.Text.Trim() + if ([string]::IsNullOrWhiteSpace($srv) -or [string]::IsNullOrWhiteSpace($usr)) { + $syncHash.lblConfigStatus.Text = '⚠ Enter a Domain Controller FQDN and username before saving.' + return + } + $conns = [System.Collections.ArrayList]@() + foreach ($c in (& $loadSavedConns)) { $conns.Add($c) | Out-Null } + $dup = $conns | Where-Object { $_.Server -eq $srv -and $_.Username -eq $usr } + if (-not $dup) { + $conns.Add([PSCustomObject]@{ Server = $srv; Username = $usr }) | Out-Null + & $saveSavedConns -Connections @($conns) + & $refreshSavedConnCombo + $syncHash.lblConfigStatus.Text = "✅ Connection saved: $srv ($usr)" + } else { + $syncHash.lblConfigStatus.Text = "ℹ Connection already exists: $srv ($usr)" + } + }) + + $btnDeleteConn = [Button]::new() + $btnDeleteConn.Content = '🗑 Delete' + $btnDeleteConn.AddClick({ + $idx = $cboSavedConn.SelectedIndex + if ($idx -lt 0) { + $syncHash.lblConfigStatus.Text = '⚠ Select a saved connection to delete.' + return + } + $conns = [System.Collections.ArrayList]@() + foreach ($c in (& $loadSavedConns)) { $conns.Add($c) | Out-Null } + if ($idx -ge $conns.Count) { return } + $removed = $conns[$idx] + $conns.RemoveAt($idx) + & $saveSavedConns -Connections @($conns) + $cboSavedConn.SelectedIndex = -1 + & $refreshSavedConnCombo + $syncHash.lblConfigStatus.Text = "🗑 Deleted: $($removed.Server) ($($removed.Username))" + }) + + $savedConnActionsRow = [StackPanel]::new() + $savedConnActionsRow.Orientation = 'Horizontal' + $savedConnActionsRow.Spacing = 6 + $savedConnActionsRow.Children.Add($btnSaveConn) + $savedConnActionsRow.Children.Add($btnDeleteConn) + + # ── Output Controls ───────────────────────────────────────────────────────── + $chkHTML = [CheckBox]::new(); $chkHTML.Content = 'HTML'; $chkHTML.IsChecked = $true + $chkWord = [CheckBox]::new(); $chkWord.Content = 'Word'; $chkWord.IsChecked = $false + $chkText = [CheckBox]::new(); $chkText.Content = 'Text'; $chkText.IsChecked = $false + + $fmtPanel = [StackPanel]::new() + $fmtPanel.Orientation = 'Horizontal' + $fmtPanel.Spacing = 20 + $fmtPanel.Children.Add($chkHTML) + $fmtPanel.Children.Add($chkWord) + $fmtPanel.Children.Add($chkText) + + $txtOutput = [TextBox]::new() + $txtOutput.Width = 240 + $txtOutput.Text = if ($IsWindows) { + [System.IO.Path]::Combine($env:USERPROFILE, 'Documents', 'AsBuiltReport') + } else { + [System.IO.Path]::Combine($env:HOME, 'AsBuiltReport') + } + + $btnBrowse = [Button]::new() + $btnBrowse.Content = 'Browse…' + $btnBrowse.AddClick({ + try { + $btnBrowse.IsEnabled = $false + $storageProvider = [Window]::GetTopLevel($btnBrowse).StorageProvider + if ($null -eq $storageProvider) { + Write-Host 'Storage provider not available.' -ForegroundColor Yellow + return + } + $options = [FolderPickerOpenOptions]::new() + $options.Title = 'Select Output Folder Path' + $folders = $storageProvider.OpenFolderPickerAsync($options).WaitForCompleted() + if ($folders -and $folders.Count -gt 0) { + $txtOutput.Text = $folders[0].Path.LocalPath + } + } catch { + Write-Host "Folder picker error: $_" -ForegroundColor Red + } finally { + $btnBrowse.IsEnabled = $true + } + }) + + $outputPathRow = [StackPanel]::new() + $outputPathRow.Orientation = 'Horizontal' + $outputPathRow.Spacing = 8 + $outputPathRow.Children.Add($txtOutput) + $outputPathRow.Children.Add($btnBrowse) + + $cboLang = [ComboBox]::new() + $cboLang.Width = 100 + $cboLang.Items.Add('en-US') | Out-Null + $cboLang.Items.Add('es-ES') | Out-Null + $cboLang.SelectedIndex = 0 + + # ── Report Name ───────────────────────────────────────────────────────────── + $txtReportName = [TextBox]::new() + $txtReportName.Width = 300 + $txtReportName.Text = 'Microsoft Active Directory As Built Report' + $txtReportName.Watermark = 'Output filename (without extension)' + + # ── Options Controls ──────────────────────────────────────────────────────── + # Options matching AsBuiltReport.Microsoft.AD.json > Options + $swDiagrams = [ToggleSwitch]::new(); $swDiagrams.IsChecked = $true + $swExportDiagrams = [ToggleSwitch]::new(); $swExportDiagrams.IsChecked = $true + $swTimestamp= [ToggleSwitch]::new(); $swTimestamp.IsChecked = $false + $swWinRMSSL = [ToggleSwitch]::new(); $swWinRMSSL.IsChecked = $false + $swWinRMFallback = [ToggleSwitch]::new(); $swWinRMFallback.IsChecked = $true + + $cboDiagramTheme = [ComboBox]::new() + $cboDiagramTheme.Width = 120 + @('White', 'Black', 'Neon') | ForEach-Object { $cboDiagramTheme.Items.Add($_) | Out-Null } + $cboDiagramTheme.SelectedIndex = 0 + + $cboPSDefaultAuth = [ComboBox]::new() + $cboPSDefaultAuth.Width = 160 + @('Negotiate', 'Kerberos', 'NTLM', 'Default') | ForEach-Object { $cboPSDefaultAuth.Items.Add($_) | Out-Null } + $cboPSDefaultAuth.SelectedIndex = 0 + + # ── InfoLevel Controls — matching AsBuiltReport.Microsoft.AD.json > InfoLevel ─ + function New-LevelCombo { + $cbo = [ComboBox]::new() + $cbo.Width = 160 + @('0 - Off', '1 - Enabled', '2 - Adv Summary', '3 - Detailed') | ForEach-Object { $cbo.Items.Add($_) | Out-Null } + $cbo.SelectedIndex = 1 + return $cbo + } + + $cboLvlForest = New-LevelCombo; $cboLvlForest.SelectedIndex = 2 # default 2 per JSON + $cboLvlDomain = New-LevelCombo; $cboLvlDomain.SelectedIndex = 2 # default 2 per JSON + $cboLvlDNS = New-LevelCombo; $cboLvlDNS.SelectedIndex = 1 # default 1 per JSON + + # ── Progress Bar & Log ────────────────────────────────────────────────────── + $progressBar = [ProgressBar]::new() + $progressBar.IsIndeterminate = $true + $progressBar.IsVisible = $false + $progressBar.Margin = '0,8,0,4' + $syncHash.progressBar = $progressBar + + $txtLog = [TextBox]::new() + $txtLog.IsReadOnly = $true + $txtLog.AcceptsReturn = $true + $txtLog.Height = 220 + $txtLog.FontSize = 16 + $txtLog.TextWrapping = 'Wrap' + $txtLog.Watermark = 'Output log will appear here…' + try { $txtLog.FontFamily = 'Consolas,Courier New,Monospace' } catch { Out-Null } + $syncHash.txtLog = $txtLog + + $chkVerbose = [CheckBox]::new() + $chkVerbose.Content = '🔍Verbose' + $chkVerbose.IsChecked = $false + $chkVerbose.HorizontalAlignment = 'Right' + $chkVerbose.VerticalAlignment = 'Center' + $chkVerbose.Margin = '0,0,8,0' + $syncHash.chkVerbose = $chkVerbose + + # ── Action Buttons ────────────────────────────────────────────────────────── + $btnCancel = [Button]::new() + $btnCancel.Content = '✕ Cancel' + $btnCancel.IsVisible = $false + $btnCancel.Margin = '0,0,0,0' + $btnCancel.AddClick({ + $syncHash.CancelRequested = $true + $rps = $syncHash.reportPS + if ($null -ne $rps) { $rps.Stop() } + }) + $syncHash.btnCancel = $btnCancel + + $btnExportLog = [Button]::new() + $btnExportLog.Content = '💾 Export Log' + $btnExportLog.Margin = '0,0,0,0' + $btnExportLog.AddClick({ + try { + $btnExportLog.IsEnabled = $false + $logText = $syncHash.txtLog.Text + if ([string]::IsNullOrWhiteSpace($logText)) { + $syncHash.lblConfigStatus.Text = '⚠ Log is empty — nothing to export.' + return + } + $storageProvider = [Window]::GetTopLevel($btnExportLog).StorageProvider + if ($null -eq $storageProvider) { return } + $saveOpts = [FilePickerSaveOptions]::new() + $saveOpts.Title = 'Export Output Log' + $saveOpts.SuggestedFileName = "MSAD-AsBuiltReport-$(Get-Date -Format 'yyyyMMdd-HHmmss').log" + $file = $storageProvider.SaveFilePickerAsync($saveOpts).WaitForCompleted() + if ($null -ne $file) { + $logText | Set-Content -Path $file.Path.LocalPath -Encoding UTF8 + $syncHash.lblConfigStatus.Text = "✅ Log exported: $(Split-Path $file.Path.LocalPath -Leaf)" + } + } catch { + $syncHash.lblConfigStatus.Text = "❌ Log export failed: $_" + } finally { + $btnExportLog.IsEnabled = $true + } + }) + + $btnGenerate = [Button]::new() + $btnGenerate.Content = '▶ Generate Report' + $btnGenerate.HorizontalAlignment = 'Stretch' + $btnGenerate.HorizontalContentAlignment = 'Center' + $btnGenerate.FontSize = 14 + $btnGenerate.FontWeight = 'SemiBold' + $btnGenerate.Margin = '0,22,0,0' + $btnGenerate.Classes.Add('accent') + $syncHash.btnGenerate = $btnGenerate + + # ── Generate Callback ──────────────────────────────────────────────────────── + $generateCallback = [EventCallback]::new() + $generateCallback.RunspaceMode = 'RunspacePoolAsyncUI' + $generateCallback.DisabledControlsWhileProcessing = $btnGenerate + + $generateCallback.ArgumentList = @{ + SyncHash = $syncHash + Server = $txtServer + Username = $txtUser + Password = $txtPass + ReportName = $txtReportName + OutPath = $txtOutput + FmtHTML = $chkHTML + FmtWord = $chkWord + FmtText = $chkText + Lang = $cboLang + DiagramTheme = $cboDiagramTheme + PSDefaultAuth = $cboPSDefaultAuth + Diagrams = $swDiagrams + ExportDiagrams = $swExportDiagrams + Timestamp = $swTimestamp + WinRMSSL = $swWinRMSSL + WinRMFallback = $swWinRMFallback + LvlForest = $cboLvlForest + LvlDomain = $cboLvlDomain + LvlDNS = $cboLvlDNS + Verbose = $chkVerbose + # ConfigPath and AbrConfigPath are late-bound below after TextBox creation + } + + $generateCallback.ScriptBlock = { + param ($ui) + + $sh = $ui.SyncHash + if ($sh.IsBusy) { + $sh.lblConfigStatus.Text = '⚠ Another operation is already running. Please wait.' + return + } + $sh.IsBusy = $true + $sh.CancelRequested = $false + $sh.progressBar.IsVisible = $true + $sh.btnCancel.IsVisible = $true + $sh.txtLog.Text = '' + + $verboseEnabled = $ui.Verbose.IsChecked -eq $true + + function Write-Logging ([string]$Msg, [string]$Level = '', [bool]$AddTimestamp = $false) { + $ts = Get-Date -Format 'HH:mm:ss' + if ($Level -eq '') { + if ($AddTimestamp) { + $sh.txtLog.Text += "[$ts] $Msg`n" + } else { + $sh.txtLog.Text += "$Msg`n" + } + } else { + if ($AddTimestamp) { + $sh.txtLog.Text += "[$ts][$Level] $Msg`n" + } else { + $sh.txtLog.Text += "[$Level] $Msg`n" + } + } + $sh.txtLog.CaretIndex = $sh.txtLog.Text.Length + } + + function Build-MSADConfigObject { + param ( + [string]$ReportName, + [string]$Lang, + [string]$Theme, + [bool]$EnableDiagrams, + [bool]$ExportDiagrams, + [string]$PSDefaultAuthentication, + [bool]$WinRMSSL, + [bool]$WinRMFallbackToNoSSL, + [int]$LvlForest, + [int]$LvlDomain, + [int]$LvlDNS + ) + return [ordered]@{ + Report = [ordered]@{ + Name = $ReportName + Version = '1.0' + Status = 'Released' + Language = $Lang + ShowCoverPageImage = $true + ShowTableOfContents = $true + ShowHeaderFooter = $true + ShowTableCaptions = $true + } + Options = [ordered]@{ + ShowExecutionTime = $false + ShowDefinitionInfo = $false + PSDefaultAuthentication = $PSDefaultAuthentication + Exclude = [ordered]@{ Domains = @(); DCs = @() } + Include = [ordered]@{ Domains = @() } + WinRMSSL = $WinRMSSL + WinRMFallbackToNoSSL = $WinRMFallbackToNoSSL + WinRMSSLPort = 5986 + WinRMPort = 5985 + EnableDiagrams = $EnableDiagrams + EnableDiagramDebug = $false + DiagramTheme = $Theme + DiagramObjDebug = $false + DiagramWaterMark = '' + DiagramType = [ordered]@{ + CertificateAuthority = $true + Forest = $true + Replication = $true + Sites = $true + SitesInventory = $true + Trusts = $true + } + ExportDiagrams = $ExportDiagrams + ExportDiagramsFormat = @('pdf') + EnableDiagramSignature = $false + SignatureAuthorName = '' + SignatureCompanyName = '' + JobsTimeOut = 900 + DCStatusPingCount = 2 + } + InfoLevel = [ordered]@{ + Forest = $LvlForest + Domain = $LvlDomain + DNS = $LvlDNS + } + HealthCheck = [ordered]@{ + Domain = [ordered]@{ + GMSA = $true + GPO = $true + Backup = $true + DFS = $true + SPN = $true + DuplicateObject = $true + Security = $true + BestPractice = $true + } + DomainController = [ordered]@{ + Diagnostic = $true + Services = $true + Software = $true + BestPractice = $true + } + Site = [ordered]@{ + Replication = $true + BestPractice = $true + } + DNS = [ordered]@{ + Aging = $true + DP = $true + Zones = $true + BestPractice = $true + } + CA = [ordered]@{ + Status = $true + Statistics = $true + BestPractice = $true + } + } + } + } + + # ── Collect values ──────────────────────────────────────────────────────── + $server = $ui.Server.Text.Trim() + $username = $ui.Username.Text.Trim() + $password = $ui.Password.Text + $reportName = $ui.ReportName.Text.Trim() + $outPath = $ui.OutPath.Text.Trim() + $lang = [string]$ui.Lang.SelectedItem + $configPath = $ui.ConfigPath.Text.Trim() + $abrConfigPath = $ui.AbrConfigPath.Text.Trim() + + $formats = @() + if ($ui.FmtHTML.IsChecked -eq $true) { $formats += 'Html' } + if ($ui.FmtWord.IsChecked -eq $true) { $formats += 'Word' } + if ($ui.FmtText.IsChecked -eq $true) { $formats += 'Text' } + if ($formats.Count -eq 0) { $formats = @('Html') } + + $enableDiagrams = [bool]$ui.Diagrams.IsChecked + $exportDiagrams = [bool]$ui.ExportDiagrams.IsChecked + $addTimestamp = [bool]$ui.Timestamp.IsChecked + $winRMSSL = [bool]$ui.WinRMSSL.IsChecked + $winRMFallback = [bool]$ui.WinRMFallback.IsChecked + $psDefaultAuth = [string]$ui.PSDefaultAuth.SelectedItem + $diagramTheme = [string]$ui.DiagramTheme.SelectedItem + + # Parse InfoLevel (first char = number) + $lvlForest = [int]([string]$ui.LvlForest.SelectedItem).Substring(0, 1) + $lvlDomain = [int]([string]$ui.LvlDomain.SelectedItem).Substring(0, 1) + $lvlDNS = [int]([string]$ui.LvlDNS.SelectedItem).Substring(0, 1) + + # ── Validation ──────────────────────────────────────────────────────────── + if ([string]::IsNullOrWhiteSpace($server)) { + Write-Logging 'Domain Controller FQDN is required.' 'ERROR' + $sh.progressBar.IsVisible = $false; $sh.btnCancel.IsVisible = $false; $sh.IsBusy = $false; return + } + if ([string]::IsNullOrWhiteSpace($username)) { + Write-Logging 'Username is required.' 'ERROR' + $sh.progressBar.IsVisible = $false; $sh.btnCancel.IsVisible = $false; $sh.IsBusy = $false; return + } + if ([string]::IsNullOrWhiteSpace($password)) { + Write-Logging 'Password is required.' 'ERROR' + $sh.progressBar.IsVisible = $false; $sh.btnCancel.IsVisible = $false; $sh.IsBusy = $false; return + } + if ([string]::IsNullOrWhiteSpace($outPath)) { + $outPath = if ($IsWindows) { + [System.IO.Path]::Combine($env:USERPROFILE, 'Documents', 'AsBuiltReport') + } else { + [System.IO.Path]::Combine($env:HOME, 'AsBuiltReport') + } + } + if (-not (Test-Path $outPath)) { + New-Item -Path $outPath -ItemType Directory -Force | Out-Null + Write-Logging "Created output folder: $outPath" + } + if ([string]::IsNullOrWhiteSpace($reportName)) { $reportName = 'Microsoft Active Directory As Built Report' } + if ([string]::IsNullOrWhiteSpace($abrConfigPath)) { + Write-Logging 'AsBuiltReport config file path is required. Use the "⚙️ AsBuiltReport Global Settings" expander to create one.' 'ERROR' + $sh.progressBar.IsVisible = $false; $sh.btnCancel.IsVisible = $false; $sh.IsBusy = $false; return + } + if (-not (Test-Path $abrConfigPath)) { + Write-Logging "AsBuiltReport config file not found: $abrConfigPath" 'ERROR' + $sh.progressBar.IsVisible = $false; $sh.btnCancel.IsVisible = $false; $sh.IsBusy = $false; return + } + + Write-Logging "Target : $server" + Write-Logging "User : $username" + Write-Logging "Formats : $($formats -join ', ')" + Write-Logging "Output : $outPath" + + # ── Import modules in this runspace ─────────────────────────────────────── + Write-Logging 'Loading AsBuiltReport modules…' + try { + Import-Module AsBuiltReport.Core, AsBuiltReport.Microsoft.AD -Force -ErrorAction Stop + } catch { + Write-Logging "Failed to load modules: $_" 'ERROR' + $sh.progressBar.IsVisible = $false; $sh.btnCancel.IsVisible = $false; $sh.IsBusy = $false; return + } + + # ── Resolve ReportConfigFilePath ────────────────────────────────────────── + # Use the saved config file from Config Management if provided; + # otherwise build a temp config from the current UI control values. + $tempConfig = $null + if (-not [string]::IsNullOrWhiteSpace($configPath) -and (Test-Path $configPath)) { + $reportConfigFilePath = $configPath + Write-Logging "Using config file: $(Split-Path $configPath -Leaf)" + } else { + $configObj = Build-MSADConfigObject ` + -ReportName $reportName ` + -Lang $lang ` + -Theme $diagramTheme ` + -EnableDiagrams $enableDiagrams ` + -ExportDiagrams $exportDiagrams ` + -PSDefaultAuthentication $psDefaultAuth ` + -WinRMSSL $winRMSSL ` + -WinRMFallbackToNoSSL $winRMFallback ` + -LvlForest $lvlForest ` + -LvlDomain $lvlDomain ` + -LvlDNS $lvlDNS + + $tempConfig = [System.IO.Path]::Combine($env:TEMP, "MSAD_cfg_$(New-Guid).json") + $configObj | ConvertTo-Json -Depth 6 | Set-Content -Path $tempConfig -Encoding UTF8 + $reportConfigFilePath = $tempConfig + Write-Logging 'Using config built from UI controls.' + } + + # ── Invoke New-AsBuiltReport ────────────────────────────────────────────── + try { + if ($sh.CancelRequested) { Write-Logging 'Cancelled before start.' 'WARN'; return } + + Write-Logging 'Starting report generation…' + + $securePassword = ConvertTo-SecureString $password -AsPlainText -Force + $credential = [PSCredential]::new($username, $securePassword) + + $params = @{ + Report = 'Microsoft.AD' + Target = $server + Credential = $credential + OutputFolderPath = $outPath + Format = $formats + ReportConfigFilePath = $reportConfigFilePath + AsBuiltConfigFilePath = $abrConfigPath + } + + if ($addTimestamp) { $params['Timestamp'] = $true } + if ($verboseEnabled) { $params['Verbose'] = $true } + + Write-Logging "Using AsBuiltReport config: $(Split-Path $abrConfigPath -Leaf)" + + New-AsBuiltReport @params *>&1 | ForEach-Object { + $line = if ($_ -is [System.Management.Automation.ErrorRecord]) { + Write-Logging "$($_.Exception.Message)" 'ERROR' + return + } elseif ($_ -is [System.Management.Automation.WarningRecord]) { + Write-Logging "$($_.Message)" 'WARN' + return + } elseif ($_ -is [System.Management.Automation.VerboseRecord]) { + if ($verboseEnabled) { + Write-Logging "$($_.Message)" 'VERBOSE' + } + return + } elseif ($_ -is [System.Management.Automation.InformationRecord]) { + "$($_.MessageData)" + } else { + "$_" + } + if (-not [string]::IsNullOrWhiteSpace($line)) { + Write-Logging $line + } + } + Write-Logging -Msg "✅ Report generation completed. Files saved to: $outPath" -Level '' -AddTimestamp $true + } catch { + Write-Logging $_.Exception.Message 'ERROR' + if ($_.ScriptStackTrace) { Write-Logging $_.ScriptStackTrace 'ERROR' } + } finally { + if ($null -ne $tempConfig) { + Remove-Item -Path $tempConfig -Force -ErrorAction SilentlyContinue + } + $sh.progressBar.IsVisible = $false + $sh.btnCancel.IsVisible = $false + $sh.IsBusy = $false + } + } + + $btnGenerate.AddClick($generateCallback) + + # ── Config Management Controls ─────────────────────────────────────────────── + $txtConfigPath = [TextBox]::new() + $txtConfigPath.Width = 298 + $txtConfigPath.Watermark = 'Path to AsBuiltReport.Microsoft.AD.json (optional)' + $txtConfigPath.Text = if ($IsWindows) { + [System.IO.Path]::Combine($env:USERPROFILE, 'AsBuiltReport', 'AsBuiltReport.Microsoft.AD.json') + } else { + [System.IO.Path]::Combine($env:HOME, 'AsBuiltReport', 'AsBuiltReport.Microsoft.AD.json') + } + + $btnBrowseConfig = [Button]::new() + $btnBrowseConfig.Content = 'Browse…' + $btnBrowseConfig.AddClick({ + try { + $btnBrowseConfig.IsEnabled = $false + $storageProvider = [Window]::GetTopLevel($btnBrowseConfig).StorageProvider + if ($null -eq $storageProvider) { + Write-Host 'Storage provider not available.' -ForegroundColor Yellow + return + } + $options = [FilePickerOpenOptions]::new() + $options.Title = 'Select AsBuiltReport.Microsoft.AD JSON Config File' + $JsonConfigFile = $storageProvider.OpenFilePickerAsync($options).WaitForCompleted() + if ($JsonConfigFile -and $JsonConfigFile.Count -gt 0) { + $txtConfigPath.Text = $JsonConfigFile[0].Path.LocalPath + } + } catch { + Write-Host "File picker error: $_" -ForegroundColor Red + } finally { + $btnBrowseConfig.IsEnabled = $true + } + }) + + $configPathRow = [StackPanel]::new() + $configPathRow.Orientation = 'Horizontal' + $configPathRow.Spacing = 8 + $configPathRow.Children.Add($txtConfigPath) + $configPathRow.Children.Add($btnBrowseConfig) + + $lblConfigStatus = [TextBlock]::new() + $lblConfigStatus.FontSize = 11 + $lblConfigStatus.Margin = '0,4,0,0' + $lblConfigStatus.Text = '' + $syncHash.lblConfigStatus = $lblConfigStatus + + # ── AsBuiltReport Global Config (AsBuiltReport.json) ───────────────────────── + $txtAbrConfigPath = [TextBox]::new() + $txtAbrConfigPath.Width = 298 + $txtAbrConfigPath.Watermark = 'Required: path to AsBuiltReport.json' + + $btnBrowseAbrConfig = [Button]::new() + $btnBrowseAbrConfig.Content = 'Browse…' + $btnBrowseAbrConfig.AddClick({ + try { + $btnBrowseAbrConfig.IsEnabled = $false + $storageProvider = [Window]::GetTopLevel($btnBrowseAbrConfig).StorageProvider + if ($null -eq $storageProvider) { return } + $options = [FilePickerOpenOptions]::new() + $options.Title = 'Select AsBuiltReport.json' + $options.AllowMultiple = $false + $picked = $storageProvider.OpenFilePickerAsync($options).WaitForCompleted() + if ($picked -and $picked.Count -gt 0) { + $txtAbrConfigPath.Text = $picked[0].Path.LocalPath + $syncHash.lblConfigStatus.Text = "📄 AsBuiltReport config: $(Split-Path $txtAbrConfigPath.Text -Leaf)" + } + } catch { + $syncHash.lblConfigStatus.Text = "❌ Browse error: $_" + } finally { + $btnBrowseAbrConfig.IsEnabled = $true + } + }) + + $abrConfigPathRow = [StackPanel]::new() + $abrConfigPathRow.Orientation = 'Horizontal' + $abrConfigPathRow.Spacing = 8 + $abrConfigPathRow.Children.Add($txtAbrConfigPath) + $abrConfigPathRow.Children.Add($btnBrowseAbrConfig) + + # Late-bind after TextBox objects exist + $generateCallback.ArgumentList['ConfigPath'] = $txtConfigPath + $generateCallback.ArgumentList['AbrConfigPath'] = $txtAbrConfigPath + + # ── AsBuiltReport Global Settings (AsBuiltReport.json editor) ──────────────── + $txtAbrCoFullName = [TextBox]::new(); $txtAbrCoFullName.Width = 298; $txtAbrCoFullName.Watermark = 'e.g. Acme Corporation' + $txtAbrCoShortName = [TextBox]::new(); $txtAbrCoShortName.Width = 298; $txtAbrCoShortName.Watermark = 'e.g. ACME' + $txtAbrCoContact = [TextBox]::new(); $txtAbrCoContact.Width = 298; $txtAbrCoContact.Watermark = 'Contact person' + $txtAbrCoPhone = [TextBox]::new(); $txtAbrCoPhone.Width = 298; $txtAbrCoPhone.Watermark = 'e.g. +1-800-555-0100' + $txtAbrCoAddress = [TextBox]::new(); $txtAbrCoAddress.Width = 298; $txtAbrCoAddress.Watermark = 'Street, City, Country' + $txtAbrCoEmail = [TextBox]::new(); $txtAbrCoEmail.Width = 298; $txtAbrCoEmail.Watermark = 'company@example.com' + $txtAbrRptAuthor = [TextBox]::new(); $txtAbrRptAuthor.Width = 298; $txtAbrRptAuthor.Watermark = 'Report author' + $txtAbrMailServer = [TextBox]::new(); $txtAbrMailServer.Width = 298; $txtAbrMailServer.Watermark = 'smtp.example.com' + $txtAbrMailPort = [TextBox]::new(); $txtAbrMailPort.Width = 298; $txtAbrMailPort.Watermark = '587' + $txtAbrMailFrom = [TextBox]::new(); $txtAbrMailFrom.Width = 298; $txtAbrMailFrom.Watermark = 'from@example.com' + $txtAbrMailTo = [TextBox]::new(); $txtAbrMailTo.Width = 298; $txtAbrMailTo.Watermark = 'to@example.com, other@example.com' + $txtAbrMailBody = [TextBox]::new(); $txtAbrMailBody.Width = 298; $txtAbrMailBody.Watermark = 'Email body text' + $swAbrMailUseSSL = [ToggleSwitch]::new(); $swAbrMailUseSSL.IsChecked = $true + $swAbrMailCreds = [ToggleSwitch]::new(); $swAbrMailCreds.IsChecked = $true + $txtAbrFolderPath = [TextBox]::new(); $txtAbrFolderPath.Width = 298; $txtAbrFolderPath.Watermark = '.\AsBuiltReport' + + $loadAbrFields = { + param ([hashtable]$j) + $txtAbrCoFullName.Text = if ($j.Company.FullName) { $j.Company.FullName } else { '' } + $txtAbrCoShortName.Text = if ($j.Company.ShortName) { $j.Company.ShortName } else { '' } + $txtAbrCoContact.Text = if ($j.Company.Contact) { $j.Company.Contact } else { '' } + $txtAbrCoPhone.Text = if ($j.Company.Phone) { $j.Company.Phone } else { '' } + $txtAbrCoAddress.Text = if ($j.Company.Address) { $j.Company.Address } else { '' } + $txtAbrCoEmail.Text = if ($j.Company.Email) { $j.Company.Email } else { '' } + $txtAbrRptAuthor.Text = if ($j.Report.Author) { $j.Report.Author } else { '' } + $txtAbrMailServer.Text = if ($j.Email.Server) { $j.Email.Server } else { '' } + $txtAbrMailPort.Text = if ($j.Email.Port) { $j.Email.Port } else { '' } + $txtAbrMailFrom.Text = if ($j.Email.From) { $j.Email.From } else { '' } + $txtAbrMailTo.Text = if ($j.Email.To) { ($j.Email.To -join ', ') } else { '' } + $txtAbrMailBody.Text = if ($j.Email.Body) { $j.Email.Body } else { '' } + $swAbrMailUseSSL.IsChecked = if ($null -ne $j.Email.UseSSL) { [bool]$j.Email.UseSSL } else { $true } + $swAbrMailCreds.IsChecked = if ($null -ne $j.Email.Credentials) { [bool]$j.Email.Credentials } else { $true } + $txtAbrFolderPath.Text = if ($j.UserFolder.Path) { $j.UserFolder.Path } else { + if ($IsWindows) { [System.IO.Path]::Combine($env:USERPROFILE, 'Documents', 'AsBuiltReport') } else { [System.IO.Path]::Combine($env:HOME, 'AsBuiltReport') } + } + } + + $buildAbrConfig = { + $toList = ([string]$txtAbrMailTo.Text).Trim() -split '\s*,\s*' | Where-Object { $_ -ne '' } + $portRaw = ([string]$txtAbrMailPort.Text).Trim() + $portVal = if ($portRaw -match '^\d+$') { [int]$portRaw } else { $null } + return [ordered]@{ + Company = [ordered]@{ + FullName = ([string]$txtAbrCoFullName.Text).Trim() + Phone = ([string]$txtAbrCoPhone.Text).Trim() + Address = ([string]$txtAbrCoAddress.Text).Trim() + ShortName = ([string]$txtAbrCoShortName.Text).Trim() + Contact = ([string]$txtAbrCoContact.Text).Trim() + Email = ([string]$txtAbrCoEmail.Text).Trim() + } + Email = [ordered]@{ + Credentials = [bool]$swAbrMailCreds.IsChecked + Body = ([string]$txtAbrMailBody.Text).Trim() + From = ([string]$txtAbrMailFrom.Text).Trim() + UseSSL = [bool]$swAbrMailUseSSL.IsChecked + Server = ([string]$txtAbrMailServer.Text).Trim() + To = if ($toList.Count -gt 0) { @($toList) } else { @() } + Port = $portVal + } + Report = [ordered]@{ Author = ([string]$txtAbrRptAuthor.Text).Trim() } + UserFolder = [ordered]@{ Path = ([string]$txtAbrFolderPath.Text).Trim() } + } + }.GetNewClosure() + $syncHash.buildAbrConfig = $buildAbrConfig + + $validateAbrRequired = { + $missing = @() + if ([string]::IsNullOrWhiteSpace($txtAbrCoFullName.Text)) { $missing += 'Full Name' } + if ([string]::IsNullOrWhiteSpace($txtAbrCoShortName.Text)) { $missing += 'Short Name' } + if ([string]::IsNullOrWhiteSpace($txtAbrCoContact.Text)) { $missing += 'Contact' } + if ([string]::IsNullOrWhiteSpace($txtAbrCoEmail.Text)) { $missing += 'Email' } + if ([string]::IsNullOrWhiteSpace($txtAbrRptAuthor.Text)) { $missing += 'Author' } + if ([string]::IsNullOrWhiteSpace($txtAbrFolderPath.Text)) { $missing += 'Path' } + if ($missing.Count -gt 0) { + return "⚠ Required fields missing: $($missing -join ', ')" + } + return $null + }.GetNewClosure() + $syncHash.validateAbrRequired = $validateAbrRequired + + $btnAbrNew = [Button]::new() + $btnAbrNew.Content = '🆕 Create New' + $btnAbrNew.Margin = '0,0,8,0' + $btnAbrNew.AddClick({ + try { + $btnAbrNew.IsEnabled = $false + $storageProvider = [Window]::GetTopLevel($btnAbrNew).StorageProvider + if ($null -eq $storageProvider) { + $syncHash.lblConfigStatus.Text = '⚠ Cannot open save dialog.' + return + } + $saveOpts = [FilePickerSaveOptions]::new() + $saveOpts.Title = 'Create New AsBuiltReport Config File' + $saveOpts.SuggestedFileName = 'AsBuiltReport.json' + $saveOpts.DefaultExtension = 'json' + $file = $storageProvider.SaveFilePickerAsync($saveOpts).WaitForCompleted() + if ($null -eq $file) { return } + if ($null -eq $file.Path) { + $syncHash.lblConfigStatus.Text = '⚠ Could not resolve file path from dialog.' + return + } + $validationError = & $syncHash.validateAbrRequired + if ($null -ne $validationError) { + $syncHash.lblConfigStatus.Text = $validationError + return + } + $dest = $file.Path.LocalPath + $cfg = & $syncHash.buildAbrConfig + $destDir = Split-Path $dest -Parent + if (-not (Test-Path $destDir)) { New-Item -Path $destDir -ItemType Directory -Force | Out-Null } + $cfg | ConvertTo-Json -Depth 4 | Set-Content -Path $dest -Encoding UTF8 + $txtAbrConfigPath.Text = $dest + $syncHash.lblConfigStatus.Text = "✅ Created: $(Split-Path $dest -Leaf)" + } catch { + $syncHash.lblConfigStatus.Text = "❌ Create failed: $_" + } finally { + $btnAbrNew.IsEnabled = $true + } + }) + + $btnAbrLoad = [Button]::new() + $btnAbrLoad.Content = '📂 Load from File' + $btnAbrLoad.Margin = '0,0,8,0' + $btnAbrLoad.AddClick({ + try { + $btnAbrLoad.IsEnabled = $false + $src = if ($txtAbrConfigPath.Text) { $txtAbrConfigPath.Text.Trim() } else { '' } + if ([string]::IsNullOrWhiteSpace($src) -or -not (Test-Path $src)) { + $syncHash.lblConfigStatus.Text = '⚠ Set a valid AsBuiltReport.json path first.' + return + } + $j = Get-Content -Path $src -Raw | ConvertFrom-Json -AsHashtable + & $loadAbrFields $j + $syncHash.lblConfigStatus.Text = "✅ Loaded: $(Split-Path $src -Leaf)" + } catch { + $syncHash.lblConfigStatus.Text = "❌ Load failed: $_" + } finally { + $btnAbrLoad.IsEnabled = $true + } + }) + + $btnAbrSave = [Button]::new() + $btnAbrSave.Content = '💾 Save to File' + $btnAbrSave.AddClick({ + try { + $btnAbrSave.IsEnabled = $false + $validationError = & $syncHash.validateAbrRequired + if ($null -ne $validationError) { + $syncHash.lblConfigStatus.Text = $validationError + return + } + if ([string]::IsNullOrWhiteSpace($txtAbrConfigPath.Text)) { + $syncHash.lblConfigStatus.Text = '❌ Please provide a config file path before saving.' + return + } + $dest = $txtAbrConfigPath.Text.Trim() + $cfg = & $syncHash.buildAbrConfig + $destDir = Split-Path $dest -Parent + if (-not (Test-Path $destDir)) { New-Item -Path $destDir -ItemType Directory -Force | Out-Null } + $cfg | ConvertTo-Json -Depth 4 | Set-Content -Path $dest -Encoding UTF8 + $syncHash.lblConfigStatus.Text = "✅ Saved: $(Split-Path $dest -Leaf)" + } catch { + $syncHash.lblConfigStatus.Text = "❌ Save failed: $_" + } finally { + $btnAbrSave.IsEnabled = $true + } + }) + + $abrActionRow = [StackPanel]::new() + $abrActionRow.Orientation = 'Horizontal' + $abrActionRow.Margin = '0,10,0,0' + $abrActionRow.Children.Add($btnAbrNew) + $abrActionRow.Children.Add($btnAbrLoad) + $abrActionRow.Children.Add($btnAbrSave) + + $abrRequiredNote = [TextBlock]::new() + $abrRequiredNote.Text = '* Required' + $abrRequiredNote.FontSize = 12 + $abrRequiredNote.Margin = '0,0,0,8' + $abrRequiredNote.TextAlignment = 'Right' + + $abrInnerPanel = [StackPanel]::new() + $abrInnerPanel.Spacing = 2 + $abrInnerPanel.Margin = '4,4,4,8' + $abrInnerPanel.Children.Add($abrRequiredNote) + $abrInnerPanel.Children.Add((New-SectionTitle '🏢 Company')) + $abrInnerPanel.Children.Add((New-FormRow -Label '* Full Name' -Control $txtAbrCoFullName)) + $abrInnerPanel.Children.Add((New-FormRow -Label '* Short Name' -Control $txtAbrCoShortName)) + $abrInnerPanel.Children.Add((New-FormRow -Label '* Contact' -Control $txtAbrCoContact)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'Phone' -Control $txtAbrCoPhone)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'Address' -Control $txtAbrCoAddress)) + $abrInnerPanel.Children.Add((New-FormRow -Label '* Email' -Control $txtAbrCoEmail)) + $abrInnerPanel.Children.Add((New-SectionTitle '📝 Report')) + $abrInnerPanel.Children.Add((New-FormRow -Label '* Author' -Control $txtAbrRptAuthor)) + $abrInnerPanel.Children.Add((New-SectionTitle '📧 Email')) + $abrInnerPanel.Children.Add((New-FormRow -Label 'SMTP Server' -Control $txtAbrMailServer)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'Port' -Control $txtAbrMailPort)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'From' -Control $txtAbrMailFrom)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'To (comma-sep.)' -Control $txtAbrMailTo)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'Body' -Control $txtAbrMailBody)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'Use SSL' -Control $swAbrMailUseSSL)) + $abrInnerPanel.Children.Add((New-FormRow -Label 'Credentials' -Control $swAbrMailCreds)) + $abrInnerPanel.Children.Add((New-SectionTitle '📁 User Folder')) + $abrInnerPanel.Children.Add((New-FormRow -Label '* Path' -Control $txtAbrFolderPath)) + $abrInnerPanel.Children.Add($abrActionRow) + + $abrExpander = [Expander]::new() + $abrExpander.Header = '⚙️ AsBuiltReport Global Settings' + $abrExpander.IsExpanded = $false + $abrExpander.Margin = '0,8,0,0' + $abrExpander.Content = $abrInnerPanel + + # ── Save Config Button ───────────────────────────────────────────────────── + function Build-MSADConfigForSave { + param ( + [string]$ReportName, [string]$Lang, [string]$Theme, + [bool]$EnableDiagrams, [bool]$ExportDiagrams, + [string]$PSDefaultAuthentication, [bool]$WinRMSSL, [bool]$WinRMFallbackToNoSSL, + [int]$LvlForest, [int]$LvlDomain, [int]$LvlDNS + ) + return [ordered]@{ + Report = [ordered]@{ + Name = $ReportName + Version = '1.0' + Status = 'Released' + Language = $Lang + ShowCoverPageImage = $true + ShowTableOfContents = $true + ShowHeaderFooter = $true + ShowTableCaptions = $true + } + Options = [ordered]@{ + ShowExecutionTime = $false + ShowDefinitionInfo = $false + PSDefaultAuthentication = $PSDefaultAuthentication + Exclude = [ordered]@{ Domains = @(); DCs = @() } + Include = [ordered]@{ Domains = @() } + WinRMSSL = $WinRMSSL + WinRMFallbackToNoSSL = $WinRMFallbackToNoSSL + WinRMSSLPort = 5986 + WinRMPort = 5985 + EnableDiagrams = $EnableDiagrams + EnableDiagramDebug = $false + DiagramTheme = $Theme + DiagramObjDebug = $false + DiagramWaterMark = '' + DiagramType = [ordered]@{ + CertificateAuthority = $true + Forest = $true + Replication = $true + Sites = $true + SitesInventory = $true + Trusts = $true + } + ExportDiagrams = $ExportDiagrams + ExportDiagramsFormat = @('pdf') + EnableDiagramSignature = $false + SignatureAuthorName = '' + SignatureCompanyName = '' + JobsTimeOut = 900 + DCStatusPingCount = 2 + } + InfoLevel = [ordered]@{ + Forest = $LvlForest + Domain = $LvlDomain + DNS = $LvlDNS + } + HealthCheck = [ordered]@{ + Domain = [ordered]@{ + GMSA = $true; GPO = $true; Backup = $true; DFS = $true + SPN = $true; DuplicateObject = $true; Security = $true; BestPractice = $true + } + DomainController = [ordered]@{ + Diagnostic = $true; Services = $true; Software = $true; BestPractice = $true + } + Site = [ordered]@{ Replication = $true; BestPractice = $true } + DNS = [ordered]@{ Aging = $true; DP = $true; Zones = $true; BestPractice = $true } + CA = [ordered]@{ Status = $true; Statistics = $true; BestPractice = $true } + } + } + } + + $btnSaveConfig = [Button]::new() + $btnSaveConfig.Content = '💾 Save Config' + $btnSaveConfig.HorizontalAlignment = 'Stretch' + $btnSaveConfig.HorizontalContentAlignment = 'Center' + $btnSaveConfig.Width = 196 + $btnSaveConfig.Margin = '0,0,4,0' + $btnSaveConfig.AddClick({ + $destPath = $txtConfigPath.Text.Trim() + if ([string]::IsNullOrWhiteSpace($destPath)) { + $syncHash.lblConfigStatus.Text = '⚠ Please enter a destination path first.' + return + } + try { + $parent = Split-Path $destPath -Parent + if (-not [string]::IsNullOrEmpty($parent) -and -not (Test-Path $parent)) { + New-Item -Path $parent -ItemType Directory -Force | Out-Null + } + function Get-LevelVal ($cbo) { [int]([string]$cbo.SelectedItem).Substring(0, 1) } + $configObj = Build-MSADConfigForSave ` + -ReportName ($txtReportName.Text.Trim()) ` + -Lang ([string]$cboLang.SelectedItem) ` + -Theme ([string]$cboDiagramTheme.SelectedItem) ` + -EnableDiagrams ([bool]$swDiagrams.IsChecked) ` + -ExportDiagrams ([bool]$swExportDiagrams.IsChecked) ` + -PSDefaultAuthentication ([string]$cboPSDefaultAuth.SelectedItem) ` + -WinRMSSL ([bool]$swWinRMSSL.IsChecked) ` + -WinRMFallbackToNoSSL ([bool]$swWinRMFallback.IsChecked) ` + -LvlForest (Get-LevelVal $cboLvlForest) ` + -LvlDomain (Get-LevelVal $cboLvlDomain) ` + -LvlDNS (Get-LevelVal $cboLvlDNS) + $configObj| ConvertTo-Json -Depth 6 | Set-Content -Path $destPath -Encoding UTF8 + $syncHash.lblConfigStatus.Text = "✅ Config saved: $(Split-Path $destPath -Leaf)" + } catch { + $syncHash.lblConfigStatus.Text = "❌ Save failed: $_" + } + }) + + $btnLoadConfig = [Button]::new() + $btnLoadConfig.Content = '📂 Load Config' + $btnLoadConfig.HorizontalAlignment = 'Stretch' + $btnLoadConfig.HorizontalContentAlignment = 'Center' + $btnLoadConfig.Width = 196 + $btnLoadConfig.Margin = '0,0,4,0' + $btnLoadConfig.AddClick({ + $srcPath = $txtConfigPath.Text.Trim() + if ([string]::IsNullOrWhiteSpace($srcPath) -or -not (Test-Path $srcPath)) { + $syncHash.lblConfigStatus.Text = '⚠ Config file path not found.' + return + } + try { + $j = Get-Content -Path $srcPath -Raw | ConvertFrom-Json + if ($j.Report.Name) { $txtReportName.Text = $j.Report.Name } + if ($j.Report.Language) { $idx = $cboLang.Items.IndexOf($j.Report.Language); if ($idx -ge 0) { $cboLang.SelectedIndex = $idx } } + if ($null -ne $j.Options.EnableDiagrams) { $swDiagrams.IsChecked = [bool]$j.Options.EnableDiagrams } + if ($null -ne $j.Options.ExportDiagrams) { $swExportDiagrams.IsChecked = [bool]$j.Options.ExportDiagrams } + if ($null -ne $j.Options.ShowExecutionTime) { Out-Null } + if ($null -ne $j.Options.ShowDefinitionInfo) { Out-Null } + if ($null -ne $j.Options.WinRMSSL){ $swWinRMSSL.IsChecked = [bool]$j.Options.WinRMSSL } + if ($null -ne $j.Options.WinRMFallbackToNoSSL) { $swWinRMFallback.IsChecked = [bool]$j.Options.WinRMFallbackToNoSSL } + if ($j.Options.DiagramTheme) { $idx = $cboDiagramTheme.Items.IndexOf($j.Options.DiagramTheme); if ($idx -ge 0) { $cboDiagramTheme.SelectedIndex = $idx } } + if ($j.Options.PSDefaultAuthentication) { $idx = $cboPSDefaultAuth.Items.IndexOf($j.Options.PSDefaultAuthentication); if ($idx -ge 0) { $cboPSDefaultAuth.SelectedIndex = $idx } } + if ($null -ne $j.InfoLevel.Forest) { $cboLvlForest.SelectedIndex = [int]$j.InfoLevel.Forest } + if ($null -ne $j.InfoLevel.Domain) { $cboLvlDomain.SelectedIndex = [int]$j.InfoLevel.Domain } + if ($null -ne $j.InfoLevel.DNS) { $cboLvlDNS.SelectedIndex = [int]$j.InfoLevel.DNS } + $syncHash.lblConfigStatus.Text= "✅ Config loaded: $(Split-Path $srcPath -Leaf)" + } catch { + $syncHash.lblConfigStatus.Text = "❌ Load failed: $_" + } + }) + + $btnOpenConfig = [Button]::new() + $btnOpenConfig.Content = '📄 Open File' + $btnOpenConfig.HorizontalAlignment = 'Stretch' + $btnOpenConfig.HorizontalContentAlignment = 'Center' + $btnOpenConfig.Width = 196 + $btnOpenConfig.AddClick({ + $filePath = $txtConfigPath.Text.Trim() + if ([string]::IsNullOrWhiteSpace($filePath) -or -not (Test-Path $filePath)) { + $syncHash.lblConfigStatus.Text = '⚠ Config file not found.' + return + } + try { Start-Process $filePath } catch { $syncHash.lblConfigStatus.Text = "❌ Could not open file: $_" } + }) + + $cfgBtnRow = [StackPanel]::new() + $cfgBtnRow.Orientation = 'Horizontal' + $cfgBtnRow.Margin = '0,4,0,0' + $cfgBtnRow.Children.Add($btnSaveConfig) + $cfgBtnRow.Children.Add($btnLoadConfig) + $cfgBtnRow.Children.Add($btnOpenConfig) + + # ── Assemble Main Panel (Report Page) ─────────────────────────────────────── + $mainPanel = [StackPanel]::new() + $mainPanel.Margin = '28,20,28,24' + $mainPanel.Spacing = 2 + + $headerPanel = [StackPanel]::new() + $headerPanel.HorizontalAlignment = 'Center' + $headerPanel.Spacing = 4 + $headerPanel.Margin = '0,0,0,4' + + $hTitle = [TextBlock]::new() + $hTitle.Text = 'Microsoft Active Directory' + $hTitle.FontSize = 22 + $hTitle.FontWeight = 'Bold' + $hTitle.HorizontalAlignment = 'Center' + + $hSub = [TextBlock]::new() + $hSub.Text = 'As-Built Report Generator' + $hSub.FontSize = 13 + $hSub.HorizontalAlignment = 'Center' + + $headerPanel.Children.Add($hTitle) + $headerPanel.Children.Add($hSub) + $mainPanel.Children.Add($headerPanel) + + # Row 1: Server Connection | Report Output + $topGrid = [Grid]::new() + $topGrid.ColumnDefinitions = [ColumnDefinitions]::Parse('*, *') + $topGrid.ColumnSpacing = 24 + $topGrid.Margin = '0,4,0,0' + + $connPanel = [StackPanel]::new() + $connPanel.Spacing = 2 + $connPanel.Children.Add((New-SectionTitle '🔌 Server Connection')) + $connPanel.Children.Add((New-FormRow -Label 'Saved Connections' -Control $cboSavedConn -LabelWidth 150)) + $connPanel.Children.Add((New-FormRow -Label 'Domain Controller' -Control $txtServer -LabelWidth 150)) + $connPanel.Children.Add((New-FormRow -Label 'Username' -Control $txtUser -LabelWidth 150)) + $connPanel.Children.Add((New-FormRow -Label 'Password' -Control (New-PasswordRow $txtPass) -LabelWidth 150)) + $connPanel.Children.Add((New-FormRow -Label '' -Control $savedConnActionsRow -LabelWidth 150)) + [Grid]::SetColumn($connPanel, 0) + $topGrid.Children.Add($connPanel) + + $outPanel = [StackPanel]::new() + $outPanel.Spacing = 2 + $outPanel.Children.Add((New-SectionTitle '📄 Report Output')) + $outPanel.Children.Add((New-FormRow -Label 'Report Name' -Control $txtReportName -LabelWidth 130)) + $outPanel.Children.Add((New-FormRow -Label 'Format' -Control $fmtPanel -LabelWidth 130)) + $outPanel.Children.Add((New-FormRow -Label 'Output Folder' -Control $outputPathRow -LabelWidth 130)) + $outPanel.Children.Add((New-FormRow -Label 'Language' -Control $cboLang -LabelWidth 130)) + $outPanel.Children.Add((New-FormRow -Label 'Add Timestamp' -Control $swTimestamp -LabelWidth 130)) + [Grid]::SetColumn($outPanel, 1) + $topGrid.Children.Add($outPanel) + + $mainPanel.Children.Add($topGrid) + + # Row 2: Options | Info Level + $bottomGrid = [Grid]::new() + $bottomGrid.ColumnDefinitions = [ColumnDefinitions]::Parse('*, *') + $bottomGrid.ColumnSpacing = 24 + $bottomGrid.Margin = '0,4,0,0' + + $optPanel = [StackPanel]::new() + $optPanel.Spacing = 2 + $optPanel.Children.Add((New-SectionTitle '⚙️ Options')) + $optPanel.Children.Add((New-FormRow -Label 'Enable Diagrams' -Control $swDiagrams -LabelWidth 185)) + $optPanel.Children.Add((New-FormRow -Label 'Export Diagrams' -Control $swExportDiagrams -LabelWidth 185)) + $optPanel.Children.Add((New-FormRow -Label 'Diagram Theme' -Control $cboDiagramTheme -LabelWidth 185)) + $optPanel.Children.Add((New-FormRow -Label 'WinRM SSL' -Control $swWinRMSSL -LabelWidth 185)) + $optPanel.Children.Add((New-FormRow -Label 'WinRM Fallback' -Control $swWinRMFallback -LabelWidth 185)) + $optPanel.Children.Add((New-FormRow -Label 'PS Authentication' -Control $cboPSDefaultAuth -LabelWidth 185)) + [Grid]::SetColumn($optPanel, 0) + $bottomGrid.Children.Add($optPanel) + + $lvlPanel = [StackPanel]::new() + $lvlPanel.Spacing = 2 + $lvlPanel.Children.Add((New-SectionTitle '📊 Info Level')) + $lvlPanel.Children.Add((New-FormRow -Label 'Forest' -Control $cboLvlForest)) + $lvlPanel.Children.Add((New-FormRow -Label 'Domain' -Control $cboLvlDomain)) + $lvlPanel.Children.Add((New-FormRow -Label 'DNS' -Control $cboLvlDNS)) + [Grid]::SetColumn($lvlPanel, 1) + $bottomGrid.Children.Add($lvlPanel) + + $mainPanel.Children.Add($bottomGrid) + + $mainPanel.Children.Add((New-SectionTitle '🗂️ Config Management')) + $mainPanel.Children.Add((New-FormRow -Label '📄 MSAD Config File' -Control $configPathRow)) + $mainPanel.Children.Add($cfgBtnRow) + $mainPanel.Children.Add((New-FormRow -Label '📄 AsBuiltReport Config File' -Control $abrConfigPathRow)) + $mainPanel.Children.Add($abrExpander) + + $mainPanel.Children.Add($btnGenerate) + + # Log area header + $logTitle = [TextBlock]::new() + $logTitle.Text = '📋 Output Log' + $logTitle.FontSize = 13 + $logTitle.FontWeight = 'SemiBold' + $logTitle.VerticalAlignment = 'Center' + + $logHeaderGrid = [Grid]::new() + $logHeaderGrid.Margin = '0,14,0,6' + $logHeaderGrid.ColumnDefinitions.Add( + [ColumnDefinition]::new([GridLength]::new(1, [GridUnitType]::Star))) + $logHeaderGrid.ColumnDefinitions.Add( + [ColumnDefinition]::new([GridLength]::new(0, [GridUnitType]::Auto))) + $logHeaderGrid.ColumnDefinitions.Add( + [ColumnDefinition]::new([GridLength]::new(0, [GridUnitType]::Auto))) + [Grid]::SetColumn($logTitle, 0) + [Grid]::SetColumn($chkVerbose, 1) + [Grid]::SetColumn($btnExportLog, 2) + $logHeaderGrid.Children.Add($logTitle) + $logHeaderGrid.Children.Add($chkVerbose) + $logHeaderGrid.Children.Add($btnExportLog) + + $btnOpenOutputFolder = [Button]::new() + $btnOpenOutputFolder.Content = '📁 Open Output Folder' + $btnOpenOutputFolder.Margin = '0,0,8,0' + $btnOpenOutputFolder.AddClick({ + $path = $txtOutput.Text.Trim() + if ([string]::IsNullOrWhiteSpace($path)) { + $syncHash.lblConfigStatus.Text = '⚠ No output folder set.' + return + } + if (-not (Test-Path $path)) { + $syncHash.lblConfigStatus.Text = "⚠ Output folder not found: $path" + return + } + try { Start-Process $path } catch { $syncHash.lblConfigStatus.Text = "❌ Could not open folder: $_" } + }) + + $logActionsRow = [StackPanel]::new() + $logActionsRow.Orientation = 'Horizontal' + $logActionsRow.HorizontalAlignment = 'Right' + $logActionsRow.Margin = '0,6,0,0' + $logActionsRow.Children.Add($btnOpenOutputFolder) + $logActionsRow.Children.Add($btnCancel) + + $scrollView = [ScrollViewer]::new() + $scrollView.Content = $mainPanel + + # ── Drawer Pages ──────────────────────────────────────────────────────────── + $reportPage = [ContentPage]::new() + $reportPage.Header = 'Report' + $reportPage.Content = $scrollView + + $navigationPage = [NavigationPage]::new() + $navigationPage.Content = $reportPage + + # MDI path geometry for nav icons + $reportGeometry = 'M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z' + + $btnNavReport = New-DrawerMenuItem -Title 'Report' -IconGeometry $reportGeometry -Page $reportPage -NavigationPage $navigationPage + + $drawerMenuPanel = [StackPanel]::new() + $drawerMenuPanel.Margin = 12 + $drawerMenuPanel.Children.Add($btnNavReport) + + $drawerMenu = [ContentPage]::new() + $drawerMenu.Content = $drawerMenuPanel + + $drawerHeader = [TextBlock]::new() + $drawerHeader.Text = 'Navigation' + $drawerHeader.FontSize = 16 + $drawerHeader.FontWeight = 'SemiBold' + $drawerHeader.VerticalAlignment = 'Center' + $drawerHeader.Padding = '16,10,12,10' + + $drawerPage = [DrawerPage]::new() + $drawerPage.DrawerHeader = $drawerHeader + $drawerPage.Drawer = $drawerMenu + $drawerPage.Content = $navigationPage + + # ── Shared bottom strip (log + status — visible from all drawer pages) ──────── + $sharedBottomPanel = [StackPanel]::new() + $sharedBottomPanel.Margin = '28,4,28,16' + $sharedBottomPanel.Children.Add($progressBar) + $sharedBottomPanel.Children.Add($logHeaderGrid) + $sharedBottomPanel.Children.Add($txtLog) + $sharedBottomPanel.Children.Add($logActionsRow) + $sharedBottomPanel.Children.Add($lblConfigStatus) + + # ── Outer grid: drawer (fills space) above shared log strip ────────────────── + $outerGrid = [Grid]::new() + $outerGrid.RowDefinitions.Add([RowDefinition]::new([GridLength]::new(1, [GridUnitType]::Star))) + $outerGrid.RowDefinitions.Add([RowDefinition]::new([GridLength]::new(0, [GridUnitType]::Auto))) + [Grid]::SetRow($drawerPage, 0) + [Grid]::SetRow($sharedBottomPanel, 1) + $outerGrid.Children.Add($drawerPage) + $outerGrid.Children.Add($sharedBottomPanel) + + # ── Window ────────────────────────────────────────────────────────────────── + $win = [Window]::new() + $win.Title = 'Microsoft AD — As-Built Report Generator' + $win.Width = 1050 + $win.Height = 920 + $win.MinWidth = 880 + $win.MinHeight = 500 + $win.Content = $outerGrid + + $win.Show() + $win.WaitForClosed() +} diff --git a/CHANGELOG.md b/CHANGELOG.md index e9c2836..ae4c61c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0] - 2026-04-?? +### Added + +- Add support for GliderUI to generate the report using a graphical interface instead of command line. The GUI will allow users to select the target domain, customize report options, and initiate the report generation process with a user-friendly experience. + ### :arrows_clockwise: Changed - Improved multi-language support by refactoring localization strings and enhancing documentation clarity in MicrosoftAD.psd1 for English and Spanish languages. @@ -17,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgrade AsBuiltReport.Diagram module to version `1.0.6` - Upgrade AsBuiltReport.Chart module to version `0.3.1` +## :bug: Fixed + +- Fix diagram theme generation not respecting the selected theme in the configuration file, ensuring that diagrams are rendered with the correct visual style as defined by the user. + ## [0.9.12] - 2026-04-02 ### :toolbox: Added From c48185abc09b0d0a9106f9e63dccc394162d402d Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 16:35:01 -0400 Subject: [PATCH 08/11] refactor: Clean up formatting and spacing in Start-AsBuiltReportMSAD.ps1 --- .../Private/Gui/Start-AsBuiltReportMSAD.ps1 | 418 +++++++++--------- 1 file changed, 209 insertions(+), 209 deletions(-) diff --git a/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 b/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 index b7ddb6a..42a9b65 100644 --- a/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 +++ b/AsBuiltReport.Microsoft.AD/Src/Private/Gui/Start-AsBuiltReportMSAD.ps1 @@ -41,8 +41,8 @@ function Start-AsBuiltReportMSAD { } $gliderMod = Get-Module -ListAvailable -Name GliderUI | - Sort-Object Version -Descending | - Select-Object -First 1 + Sort-Object Version -Descending | + Select-Object -First 1 if ($null -eq $gliderMod -or $gliderMod.Version -lt $requiredGliderUIVersion) { $found = if ($null -eq $gliderMod) { 'not installed' } else { "v$($gliderMod.Version)" } @@ -55,7 +55,7 @@ function Start-AsBuiltReportMSAD { # Thread-safe store shared between the main runspace and the report runspace $syncHash = [Hashtable]::Synchronized(@{ CancelRequested = $false - IsBusy = $false + IsBusy = $false }) # ── UI Helper Functions ───────────────────────────────────────────────────── @@ -318,11 +318,11 @@ function Start-AsBuiltReportMSAD { # ── Options Controls ──────────────────────────────────────────────────────── # Options matching AsBuiltReport.Microsoft.AD.json > Options - $swDiagrams = [ToggleSwitch]::new(); $swDiagrams.IsChecked = $true + $swDiagrams = [ToggleSwitch]::new(); $swDiagrams.IsChecked = $true $swExportDiagrams = [ToggleSwitch]::new(); $swExportDiagrams.IsChecked = $true - $swTimestamp= [ToggleSwitch]::new(); $swTimestamp.IsChecked = $false - $swWinRMSSL = [ToggleSwitch]::new(); $swWinRMSSL.IsChecked = $false - $swWinRMFallback = [ToggleSwitch]::new(); $swWinRMFallback.IsChecked = $true + $swTimestamp = [ToggleSwitch]::new(); $swTimestamp.IsChecked = $false + $swWinRMSSL = [ToggleSwitch]::new(); $swWinRMSSL.IsChecked = $false + $swWinRMFallback = [ToggleSwitch]::new(); $swWinRMFallback.IsChecked = $true $cboDiagramTheme = [ComboBox]::new() $cboDiagramTheme.Width = 120 @@ -345,7 +345,7 @@ function Start-AsBuiltReportMSAD { $cboLvlForest = New-LevelCombo; $cboLvlForest.SelectedIndex = 2 # default 2 per JSON $cboLvlDomain = New-LevelCombo; $cboLvlDomain.SelectedIndex = 2 # default 2 per JSON - $cboLvlDNS = New-LevelCombo; $cboLvlDNS.SelectedIndex = 1 # default 1 per JSON + $cboLvlDNS = New-LevelCombo; $cboLvlDNS.SelectedIndex = 1 # default 1 per JSON # ── Progress Bar & Log ────────────────────────────────────────────────────── $progressBar = [ProgressBar]::new() @@ -428,27 +428,27 @@ function Start-AsBuiltReportMSAD { $generateCallback.DisabledControlsWhileProcessing = $btnGenerate $generateCallback.ArgumentList = @{ - SyncHash = $syncHash - Server = $txtServer - Username = $txtUser - Password = $txtPass - ReportName = $txtReportName - OutPath = $txtOutput - FmtHTML = $chkHTML - FmtWord = $chkWord - FmtText = $chkText - Lang = $cboLang - DiagramTheme = $cboDiagramTheme - PSDefaultAuth = $cboPSDefaultAuth - Diagrams = $swDiagrams - ExportDiagrams = $swExportDiagrams - Timestamp = $swTimestamp - WinRMSSL = $swWinRMSSL - WinRMFallback = $swWinRMFallback - LvlForest = $cboLvlForest - LvlDomain = $cboLvlDomain - LvlDNS = $cboLvlDNS - Verbose = $chkVerbose + SyncHash = $syncHash + Server = $txtServer + Username = $txtUser + Password = $txtPass + ReportName = $txtReportName + OutPath = $txtOutput + FmtHTML = $chkHTML + FmtWord = $chkWord + FmtText = $chkText + Lang = $cboLang + DiagramTheme = $cboDiagramTheme + PSDefaultAuth = $cboPSDefaultAuth + Diagrams = $swDiagrams + ExportDiagrams = $swExportDiagrams + Timestamp = $swTimestamp + WinRMSSL = $swWinRMSSL + WinRMFallback = $swWinRMFallback + LvlForest = $cboLvlForest + LvlDomain = $cboLvlDomain + LvlDNS = $cboLvlDNS + Verbose = $chkVerbose # ConfigPath and AbrConfigPath are late-bound below after TextBox creation } @@ -501,82 +501,82 @@ function Start-AsBuiltReportMSAD { [int]$LvlDNS ) return [ordered]@{ - Report = [ordered]@{ - Name = $ReportName - Version = '1.0' - Status = 'Released' - Language = $Lang - ShowCoverPageImage = $true + Report = [ordered]@{ + Name = $ReportName + Version = '1.0' + Status = 'Released' + Language = $Lang + ShowCoverPageImage = $true ShowTableOfContents = $true - ShowHeaderFooter = $true - ShowTableCaptions = $true + ShowHeaderFooter = $true + ShowTableCaptions = $true } - Options = [ordered]@{ - ShowExecutionTime = $false - ShowDefinitionInfo = $false + Options = [ordered]@{ + ShowExecutionTime = $false + ShowDefinitionInfo = $false PSDefaultAuthentication = $PSDefaultAuthentication - Exclude = [ordered]@{ Domains = @(); DCs = @() } - Include = [ordered]@{ Domains = @() } - WinRMSSL = $WinRMSSL - WinRMFallbackToNoSSL = $WinRMFallbackToNoSSL - WinRMSSLPort = 5986 - WinRMPort = 5985 - EnableDiagrams = $EnableDiagrams - EnableDiagramDebug = $false - DiagramTheme = $Theme - DiagramObjDebug = $false - DiagramWaterMark = '' - DiagramType = [ordered]@{ + Exclude = [ordered]@{ Domains = @(); DCs = @() } + Include = [ordered]@{ Domains = @() } + WinRMSSL = $WinRMSSL + WinRMFallbackToNoSSL = $WinRMFallbackToNoSSL + WinRMSSLPort = 5986 + WinRMPort = 5985 + EnableDiagrams = $EnableDiagrams + EnableDiagramDebug = $false + DiagramTheme = $Theme + DiagramObjDebug = $false + DiagramWaterMark = '' + DiagramType = [ordered]@{ CertificateAuthority = $true - Forest = $true - Replication = $true - Sites = $true - SitesInventory = $true - Trusts = $true + Forest = $true + Replication = $true + Sites = $true + SitesInventory = $true + Trusts = $true } - ExportDiagrams = $ExportDiagrams - ExportDiagramsFormat = @('pdf') - EnableDiagramSignature = $false - SignatureAuthorName = '' - SignatureCompanyName = '' - JobsTimeOut = 900 - DCStatusPingCount = 2 + ExportDiagrams = $ExportDiagrams + ExportDiagramsFormat = @('pdf') + EnableDiagramSignature = $false + SignatureAuthorName = '' + SignatureCompanyName = '' + JobsTimeOut = 900 + DCStatusPingCount = 2 } - InfoLevel = [ordered]@{ + InfoLevel = [ordered]@{ Forest = $LvlForest Domain = $LvlDomain - DNS = $LvlDNS + DNS = $LvlDNS } HealthCheck = [ordered]@{ - Domain = [ordered]@{ - GMSA = $true - GPO = $true - Backup = $true - DFS = $true - SPN = $true + Domain = [ordered]@{ + GMSA = $true + GPO = $true + Backup = $true + DFS = $true + SPN = $true DuplicateObject = $true - Security = $true - BestPractice = $true + Security = $true + BestPractice = $true } DomainController = [ordered]@{ - Diagnostic = $true - Services = $true - Software = $true + Diagnostic = $true + Services = $true + Software = $true BestPractice = $true } - Site = [ordered]@{ - Replication = $true + Site = [ordered]@{ + Replication = $true BestPractice = $true } - DNS = [ordered]@{ - Aging = $true - DP = $true - Zones = $true + DNS = [ordered]@{ + Aging = $true + DP = $true + Zones = $true BestPractice = $true } - CA = [ordered]@{ - Status = $true - Statistics = $true + CA = [ordered]@{ + Status = $true + Statistics = $true BestPractice = $true } } @@ -584,13 +584,13 @@ function Start-AsBuiltReportMSAD { } # ── Collect values ──────────────────────────────────────────────────────── - $server = $ui.Server.Text.Trim() - $username = $ui.Username.Text.Trim() - $password = $ui.Password.Text - $reportName = $ui.ReportName.Text.Trim() - $outPath = $ui.OutPath.Text.Trim() - $lang = [string]$ui.Lang.SelectedItem - $configPath = $ui.ConfigPath.Text.Trim() + $server = $ui.Server.Text.Trim() + $username = $ui.Username.Text.Trim() + $password = $ui.Password.Text + $reportName = $ui.ReportName.Text.Trim() + $outPath = $ui.OutPath.Text.Trim() + $lang = [string]$ui.Lang.SelectedItem + $configPath = $ui.ConfigPath.Text.Trim() $abrConfigPath = $ui.AbrConfigPath.Text.Trim() $formats = @() @@ -599,18 +599,18 @@ function Start-AsBuiltReportMSAD { if ($ui.FmtText.IsChecked -eq $true) { $formats += 'Text' } if ($formats.Count -eq 0) { $formats = @('Html') } - $enableDiagrams = [bool]$ui.Diagrams.IsChecked - $exportDiagrams = [bool]$ui.ExportDiagrams.IsChecked - $addTimestamp = [bool]$ui.Timestamp.IsChecked - $winRMSSL = [bool]$ui.WinRMSSL.IsChecked - $winRMFallback = [bool]$ui.WinRMFallback.IsChecked - $psDefaultAuth = [string]$ui.PSDefaultAuth.SelectedItem - $diagramTheme = [string]$ui.DiagramTheme.SelectedItem + $enableDiagrams = [bool]$ui.Diagrams.IsChecked + $exportDiagrams = [bool]$ui.ExportDiagrams.IsChecked + $addTimestamp = [bool]$ui.Timestamp.IsChecked + $winRMSSL = [bool]$ui.WinRMSSL.IsChecked + $winRMFallback = [bool]$ui.WinRMFallback.IsChecked + $psDefaultAuth = [string]$ui.PSDefaultAuth.SelectedItem + $diagramTheme = [string]$ui.DiagramTheme.SelectedItem # Parse InfoLevel (first char = number) $lvlForest = [int]([string]$ui.LvlForest.SelectedItem).Substring(0, 1) $lvlDomain = [int]([string]$ui.LvlDomain.SelectedItem).Substring(0, 1) - $lvlDNS = [int]([string]$ui.LvlDNS.SelectedItem).Substring(0, 1) + $lvlDNS = [int]([string]$ui.LvlDNS.SelectedItem).Substring(0, 1) # ── Validation ──────────────────────────────────────────────────────────── if ([string]::IsNullOrWhiteSpace($server)) { @@ -697,11 +697,11 @@ function Start-AsBuiltReportMSAD { $credential = [PSCredential]::new($username, $securePassword) $params = @{ - Report = 'Microsoft.AD' - Target = $server - Credential = $credential - OutputFolderPath = $outPath - Format = $formats + Report = 'Microsoft.AD' + Target = $server + Credential = $credential + OutputFolderPath = $outPath + Format = $formats ReportConfigFilePath = $reportConfigFilePath AsBuiltConfigFilePath = $abrConfigPath } @@ -827,70 +827,70 @@ function Start-AsBuiltReportMSAD { $abrConfigPathRow.Children.Add($btnBrowseAbrConfig) # Late-bind after TextBox objects exist - $generateCallback.ArgumentList['ConfigPath'] = $txtConfigPath + $generateCallback.ArgumentList['ConfigPath'] = $txtConfigPath $generateCallback.ArgumentList['AbrConfigPath'] = $txtAbrConfigPath # ── AsBuiltReport Global Settings (AsBuiltReport.json editor) ──────────────── - $txtAbrCoFullName = [TextBox]::new(); $txtAbrCoFullName.Width = 298; $txtAbrCoFullName.Watermark = 'e.g. Acme Corporation' + $txtAbrCoFullName = [TextBox]::new(); $txtAbrCoFullName.Width = 298; $txtAbrCoFullName.Watermark = 'e.g. Acme Corporation' $txtAbrCoShortName = [TextBox]::new(); $txtAbrCoShortName.Width = 298; $txtAbrCoShortName.Watermark = 'e.g. ACME' - $txtAbrCoContact = [TextBox]::new(); $txtAbrCoContact.Width = 298; $txtAbrCoContact.Watermark = 'Contact person' - $txtAbrCoPhone = [TextBox]::new(); $txtAbrCoPhone.Width = 298; $txtAbrCoPhone.Watermark = 'e.g. +1-800-555-0100' - $txtAbrCoAddress = [TextBox]::new(); $txtAbrCoAddress.Width = 298; $txtAbrCoAddress.Watermark = 'Street, City, Country' - $txtAbrCoEmail = [TextBox]::new(); $txtAbrCoEmail.Width = 298; $txtAbrCoEmail.Watermark = 'company@example.com' - $txtAbrRptAuthor = [TextBox]::new(); $txtAbrRptAuthor.Width = 298; $txtAbrRptAuthor.Watermark = 'Report author' - $txtAbrMailServer = [TextBox]::new(); $txtAbrMailServer.Width = 298; $txtAbrMailServer.Watermark = 'smtp.example.com' - $txtAbrMailPort = [TextBox]::new(); $txtAbrMailPort.Width = 298; $txtAbrMailPort.Watermark = '587' - $txtAbrMailFrom = [TextBox]::new(); $txtAbrMailFrom.Width = 298; $txtAbrMailFrom.Watermark = 'from@example.com' - $txtAbrMailTo = [TextBox]::new(); $txtAbrMailTo.Width = 298; $txtAbrMailTo.Watermark = 'to@example.com, other@example.com' - $txtAbrMailBody = [TextBox]::new(); $txtAbrMailBody.Width = 298; $txtAbrMailBody.Watermark = 'Email body text' - $swAbrMailUseSSL = [ToggleSwitch]::new(); $swAbrMailUseSSL.IsChecked = $true - $swAbrMailCreds = [ToggleSwitch]::new(); $swAbrMailCreds.IsChecked = $true - $txtAbrFolderPath = [TextBox]::new(); $txtAbrFolderPath.Width = 298; $txtAbrFolderPath.Watermark = '.\AsBuiltReport' + $txtAbrCoContact = [TextBox]::new(); $txtAbrCoContact.Width = 298; $txtAbrCoContact.Watermark = 'Contact person' + $txtAbrCoPhone = [TextBox]::new(); $txtAbrCoPhone.Width = 298; $txtAbrCoPhone.Watermark = 'e.g. +1-800-555-0100' + $txtAbrCoAddress = [TextBox]::new(); $txtAbrCoAddress.Width = 298; $txtAbrCoAddress.Watermark = 'Street, City, Country' + $txtAbrCoEmail = [TextBox]::new(); $txtAbrCoEmail.Width = 298; $txtAbrCoEmail.Watermark = 'company@example.com' + $txtAbrRptAuthor = [TextBox]::new(); $txtAbrRptAuthor.Width = 298; $txtAbrRptAuthor.Watermark = 'Report author' + $txtAbrMailServer = [TextBox]::new(); $txtAbrMailServer.Width = 298; $txtAbrMailServer.Watermark = 'smtp.example.com' + $txtAbrMailPort = [TextBox]::new(); $txtAbrMailPort.Width = 298; $txtAbrMailPort.Watermark = '587' + $txtAbrMailFrom = [TextBox]::new(); $txtAbrMailFrom.Width = 298; $txtAbrMailFrom.Watermark = 'from@example.com' + $txtAbrMailTo = [TextBox]::new(); $txtAbrMailTo.Width = 298; $txtAbrMailTo.Watermark = 'to@example.com, other@example.com' + $txtAbrMailBody = [TextBox]::new(); $txtAbrMailBody.Width = 298; $txtAbrMailBody.Watermark = 'Email body text' + $swAbrMailUseSSL = [ToggleSwitch]::new(); $swAbrMailUseSSL.IsChecked = $true + $swAbrMailCreds = [ToggleSwitch]::new(); $swAbrMailCreds.IsChecked = $true + $txtAbrFolderPath = [TextBox]::new(); $txtAbrFolderPath.Width = 298; $txtAbrFolderPath.Watermark = '.\AsBuiltReport' $loadAbrFields = { param ([hashtable]$j) - $txtAbrCoFullName.Text = if ($j.Company.FullName) { $j.Company.FullName } else { '' } - $txtAbrCoShortName.Text = if ($j.Company.ShortName) { $j.Company.ShortName } else { '' } - $txtAbrCoContact.Text = if ($j.Company.Contact) { $j.Company.Contact } else { '' } - $txtAbrCoPhone.Text = if ($j.Company.Phone) { $j.Company.Phone } else { '' } - $txtAbrCoAddress.Text = if ($j.Company.Address) { $j.Company.Address } else { '' } - $txtAbrCoEmail.Text = if ($j.Company.Email) { $j.Company.Email } else { '' } - $txtAbrRptAuthor.Text = if ($j.Report.Author) { $j.Report.Author } else { '' } - $txtAbrMailServer.Text = if ($j.Email.Server) { $j.Email.Server } else { '' } - $txtAbrMailPort.Text = if ($j.Email.Port) { $j.Email.Port } else { '' } - $txtAbrMailFrom.Text = if ($j.Email.From) { $j.Email.From } else { '' } - $txtAbrMailTo.Text = if ($j.Email.To) { ($j.Email.To -join ', ') } else { '' } - $txtAbrMailBody.Text = if ($j.Email.Body) { $j.Email.Body } else { '' } - $swAbrMailUseSSL.IsChecked = if ($null -ne $j.Email.UseSSL) { [bool]$j.Email.UseSSL } else { $true } - $swAbrMailCreds.IsChecked = if ($null -ne $j.Email.Credentials) { [bool]$j.Email.Credentials } else { $true } - $txtAbrFolderPath.Text = if ($j.UserFolder.Path) { $j.UserFolder.Path } else { + $txtAbrCoFullName.Text = if ($j.Company.FullName) { $j.Company.FullName } else { '' } + $txtAbrCoShortName.Text = if ($j.Company.ShortName) { $j.Company.ShortName } else { '' } + $txtAbrCoContact.Text = if ($j.Company.Contact) { $j.Company.Contact } else { '' } + $txtAbrCoPhone.Text = if ($j.Company.Phone) { $j.Company.Phone } else { '' } + $txtAbrCoAddress.Text = if ($j.Company.Address) { $j.Company.Address } else { '' } + $txtAbrCoEmail.Text = if ($j.Company.Email) { $j.Company.Email } else { '' } + $txtAbrRptAuthor.Text = if ($j.Report.Author) { $j.Report.Author } else { '' } + $txtAbrMailServer.Text = if ($j.Email.Server) { $j.Email.Server } else { '' } + $txtAbrMailPort.Text = if ($j.Email.Port) { $j.Email.Port } else { '' } + $txtAbrMailFrom.Text = if ($j.Email.From) { $j.Email.From } else { '' } + $txtAbrMailTo.Text = if ($j.Email.To) { ($j.Email.To -join ', ') } else { '' } + $txtAbrMailBody.Text = if ($j.Email.Body) { $j.Email.Body } else { '' } + $swAbrMailUseSSL.IsChecked = if ($null -ne $j.Email.UseSSL) { [bool]$j.Email.UseSSL } else { $true } + $swAbrMailCreds.IsChecked = if ($null -ne $j.Email.Credentials) { [bool]$j.Email.Credentials } else { $true } + $txtAbrFolderPath.Text = if ($j.UserFolder.Path) { $j.UserFolder.Path } else { if ($IsWindows) { [System.IO.Path]::Combine($env:USERPROFILE, 'Documents', 'AsBuiltReport') } else { [System.IO.Path]::Combine($env:HOME, 'AsBuiltReport') } } } $buildAbrConfig = { - $toList = ([string]$txtAbrMailTo.Text).Trim() -split '\s*,\s*' | Where-Object { $_ -ne '' } + $toList = ([string]$txtAbrMailTo.Text).Trim() -split '\s*,\s*' | Where-Object { $_ -ne '' } $portRaw = ([string]$txtAbrMailPort.Text).Trim() $portVal = if ($portRaw -match '^\d+$') { [int]$portRaw } else { $null } return [ordered]@{ - Company = [ordered]@{ - FullName = ([string]$txtAbrCoFullName.Text).Trim() - Phone = ([string]$txtAbrCoPhone.Text).Trim() - Address = ([string]$txtAbrCoAddress.Text).Trim() + Company = [ordered]@{ + FullName = ([string]$txtAbrCoFullName.Text).Trim() + Phone = ([string]$txtAbrCoPhone.Text).Trim() + Address = ([string]$txtAbrCoAddress.Text).Trim() ShortName = ([string]$txtAbrCoShortName.Text).Trim() - Contact = ([string]$txtAbrCoContact.Text).Trim() - Email = ([string]$txtAbrCoEmail.Text).Trim() + Contact = ([string]$txtAbrCoContact.Text).Trim() + Email = ([string]$txtAbrCoEmail.Text).Trim() } - Email = [ordered]@{ + Email = [ordered]@{ Credentials = [bool]$swAbrMailCreds.IsChecked - Body = ([string]$txtAbrMailBody.Text).Trim() - From = ([string]$txtAbrMailFrom.Text).Trim() - UseSSL = [bool]$swAbrMailUseSSL.IsChecked - Server = ([string]$txtAbrMailServer.Text).Trim() - To = if ($toList.Count -gt 0) { @($toList) } else { @() } - Port = $portVal + Body = ([string]$txtAbrMailBody.Text).Trim() + From = ([string]$txtAbrMailFrom.Text).Trim() + UseSSL = [bool]$swAbrMailUseSSL.IsChecked + Server = ([string]$txtAbrMailServer.Text).Trim() + To = if ($toList.Count -gt 0) { @($toList) } else { @() } + Port = $portVal } - Report = [ordered]@{ Author = ([string]$txtAbrRptAuthor.Text).Trim() } + Report = [ordered]@{ Author = ([string]$txtAbrRptAuthor.Text).Trim() } UserFolder = [ordered]@{ Path = ([string]$txtAbrFolderPath.Text).Trim() } } }.GetNewClosure() @@ -898,12 +898,12 @@ function Start-AsBuiltReportMSAD { $validateAbrRequired = { $missing = @() - if ([string]::IsNullOrWhiteSpace($txtAbrCoFullName.Text)) { $missing += 'Full Name' } + if ([string]::IsNullOrWhiteSpace($txtAbrCoFullName.Text)) { $missing += 'Full Name' } if ([string]::IsNullOrWhiteSpace($txtAbrCoShortName.Text)) { $missing += 'Short Name' } - if ([string]::IsNullOrWhiteSpace($txtAbrCoContact.Text)) { $missing += 'Contact' } - if ([string]::IsNullOrWhiteSpace($txtAbrCoEmail.Text)) { $missing += 'Email' } - if ([string]::IsNullOrWhiteSpace($txtAbrRptAuthor.Text)) { $missing += 'Author' } - if ([string]::IsNullOrWhiteSpace($txtAbrFolderPath.Text)) { $missing += 'Path' } + if ([string]::IsNullOrWhiteSpace($txtAbrCoContact.Text)) { $missing += 'Contact' } + if ([string]::IsNullOrWhiteSpace($txtAbrCoEmail.Text)) { $missing += 'Email' } + if ([string]::IsNullOrWhiteSpace($txtAbrRptAuthor.Text)) { $missing += 'Author' } + if ([string]::IsNullOrWhiteSpace($txtAbrFolderPath.Text)) { $missing += 'Path' } if ($missing.Count -gt 0) { return "⚠ Required fields missing: $($missing -join ', ')" } @@ -1052,63 +1052,63 @@ function Start-AsBuiltReportMSAD { [int]$LvlForest, [int]$LvlDomain, [int]$LvlDNS ) return [ordered]@{ - Report = [ordered]@{ - Name = $ReportName - Version = '1.0' - Status = 'Released' - Language = $Lang - ShowCoverPageImage = $true + Report = [ordered]@{ + Name = $ReportName + Version = '1.0' + Status = 'Released' + Language = $Lang + ShowCoverPageImage = $true ShowTableOfContents = $true - ShowHeaderFooter = $true - ShowTableCaptions = $true + ShowHeaderFooter = $true + ShowTableCaptions = $true } - Options = [ordered]@{ - ShowExecutionTime = $false - ShowDefinitionInfo = $false + Options = [ordered]@{ + ShowExecutionTime = $false + ShowDefinitionInfo = $false PSDefaultAuthentication = $PSDefaultAuthentication - Exclude = [ordered]@{ Domains = @(); DCs = @() } - Include = [ordered]@{ Domains = @() } - WinRMSSL = $WinRMSSL - WinRMFallbackToNoSSL = $WinRMFallbackToNoSSL - WinRMSSLPort = 5986 - WinRMPort = 5985 - EnableDiagrams = $EnableDiagrams - EnableDiagramDebug = $false - DiagramTheme = $Theme - DiagramObjDebug = $false - DiagramWaterMark = '' - DiagramType = [ordered]@{ + Exclude = [ordered]@{ Domains = @(); DCs = @() } + Include = [ordered]@{ Domains = @() } + WinRMSSL = $WinRMSSL + WinRMFallbackToNoSSL = $WinRMFallbackToNoSSL + WinRMSSLPort = 5986 + WinRMPort = 5985 + EnableDiagrams = $EnableDiagrams + EnableDiagramDebug = $false + DiagramTheme = $Theme + DiagramObjDebug = $false + DiagramWaterMark = '' + DiagramType = [ordered]@{ CertificateAuthority = $true - Forest = $true - Replication = $true - Sites = $true - SitesInventory = $true - Trusts = $true + Forest = $true + Replication = $true + Sites = $true + SitesInventory = $true + Trusts = $true } - ExportDiagrams = $ExportDiagrams - ExportDiagramsFormat = @('pdf') - EnableDiagramSignature = $false - SignatureAuthorName = '' - SignatureCompanyName = '' - JobsTimeOut = 900 - DCStatusPingCount = 2 + ExportDiagrams = $ExportDiagrams + ExportDiagramsFormat = @('pdf') + EnableDiagramSignature = $false + SignatureAuthorName = '' + SignatureCompanyName = '' + JobsTimeOut = 900 + DCStatusPingCount = 2 } - InfoLevel = [ordered]@{ + InfoLevel = [ordered]@{ Forest = $LvlForest Domain = $LvlDomain - DNS = $LvlDNS + DNS = $LvlDNS } HealthCheck = [ordered]@{ - Domain = [ordered]@{ - GMSA = $true; GPO = $true; Backup = $true; DFS = $true - SPN = $true; DuplicateObject = $true; Security = $true; BestPractice = $true + Domain = [ordered]@{ + GMSA = $true; GPO = $true; Backup = $true; DFS = $true + SPN = $true; DuplicateObject = $true; Security = $true; BestPractice = $true } DomainController = [ordered]@{ Diagnostic = $true; Services = $true; Software = $true; BestPractice = $true } - Site = [ordered]@{ Replication = $true; BestPractice = $true } - DNS = [ordered]@{ Aging = $true; DP = $true; Zones = $true; BestPractice = $true } - CA = [ordered]@{ Status = $true; Statistics = $true; BestPractice = $true } + Site = [ordered]@{ Replication = $true; BestPractice = $true } + DNS = [ordered]@{ Aging = $true; DP = $true; Zones = $true; BestPractice = $true } + CA = [ordered]@{ Status = $true; Statistics = $true; BestPractice = $true } } } } @@ -1143,7 +1143,7 @@ function Start-AsBuiltReportMSAD { -LvlForest (Get-LevelVal $cboLvlForest) ` -LvlDomain (Get-LevelVal $cboLvlDomain) ` -LvlDNS (Get-LevelVal $cboLvlDNS) - $configObj| ConvertTo-Json -Depth 6 | Set-Content -Path $destPath -Encoding UTF8 + $configObj | ConvertTo-Json -Depth 6 | Set-Content -Path $destPath -Encoding UTF8 $syncHash.lblConfigStatus.Text = "✅ Config saved: $(Split-Path $destPath -Leaf)" } catch { $syncHash.lblConfigStatus.Text = "❌ Save failed: $_" @@ -1164,20 +1164,20 @@ function Start-AsBuiltReportMSAD { } try { $j = Get-Content -Path $srcPath -Raw | ConvertFrom-Json - if ($j.Report.Name) { $txtReportName.Text = $j.Report.Name } + if ($j.Report.Name) { $txtReportName.Text = $j.Report.Name } if ($j.Report.Language) { $idx = $cboLang.Items.IndexOf($j.Report.Language); if ($idx -ge 0) { $cboLang.SelectedIndex = $idx } } - if ($null -ne $j.Options.EnableDiagrams) { $swDiagrams.IsChecked = [bool]$j.Options.EnableDiagrams } - if ($null -ne $j.Options.ExportDiagrams) { $swExportDiagrams.IsChecked = [bool]$j.Options.ExportDiagrams } - if ($null -ne $j.Options.ShowExecutionTime) { Out-Null } - if ($null -ne $j.Options.ShowDefinitionInfo) { Out-Null } - if ($null -ne $j.Options.WinRMSSL){ $swWinRMSSL.IsChecked = [bool]$j.Options.WinRMSSL } - if ($null -ne $j.Options.WinRMFallbackToNoSSL) { $swWinRMFallback.IsChecked = [bool]$j.Options.WinRMFallbackToNoSSL } + if ($null -ne $j.Options.EnableDiagrams) { $swDiagrams.IsChecked = [bool]$j.Options.EnableDiagrams } + if ($null -ne $j.Options.ExportDiagrams) { $swExportDiagrams.IsChecked = [bool]$j.Options.ExportDiagrams } + if ($null -ne $j.Options.ShowExecutionTime) { Out-Null } + if ($null -ne $j.Options.ShowDefinitionInfo) { Out-Null } + if ($null -ne $j.Options.WinRMSSL) { $swWinRMSSL.IsChecked = [bool]$j.Options.WinRMSSL } + if ($null -ne $j.Options.WinRMFallbackToNoSSL) { $swWinRMFallback.IsChecked = [bool]$j.Options.WinRMFallbackToNoSSL } if ($j.Options.DiagramTheme) { $idx = $cboDiagramTheme.Items.IndexOf($j.Options.DiagramTheme); if ($idx -ge 0) { $cboDiagramTheme.SelectedIndex = $idx } } if ($j.Options.PSDefaultAuthentication) { $idx = $cboPSDefaultAuth.Items.IndexOf($j.Options.PSDefaultAuthentication); if ($idx -ge 0) { $cboPSDefaultAuth.SelectedIndex = $idx } } if ($null -ne $j.InfoLevel.Forest) { $cboLvlForest.SelectedIndex = [int]$j.InfoLevel.Forest } if ($null -ne $j.InfoLevel.Domain) { $cboLvlDomain.SelectedIndex = [int]$j.InfoLevel.Domain } - if ($null -ne $j.InfoLevel.DNS) { $cboLvlDNS.SelectedIndex = [int]$j.InfoLevel.DNS } - $syncHash.lblConfigStatus.Text= "✅ Config loaded: $(Split-Path $srcPath -Leaf)" + if ($null -ne $j.InfoLevel.DNS) { $cboLvlDNS.SelectedIndex = [int]$j.InfoLevel.DNS } + $syncHash.lblConfigStatus.Text = "✅ Config loaded: $(Split-Path $srcPath -Leaf)" } catch { $syncHash.lblConfigStatus.Text = "❌ Load failed: $_" } From 33cc95268ad52daff1aef1fe78e5764095c19221 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 16:49:00 -0400 Subject: [PATCH 09/11] feat: Add GUI examples and usage instructions to README, including a sample image --- README.md | 13 +++++++++++++ Samples/Sample-Gui.png | Bin 0 -> 440747 bytes 2 files changed, 13 insertions(+) create mode 100644 Samples/Sample-Gui.png diff --git a/README.md b/README.md index 6df76a2..80afbf6 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,19 @@ PS C:\> New-AsBuiltReport -Report Microsoft.AD -Target 'admin-dc-01v.contoso.loc PS C:\> New-AsBuiltReport -Report Microsoft.AD -Target 'admin-dc-01v.contoso.local' -Username 'administrator@contoso.local' -Password 'P@ssw0rd' -Format Html,Word -OutputFolderPath 'C:\Users\Jon\Documents' -SendEmail ``` +## :computer: GUI Examples + +The Microsoft AD As Built Report GUI can be used to generate reports without using the console. The GUI provides the same functionality as the console, but with a user-friendly interface. To launch the GUI, run the following command in a PowerShell terminal window: + +```powershell +# Launch the Microsoft AD As Built Report GUI +PS C:\> Start-AsBuiltReportMSAD +``` + +**Beta** versions of the GUI may contain bugs and issues. If you encounter any problems while using the GUI, please report them on the project's GitHub Issues page. + +![alt text](Samples/Sample-Gui.png) + ## :x: Known Issues - **PSWriteWord Module Conflict**: PScribo and the EvotecIT "PSWriteWord" project use conflicting cmdlets. The PSWriteWord module must be uninstalled before generating reports. - **WinRM Dependency**: This report relies heavily on remote connections via WinRM. A Windows 10 client is recommended as a jumpbox for optimal connectivity. diff --git a/Samples/Sample-Gui.png b/Samples/Sample-Gui.png new file mode 100644 index 0000000000000000000000000000000000000000..72b195e888b4b4394e94db454d2414cbfa93dd70 GIT binary patch literal 440747 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�>k-;#vQ5 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

=JVU9S|~UVcgQ(?y2DY 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⁢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

|dtaf(o-LyO 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

8-ZZcYl!H?B99dw8 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 Bc7FitKrEU(;d=(uXMG_V{8AhoZnlqr!R%G zhpYG3{GNO5nD?Lc?RmUMnXCx&k=jbNCQ)gz0C~9GO@pTcRgFE-%v)Lud%ccGYJ)YewZFudD|#QA5+%A4N{d)qT7G zS^F~gm=eMa`EL8kIePCc7T;WGHoNXS*;0P@l=CP?%-&mZwtkP|h{}zbi4db0(P~i9 zj+MvchV$~f9XDQl8T88$_;OQv5NnMiYi)}c7S`tRojQzE=E>U_q zDeJ_mP>M+MJS(rUy|$L^7Oi|x8ISf+X;}g5$L)SWu74+Eu`h4#?dzL*j!-dbC|BYw z;@h`x?sPh-Ktf)_MLa)dy-KXpC)_Wt3(I5-!^I8a5n`0^es`xI z-_>J;ET`c{?@>aw=}UwW;#o{@8g1#dAPf)UT8&HF;ZUZ7fnLSACS)oEd#l&bdNCQ} z-mu2?o_o5j;k{OA|5)jRXO#&`#Vhcu8{&So^IxlbTLmTe5E6Vwe)aPQcqYGk{R>ln z@GG-Y2>ioK@0lO~*h;rye(y6jPDiy8n{lM{!E6L$h8WnrIW+I^lOba2#wob0jm91S zJZ>tmS=(#whRvR|nj5rc!;aZG`lm)M^vn$79yNjDZEAC+%F5Jn(*;%BK8)xDmOQ@=1=Y?1KKoI731in421o3UN|`x&i|${hws_b z>K3H8f#${~Qzhm?kbL6b3l$FXWP%!1{mUBwI$a*amdNOPzjn2GgwSO&zQ|`0Ky>cy z5L|R0g1|)PutgvtqI4@@`sOW{-XI&!PtIi+-T5Mu?wN%)s!x(FQVdEW5XNoIg2g-u&oK zB22i*I`?LPHLoys?Sp0Bp0Ky@t^ZBUl+S8eXI);IK0wiKRML_J1#wA^5S}fK;l&mq zz1j_jc-6&xSlS{JMrb<2(j7J&hyn?10A#xtKBV5f5J%+c4FU;^CoVBzyUfaL%*-@) z$kHF474~Z?N3lUz(>z9<_bxuoQ3e_WU8%jA7K4WiOXgO$toeZ$&Xf z)@IDwqAXLb-wyGWEpBFp4W3SB35tzg)E4Ra+1M;Aui-d(`da$Rqlg6$#~>K=25J*9 z$ZNO^?jmI+jyWp%62?*!k;ZHsQH-G~;lyi`j~ha`akZncww8)>a?ea-LmV;5>q%zL zmWWW{=&TH7Da<~{vDKDwWOnL%Zc5C^-VEQ`XB{6+y?@B{RqaOca}{rvI6{rve; z1rkyYt$rM27#Nq%NK(&C{p-tx2p-(oFO@O)FvL^DW&G(bB9J(JSC0|8+(z`PB%fvJ zjNr{DTguN1BTP7CZMcaeytE-YovvstRk*Qm4bz_f8pQgR<+{Jt{vaEFsZ1@TE$*AI zM$!20L&--W_4K8Cy6Qq|=_Dp6p6YKNbE?-Z=iEuzWo_Yfi?u5$mbhOvebZpma5srV zV?N~L6U*!T;0o0-Y)$xPZP+BI^WJJY2Ak*3^a@$F&g0KgT)7_YcFMOA(;lupwoN%- zmY<;!ZuzsHONd`XS+C7kO!8t@ua@dmr92d3?^GU^uJUBhX*AiGqD>;b+l+d0 zKUj?>FAe9qg)^7x{En#MaBW=(!i>0hgHwIy_? zBk(-m7ngg8_nVvco*!3f*Q;f++IG)xik5nmGQifplixSDFMGK);PGMc`FYuG;V;zS zTa)p@*?WCH5tT8hzYQO^wfA=rN!(k&xz$rmYyYi`&yN4o8us=*8UMWeo8E`b!w-8k zlV^6sD`S6<_@eeidNZEN7;?7jEVyF-Y)+=SeJQPb+OFD=WFcLv`)78%c`)rcAu`sdk9Q{#*FwnV6t>pImMyQfyY26v6rG%yPkZgYbN+kI{{u|$diyw+0Ji`D002ov JPDHLkV1j^3M3w*m literal 0 HcmV?d00001 From 420f801f470df18bfdca2314e8ed194f608e1429 Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 16:52:14 -0400 Subject: [PATCH 10/11] refactor: Enhance GliderUI support description in CHANGELOG for clarity and user-friendliness Co-authored-by: Copilot --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae4c61c..217206f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add support for GliderUI to generate the report using a graphical interface instead of command line. The GUI will allow users to select the target domain, customize report options, and initiate the report generation process with a user-friendly experience. +- Add support for GliderUI graphical interface to generate reports via an intuitive user interface instead of command-line execution. The GUI enables users to select target domains, customize report options (InfoLevel, HealthChecks, diagram settings), and initiate report generation with a streamlined, user-friendly experience, reducing friction for non-technical stakeholders. ### :arrows_clockwise: Changed From a0f825e3c2ee327680c0f3803cc6bc10d0ca739e Mon Sep 17 00:00:00 2001 From: Jonathan Colon Date: Fri, 24 Apr 2026 16:52:44 -0400 Subject: [PATCH 11/11] fix: Update release date for version 1.0.0 in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 217206f..e2335f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ##### This project is community maintained and has no sponsorship from Microsoft, its employees or any of its affiliates. -## [1.0.0] - 2026-04-?? +## [1.0.0] - 2026-04-24 ### Added