天天看點

如何擷取特定使用者組内的無效賬戶?

有時候,IT管理者可能會想清除某些伺服器/計算機内置管理者組裡面的一些已失效的使用者,這些使用者可能曾經被加入管理者組,但是由于離職或是其他原因,賬号已從AD登出,而在這些使用者組内,他們的SID資訊卻得以保留,就像是這樣:

像圖中的最後兩個使用者,S-1-5-21-1004336348-1220945662-1801674531-10174 和 6866,就是由于資訊從AD擷取不到,而顯示為SID的。如何批量從伺服器抓這樣的SID使用者出來呢?我們可以使用 PowerShell 腳本。

以下就是一個代碼示例,我将其做成了一個函數 QueryNonExistentUsers, 大家可以用在很多實際的工作之中,而且稍加修改,可以完成多種多樣的任務:

#Query Non-existent Users PowerShell Script Function by Eric Sheh

#Version 1.2 Build 20120626

Function QueryNonExistentUsers

{

    Param

    (

        [Parameter(Mandatory=$true,Position=0)][String]$Server,

        [Parameter(Mandatory=$true,Position=1)][String]$UserGroup,

        [Parameter(Mandatory=$false,Position=2)][Bool]$CountInstead = $False

        # Example: QueryNonExistentUsers "hostname" "Administrators" $True OR QueryNonExistentUsers -Server "hostname" -UserGroup "Administrators" -CountInstead $True

        # OR QueryNonExistentUsers "hostname" "Administrators" OR QueryNonExistentUsers -Server "hostname" -UserGroup "Administrators"

    )

    Begin

    {

        $members=@()

    }

    Process

       {

        [adsi]$computer = "WinNT://" + $Server

        $group = $computer.psbase.children | ?{$_.psbase.schemaclassname -eq 'group'} | ?{$_.Path -match $UserGroup}

        foreach ($user in $group.Members())

        {

            $usr_obj = New-Object PSObject

            $usr_obj | Add-Member -MemberType NoteProperty -Name 'aDSPath' -Value $user.GetType().InvokeMember('aDSPath','GetProperty', $null, $user, $null)

            $usr_obj | Add-Member -MemberType NoteProperty -Name 'Name' -Value $user.GetType().InvokeMember('Name', 'GetProperty', $null, $user, $null)

            $path = $usr_obj.aDSPath.split('/')

            if ($path.Count -eq 4)

            {

                $usr_obj | Add-Member -MemberType NoteProperty -Name 'Domain' -Value $path[2]

            }

            elseif ($path.Count -eq 5)

                $usr_obj | Add-Member -MemberType NoteProperty -Name 'Domain' -Value $path[3]

            else

                $usr_obj | Add-Member -MemberType NoteProperty -Name 'Domain' -Value 'Unknown'

            $members += $usr_obj

        }

        $members = @($members | Sort-Object -Property Domain, Name)

        $members = $members | Where-Object {$_.Domain -eq "Unknown"}       

       }

       End

        If ($CountInstead)

            return $members.count

        else

            return $members

}

我們可以寫兩行code來調用這個函數進行測試(例如連接配接到 TestServer,查詢其上的内建 Administrators 組裡面有沒有無效使用者):

#Test:

$Result = QueryNonExistentUsers "TestServer" "Administrators"

Write-Output $Result

可以看見執行結果與上面的第一張 UI 查詢結果圖是一緻的:

最後我解釋一下幾個要點:

1. 使用 ADSI 比使用 WMI 的運作效率高;

2. 使用 ADSI 時,操作本地對象用"WinNT://",而操作AD對象,請使用"LDAP://";

3. 獲得代碼中定義的 $user 對象後,為何要用"/"符号分段呢?有時怎麼确定 Domain 的呢?其實是利用了 Members 對象裡 aDSPath 屬性值的一些特性的: 

例如對于本地使用者,aDSPath 的值是這樣: 

即"WinNT://DomainName/HostName/LocalUserName"的形式,是以依"/"拆分後,形成了一個一維數組,共有5個元素,其中第二進制素為空。是以要取第四個元素"HostName"作為該賬戶的"域"(因為這是個本地賬戶)。 

而對于域賬戶,aDSPath 的值是這樣的: 

即"WinNT://DomainName/DomainUserName"的形式。是以拆分後形成一維數組隻有四個元素,是以要取第三個元素作為該賬戶的域名稱。 

而對于已失效的使用者,結果是這樣的: 

是以我們人為處理他的 Domain 值為"Unknown"并寫入結果中。

對了,這個函數的參數和使用方法在以上的代碼中其實已有說明,這裡再單獨列舉一下:

QueryNonExistentUsers "hostname" "groupname" $true/$false

第一個參數 hostname 自然是你要查詢的那台機器的名稱了,第二個參數是你要查詢的使用者組,而第三個參數可以省略,預設是為 $false 的,傳回具體的組内全部使用者,而如果你指定為 $true, 那麼傳回的隻是一個計數值。例如上面的例子中,如果執行"$Result = QueryNonExistentUsers "TestServer" "Administrators" $true",那麼傳回結果是數字2.

如果您要得到傳回的完整組内使用者清單,請将代碼中的"$members = $members | Where-Object {$_.Domain -eq "Unknown"}"去掉(在第46行),這裡有這一句就是為了在結果中篩出失效賬戶。

本文轉自 hbycscc 51CTO部落格,原文連結:http://blog.51cto.com/mvperic/959637

繼續閱讀