簡體   English   中英

在所有域計算機上列出本地管理員組成員身份

[英]Listing local administrator group membership on all domain computers

完整的powershell和腳本noob在這里 - 我甚至不知道危險。 我需要查詢域中的所有PC以確定其本地Administrators組成員身份是什么,並將該輸出發送到text / csv文件。

我嘗試了很多東西,比如:

Import-Module -Name ActiveDirectory
Get-ADComputer -filter * |
Foreach-Object {
 invoke-command {net localgroup administrators} -EA silentlyContinue |
} |
Out-File c:\users\ftcadmin\test.txt

這讓我重復了一個相同的列表但似乎正在擊中每個域PC。 我猜它實際上並沒有在遠程PC上運行。 還嘗試過:

$computers = Get-Content -Path c:\users\ftcadmin\computers.txt
invoke-command {net localgroup administrators} -cn $computers -EA silentlyContinue
Get-Process | Out-File c:\users\ftcadmin\test.txt

這受到computers.txt文件中預定PC列表的限制。 我試過的第三件事就是:

$a = Get-Content "C:\users\ftcadmin\computers.txt"
Start-Transcript -path C:\users\ftcadmin\output.txt -append
foreach ($i in $a)
  { $i + "`n" + "===="; net localgroup "Administrators"}
Stop-Transcript

除了輸出之外,它似乎最具潛力

computername1
====
computername2
====

等沒有任何小組成員列表。

來自社區的任何想法?

將此功能復制並粘貼到PowerShell控制台中。

function Get-LocalGroupMember
{
    [CmdletBinding()]
    param
    (
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$ComputerName = 'localhost',

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [pscredential]$Credential
    )
    process
    {
        try
        {
            $params = @{
                'ComputerName' = $ComputerName
            }
            if ($PSBoundParameters.ContainsKey('Credential'))
            {
                $params.Credential = $Credential
            }

            $sb = {
                $group = [ADSI]"WinNT://./$using:Name"
                @($group.Invoke("Members")) | foreach {
                    $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
                }
            }
            Invoke-Command @params -ScriptBlock $sb
        }
        catch
        {
            Write-Error $_.Exception.Message
        }
    }
}

然后,嘗試使用它:

Get-ADComputer -filter * | foreach {Get-LocalGroupMember -Name 'Administrators' -ComputerName $_.Name }

如果你想做一些格式化,你可以得到一個計算機列表,並在每個計算機旁邊都有所有成員。

Get-ADComputer -filter * | foreach {
    $members = Get-LocalGroupMember -Name 'Administrators' -ComputerName $_.Name
    [pscustomobject]@{
        'ComputerName' = $_.Name
        'Members' = $members    
    }   
}

這至少需要PowerShell v3。 如果您沒有,我強烈建議您升級到PowerShell v4。

在PowerShell版本5.1(WMF 5.1或Windows 10版本1607附帶的版本)中,現在(最終)有用於管理本地用戶和組的cmdlet。 https://technet.microsoft.com/en-us/library/mt651681.aspx

例如,要獲取本地Administrators組的成員,您可以使用

Get-LocalGroupMember -Group "Administrators"

遺憾的是,這些新cmdlet沒有用於遠程運行命令的ComputerName參數。 您需要使用Invoke-Command之類的東西遠程運行命令,遠程計算機也需要使用PowerShell版本5.1。

Invoke-Command cmdlet的ComputerName參數不接受管道輸入,它只接受字符串,因此我們首先需要展開Get-ADComputer返回的name屬性並將字符串存儲在變量中。 值得慶幸的是,該參數接受多個字符串,因此我們可以在單個invoke-command調用中使用$ names變量。 示例如下:

$names = Get-ADComputer -Filter * | Select-Object -ExpandProperty name
Invoke-Command -ScriptBlock {Get-LocalGroupMember -Group "Administrators"} -ComputerName $names

這實際上是我最近的工作。 似乎有兩種常規方法可以從本地Administrators組獲取成員:WMI和ADSI。

在我看來,更好的方法是使用WMI查詢來獲取成員,因為這包括域,因此您知道列出的用戶/組是服務器本地還是域帳戶。

使用ADSI的簡單方法不包括此信息,但不太可能獲得拒絕訪問類型的錯誤。

為此,我拼湊了一個腳本,檢查過去30天內活動的機器的AD(如果它不在線,則不需要浪費時間)。 然后,對於每個人,它嘗試執行WMI查詢以獲取管理員成員,如果失敗則轉向ADSI查詢。 數據存儲為哈希表,因為在我看來,這是管理嵌套數組的簡單方法。

$TMinus30 = [datetime]::Now.AddDays(-30).ToFileTime()
$Domains = 'ChinchillaFarm.COM','TacoTruck.Net'
$ServerHT = @{}
$Servers = ForEach($Domain in $Domains){Get-ADObject -LDAPFilter "(&(objectCategory=computer)(name=*))" -Server $Domain | ?{$_.lastLogonTimestamp -gt $TMinus30}}
$Servers.DNSHostName | %{$ServerHT.Add($_,$Null)}
ForEach($Server in ($Servers | ?{$(Test-Connection $_.DNSHostName -Count 1 -Quiet)})){
    Try{
        $GMembers = Get-WmiObject -ComputerName $Server -Query "SELECT * FROM win32_GroupUser WHERE GroupComponent = ""Win32_Group.Domain='$Server',Name='Administrators'"""
        $Members = $GMembers | ?{$_.PartComponent -match 'Domain="(.+?)",Name="(.+?)"'}|%{[PSCustomObject]@{'Domain'=$Matches[1];'Account'=$Matches[2]}}
    }
    Catch{
        $group = [ADSI]("WinNT://$Server/Administrators,group") 
        $GMembers = $group.psbase.invoke("Members")
        $Members = $GMembers | ForEach-Object {[PSCustomObject]@{'Domain'='';'Account'=$_.GetType().InvokeMember("Name",'GetProperty', $null, $_, $null)}}
    }

    $ServerHT.$Server = $Members
}

然后,您只需要輸出到文件。 這就是我要做的,應該輸出你想要的東西:

$ServerHT.keys|%{"`n"+("="*$_.length);$_;("="*$_.length)+"`n";$ServerHT.$_|%{"{0}{1}" -f $(If($_.Domain){$_.Domain+"\"}), $_.Account}}

如果前兩個服務器響應WMI查詢而第三個服務器沒有響應,則會給出類似下面的內容:

===========
ServerSQL01
===========

ServerSQL01\SQLAdmin
TacoTruck\TMTech
TacoTruck\Stan2112

======
XWeb03
======

ChinchillaFarm\Stan2112

============
BrokenOld486
============

TMTech
Guest

如果有人將Guest帳戶放在本地管理員組中,那么最后一個會在我的書中觸發一些危險信號,但我想這可能是你首先這樣做的原因之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM