PSAdsi-Convert.psm1

function Convert-AdsiUsers {
    <#
        .SYNOPSIS
            Converti des object ADSI et PSCustomObject
        .DESCRIPTION
            recupere les info de principale
        .PARAMETER Items
            
        .EXAMPLE
            Convert-AdsiUsers
        .NOTES
            Alban LOPEZ 2019
            alban.lopez@gmail.com
            http://git/PowerTech/
    #>

    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]$Items,
        [switch]$full,
        $blackKey = @('objectsid','objectguid','userparameters')
    )
    begin {
    }
    process {
        foreach ($item in $items) {
            try {
                $AdsiItem = $item | ForEach-Object{[adsi]$_.path}
                # write-host -ForegroundColor Green (Measure-Command {
                    try {
                        if($AdsiItem.InvokeGet("AllowLogon") -ne $false) {
                            $TsAllowLogon = 'RD Session'
                        } elseif ($AdsiItem.mail) {
                            $TsAllowLogon = 'Bal Only'
                        } else {
                            $TsAllowLogon = 'Just Account'
                        }
                    } catch {$TsAllowLogon = 'RD Session'} # n'as jamais été défini pour ce User
                    # Write-Color '[',$item.invokeget('mstsallowlogon'),' vs ',$AdsiItem.invokeget('mstsallowlogon'),' vs ',$TsAllowLogon,']' -fore white,Magenta,Cyan,Yellow,Cyan,Green,white
                    if (($AdsiItem.userAccountControl.value -band 0x02)) {$state ='Disabled'} else {$state = ''}
                # }).TotalSeconds
                # write-host -ForegroundColor cyan (Measure-Command {
                    try {
                        $sid = (New-Object Security.Principal.SecurityIdentifier( $AdsiItem.objectSid.Value, 0)).Value
                    } catch {$sid = $null}
                # }).TotalSeconds
                # write-host -ForegroundColor Yellow (Measure-Command {

                    $factu = ''
                    if($AdsiItem.extensionattribute6){$factu += "Cap:$($AdsiItem.extensionattribute6)"}
                    if($AdsiItem.extensionattribute7){$factu += "Asp:$($AdsiItem.extensionattribute7)"}


                    # write-color $AdsiItem.samaccountname.padright(30),' ', "$($item.accountexpires)".padright(20),' ',$item.pwdlastset -fore cyan,yellow,red
                    
                    $PwdLastSet = [datetime]::FromFileTimeUtc($AdsiItem.ConvertLargeIntegerToInt64($AdsiItem.pwdlastset.value))
                    if($AdsiItem.extensionattribute14 -match '\d{18}@.+\\.+'){
                        ($lesspassTicks, $lesspassScope) = $AdsiItem.extensionattribute14 -split('@')
                        $LesspassDate = (get-date ([int64]$lesspassTicks)).ToUniversalTime()
                        if([Math]::Abs(($PwdLastSet - $LesspassDate).Totalseconds) -lt 120) {
                            $PassWordType = $lesspassScope
                        } else {
                            $PassWordType = $null
                        }
                    } else {
                        $PassWordType = $null
                    }

                    # write-color $AdsiItem.extensionattribute14, ' ',$PassWordType -fore cyan, red, Magenta, Yellow
                    $ExpireDate = $ExpireCode = $null # [datetime]::MaxValue
                    if($Item.properties.accountexpires -and $Item.properties.accountexpires -lt 9223372036854775807){
                        $ExpireDate = [datetime]::fromfiletime([int64]$($Item.properties.accountexpires))
                        # $Item.properties.accountexpires | Write-Object -back black -fore red
                    }
                    
                    if (!($AdsiItem.Properties.useraccountcontrol.value -band 0x10000)) {
                        if($($AdsiItem.userPrincipalName) -notmatch 'coaxis-asp.com$'){ # trop vieux AD
                            $URPP = (Get-ADUserResultantPasswordPolicy -Server ($($AdsiItem.userPrincipalName) -replace ('(.+)@(.+\..+)', '$2')) -Identity $($AdsiItem.samAccountName))
                            # $URPP | Write-Object -back black -fore red
                            if ($URPP.MaxPasswordAge) {
                                $ExpireCode = $PwdLastSet.add($URPP.MaxPasswordAge)
                                # Write-logstep $ExpireCode,"(Get-ADUserResultantPasswordPolicy -Server $($($AdsiItem.userPrincipalName) -replace ('(.+)@(.+\..+)', '$2')) -Identity $($AdsiItem.samAccountName))" ok
                            }
                        }
                    }
                    # $ExpireCode , $ExpireDate | Write-Object -back black -fore red
                    if($ExpireCode -or $ExpireDate){
                        if($ExpireCode -and $ExpireCode -lt $ExpireDate -or !$ExpireDate ){
                            $Expire = "$(Get-date -format 'yyyy-MM-dd' $ExpireCode) (Pwd)"
                        } elseif($ExpireDate) {
                            $Expire = "$(Get-date -format 'yyyy-MM-dd' $ExpireDate) (Account)"
                        }
                    } else {
                        $Expire = "$([datetime]::new(2099,12,31).ToString('yyyy-MM-dd')) (FullTime)" # [double]::PositiveInfinity
                    }

                # }).TotalSeconds
                $Prop = @{
                    Name                 = "$($AdsiItem.Name)"
                    DisplayName          = "$($AdsiItem.DisplayName)"
                    NtAccountName        = $($AdsiItem.userPrincipalName) -replace ('(.+)@(.+)\..+', '$2\$1')
                    Sid                  = "$sid"
                    email                = "$($AdsiItem.mail)" # + $($AdsiItem.proxyAddresses)"
                    Type                 = $TsAllowLogon
                    State                = $state
                    Phone                = "$($AdsiItem.telephonenumber)"
                    Description          = "$($AdsiItem.description)"
                    Facturation          = $factu
                    PasswordType         = $PassWordType
                    PasswordDate         = $PwdLastSet
                    CreateDate           = "$($Item.properties.whencreated)"
                    Expire               = $Expire
                    Groupes              = $($AdsiItem.memberOf | ? {$_} | % {$_.split(',=')[1]}) # -join ("`n") # | ForEach-Object {([adsi]"LDAP://$_").name}
                    Externe              = $($AdsiItem.properties.extensionattribute6) -match 'EXT$' -or $($AdsiItem.properties.extensionattribute7) -match 'EXT$'
                }
                if($full){
                    foreach($key in $item.Properties.GetEnumerator().name){
                        # Write-Host $key,'-',$Prop.$Key,'-',$($item.Properties.$key) -fore red
                        if($blackKey -notcontains $key -and !$Prop.$Key -and $($item.Properties.$key)){
                            # Write-Host $key -fore Yellow
                            $Prop.$Key = $($item.Properties.$key)
                        }
                    }
                }
                $Prop
            } catch {
                Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber)" '',$_ error
            }
        }
    }
    end {}
}
function Convert-AdsiUserToMail {
    <#
        .SYNOPSIS
            Converti des object ADSI et PSCustomObject
        .DESCRIPTION
            recupere les info de principale
        .PARAMETER Items
            
        .EXAMPLE
            Convert-AdsiUsers
        .NOTES
            Alban LOPEZ 2019
            alban.lopez@gmail.com
            http://git/PowerTech/
    #>

    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]$Items
    )
    begin {
    }
    process {
        foreach ($item in $items) {
            $AdsiItem = $item | ForEach-Object{[adsi]$_.path}
            if (($AdsiItem.userAccountControl.value -band 0x02)) {$state ='Disabled'} else {$state = ''}
            [PSCustomObject]@{
                NtAccountName        = $($AdsiItem.userPrincipalName) -replace ('(.+)@(.+)\..+', '$2\$1')
                Name                 = "$($AdsiItem.Name)"
                DisplayName          = "$($AdsiItem.DisplayName)"
                email                = $($AdsiItem.mail) # + $($AdsiItem.proxyAddresses)"
                State                = $state
                ExtensionAttribute1  = $($AdsiItem.properties.extensionattribute1)
                # proxyaddresses = $($AdsiItem.properties.proxyaddresses)
                AllAddresses         = $($AdsiItem.properties.proxyaddresses -match '\w[A-Za-z0-9-_]+@[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+') -replace('.+:(.+@.+)','$1')
                msexchhomeservername = $($AdsiItem.properties.msexchhomeservername)
                msExchServerName     = $($AdsiItem.properties.msexchhomeservername -replace('.*/cn=(.+)$','$1'))
                msExchDbName         = $($AdsiItem.properties.homemdb -replace('^CN=(.|[^,]+),CN=.*','$1'))
                msExchQuotaGb        = $($Item.properties.msexchdumpsterquota) / 1Mb
                msExchDelegateBal    = $($AdsiItem.properties.msexchdelegatelistbl)
                msExchArchiveName    = $($AdsiItem.properties.msexcharchivename)
                msExchArchDbName     = $($AdsiItem.properties.msexcharchivedatabaselink -replace('^CN=(.|[^,]+),CN=.*','$1'))
                msExchArchPolicy     = $($AdsiItem.properties.msexchmailboxtemplatelink -replace('^CN=(.|[^,]+),CN=.*','$1'))
                msExchArchiveQuotaGb = $($Item.properties.msexcharchivequota) / 1Mb
            }
        }
    }
    end {}
}
function Convert-AdsiFactUsers {
    <#
        .SYNOPSIS
            Converti des object ADSI et PSCustomObject
        .DESCRIPTION
            recupere les info de factu
        .PARAMETER Items
            
        .EXAMPLE
            Convert-AdsiUsers
        .NOTES
            Alban LOPEZ 2019
            alban.lopez@gmail.com
            http://git/PowerTech/
    #>


    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]$Items
    )
    begin {
    }
    process {
        foreach ($item in $items) {
            # Write-Object $item -fore Magenta -backGroundColor Gray
            $AdsiItem = $item | ForEach-Object {[adsi]$_.path}
            # write-host -ForegroundColor Green (Measure-Command {
                try {
                    if($AdsiItem.InvokeGet("AllowLogon") -ne $false) {
                        $TsAllowLogon = $true
                    } else {
                        $TsAllowLogon = $false
                    }
                    # $TsAllowLogon = !($AdsiItem.InvokeGet("AllowLogon"))
                } catch {$TsAllowLogon = $true}
            # }).TotalSeconds
            # Write-Color '[',$item.invokeget('allowlogon'),' vs ',$AdsiItem.invokeget('allowlogon'),' vs ',$TsAllowLogon,']' -fore white,Magenta,Cyan,Yellow,Cyan,Green,white

            # write-host -ForegroundColor cyan (Measure-Command {
                try {
                    $sid = (New-Object Security.Principal.SecurityIdentifier( $AdsiItem.objectSid.Value, 0)).Value
                } catch {$sid = $null}
            # }).TotalSeconds
            [PSCustomObject]@{
                Sid            = $sid
                Enabled        = [bool](!($AdsiItem.userAccountControl.value -band 0x02))
                SamAccountName = $($AdsiItem.SamAccountName)
                NtAccountName  = $($AdsiItem.userPrincipalName) -replace ('(.+)@(.+)\..+', '$2\$1')
                email          = "$($AdsiItem.mail)" # + $($AdsiItem.proxyAddresses)"
                TsAllowLogon   = $TsAllowLogon
                Externe        = $($AdsiItem.properties.extensionattribute6) -match 'EXT$' -or $($AdsiItem.properties.extensionattribute7) -match 'EXT$'
                Facturation    = [PSCustomObject]@{
                    Groups         = ($AdsiItem.memberOf -match '_FACT')
                    Attribut       = [PSCustomObject]@{
                        CAP             = $($AdsiItem.properties.extensionattribute6)
                        ASP             = $($AdsiItem.properties.extensionattribute7)
                    }
                }
            }
        }
    }
    end {}
}
function Convert-AdsiComputers {
    <#
        .SYNOPSIS
            Converti des object ADSI et PSCustomObject
        .DESCRIPTION
            recupere les info de principale
        .PARAMETER Items
            
        .EXAMPLE
            Convert-AdsiUsers
        .NOTES
            Alban LOPEZ 2019
            alban.lopez@gmail.com
            http://git/PowerTech/
    #>

    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]$Items
    )
    begin {
    }
    process {
        foreach ($item in $items) {
            try {
                $AdsiItem = $item | ForEach-Object{[adsi]$_.path}
                try {
                    $sid = (New-Object Security.Principal.SecurityIdentifier( $AdsiItem.objectSid.Value, 0)).Value
                } catch {$sid = $null}
                @{
                    Name                   = "$($AdsiItem.name)"
                    NtAccountName          = $($AdsiItem.adspath) -replace ('LDAP://CN=([\w\d-]+),.*,DC=([\w\d-]+),DC=(com|adds)', '$2\$1')
                    DnsHostName            = $($AdsiItem.dnshostname)
                    Sid                    = "$sid"
                    operatingsystem        = $($AdsiItem.operatingsystem)
                    operatingsystemversion = $($AdsiItem.operatingsystemversion)
                    whencreated            = $($AdsiItem.whencreated)
                    adspath                = $($AdsiItem.adspath)
                    # distinguishedname = $($AdsiItem.distinguishedname)
                    memberof               = $($AdsiItem.memberof)
                }
            } catch {
                Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber)" '',$_ error
            }
        }
    }
    end {}
}
function Get-UserAccountControl {
    <#
        .SYNOPSIS
            [Descriptif en quelques mots]
        .DESCRIPTION
            [Descriptif en quelques lignes]
        .PARAMETER flags
            
        .EXAMPLE
            Get-UserAccountControl
        .NOTES
            Alban LOPEZ 2020
            alban.lopez@gmail.com
            http://git/PowerTech/
        #>


    param(
        $flags
    )
    $flags_enum = @{
        SCRIPT                                 = 1 # ADS_UF_
        ACCOUNTDISABLE                         = 2 # ADS_UF_
        HOMEDIR_REQUIRED                       = 8 # ADS_UF_
        LOCKOUT                                = 16 # ADS_UF_
        PASSWD_NOTREQD                         = 32 # ADS_UF_
        PASSWD_CANT_CHANGE                     = 64 # ADS_UF_
        ENCRYPTED_TEXT_PASSWORD_ALLOWED        = 128 # ADS_UF_
        TEMP_DUPLICATE_ACCOUNT                 = 256 # ADS_UF_
        NORMAL_ACCOUNT                         = 512 # ADS_UF_
        INTERDOMAIN_TRUST_ACCOUNT              = 2048 # ADS_UF_
        WORKSTATION_TRUST_ACCOUNT              = 4096 # ADS_UF_
        SERVER_TRUST_ACCOUNT                   = 8192 # ADS_UF_
        DONT_EXPIRE_PASSWD                     = 65536 # ADS_UF_
        MNS_LOGON_ACCOUNT                      = 131072 # ADS_UF_
        SMARTCARD_REQUIRED                     = 262144 # ADS_UF_
        TRUSTED_FOR_DELEGATION                 = 524288 # ADS_UF_
        NOT_DELEGATED                          = 1048576 # ADS_UF_
        USE_DES_KEY_ONLY                       = 2097152 # ADS_UF_
        DONT_REQUIRE_PREAUTH                   = 4194304 # ADS_UF_
        PASSWORD_EXPIRED                       = 8388608 # ADS_UF_
        TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216 # ADS_UF_
    }
    Write-LogStep 'UserAccountControl',[Convert]::ToString($flags,2) ok
    $flags_enum.GetEnumerator() | % { 
        if ( $_.value -band $flags ) { $_.name }
    }
}

# Export-ModuleMember -Function Convert-RdSession, Get-RdSession
Write-LogStep 'Chargement du module ',$PSCommandPath ok

<#
    ipmo .\PSAdsi.psd1
    # ipmo .\PSAdsi-Convert.psm1
    ipmo C:\git\RDS.Dragonfly\Ressources\RDS.DragonFly-Tools.psm1
    $filtered = Get-ADSIComputer * | Convert-AdsiComputers | ?{
        $_.operatingsystem -and $_.adspath -match ',OU=Serveurs,' -and (Test-TcpPort $_.DnsHostName -port 445 -ConfirmIfDown)
    }

    $data = $filtered | Invoke-Parallel -ScriptBlock { # <!> tronque les resultat
        param($item)
        try {
            $item.wsusid = $([Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $item.DnsHostName).OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate").GetValue('SusClientId'))
        } catch {
            $item.wsusid = $_
        }
        [pscustomobject]$item
    } -MaxThreads 256 -TimeOutGlobal 3600 -TimeOutThread 10

    $excel = $data | Export-XLSX -Path '.\wsus.xlsx' -ClearSheet -Force -WorksheetName 'Users-Groups' -Table -TableStyle Medium16 -Passthru # -PivotRows 2 -PivotColumns 6

    $data | out-gridview -OutputMode Multiple

#>