ADAccount неактивных учетных записей по ADUser проблемы - PullRequest
1 голос
/ 16 апреля 2019

Я сделал несколько сценариев PowerShell, чтобы найти неактивных пользователей в AD, которым 90 дней, и которые прошли через все контроллеры домена, чтобы получить атрибут LastLogon. Мне также нужны некоторые дополнительные атрибуты, которые может вывести только ADUser. У меня ошибка при запуске скрипта с конвейером в строке $users = Search-ADAccount.

Import-Module ActiveDirectory

function Get-ADUsersLastLogon() {
  $dcs = Get-ADDomainController -Filter {Name -like "*"}
  $OUs = @()
  $OU += "ou=Users-A,ou=Users,ou=Items,dc=mydc,dc=com"
  $OU += "ou=Users-B,ou=Users,ou=Items,dc=mydc,dc=com"

  $time = 0
  $exportFilePath = "c:\tmp\lastLogon-test $(get-date -f dd-MM-yyyy).csv"
  $columns = "name;username;whencreated;whenchanged;DNname;datetime"
  #InactiveTest
  $InactiveFilter = @{
      UsersOnly = $true
      AccountInactive = $true
      TimeSpan = New-Timespan -Days 90
  }
  #EndInactiveTest
  Out-File -FilePath $exportFilePath -Force -InputObject $columns

  foreach ($OU in $OUs) {
    $users = Search-ADAccount @InactiveFilter |
             Get-ADUser -Filter * -SearchBase $OUs -Property displayName, whenCreated, whenChanged
    foreach ($user in $users) {
      foreach($dc in $dcs) { 
        $hostname = $dc.HostName
        $currentUser = Get-ADUser $user.SamAccountName |
                       Get-ADObject -Server $hostname -Properties lastLogon
        if ($currentUser.LastLogon -gt $time) {
          $time = $currentUser.LastLogon
        }
      }

      $dt = [DateTime]::FromFileTime($time)
      $row = $user.displayName + ";" + $user.SamAccountName + ";" +
             $user.whenCreated + ";" + $user.whenChanged + ";" +
             $user.distinguishedName + ";" + $dt

      Out-File -FilePath $exportFilePath -Append -NoClobber -InputObject $row

      $time = 0
    }
  }
}

Get-ADUsersLastLogon

Ответы [ 2 ]

0 голосов
/ 16 апреля 2019

Я думаю, что перебирать DC и OU, а затем собирать только неактивных пользователей, последние даты входа в систему лучше всего сделать, используя объект Hashtable в качестве промежуточного хранилища.

Это помогает избежать дублирования записей и дает возможность сравнитьСвойства LastLogonDate.

Для окончательного вывода используется один единственный командлет с именем Export-Csv.

Ниже моего (непроверенного) кода:

function Get-ADUsersLastLogon {
    # get your ad domain
    $DomainName = (Get-ADDomain).DNSRoot
    # get all DC hostnames as string array
    $DCs = Get-ADDomainController -Filter * -Server $DomainName | Select-Object -ExpandProperty Hostname
    # create an array of OU distinghuished names used as SearchBase
    $OUs = "OU=Users-A,OU=Users,OU=Items,DC=mydc,DC=com", "OU=Users-B,OU=Users,OU=Items,DC=mydc,DC=com"
    $exportFilePath = "c:\tmp\lastLogon-test $(Get-Date -Format dd-MM-yyyy).csv"

    $InactiveFilter = @{
        UsersOnly       = $true
        AccountInactive = $true
        TimeSpan        = New-Timespan -Days 90
    }

    # use a lookup Hashtable to eliminate duplicates and collect only the latest logon dates
    $lookup = @{}

    # loop through the list of dc's
    foreach ($dc in $DCs) {
        # loop through the list of OU's
        foreach ($ou in $OUs) {
            $users = Search-ADAccount @InactiveFilter -SearchBase $ou -Server $dc
            foreach($user in $users) {
                # get the properties we want from the AD User. 
                # using the PowerShell property names, we get the dates already converted into DateTime objects.
                $usr = Get-ADUser -Identity $user.DistinguishedName -Server $dc -Properties DisplayName, Created, Modified, LastLogonDate |
                        Select-Object @{Name = 'Name'; Expression = {$_.DisplayName}},
                                        SamAccountName,
                                        @{Name = 'WhenCreated'; Expression = {$_.Created}},
                                        @{Name = 'WhenChanged'; Expression = {$_.Modified}},
                                        @{Name = 'DistinguishedName'; Expression = {$_.DistinguishedName}},
                                        @{Name = 'LastLogon'; Expression = {$_.LastLogonDate}}
                if ($usr) {
                    if ($lookup.ContainsKey($($user.DistinguishedName))) {
                        # we have collected this user before 
                        $lastLogon = $lookup[$($user.DistinguishedName)].LastLogon
                        if ($lastLogon) {
                            if (($usr.LastLogon) -and $lastLogon -lt $usr.LastLogon) {
                                # only store this new instance if the $user.LastLogon property is of a later date
                                $lookup[$($user.DistinguishedName)] = $usr
                            }
                        }
                    }
                    else {
                        # this is a new user, so add the object to the HashTable
                        $lookup[$($user.DistinguishedName)] = $usr
                    }
                }
                else {
                    # should never happen..
                    Write-Warning "User $($user.SamAccountName) not found."
                }
            }
        }
    }

    # export the objects contained in the $lookup Hashtable as CSV
    ($output = foreach ($key in $lookup.Keys) {
        $lookup.$key
    }) | Export-Csv -Path $exportFilePath -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Force

}

Надеюсь, что это поможет

0 голосов
/ 16 апреля 2019

@ voilier Извините, я не понимаю, как это работает для вас. Вставьте свой код, и командлет Get-ADUser ожидает значения фильтра. Если вы используете get-help get-aduser -full, вы увидите, что параметр searchbase может использоваться только с параметрами Filter или LDAPFilter. Более того, ни один из них не принимает входные данные конвейера. Параметр Identity принимает входные данные конвейера только по значению. поэтому вам нужно использовать свойство Отличительное имя из Search-ADAccount @InactiveFilter, например, отличительное имя и передать его в фильтр

$users = Search-ADAccount @InactiveFilter | %{Get-ADUser -filter {distinguishedname -eq $_.distinguishedname}  -SearchBase $OU -Property displayName, whenCreated, whenChanged}

Я заменил вашу $users=... деталь на приведенный выше код, и теперь я не вижу ошибок и файл CSV успешно создан.

Замените ваш foreach $ ou на $ uous этим и проверьте файл csv. это работает на моем компьютере

Foreach ($ou in $ous){
$users = (Search-ADAccount @InactiveFilter | %{Get-ADUser -filter {distinguishedname -eq $_.distinguishedname} -SearchBase $OU -Property displayName, whenCreated, whenChanged})  
    foreach ($user in $users) {
      foreach($dc in $dcs) { 
        $hostname = $dc.Name
        $last_logon_time=((Get-ADUser $user.SamAccountName | Get-ADObject -Server "$hostname" -Properties lastLogon) |?{$_.lastlogon -gt $time}) | select -ExpandProperty lastlogon
      }
      $dt = [DateTime]::FromFileTime("$last_logon_time")
      $row = $user.displayName + ";" + $user.SamAccountName + ";" +
             $user.whenCreated + ";" + $user.whenChanged + ";" +
             $user.distinguishedName + ";" + $dt
      Out-File -FilePath $exportFilePath -Append -NoClobber -InputObject $row

      $last_logon_time = 0
    }
  }

Надеюсь, это поможет вам

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...