Pws.psm1

#Region './_PrefixCode.ps1' 0
# Code in here will be prepended to top of the psm1-file.
# Set Module Registry Path
$Global:PwsRegistryPath = 'HKLM:\SOFTWARE\Partitio\Pws'

# In Powershell v6+ $IsMacOS, $IsLinux, $IsWindows are defined
# Since the module is for Windows, and powershell may be older,
# these variables wont be defined, so we cannot use $IsWindows as
# it would failed
if (!$IsMacOS -and !$IsLinux) {
    if ( !(Test-Path $Global:PwsRegistryPath)) {
        New-Item $Global:PwsRegistryPath -Force|Out-Null
    }
}
#EndRegion './_PrefixCode.ps1' 13
#Region './Classes/ADUser.ps1' 0
class ADUser
{

}
#EndRegion './Classes/ADUser.ps1' 4
#Region './Private/Compare-CertificateIssuer.ps1' 0
<#
    .SYNOPSIS
    Checks if the Certificate Issuer matches the CA Root Name.
    .PARAMETER Issuer
    The Certificate Issuer.
    .PARAMETER CARootName
    The CA Root Name to compare with the Certificate Issuer.
#>

function Compare-CertificateIssuer
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $Issuer,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $CARootName
    )

    return ((Get-CertificateCommonName -DistinguishedName $Issuer) -eq $CARootName)
}
#EndRegion './Private/Compare-CertificateIssuer.ps1' 27
#Region './Private/DscADCSConfiguration.ps1' 0
Configuration DscADCSConfiguration {
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DataPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $LogPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [System.Management.Automation.PSCredential]
        $Credential
    )

    Import-DscResource -Module ActiveDirectoryCSDsc

    Node localhost
    {
        WindowsFeature ADCS-Cert-Authority
        {
            Ensure = 'Present'
            Name   = 'ADCS-Cert-Authority'
        }

        WindowsFeature ADCS-Web-Enrollment
        {
            Ensure = 'Present'
            Name   = 'ADCS-Web-Enrollment'
        }

        AdcsCertificationAuthority CertificateAuthority
        {
            IsSingleInstance = 'Yes'
            Ensure           = 'Present'
            Credential       = $Credential
            CAType           = 'EnterpriseRootCA'

            ValidityPeriod      = "Years"
            ValidityPeriodUnits = 99
            DatabaseDirectory   = $DataPath
            LogDirectory        = $LogPath
            DependsOn           = '[WindowsFeature]ADCS-Cert-Authority'
        }

        AdcsWebEnrollment WebEnrollment
        {
            Ensure           = 'Present'
            IsSingleInstance = 'Yes'
            Credential       = $Credential
            DependsOn        = '[WindowsFeature]ADCS-Web-Enrollment'
        }
    }
}

#EndRegion './Private/DscADCSConfiguration.ps1' 59
#Region './Private/DscADDCConfiguration.ps1' 0
Configuration DscADDCConfiguration
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Domain,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DatabasePath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $LogPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $SysvolPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.PSCredential]
        $SafeModePassword
    )

    Import-DscResource -ModuleName PSDscResources
    Import-DscResource -ModuleName ActiveDirectoryDsc

    node 'localhost'
    {
        WindowsFeature 'ADDS'
        {
            Name = 'AD-Domain-Services'
            Ensure = 'Present'
        }

        WindowsFeature 'RSAT'
        {
            Name = 'RSAT-AD-PowerShell'
            Ensure = 'Present'
        }

        ADDomain $Domain
        {
            DomainName = $Domain
            Credential = $Credential
            SafemodeAdministratorPassword = $SafeModePassword
            ForestMode = 'WinThreshold'
            DatabasePath = $DatabasePath
            SysvolPath = $SysvolPath
            LogPath = $LogPath
        }
    }
}
#EndRegion './Private/DscADDCConfiguration.ps1' 64
#Region './Private/DscADStructureConfiguration.ps1' 0
Configuration DscADStructureConfiguration
{

    $RootPath = (Get-ADDomain).DistinguishedName
    $RootName = ((Get-Culture).TextInfo).ToTitleCase($env:userdomain.ToLower())
    $RootOU = "OU=$RootName,$RootPath"
    
    $OUs = @("Computers", "Servers", "Groups", "Users")

    Import-DscResource -Module ActiveDirectoryDsc

    Node localhost
    {
        # TODO : Wait For AD Domain
        # WaitForADDomain

        ADOrganizationalUnit RootOU
        {
            Name                            = $RootName
            Path                            = $RootPath
            Description                     = "$RootName root Organization Unit"
            Ensure                          = "Present"
        }

        WaitForAll RootOU
        {
            NodeName = "localhost"
            ResourceName = "[ADOrganizationalUnit]RootOU"
        }

        foreach ($OU in $OUs)
        {
            $ResourceName = $OU + "OU"
            ADOrganizationalUnit $ResourceName
            {
                Name                            = $OU
                Path                            = $RootOU
                Description                     = "Root Organization Unit for $OU"
                Ensure                          = "Present"
            }
        }

        ADGroup RDSUsersGroup
        {
            GroupName   = 'RDS-Users'
            GroupScope  = 'Universal'
            Category    = 'Security'
            Ensure      = 'Present'
        }
    }
}
#EndRegion './Private/DscADStructureConfiguration.ps1' 51
#Region './Private/DscComputerConfiguration.ps1' 0
Configuration DscComputerConfiguration
{

    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $ComputerName,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $IP,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Gateway,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DnsServer
    )

    Import-DscResource -Module ComputerManagementDsc
    Import-DscResource -Module NetworkingDsc
    Import-DscResource -Module PSDesiredStateConfiguration

    Node localhost
    {
        Computer RenameComputer
        {
            Name = $ComputerName
        }
        IPAddress IPv4Address
        {
            IPAddress = "$IP/24"
            InterfaceAlias = 'Ethernet0'
            AddressFamily = 'IPV4'
            KeepExistingAddress = $true
        }
        DefaultGatewayAddress DefaultGateway
        {
            Address = $Gateway
            InterfaceAlias = 'Ethernet0'
            AddressFamily = 'IPv4'
        }
        DnsServerAddress DnsServerAddress
        {
            Address = $DnsServer
            InterfaceAlias = 'Ethernet0'
            AddressFamily = 'IPv4'
            Validate = $true
        }
    }

}
#EndRegion './Private/DscComputerConfiguration.ps1' 59
#Region './Private/DscDomainController.ps1' 0
Configuration DscDomainController
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Domain,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $DomainControllerIP,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DatabasePath,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $LogPath,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $SysvolPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.PSCredential]
        $SafeModePassword
    )

    Import-DscResource -ModuleName PSDscResources
    Import-DscResource -ModuleName ActiveDirectoryDsc
    Import-DscResource -Module NetworkingDsc

    Node localhost
    {
        DnsServerAddress DnsServerAddress
        {
            Address = $DomainControllerIP
            InterfaceAlias = 'Ethernet0'
            AddressFamily = 'IPv4'
            Validate = $true
        }

        WindowsFeature 'InstallADDomainServicesFeature'
        {
            Ensure = 'Present'
            Name = 'AD-Domain-Services'
            DependsOn = '[DnsServerAddress]DnsServerAddress'
        }

        WindowsFeature 'RSATADPowerShell'
        {
            Ensure = 'Present'
            Name = 'RSAT-AD-PowerShell'
            DependsOn = '[WindowsFeature]InstallADDomainServicesFeature'
        }

        WaitForADDomain 'WaitForestAvailability'
        {
            DomainName = $Domain
            Credential = $Credential
            DependsOn = '[WindowsFeature]RSATADPowerShell'
        }

        ADDomainController 'DomainController'
        {
            DomainName = $Domain
            Credential = $Credential
            SafeModeAdministratorPassword = $SafeModePassword
            DatabasePath = $DatabasePath
            SysvolPath = $SysvolPath
            LogPath = $LogPath
            DependsOn = '[WaitForADDomain]WaitForestAvailability'
        }
    }
}
#EndRegion './Private/DscDomainController.ps1' 87
#Region './Private/DscDomainJoinConfiguration.ps1' 0
Configuration DscDomainJoinConfiguration
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $ComputerName,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $OrganizationUnit,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $DomainControllerIP,

        [Parameter(Mandatory = $false)]
        [String]
        $Description,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [System.Management.Automation.PSCredential]
        $Credential
    )

    $Domain = Get-DomainFromDN $OrganizationUnit

    Import-DscResource -Module NetworkingDsc
    Import-DscResource -Module ComputerManagementDsc
    Import-DscResource -Module PSDesiredStateConfiguration

    Node localhost
    {
        DnsServerAddress DnsServerAddress
        {
            Address = $DomainControllerIP, "8.8.8.8"
            InterfaceAlias = 'Ethernet0'
            AddressFamily = 'IPv4'
        }
        WaitForAll DnsServerAddress
        {
            NodeName = "localhost"
            ResourceName = "[DnsServerAddress]DnsServerAddress"
        }
        Computer JoinDomain
        {
            Name = $ComputerName
            JoinOU = $OrganizationUnit
            DomainName = $Domain
            Description = $Description
            Credential = $Credential
            DependsOn = "[WaitForAll]DnsServerAddress"
        }
    }
}
#EndRegion './Private/DscDomainJoinConfiguration.ps1' 59
#Region './Private/DscICMPConfiguration.ps1' 0
Configuration DscICMPConfiguration
{
    param
    (
        [Parameter(Mandatory = $false)]
        [Switch]
        $Disable
    )

    if ($Disable)
    {
        $Action = "Block"
    }
    else {
        $Action = "Allow"
    }

    Import-DSCResource -ModuleName NetworkingDsc

    Node localhost
    {
        Firewall EnableICMPv4
        {
            Name = 'ICMPv4'
            DisplayName = 'Allow inbound ICMPv4'
            Ensure = 'Present'
            Enabled = 'True'
            Action = $Action
            Profile = ('Domain', 'Private')
            Direction = 'Inbound'
            Protocol = 'ICMPv4'
            IcmpType = ('8')
        }
        Firewall EnableICMPv6
        {
            Name = 'ICMPv6'
            DisplayName = 'Allow inbound ICMPv6'
            Ensure = 'Present'
            Enabled = 'True'
            Action = $Action
            Profile = ('Domain', 'Private')
            Direction = 'Inbound'
            Protocol = 'ICMPv6'
            IcmpType = ('8')
        }
    }
}
#EndRegion './Private/DscICMPConfiguration.ps1' 47
#Region './Private/DscInitializeDataDisks.ps1' 0
Configuration DscInitializeDataDisks
{
    Import-DSCResource -ModuleName StorageDsc

    Node 'localhost'
    {
        $Count = 0
        $Letters = 67..90 | % { "$( [char]$_ ):" }|Where-Object { !(Test-Path $_) } | %{ $_[0] }
        if (!$Letters)
        {
            return
        }
        foreach ($Disk in (Get-Disk | Where-Object { $_.OperationalStatus -eq "Offline" }))
        {
            $DiskNumber = $Disk.Number
            $DiskName = "Disk" + $DiskNumber
            $Letter = $Letters[$Count]
            WaitForDisk $DiskName
            {
                DiskId = $Disk.Number
                RetryIntervalSec = 60
                RetryCount = 60
            }

            Disk $DiskName
            {
                DiskId = $Disk.Number
                DriveLetter = $Letter
                FSFormat = 'NTFS'
                FSLabel = "Data$DiskNumber"
                PartitionStyle = "MBR"
                DependsOn = "[WaitForDisk]$DiskName"
            }
            $Count++
        }
    }
}
#EndRegion './Private/DscInitializeDataDisks.ps1' 37
#Region './Private/DscMountSmbShareConfiguration.ps1' 0
Configuration DscMountSmbShareConfiguration
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DriveLetter,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $NetworkDriveRoot
    )

    Import-DscResource -ModuleName PSDesiredStateConfiguration
    Node localhost
    {
        Script MountSmbShare
        {
            GetScript = {
                @{
                    Result = (Get-PSDrive | Where-Object {
                        $_.Name -eq $using:DriveLetter -and $_.DisplayRoot -eq $using:NetworkDriveRoot
                    })
                }
            }
            SetScript = {
                if (Get-PSDrive | Where-Object { $_.Name -eq $using:DriveLetter})
                {
                    Write-Error "A Drive named $using:DriveLetter already exists"
                    exit 1
                }
                if (Get-PSDrive | Where-Object { $_.DisplayRoot -eq $using:NetworkDriveRoot})
                {
                    Write-Warning "A Drive with Root $using:NetworkDriveRoot already exists"
                }
                New-PSDrive -Name $using:DriveLetter -PSProvider FileSystem -Root $NetworkDriveRoot -Persist -Scope 'Global'
            }
            TestScript = {
                return (Get-PSDrive | Where-Object {
                    $_.Name -eq $using:DriveLetter -and $_.DisplayRoot -eq $using:NetworkDriveRoot
                }) -ne $null
            }
        }
    }
}
#EndRegion './Private/DscMountSmbShareConfiguration.ps1' 47
#Region './Private/DscRDSCertificateConfiguration.ps1' 0
Configuration DscRDSCertificateConfiguration
{
    param
    (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $GatewayAddress,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $CAServerFQDN,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [PSCredential]
        $Credential
    )
    Import-DscResource -ModuleName CertificateDsc
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    Import-Module RemoteDesktop

    $CARootName = Get-CARootName $CAServerFQDN
    $FQDN = [System.Net.Dns]::GetHostByName($env:computerName).Hostname
    Node localhost
    {
        CertReq RDSGatewayCert
        {
            CARootName = $CARootName
            CAServerFQDN = $CAServerFQDN
            Subject = $GatewayAddress
            AutoRenew = $true
            FriendlyName = 'SSL Cert for RDS Gateway'
            Credential = $Credential
        }
        CertReq RDSCert
        {
            CARootName = $CARootName
            CAServerFQDN = $CAServerFQDN
            Subject = $FQDN
            AutoRenew = $true
            FriendlyName = 'SSL Cert for RDS'
            Credential = $Credential
        }
        WaitForAll RDSGatewayCert
        {
            NodeName = 'localhost'
            ResourceName = '[CertReq]RDSGatewayCert'
            RetryIntervalSec = 15
            RetryCount = 50
        }

        WaitForAll RDSCert
        {
            NodeName = 'localhost'
            ResourceName = '[CertReq]RDSCert'
            RetryIntervalSec = 15
            RetryCount = 50
        }

        # TODO : Spit to parallelize certs registration
        Script InstallRDSCerts
        {
            GetScript = {
                return @{ Result = Get-RDCertificate }
            }
            SetScript = {
                $publicCert = Get-Childitem -Path Cert:\LocalMachine\My | Where-Object -FilterScript {
                    $_.Subject -eq "CN=$using:GatewayAddress" -and (Compare-CertificateIssuer -Issuer $_.Issuer -CARootName $using:CARootName)
                }
                if(!$publicCert)
                {
                    Write-Error "Cert for $($using:GatewayAddress) not found"
                    exit 1
                }
                Write-Verbose "Using Cert: $($GatewayAddress) $($publicCert.Thumbprint)"
                $localCert = Get-Childitem -Path Cert:\LocalMachine\My | Where-Object -FilterScript {
                    $_.Subject -eq "CN=$using:FQDN" -and (Compare-CertificateIssuer -Issuer $_.Issuer -CARootName $using:CARootName)
                }
                if(!$publicCert)
                {
                    Write-Error "Cert for $($using:FQDN) not found"
                    exit 1
                }
                Write-Verbose "Using Cert: $($using:FQDN) $($localCert.Thumbprint)"
                foreach ($s in Get-RDCertificate)
                {
                    Write-Verbose "$($s.Role) Status: $($s.Level)"
                    if($s.Level -ne "NotConfigured")
                    {
                        continue
                    }
                    if($s.Role -eq 'RDWebAccess' -or $s.Role -eq 'RDGateway')
                    {
                        $cert = $publicCert
                    }
                    else
                    {
                        $cert = $localCert
                    }
                    $RDCertParams = @{
                        Role = $s.Role
                        ConnectionBroker = $using:FQDN
                        Thumbprint = $cert.Thumbprint
                        Force = $true
                        ErrorAction = 'Stop'
                    }
                    try
                    {
                        Write-Verbose "Installing $($s.Role) Certificate"
                        Set-RDCertificate @RDCertParams
                    }
                    catch
                    {
                        Write-Error $_.Exception.Message
                    }
                }
            }
            TestScript = {
                try
                {
                    $res = $true
                    $certs = Get-RDCertificate
                    if (!$certs)
                    {
                        return $false
                    }
                    foreach ($s in $certs)
                    {
                        Write-Verbose "$($s.Role) Status: $($s.Level)"
                        if($s.Level -eq "NotConfigured")
                        {
                            $res = $false
                        }
                    }
                    return $res
                }
                catch
                {
                    Write-Error $_.Exception.Message
                    return $false
                }
            }
        }
    }
}
#EndRegion './Private/DscRDSCertificateConfiguration.ps1' 147
#Region './Private/DscRDSConfiguration.ps1' 0
Configuration DscRDSConfiguration
{

    param
    (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $GatewayAddress,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $UserGroup = 'RDS-Users',

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $CollectionName = 'RDS',

    # [Parameter(Mandatory = $true)]
    # [ValidateNotNullOrEmpty()]
    # [String]
    # $UserProfileDiskPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [PSCredential]
        $Credential

    )

    $FQDN = [System.Net.Dns]::GetHostByName($env:computerName).Hostname
    if ($Join)
    {
        $FQDN = $Join
    }
    if (!$Join -and !$GatewayAddress)
    {
        ThrowError "GatewayAddress is required when not joining a RDS Cluster"
    }
    $ConnectionBroker = $FQDN
    $SessionHost = $FQDN
    $WebAccessServer = $FQDN

    $AutomaticReconnectionEnabled = $true
    $DisconnectedSessionLimitMin = 180
    $IdleSessionLimitMin = 0
    $BrokenConnectionAction = 'Disconnect'

    $LicenseServer = $FQDN
    $LicenseMode = 'PerUser'

    Import-DscResource -ModuleName PSDesiredStateConfiguration
    Import-DscResource -ModuleName xRemoteDesktopSessionHost

    # TODO : Join A cluster
    # TODO : Gateway Certificate (https://github.com/PowerShell/xRemoteDesktopSessionHost/pull/67)
    Node localhost
    {
        WindowsFeature SessionHost
        {
            Name = 'RDS-RD-Server'
            Ensure = 'Present'
        }

        WindowsFeature WebAccess
        {
            Name = 'RDS-Web-Access'
            Ensure = 'Present'
        }

        WindowsFeature RDSConnectionBroker
        {
            Name = 'RDS-Connection-Broker'
            Ensure = 'Present'
        }

        WindowsFeature RDLicensing
        {
            Ensure = "Present"
            Name = "RDS-Licensing"
        }

        WaitForAll SessionHost
        {
            NodeName = 'localhost'
            ResourceName = '[WindowsFeature]SessionHost'
            RetryIntervalSec = 15
            RetryCount = 50
            DependsOn = '[WindowsFeature]RDLicensing'
        }

        WaitForAll WebAccess
        {
            NodeName = 'localhost'
            ResourceName = '[WindowsFeature]WebAccess'
            RetryIntervalSec = 15
            RetryCount = 50
            DependsOn = '[WaitForAll]SessionHost'
        }

        xRDSessionDeployment NewDeployment
        {
            ConnectionBroker = $ConnectionBroker
            SessionHost = $SessionHost
            WebAccessServer = $WebAccessServer
            DependsOn = '[WaitForAll]WebAccess'
            PsDscRunAsCredential = $Credential
        }

        # Should Reboot after xRDSessionDeployment

        xRDSessionCollection Collection
        {
            CollectionName = $CollectionName
            SessionHost = $SessionHost
            ConnectionBroker = $ConnectionBroker
            DependsOn = '[xRDSessionDeployment]NewDeployment'
            PsDscRunAsCredential = $Credential
        }

        xRDSessionCollectionConfiguration CollectionConfig
        {
            CollectionName = $CollectionName
            ConnectionBroker = $ConnectionBroker
            AutomaticReconnectionEnabled = $true
            DisconnectedSessionLimitMin = $DisconnectedSessionLimitMin
            IdleSessionLimitMin = $IdleSessionLimitMin
            BrokenConnectionAction = $BrokenConnectionAction
            # TODO : Specifies a domain group authorized to connect to the RD Session Host servers in a session collection
            # UserGroup = $UserGroup
            # TODO : Specifies the target path to store the User Profile Disks
            # DiskPath = $UserProfileDiskPath
            # TODO : Specifies if this collection uses UserProfileDisks
            # EnableUserProfileDisk = $true
            # TODO : Specifies whether to enable the Remote Desktop Easy Print driver
            # RDEasyPrintDriverEnabled =
            DependsOn = '[xRDSessionCollection]Collection'
            PsDscRunAsCredential = $Credential
        }

        xRDLicenseConfiguration LicenseConfig
        {
            ConnectionBroker = $ConnectionBroker
            LicenseServer = $LicenseServer
            LicenseMode = $LicenseMode
            DependsOn = '[xRDSessionCollectionConfiguration]CollectionConfig'
            PsDscRunAsCredential = $Credential
        }

        xRDGatewayConfiguration Gateway
        {
            ConnectionBroker = $ConnectionBroker
            GatewayServer = $FQDN
            ExternalFqdn = $GatewayAddress
            GatewayMode = "Custom"
            LogonMethod = "Password"
            UseCachedCredentials = $false
            BypassLocal = $true
        }
    }
}
#EndRegion './Private/DscRDSConfiguration.ps1' 163
#Region './Private/DscSmbShareConfiguration.ps1' 0
Configuration DscSmbShareConfiguration
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Name,
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Path,
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $FullAccessUser
    )
    Import-DscResource -ModuleName ComputerManagementDsc

    Node localhost
    {
        SmbShare "$( $Name )Share"
        {
            Name = $Name
            Path = $Path
            # TODO : Permissions
            FullAccess = @($FullAccessUser)
        }
    }
}
#EndRegion './Private/DscSmbShareConfiguration.ps1' 30
#Region './Private/DscSNMPConfiguration.ps1' 0
Configuration DscSNMPConfiguration
{
    param
    (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Community = "public",

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Manager = "Any"
    )

    Import-DscResource -ModuleName PSDesiredStateConfiguration
    Import-DscResource -ModuleName cSNMP
    Import-DSCResource -ModuleName NetworkingDsc

    Node localhost{

        WindowsFeature SNMPService
        {
            Name = "SNMP-Service"
            Ensure = "Present"
        }

        WindowsFeature SNMPWMI
        {
            Name = "SNMP-WMI-Provider"
            Ensure = "Present"
        }

        cSNMPCommunity Community {
            Community = $Community
            Right = "ReadOnly"
            Ensure = "Present"
        }

        cSNMPManager Manager
        {
            Manager = $Manager
            Ensure = "Present"
        }

        Firewall EnableBuiltInFirewallRule
        {
            Name                  = 'SNMP-In-UDP'
            Ensure                = 'Present'
            Enabled               = 'True'
            RemoteAddress         = @('Any')
        }
    }
}
#EndRegion './Private/DscSNMPConfiguration.ps1' 54
#Region './Private/DscWinRMConfiguration.ps1' 0
Configuration DscWinRMConfiguration
{
    Import-DscResource -Module xWinRM
    xWinRM WinRMHTTPS
    {
        Protocol = "HTTPS"
        Ensure = "Present"
        Service_AllowUnencrypted = 'false'
        RestartService = $true
    }
}
#EndRegion './Private/DscWinRMConfiguration.ps1' 11
#Region './Private/Find-DscConfiguration.ps1' 0
function Find-DscConfiguration
{
    param(
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $ConfigurationName
    )

    $confgs = Get-DscConfiguration
    foreach ($c in $configs) {
        if ($c.ConfigurationName -eq $ConfigurationName) {
            return $c
        }
    }
}
#EndRegion './Private/Find-DscConfiguration.ps1' 16
#Region './Private/Get-CARootName.ps1' 0
function Get-CARootName
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $CAServerFQDN
    )
    $CAServer = $CAServerFQDN.Substring(0, $CAServerFQDN.LastIndexOf('.'))
    $Parts = $CAServer.Split('.')
    [Array]::Reverse($Parts)
    $CARootName = ($Parts -join '-') + "-CA"
    return $CARootName
}
#EndRegion './Private/Get-CARootName.ps1' 15
#Region './Private/Get-CertificateCommonName.ps1' 0
function Get-CertificateCommonName
{
    <#
    .SYNOPSIS
    Finds the Common Name in a X500 Distinguished Name.
    .PARAMETER DistinguishedName
    The X500 Distinguished Name.
    #>


    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.String]
        $DistinguishedName
    )

    return ($DistinguishedName.split(',') |
            ForEach-Object -Process { $_.TrimStart(' ') } |
            Where-Object -FilterScript { $_ -match 'CN=' }).replace('CN=', '')
}
#EndRegion './Private/Get-CertificateCommonName.ps1' 23
#Region './Private/Get-DomainFromDN.ps1' 0
function Get-DomainFromDN
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DN
    )

    return $DN -replace '^.*?,dc=' -replace ',dc=', '.'
}
#EndRegion './Private/Get-DomainFromDN.ps1' 12
#Region './Private/Get-DomainNameFromDN.ps1' 0
function Get-DomainNameFromDN
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DN
    )

    $domain = $DN -replace '^.*?,dc=' -replace ',dc=', '.'
    $parts = $domain.Split('.')
    return $parts[$parts.Length - 2]
}
#EndRegion './Private/Get-DomainNameFromDN.ps1' 14
#Region './Private/Get-RDServerWithRetry.ps1' 0
function Get-RDServerWithRetry
{
    param
    (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [Int16]
        $Count
    )
    $s
    try
    {
        Import-Module RemoteDesktop
        $s = Get-RDServer
    }
    catch
    {
        Write-Error "Failed to get RDServer"
        $Count -= 1
        if ($Count -gt 0)
        {
            Write-Host "Remaining attempts: " $Count
            Get-RDServerWithRetry $Count
        }
        else
        {
            throw $_
        }
    }
    return $s
}
#EndRegion './Private/Get-RDServerWithRetry.ps1' 31
#Region './Public/Backup-AD.ps1' 0
function Backup-AD
{
    <#

    .SYNOPSIS
    Backup Active Directory Objects

    .DESCRIPTION
    Backup Active Directory Objects

    .ROLE
    Administrators

    #>

    param(
        [Parameter(Mandatory = $true)]
        [String]
        $BackupPath
    )
    
    #Backup all Distinguished Name of Objects in the Root Domain.START
    $DNFolderDelPath = "$BackupPath\*"
    Test-Path -Path $BackupPath -PathType Container
    if (-Not(Test-Path $BackupPath))
    {
        New-Item -Path $BackupPath -ItemType Directory
    }

    $DNFileName = "ADBackup_$( get-date -Uformat "%Y%m%d-%H%M%S" ).txt"
    $DNFilePath = "$BackupPath\$DNFileName"
    $DNList_command = "dsquery * domainroot -scope subtree -attr modifytimestamp distinguishedname -limit 0 > $DNFilePath"
    Invoke-expression $DNList_command
    Get-ChildItem $DNFolderDelPath | Where-Object { $_.Lastwritetime -lt (date).adddays(-10) } | Remove-Item -force -recurse -Confirm:$false
    
}
#EndRegion './Public/Backup-AD.ps1' 35
#Region './Public/Backup-ADDC.ps1' 0
function Backup-ADDC
{
    <#

    .SYNOPSIS
    Backup Active Directory Domain Controller

    .DESCRIPTION
    Backup Active Directory Domain Controller

    .ROLE
    Administrators

    #>

    param(
        [Parameter(Mandatory = $true)]
        [String]
        $BackupPath
    )
    if (!(Test-Path $BackupPath))
    {
        New-Item -ItemType Directory $BackupPath
    }

    Backup-Gpo "$BackupPath\GPO"
    Backup-AD "$BackupPath\AD"
    Backup-Dns "$BackupPath\DNS"
}
#EndRegion './Public/Backup-ADDC.ps1' 28
#Region './Public/Backup-Dns.ps1' 0
#*********************************************************************************************
# BareMetalADDisasterBackupScript.ps1
# Version 1.0
# Date: 8/03/2013
# Author: Cengiz KUSKAYA (www.Kuskaya.Info)
# Description: A PowerShell script to make a full server backup of a Domain Controller,
# all group policies, all group policy links,
# all Distinguished Name of objects and AD integrated DNS.
#*********************************************************************************************
# Requirements:
# Create a folder named “C:\Script” prior executing the Script and a BATCH file
# named C:\Script\DNSBackup.bat . Copy and paste the following commands
# into the BATCH file.
# dnscmd /enumzones > C:\Script\AllZones.txt
# for /f %%a in (C:\Script\AllZones.txt) do dnscmd /ZoneExport %%a Export\%%a.dns
#*********************************************************************************************

function Backup-Dns
{
    <#

    .SYNOPSIS
    Backup Active Directory DNS

    .DESCRIPTION
    Backup Active Directory DNS

    .ROLE
    Administrators

    #>

    param(
        [Parameter(Mandatory = $true)]
        [String]
        $BackupPath
    )

    $tmp = "C:\Windows\Temp"
    $BatScript = "$tmp\DNSBacckup.bat"
    Set-Content $BatScript -Value "
dnscmd /enumzones > $tmp\AllZones.txt
for /f %%a in ($tmp\AllZones.txt) do dnscmd /ZoneExport %%a Export\%%a.dns
    "


    $DNSDestFolderPath = "$BackupPath\$Computer-$date"
    $DNSOldLogDelPath = "$BackupPath\*"
    $DNSExportFolderPath = "$tmp\DNSExport"
    Test-Path -Path $BackupPath -PathType Container
    if (-Not(Test-Path $BackupPath))
    {
        New-Item -Path $BackupPath -ItemType Directory
    }

    Test-Path -Path $DNSExportFolderPath -PathType Container
    if (-Not(Test-Path $DNSExportFolderPath))
    {
        New-Item -Path $DNSExportFolderPath -ItemType Directory
    }

    $BatScript
    New-Item -Path $DNSDestFolderPath -ItemType Directory
    Copy-Item "$DNSExportFolderPath\*" $DNSDestFolderPath
    Get-ChildItem $DNSOldLogDelPath | Where-Object { $_.Lastwritetime -lt (date).adddays(-5) } | Remove-Item -force -recurse -Confirm:$false
}
#EndRegion './Public/Backup-Dns.ps1' 64
#Region './Public/Backup-Gpo.ps1' 0
function Backup-GPO
{
    <#

    .SYNOPSIS
    Backup Active Directory GPO

    .DESCRIPTION
    Backup Active Directory GPO

    .ROLE
    Administrators

    #>

    param(
        [Parameter(Mandatory = $true)]
        [String]
        $BackupPath
    )

    Import-Module ActiveDirectory
    Import-Module GroupPolicy

    $Computer = Get-Content env:COMPUTERNAME
    $date = Get-Date -format H.m.d.M.yyyy
    $GPOPath = "$BackupPath\GPObjects"
    $DestGPO = "$GPOPath\$Computer-$date"
    $DestDelGPO = "$GPOPath\*"
    Test-Path -Path $GPOPath -PathType Container
    if ( -Not (Test-Path $GPOPath))
    {
        New-Item -Path $GPOPath -ItemType Directory
    }

    New-Item -Path $DestGPO -ItemType Directory
    Get-GPO -all | Backup-GPO -path $DestGPO
    Get-ChildItem $DestDelGPO | Where-Object {$_.Lastwritetime -lt (date).adddays(-2)} | Remove-Item -force -recurse -Confirm:$false

    $GPLinkPath = "$BackupPath\GPLink"
    $DestGPLinkPath = "$GPLinkPath\$Computer-$date"
    $DestGPLinkDelPath = "$GPLinkPath\*"
    Test-Path -Path $GPLinkPath -PathType Container
    if ( -Not (Test-Path $GPLinkPath))
    {
        New-Item -Path $GPLinkPath -ItemType Directory
    }

    New-Item -Path $DestGPLinkPath -ItemType Directory
    Get-ADOrganizationalUnit -Filter 'Name -like "*"' |
            foreach-object {(Get-GPInheritance -Target $_.DistinguishedName).GpoLinks} |
            export-csv $DestGPLinkPath\GPLinkBackup.csv -notypeinformation -delimiter ';'
    Get-ChildItem $DestGPLinkDelPath | Where-Object {$_.Lastwritetime -lt (date).adddays(-5)} | Remove-Item -force -recurse -Confirm:$false

}
#EndRegion './Public/Backup-Gpo.ps1' 54
#Region './Public/Disable-Firewall.ps1' 0
function Disable-Firewall
{
    Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
}
#EndRegion './Public/Disable-Firewall.ps1' 4
#Region './Public/Disable-Ping.ps1' 0
function Disable-Ping
{
    $tmp = "C:\Windows\Temp"
    DscICMPConfiguration -Disable -OutputPath $tmp | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Disable-Ping.ps1' 6
#Region './Public/Enable-Firewall.ps1' 0
function Enable-Firewall
{
    Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
}
#EndRegion './Public/Enable-Firewall.ps1' 4
#Region './Public/Enable-Ping.ps1' 0
function Enable-Ping
{
    $tmp = "C:\Windows\Temp"
    DscICMPConfiguration -OutputPath $tmp | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Enable-Ping.ps1' 6
#Region './Public/Enable-WinRM.ps1' 0
function Enable-WinRM
{
    $tmp = "C:\Windows\Temp"
    DscWinRMConfiguration -OutputPath $tmp | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Enable-WinRM.ps1' 6
#Region './Public/Get-ADDitReport.ps1' 0
Function Get-DitReport
{
    <#

    .SYNOPSIS
    Scans the registry for NTDS parameters. Very useful in confirm NTDS changes

    .DESCRIPTION
    Scans the registry for NTDS parameters. Very useful in confirm NTDS changes
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File")
    $DITSize = (get-item -Path $NTDSDIT).Length
    $DitStats = Get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters"
    $DitStats
    Write-Host " Present NTDS DB Size : $DitSize"
}
#EndRegion './Public/Get-ADDitReport.ps1' 21
#Region './Public/Initialize-DataDisks.ps1' 0
function Initialize-DataDisks {
    <#

    .SYNOPSIS
    Initialize-DataDisks use Storage Dsc to ensure data disks are initializes

    .DESCRIPTION
    Initialize-DataDisks use Storage Dsc to ensure data disks are initializes

    .ROLE
    Administrators

    #>

    $tmp = "C:\Windows\Temp"
    DscInitializeDataDisks -OutputPath $tmp | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}

#EndRegion './Public/Initialize-DataDisks.ps1' 18
#Region './Public/Install-ADCS.ps1' 0
function Install-ADCS
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DataPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Username,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password
    )

    $CertsPath = "$DataPath\CERTS"
    $CertsLogPath = "$DataPath\LOGS"

    if (!(Test-Path $DataPath))
    {
        try
        {
            New-Item -Type Directory -Force $DataPath | Out-Null
        }
        catch
        {
            throw $_
        }
    }
    New-Item -Type Directory -Force $CertsPath | Out-Null
    New-Item -Type Directory -Force $CertsLogPath | Out-Null
    $cd = @{
        AllNodes = @(
        @{
            NodeName = 'localhost'
            PSDscAllowPlainTextPassword = $true
        }
        )
    }
    $tmp = "C:\Windows\Temp"
    $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))

    $Params = @{
        DataPath = $CertsPath
        LogPath = $CertsLogPath
        OutputPath = $tmp
        Credential = $Credential
        ConfigurationData = $cd
    }
    # Use DscADCS to install Active Directory CA Services
    DscADCSConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Install-ADCS.ps1' 58
#Region './Public/Install-ADDC.ps1' 0
function Install-ADDC
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Domain,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DataPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Username,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $SafeModePassword
    )
    $DatabasePath = "$DataPath\NTDS"
    $ADSysvolPath = "$DataPath\SYSVOL"
    $ADLogPath = "$DataPath\LOGS"

    if (!(Test-Path $DataPath))
    {
        try
        {
            New-Item -Type Directory -Force $DataPath | Out-Null
        }
        catch
        {
            throw $_
        }
    }
    New-Item -Type Directory -Force $DatabasePath | Out-Null
    New-Item -Type Directory -Force $ADSysvolPath | Out-Null
    New-Item -Type Directory -Force $ADLogPath | Out-Null

    $cd = @{
        AllNodes = @(
        @{
            NodeName = 'localhost'
            PSDscAllowPlainTextPassword = $true
        }
        )
    }
    # Use DscADDC to install new AD Forest
    $tmp = "C:\Windows\Temp"
    $smp = New-Object System.Management.Automation.PSCredential('(Password Only)', (ConvertTo-SecureString $SafeModePassword -AsPlainText -Force))
    $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))

    $Params = @{
        Domain = $Domain
        DatabasePath = $DatabasePath
        LogPath = $ADLogPath
        SysvolPath = $ADSysvolPath
        SafeModePassword = $smp
        Credential = $Credential
        OutputPath = $tmp
        ConfigurationData = $cd
    }
    DscADDCConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Install-ADDC.ps1' 74
#Region './Public/Install-RDS.ps1' 0
function Install-RDS
{
    param (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $GatewayAddress,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $UserGroup = 'RDS_Users',

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $CollectionName = 'RDS',

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Username,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password
    )

    $tmp = "C:\Windows\Temp"

    $cd = @{
        AllNodes = @(
        @{
            NodeName = 'localhost'
            PSDscAllowPlainTextPassword = $true
            ActionAfterReboot  = 'StopConfiguration'
        }
        )
    }
    $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))

    $Params = @{
        Credential = $Credential
        GatewayAddress = $GatewayAddress
        UserGroup = $UserGroup
        CollectionName = $CollectionName
        OutputPath = $tmp
        ConfigurationData = $cd
    }
    DscRDSConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose

}
#EndRegion './Public/Install-RDS.ps1' 54
#Region './Public/Install-RDSCertificates.ps1' 0
function Install-RDSCertificates
{
    param
    (

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $CAServerFQDN,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $GatewayAddress,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Username,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password
    )

    $tmp = "C:\Windows\Temp"

    $cd = @{
        AllNodes = @(
        @{
            NodeName = 'localhost'
            PSDscAllowPlainTextPassword = $true
            ActionAfterReboot = 'StopConfiguration'
        }
        )
    }
    $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))

    $Params = @{
        Credential = $Credential
        GatewayAddress = $GatewayAddress
        CAServerFQDN = $CAServerFQDN
        OutputPath = $tmp
        ConfigurationData = $cd
    }

    DscRDSCertificateConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Install-RDSCertificates.ps1' 50
#Region './Public/Install-SNMP.ps1' 0
function Install-SNMP
{
    param
    (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Community = "public",

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Manager = "Any"
    )
    $tmp = "C:\Windows\Temp"
    DscSNMPConfiguration -Community $Community -Manager $Manager -OutputPath $tmp | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Install-SNMP.ps1' 18
#Region './Public/Join-Domain.ps1' 0
function Join-Domain
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $ComputerName,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $OrganizationUnit,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $DomainControllerIP,

        [Parameter(Mandatory = $false)]
        [String]
        $Description,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $Username,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $Password
    )

    $cd = @{
        AllNodes = @(
        @{
            NodeName = 'localhost'
            PSDscAllowPlainTextPassword = $true
        }
        )
    }
    $tmp = "C:\Windows\Temp"
    $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))
    $Params = @{
        ComputerName = $ComputerName
        OrganizationUnit = $OrganizationUnit
        DomainControllerIP = $DomainControllerIP
        Description = $Description
        Credential = $Credential
        ConfigurationData = $cd
        OutputPath = $tmp
    }
    DscDomainJoinConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Join-Domain.ps1' 56
#Region './Public/Mount-SmbShare.ps1' 0
function Mount-SmbShare
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DriveLetter,
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $NetworkDriveRoot
    )

    $tmp = "C:\Windows\Temp"
    $Params = @{
        DriveLetter = $DriveLetter
        NetworkDriveRoot = $NetworkDriveRoot
        OutputPath = $tmp
    }

    DscMountSmbShareConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/Mount-SmbShare.ps1' 24
#Region './Public/Move-ADDit.ps1' 0
Function Move-ADDIT
{

    <#

    .SYNOPSIS
    Move NTDS.DIT and make DS-related registry changes

    .DESCRIPTION
    Move NTDS.DIT and make DS-related registry changes
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    param(
    # target path for new NTDS location. EX: D:\Windows\NTDS"
        [Parameter(Mandatory = $true)]
        [String]
        $NewPath
    )

    if ($NewPath -eq "")
    {
        Write-Host "Target Path unspecified. Cannot continue..." -ForegroundColor Red
        Break
    }

    # Extract Target's drive letter from given path
    $Newdrive = $NewPath.substring(0, 2)

    # Get the target drive's free space
    $freespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$newdrive'").freespace

    # Get the target drive's file format
    $FS = (Get-WmiObject -Class Win32_volume -Filter "DriveLetter = '$newdrive'").FileSystem
    $NewDit = $NewPath + "\ntds.dit"
    $NewDitBak = $NewPath + "\dsadata.bak"

    #Extract NTDS parameters from registry
    $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File")
    $NTDSPath = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Working Directory")
    $DITSize = (get-item -Path $NTDSDIT).Length

    #Check target disk free space
    If ($DITSize -le $Freespace)
    {
        Write-Host "Available Free space on $NewPath = $Freespace - Good" -foregroundColor Green
    }
    Else
    {
        Write-Host "Not enough free space on $NewPath = $Freespace " -foregroundColor Red
        Break
    }

    #Check target disk format
    If ($FS -notmatch "NTFS")
    {
        Write-Host "Cannot continue NTDS database move. $newDrive is not a NTFS formatted drive." -foregroundColor Red
        Break
    }

    #Check for older NTDS.DIT file
    If ((get-childitem -Path $NewPath -Recurse -Filter "NTDS.DIT").Exists -eq "True")
    {
        Write-Host "Cannot continue. Old NTDS.DIT file exists in $NewPath ."
        Break
    }

    Write-Host "Moving NTDS database from $NTDSpath to $NewPath"

    #Set DS registry keys to reflect new path
    set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "DSA Database File" -value $NewDit
    set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "DSA Working Directory" -value $NewPath
    set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "Database backup path" -value $NewDitBak

    #Move the NTDS.Dit file
    Move-Item $NTDSDIT $NewPath

    If ($NewNTDSPath + "\NTDS.DIT")
    {
        Write-Host "NTDS.DIT file sucessfully moved to $NewPath" -ForegroundColor Green
        Test-ADDit

        Write-Host "NTDS database operation sucessfully completed!!!" -ForegroundColor Green
        Write-Host ""
    }
}
#EndRegion './Public/Move-ADDit.ps1' 89
#Region './Public/Move-ADLogs.ps1' 0
Function Move-ADLogs
{
    <#

    .SYNOPSIS
    Move EDB.Log and make DS-related registry changes

    .DESCRIPTION
    Move EDB.Log and make DS-related registry changes
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    param(
    # Target path for new EDB Log location. EX: D:\Windows\NTDS
        [Parameter(Mandatory = $true)]
        [String]
        $NewPath
    )
    if ($NewPath -eq "")
    {
        Write-Host "Target Path unspecified. Cannot continue..." -ForegroundColor Red
        Break
    }

    #Variables

    #Extract the Target drive letter from the given path
    $NewLogdrive = $NewPath.substring(0, 2)

    # Get the target drive's free space
    $NewLogfreespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$newlogdrive'").freespace

    #Extract NTDS parameters from registry
    $DitLogPath = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("Database log files path")
    $Log = $DitLogPath + "\EDB.Log"
    $LogSize = (get-item -Path $Log).Length

    # Get the target drive's file format
    $LogFS = (Get-WmiObject -Class Win32_volume -Filter "DriveLetter = '$newlogdrive'").FileSystem

    # Check target disk free space
    If ($LOGSize -le $NewLogfreespace)
    {
        Write-Host "Available Free space on $NewNTDS_Path = $NewLogfreespace - Good" -foregroundColor Green
    }
    Else
    {
        Write-Host "Not enough free space on $NewPath = $NewLogfreespace " -foregroundColor Red
        Start-Service NTDS -Confirm
        Break
    }

    # Check the target drive's file format
    If ($LogFS -ne "NTFS")
    {
        Write-Host "Cannot continue EDB Log move. $newlogDrive is not a NTFS formatted drive." -foregroundColor Red
        Start-Service NTDS -Confirm
        Break
    }

    # Check the target path for old EDB.Logs
    If ((get-childitem -Path $NewPath -Recurse -Filter "EDB.Log").Exists -eq "True")
    {
        Write-Host "Cannot continue. EDB Logs already exists."
        Break
    }

    Write-Host "Moving EDB Logs from $DitLogPath to $NewPath"
    set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "Database log files path" -value $NewPath
    Move-Item $Log $NewPath
    Get-ChildItem -Path C:\ntds -Filter "*EDB*" |Remove-item
    Write-Host ""
    If ((get-childitem -Path $NewPath -Recurse -Filter "EDB.LOG").Exists -eq "True")
    {
        Write-Host "EDB Log move operation sucessfully completed!!!" -ForegroundColor Green
        Write-Host ""
    }
}
#EndRegion './Public/Move-ADLogs.ps1' 81
#Region './Public/Move-DnsData.ps1' 0
function Move-DnsData
{
    <#
    .SYNOPSIS
    Move DNS Data location

    .DESCRIPTION
    Move DNS Data location

    .ROLE
    Administrators
    #>

    param(
    # Where to move data
        [Parameter(Mandatory = $true)]
        [String]
        $NewLocation
    )
    $RegPath = 'HKLM:\System\CurrentControlSet\Services\DNS\Parameters'
    $RegKey = 'DatabaseDirectory'
    $Location
    $DefaultLocation = "C:\Windows\System32\DNS"
    $LocationItem = Get-ItemProperty -Path $RegPath -Name $RegKey -ErrorAction 'SilentlyContinue'
    if (!$LocationItem -or !$LocationItem.DatabaseDirectory)
    {
        $Location = $DefaultLocation
    }
    else
    {
        $Location = $LocationItem.DatabaseDirectory
    }
    if (!(Test-Path $Location))
    {
        return @{
            Code = 1;
            Message = "DNS Data directory not found"
        }
    }

    try
    {
        if (!(Test-Path $NewLocation))
        {
            New-Item -ItemType Directory -Force $NewLocation
        }
        if ($Location -eq (Resolve-Path $NewLocation).Path)
        {
            return @{
                Code = 0;
                Message = "Dns data already at $Location"
            }
        }
        Write-Host "Copying C:\Windows\System32\dns to $NewLocation"
        Copy-Item -Recurse -Force "$Location\*" $NewLocation
        Write-Host "Setting DNS Data location in registry"
        Set-ItemProperty -Path $RegPath -Name $RegKey -Value $NewLocation
    }
    catch
    {
        return @{
            Code = 1;
            Message = $_.Exception
        }
    }
}
#EndRegion './Public/Move-DnsData.ps1' 65
#Region './Public/New-AD.ps1' 0
function New-AD
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Domain,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DataPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $SafeModePassword
    )

    $ErrorActionPreference = 'Stop'

    $Username = "Administrator"

    $ADDataPath = "$DataPath\AD"

    $ADDCParams = @{
        Domain = $Domain
        DataPath = $ADDataPath
        Username = $Username
        Password = $Password
        SafeModePassword = $SafeModePassword
    }

    Install-ADDC @ADDCParams

    $ADCSDataPath = "$DataPath\ADCS"
    Install-ADCS -DataPath $ADCSDataPath -Username $Username -Password $Password

    $DnsDataPath = "$DataPath\DNS"
    Move-DnsData -NewLocation $DnsDataPath
}
#EndRegion './Public/New-AD.ps1' 47
#Region './Public/New-ADIfmSnapshot.ps1' 0
Function New-ADIfmSnapshot
{
    <#

    .SYNOPSIS
    Performs IFM (AD Snapshot) using NTDSUTIL

    .DESCRIPTION
    Performs IFM (AD Snapshot) using NTDSUTIL
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    param(
    # A secured Target path for IFM files
        [Parameter(Mandatory = $true)]
        [String]
        $IfmPath
    )
    if ($IfmPath -eq "")
    {
        Write-Host "Target Path unspecified. Cannot continue..." -ForegroundColor Red
        Break
    }

    $IFMdrive = $IfmPath.substring(0, 2)
    $IFMfreespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$IFMdrive'").freespace
    $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File")
    $NTDSPath = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Working Directory")
    $DITSize = (get-item -Path $NTDSDIT).Length

    If ($DITSize -le $IFMFreespace)
    {
        Write-Host "Available Free space on $IfmPath = $IFMfreespace - Good" -foregroundColor Green
    }
    Else
    {
        Write-Host "Not enough free space on $IfmPath = $IFMFreespace " -foregroundColor Red
        Break
    }

    If ((get-childitem -Path $IfmPath -Recurse -Filter "*.dit").Exists -eq "True")
    {
        Write-Host "AD Snapshot file already exists in $IfmPath. Cannot continue operation" -ForegroundColor Red
        Break
    }

    # Check for running AD service. IF AD services are stopped, service will be started
    $DSSRV = (Get-Service NTDS).Status
    IF ($DSSRV -ne "Running")
    {
        Start-Service NTDS -Confirm
    }

    Write-Host "Creating Full IFM File package in $IfmPath ..."
    Write-Host ""
    Write-Host "____________________________________________________________" -ForegroundColor Blue
    $IFMCMD = ntdsutil "activate instance NTDS" IFM "Create Full $IfmPath" quit quit
    $IFMCMD
    $IFMFS = get-childitem -Path $IfmPath -Recurse -Verbose
    foreach ($IFMF in $IFMFS)
    {
        $IFMTS = $IFMF.length + $IFMF.length
    }
    Write-Host ""
    Write-Host "Total size for IFM is $IFMTS"
    Write-Host ""
}
#EndRegion './Public/New-ADIfmSnapshot.ps1' 70
#Region './Public/New-ADOfflineDefrag.ps1' 0
Function New-ADOfflineDefrag
{
    <#

    .SYNOPSIS
    Performs AD Offline Deframentation using NTDSUtil

    .DESCRIPTION
    Performs AD Offline Deframentation using NTDSUtil
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    param(
    # Temp path for NTDS.Dit file defragmentation process Default= C:\Temp
        [Parameter(Mandatory = $false)]
        [String]
        $TempPath
    )
    if ($TempPath -eq "")
    {
        $TempPath = "C:\temp"
    }

    #Varibles

    $Tempdrive = $TempPath.substring(0, 2)
    $Tempfreespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$Tempdrive'").freespace
    $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File")
    $DITSize = (get-item -Path $NTDSDIT).Length


    If ($DITSize -ge $Tempfreespace)
    {
        Write-Host "Not Enough Disk Space on $TempPath for defragmentation process. Cannot continue.." -ForegroundColor Red
        Break
    }

    IF ((get-childitem -Path $TempPath -Recurse -Filter "*.dit").Exists -eq "True")
    {
        Write-Host "NTDS.DIT already exists - please remove first" -ForegroundColor Red
        Break
    }

    Write-Host ""
    Write-Host "Compacting NTDS database..."
    Write-Host ""
    Write-Host "____________________________________________________________" -ForegroundColor Blue

    # Compile NTDSUTIL required commands in series
    $NTDSdbCompactor = ntdsutil "activate instance ntds" "files" "Compact to $TempPath" "q" "q"

    #Execute compiled NTDSUTIL commands
    $NTDSdbCompactor

    $NewDit = $TempPath + "\ntds.dit"
    Write-Host ""

    # Move newly compacted NTDS.DIT to the working DSA directory
    Move-Item $NewDit $NTDSPath

    # Clear the DSA Database Epoch key to indicate backup. Note: Future DS operations will error if this parameter isn't cleared
    Remove-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters"  -name "DSA Database Epoch" -ErrorAction SilentlyContinue

    # Delete all logs for DB consistency
    Remove-item $DitLogPath\*.log
    Write-Host ""
    Write-Host "NTDS Defragmentation Completed" -ForegroundColor Green
    Write-Host ""
}
#EndRegion './Public/New-ADOfflineDefrag.ps1' 72
#Region './Public/New-ADStructure.ps1' 0
function New-ADStructure
{
    $tmp = "C:\Windows\Temp"
    DscADStructureConfiguration -OutputPath $tmp | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/New-ADStructure.ps1' 6
#Region './Public/New-ComputerConfiguration.ps1' 0
function New-ComputerConfiguration
{

    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $ComputerName,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $IP,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Gateway,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DnsServer,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password
    )

    $tmp = "C:\Windows\Temp"
    $Params = @{
        ComputerName = $ComputerName
        IP = $IP
        Gateway = $Gateway
        DnsServer = $DnsServer
        OutputPath = $tmp
    }

    DscComputerConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose

    if($Password)
    {
        Get-LocalUser -Name "Administrator" | Set-LocalUser -Password (New-SecureString $Password)
    }
}
#EndRegion './Public/New-ComputerConfiguration.ps1' 48
#Region './Public/New-DomainController.ps1' 0
function New-DomainController
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Domain,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [String]
        $DomainControllerIP,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $DataPath,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Username,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Password,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $SafeModePassword
    )
    $DatabasePath = "$DataPath\NTDS"
    $ADSysvolPath = "$DataPath\SYSVOL"
    $ADLogPath = "$DataPath\LOGS"

    if (!(Test-Path $DataPath))
    {
        try
        {
            New-Item -Type Directory -Force $DataPath | Out-Null
        }
        catch
        {
            throw $_
        }
    }
    New-Item -Type Directory -Force $DatabasePath | Out-Null
    New-Item -Type Directory -Force $ADSysvolPath | Out-Null
    New-Item -Type Directory -Force $ADLogPath | Out-Null

    $cd = @{
        AllNodes = @(
        @{
            NodeName = 'localhost'
            PSDscAllowPlainTextPassword = $true
        }
        )
    }
    # Use DscADDC to install new AD Forest
    $tmp = "C:\Windows\Temp"
    $smp = New-Object System.Management.Automation.PSCredential('(Password Only)', (ConvertTo-SecureString $SafeModePassword -AsPlainText -Force))
    $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))

    $Params = @{
        Domain = $Domain
        DomainControllerIP = $DomainControllerIP
        DatabasePath = $DatabasePath
        LogPath = $ADLogPath
        SysvolPath = $ADSysvolPath
        SafeModePassword = $smp
        Credential = $Credential
        OutputPath = $tmp
        ConfigurationData = $cd
    }
    DscDomainController @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/New-DomainController.ps1' 80
#Region './Public/New-SecureString.ps1' 0
function New-SecureString
{
    <#

    .SYNOPSIS
    Convert given string as secure string

    .DESCRIPTION
    Convert given string as secure string

    .ROLE
    Administrators

    #>

    param(
    # String to secure
        [Parameter(Mandatory = $true)]
        [String]
        $String
    )
    return ConvertTo-SecureString $String -AsPlainText -Force
}
#EndRegion './Public/New-SecureString.ps1' 22
#Region './Public/New-SmbShare.ps1' 0
function New-SmbShare
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Name,
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Path,
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $FullAccessUser = $env:USER
    )
    $tmp = "C:\Windows\Temp"
    $Params = @{
        Name = $Name
        Path = $Path
        FullAccessUser = $FullAccessUser
        OutputPath = $tmp
    }

    DscSmbShareConfiguration @Params | Out-Null
    Start-DscConfiguration -Wait -Force -Path $tmp -Verbose
}
#EndRegion './Public/New-SmbShare.ps1' 28
#Region './Public/Register-AsLibreNMSDevice.ps1' 0
function Register-AsLibreNMSDevice
{
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $BaseUrl,
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Token,
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Community = "public",
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [String]
        $SNMPVersion = "v2c"
    )
    $url = $BaseUrl.TrimEnd("/") + "/api/v0/devices"
    $hostname = [System.Net.Dns]::GetHostByName($env:computerName).Hostname
    $headers = @{
        "X-Auth-Token" = $Token
    }
    $body = @{
        hostname = $hostname
        version = $SNMPVersion
        community = $Community
    } | ConvertTo-Json

    Invoke-WebRequest -Method Post -Headers $headers -Uri $url -Body $body -UseBasicParsing
}
#EndRegion './Public/Register-AsLibreNMSDevice.ps1' 33
#Region './Public/Rename-ADDomain.ps1' 0
function Rename-ADDomain
{
    <#
    .SYNOPSIS
    Remame-ADDomain rename the active directory domain on all Domain Controllers

    .DESCRIPTION
    Remame-ADDomain rename the active directory domain on all Domain Controllers

    .ROLE
    Administrators
    #>

    param(
        [Parameter(Mandatory = $true)]
        [String]
        $NewDomain,
        [Parameter(Mandatory = $true)]
        [String]
        $NewNetBIOSName,
        [Switch]
        $Restart
    )

    $ErrorActionPreference = 'Stop'
    $ProgressPreference = 'SilentlyContinue'

    # Get domain name
    $oldDomain = (Get-ADDomain).Forest
    $oldName = (Get-ADDomain).NetBIOSName

    $tmpDir = "C:\Windows\Temp"
    Write-Host "Saving old domain and old netbios name in registry"
    New-Item -Force $Global:PwsRegistryPath
    Set-ItemProperty $Global:PwsRegistryPath -Name "OldDomain" -Value $oldDomain
    Set-ItemProperty $Global:PwsRegistryPath -Name "OldNetBiosName" -Value $oldName

    # We will move to temp directory during the script
    # So we need to store the current location go back there at the end
    $originalLocation = Get-Location
    Set-Location $tmpDir
    $listFile = "$tmpDir\Domainlist.xml"
    $listFileBkp = "$listFile.bkp"

    Write-Host "Dumping Domain listfile to $listFile"
    rendom /list /listfile:$listFile
    Write-Debug "Moving $listFile to $listFileBkp"
    Move-Item $listFile $listFileBkp -Force
    Write-Debug "Updating listfile $listFile"
    Get-Content $listFileBkp | ForEach-Object { $_ -Replace "$oldDomain", "$NewDomain" } | ForEach-Object { $_ -Replace "$oldName", "$NewNetBIOSName" } > $listFile

    Write-Host "New Domain"
    rendom /showforest /listfile:$listFile
    Write-Host "Uploading new Domain listfile"
    rendom /upload /listfile:$listFile | Out-Null
    Write-Host "Preparing to rename domain"
    rendom /prepare /listfile:$listFile | Out-Null
    Write-Host "Executing domain rename"
    rendom /execute /listfile:$listFile | Out-Null

    Write-Debug "Cleaning $listFile"
    Remove-Item -Force $listFile | Out-Null
    Write-Debug "Cleaning $listFileBkp"
    Remove-Item -Force $listFileBkp | Out-Null

    Set-Location $originalLocation

    Write-Warning "The computer must be restarted twice to finish domain renaming"

    if ($Restart)
    {
        Write-Host "Restarting"
        Restart-Computer -Force
    }
}
#EndRegion './Public/Rename-ADDomain.ps1' 74
#Region './Public/Start-ADDS.ps1' 0
Function Start-ADDS
{
    <#

    .SYNOPSIS
    Start AD and its dependant services

    .DESCRIPTION
    Start AD and its dependant services
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    Write-Output "Starting Active directory Domain Service.... "
    Start-Service NTDS -Confirm:$false

    #Routine to Confirm Service Status
    $DSSRV = (Get-Service NTDS).Status
    IF ($DSSRV -eq "Running")
    {
        Write-Host "Active Directory Domain Service is $DSSRV" -ForegroundColor Green
    }

    IF ($DSSRV -eq "Stopped")
    {
        Write-Host "Active Directory Domain Service is $DSSRV" -ForegroundColor Red
    }
}
#EndRegion './Public/Start-ADDS.ps1' 30
#Region './Public/Stop-ADDS.ps1' 0
Function Stop-ADDS
{
    <#

    .SYNOPSIS
    Stop AD and its dependant services

    .DESCRIPTION
    Stop AD and its dependant services
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    Write-Output "Stopping Active directory Domain Service.... "
    Stop-Service NTDS -Force
}
#EndRegion './Public/Stop-ADDS.ps1' 18
#Region './Public/Sync-DnsDomain.ps1' 0
function Sync-DnsDomain
{
    <#
    .SYNOPSIS
    Sync-DNSDomain synchronize DNS Server Name with Active Directory Domain

    .DESCRIPTION
    Sync-DNSDomain synchronize DNS Server Name with Active Directory Domain

    .ROLE
    Administrators
    #>

    param(
        [Switch]
        $Restart
    )

    $dnsDomain = (Get-DnsServerSetting).ComputerName -Replace "$env:ComputerName.", ""
    if (!$dnsDomain)
    {
        Write-Error "Cannot find Dns Server Domain"
        return 1
    }

    $dcDomain = (Get-ADDomain).DNSRoot
    if (!$dcDomain)
    {
        Write-Error "Cannot find Active Directory Domain"
        return 1
    }
    if ($dcDomain -eq $dnsDomain)
    {
        Write-Host "DC domain and DNS domain are already synched: $dnsDomain"
        return 0
    }
    netdom computername "$env:ComputerName.$dnsDomain" /add:"$env:ComputerName.$dcDomain"
    netdom computername "$env:ComputerName.$dnsDomain" /makeprimary:"$env:ComputerName.$dcDomain"
    if ($Restart)
    {
        Write-Host "Restarting Computer"
        Restart-Computer -Force
        return 0
    }
    Write-Host "The computer must be restarted"
}
#EndRegion './Public/Sync-DnsDomain.ps1' 45
#Region './Public/Sync-GpoDomain.ps1' 0
function Sync-GpoDomain
{
    <#
    .SYNOPSIS
    Sync-GpoDomain synchronize DNS name and NetBiosName with Active Directory Domain

    .DESCRIPTION
    Sync-GpoDomain synchronize DNS name and NetBiosName with Active Directory Domain

    .ROLE
    Administrators
    #>

    param(
    # The old NetBiosName
        [Parameter(Mandatory = $false)]
        [String]
        $OldNetBIOSName,
    # The old Dns Domain
        [Parameter(Mandatory = $false)]
        [String]
        $OldDomain
    )

    if (!$OldNetBIOSName)
    {
        $OldNetBIOSName = (Get-ItemProperty -Path $Global:PwsRegistryPath).OldNetBiosName
        if (!$OldNetBIOSName)
        {
            Write-Error "Cannot get old NetBIOSName from Registry, please provide -OldNetBIOSName"
            return 1
        }
    }
    if (!$OldDomain)
    {
        $OldDomain = (Get-ItemProperty -Path $Global:PwsRegistryPath).OldDomain
        if (!$OldDomain)
        {
            Write-Error "Cannot get old Domain from Registry, please povide -OldDomain"
            return 1
        }
    }

    $adDomain = Get-ADDomain
    $domain = $adDomain.DNSRoot
    $netBIOSName = $adDomain.NetBIOSName

    Write-Host "Synching Group Policy Dns Domain"
    gpfixup /olddns:$OldDomain /newdns:$domain | Out-Null
    Write-Host "Synching Group Policy NetBIOS name"
    gpfixup /oldnb:$OldNetBIOSName /newnb:$netBIOSName | Out-Null
}
#EndRegion './Public/Sync-GpoDomain.ps1' 51
#Region './Public/Test-ADDit.ps1' 0
Function Test-ADDit
{
    <#

    .SYNOPSIS
    Trigger NTDSUTIL's semantic database analysis in non-repair mode

    .DESCRIPTION
    Trigger NTDSUTIL's semantic database analysis in non-repair mode
    Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815

    .ROLE
    Administrators

    #>

    Write-Output "Checking NTDS database for errors (semantic database analysis)..."
    Write-Host ""
    ntdsutil "activate instance ntds"  "semantic database analysis" "Go" q "files" "checksum" q q
}
#EndRegion './Public/Test-ADDit.ps1' 19