.: Blog 4Srv.net :.

Um lugar onde voce encontra dicas de suporte

Powershell Scripts Windows Server

Usando PowerShell para exportar LogonHours

Oi Pessoal!!!

Hoje tive a necessidade de exportar de um AD (Active Directory) uma listagem de todos os usuarios com o limite de horas de acesso (a variavel LogonHours), aí encontrei alguns scripts e tive que adapta-los para a necessidade, com isso resolvi publica-los para poder ajudar a outras pessoas assim como ele me ajudou, na realidade deu um trabalhão gerar isso.

Então com acabei fazendo de duas formas, um em txt e o outro em csv.

1. Arquivo PS1

Usando código abaixo devemos criar um arquivo com a extensão ps1 (neste exemplo vou usar script.ps1)

Function OctetToHours ($Octet)
{
    For ($j = 0; $j -le 20; $j = $j + 1)
    {
        For ($k = 7; $k -ge 0; $k = $k - 1)
        {
            $m = 8*$j + $k - $Bias
            If ($m -lt 0) {$m = $m + 168}
            If ($Octet[$j] -band [Math]::Pow(2, $k)) {$LH[$m] = "1"}
            Else {$LH[$m] = "0"}
        }
    }
    "            --------------- Horas do dia ------------------"
    "             0-3   3-6   6-9  9-12  12-15 15-18 18-21 21-0"
    $arrDays = ("Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab")
    
    For ($j = 0; $j -le 167; $j = $j + 1)
    {
        If (($j % 24) -eq 0)
        {
            $Line = "    " + $arrDays[$j / 24] + "   "
        }
        If (($j %3) -eq 0)
        {
            $Line = $Line + "   "
        }
        $Line = $Line + $LH[$j]
        If ((($j + 1) % 24) -eq 0) {$Line}
    }
}

$Domain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = $Domain
$Searcher.PageSize = 200
$Searcher.Filter = "(&(objectCategory=person)(objectClass=user))"

$Searcher.PropertiesToLoad.Add("logonHours") > $Null
$Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
$Searcher.PropertiesToLoad.Add("name") > $Null
$Results = $Searcher.FindAll()

$Bias = [Math]::Round((Get-ItemProperty `
    -Path HKLM:\System\CurrentControlSet\Control\TimeZoneInformation).Bias/60, `
    0, [MidpointRounding]::AwayFromZero)

$LH = New-Object 'object[]' 168

ForEach ($Result in $Results)
{
    $DN = "`r`n`r`n Usuario: " + $Result.Properties.Item("name")
    $Values = $Result.Properties.Item("logonHours")
    $DN
    $Flag = $False
    ForEach ($Value In $Values)
    {
        OctetToHours $Value
        $Flag = $True
    }
    If ($Flag -eq $False) {"    Liberado Geral"}
}
Code language: PowerShell (powershell)

Depois de voce copiar o codigo acima e criar o arquivo descrito, abrimos o PowerShell (eu particularmente gosto muito de usar a interface ISE).

Para poder conectar corretamente no dominio e exportar os dados que necessitamos, devemos executar o PowerShell como administrador.

Com o programa aberto, podemos abrir o script e verificar a sintaxe.

E finalmente para executar digitamoso comando como na figura acima.

./script.ps1 * > result.txt

e o resultado do comando é escrito no arquivo texto.

O retorno do programa será parecido com esse:

2. Segundo Exemplo

O segundo exemplo eu exportei as informações para um arquivo csv que da para abrir no excel, da mesma forma que o exemplo anterior, podemos abrir na interface do PowerShell e executar diretamente nele, clicando em executar ou apretando F5

Nesta exemplo o resultado desse comando sera exportado para o arquivo usuarios.csv

Depois de pronto e antes de abrir o arquivo no Excel uma dica de ouro, é abrir o arquivo no notepad++ ou qualquer editor de textos e adicionar a linha

SEP=,

antes de todo o resultado , isso fará com que o excel ja reconheça as separações do arquivo e já o abra formatado

O codigo completo deste segundo exemplo está logo abaixo:

Function Convert-ADLogonHours {
    Param(
        [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.ActiveDirectory.Management.ADUser]$User,
        [Parameter(Mandatory=$False)]
        [Switch]$NoWarnings = $False
    )
    Process {
        $Properties = $User | Get-Member -MemberType Property | Select-Object -ExpandProperty Name
        If ($Properties -contains "LogonHours") {
            If ($User.LogonHours.Count -eq 21) {
                $ExportArray = For ($Inc = 0; $Inc -lt $User.LogonHours.Count; $Inc += 3) {
        
                    $EndIndex = $Inc + 2

                    Switch ($Inc) {
                        0 {$DayOfWeek = "Domingo"}
                        3 {$DayOfWeek = "Segunda"}
                        6 {$DayOfWeek = "Terca"}
                        9 {$DayOfWeek = "Quarta"}
                        12 {$DayOfWeek = "Quinta"}
                        15 {$DayOfWeek = "Sexta"}
                        18 {$DayOfWeek = "Sabado"}
                    }

                    $BinaryArray = $User.LogonHours[$Inc..$EndIndex] | ForEach {
                        $TempArray = [Convert]::ToString($_,2).PadLeft(8,'0').ToCharArray()
                        [Array]::Reverse($TempArray)
                        $TempArray
                    }

                    $ExportObj = New-Object PsObject
                    $ExportObj | Add-Member -MemberType NoteProperty -Name "Nome" -Value $User.Name
                    $ExportObj | Add-Member -MemberType NoteProperty -Name "Ultimo Login" -Value $User.LastLogonDate
                    $ExportObj | Add-Member -MemberType NoteProperty -Name "Dia das semana" -Value $DayOfWeek

                    For ($Hour = 0; $Hour -lt 24; $Hour++) {

                        If ($Hour -eq 23) {$EndHour = 0}
                        Else {$EndHour = $Hour + 1}

                        Switch ($BinaryArray[$Hour]) {
                            '1' {$LogonAuth = 'Permitido'}
                            '0' {$LogonAuth = 'Negado'}
                        }
                
                        $ExportObj | Add-Member -MemberType NoteProperty -Name "$Hour-$EndHour h" -Value $LogonAuth
                    }
                    $ExportObj
                }
                Return $ExportArray
            }
            ElseIf (!$NoWarnings) {Write-Warning -Message "Hora de Logon incorreta para: $_"}
        }
        ElseIf (!$NoWarnings) {
        
        
        Write-Warning -Message "Hora nao definida para object: $_ "}
    }
}

Get-ADUser -Filter * -SearchBase "OU=Usuarios,DC=dominio,DC=com" -Properties LogonHours, LastLogonDate  | Convert-ADLogonHours |Export-csv -path c:\usuarios.csv
Code language: PowerShell (powershell)

Espero que estas duas dicas possam ajudar… Até a proxima!!!

Atualização

No primeiro exemplo tive de fazer uma alteração para poder capturar todos os usuários ativos do sistema, sendo assim como já existia um grupo de segurança com estes usuários foi mais fácil, bastou criar um filtro no padrão LDAP para esse grupo (GG_Todos) e colocar no programa e executa-lo novamente isso foi feito na linha 36 como no código abaixo.

$Searcher.Filter = "(&(&(|(&(objectCategory=person)(objectSid=<em>)(!samAccountType:1.2.840.113556.1.4.804:=3))(&(objectCategory=person)(!objectSid=</em>))(&(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=14)))(objectCategory=user)(objectClass=user)(memberOf=CN=GG_Todos,OU=Grupos,OU=Rede,DC=dominio,DC=com)))"
Code language: PowerShell (powershell)

Já no segundo script alteramos a linha 63 para podermos aplicar o mesmo filtro.

Get-ADUser -LDAPFilter "(&(&(|(&(objectCategory=person)(objectSid=<em>)(!samAccountType:1.2.840.113556.1.4.804:=3))(&(objectCategory=person)(!objectSid=</em>))(&(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=14)))(objectCategory=user)(objectClass=user)(memberOf=CN=GG_Todos,OU=Grupos,OU=Rede,DC=heca,DC=com)))" -SearchBase "OU=Usuarios,DC=dominio,DC=com" -Properties LogonHours, LastLogonDate | Convert-ADLogonHours
Code language: PowerShell (powershell)

1 COMMENTS

  1. Obrigada por publicar, estava procurando algo parecido.
    Só uma observação de que o segundo script está trazendo um resultado diferente do primeiro. Horários que no primeiro mostram liberados estão sendo exibidos como negados no segundo.
    Também não entendo pq no primeiro alguns usuários retornam “liberado geral” e outros não, mas pelo que validei os resultados estão corretos no primeiro script, então estou usando ele.

LEAVE A RESPONSE

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *