簡體   English   中英

列出所有本地管理員帳戶,但域管理員和本地管理員除外

[英]List all local administrator accounts excluding domain admin and local admin

function get-localgroupmember {
  [CmdletBinding()]
  param(
    [parameter(ValueFromPipeline=$true,
      ValueFromPipelineByPropertyName=$true)]
    [string[]]$computername = $env:COMPUTERNAME
  )

  BEGIN {
    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
  }

  PROCESS{
    foreach ($computer in $computername) {
      $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $computer
      $idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
      $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $idtype, 'Administrators')
      $group.Members |
        select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName
    } # end foreach
  } # end PROCESS
}

"Win12R2", "W12SUS" | get-localgroupmember

我想要的輸出看起來像以下內容,並且我想在admin組中標記不屬於我們標准設置的用戶。 確實,我想忽略作為域帳戶的SAM帳戶,但現在將其標記為有效。 發生的情況是有一個遍歷SAM帳戶的循環來創建此輸出。 但是,當機器離線時,我也需要注意這一點。

示例輸出

我也不想使用ValueFromPipeline ,而是從此命令$allComputers = Get-ADComputer -Filter 'PasswordLastSet -ge $date' -properties PasswordLastSet | select Name PC名稱列表。 $allComputers = Get-ADComputer -Filter 'PasswordLastSet -ge $date' -properties PasswordLastSet | select Name $allComputers = Get-ADComputer -Filter 'PasswordLastSet -ge $date' -properties PasswordLastSet | select Name ,然后使用該變量作為循環源。

這是我的修改后的代碼,但是在$group.Members |select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName似乎存在循環時,創建自定義對象添加到數組時遇到了問題。成員$group.Members |select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName $group.Members |select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName

function get-localgroupmember {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$True,HelpMessage="Enter PC")]
    [ValidateNotNullorEmpty()]
    [object]$computername = $null   
  )

  BEGIN {
    $newArray = @();
    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
  }

  PROCESS{
    foreach ($computer in $computername) {
      If (Test-Connection -ComputerName $computer.name -Quiet -Count 1) {
        try {
          $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $computer.name
          $idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
          $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $idtype, 'Administrators')

          $group.Members | select @{N='Server'; E={$computer.name}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName

          $objComputer = [pscustomobject] @{
            Server = $computer.name
            Domain = $group.Members | select @{N='Domain'; E={$_.Context.Name}}
            Account = $Computer.samaccountName
          }
        } catch {
          $objComputer = [pscustomobject] @{
            Server = $computer.name
            Domain = "Error"
            Account = "Error"
          }
        }
      } else {
          $objComputer = [pscustomobject] @{
            Server = $computer.name
            Domain = "Off-Line"
            Account = "Off-Line"
          }
      } $arrayNew += $objComputer
    } # end foreach
  } # end PROCESS

  return $arrayNew
}

$date = [DateTime]::Today.AddDays(-1)

$allComputers = Get-ADComputer -Filter  'PasswordLastSet -ge $date' -properties PasswordLastSet | select Name

get-localgroupmember -computername $allComputers | Out-GridView

老實說,我不會嘗試像您一樣輸出數組對象。 確實沒有必要。 只需根據需要創建每個對象,然后將其直接輸出(您實際上不需要使用return因為該函數將在管道中傳遞任何輸出,除非您特別聲明,否則使用Write-HostOut-File )。 另外,看起來您的輸入想要一個對象(非常模糊),但是您隨后試圖遍歷該對象,並將每條記錄用作PC的名稱,因此,您真正想要輸入的是一個字符串數組。 在這種情況下,將類型從[object]更改為[string[]] 最后,如果在創建$AllComputers變量時僅擴展Name屬性,則可以簡化大量代碼。 哦,我撒謊了,這是最后一件事... return語句不在函數的有效部分中。 它將需要類似於END{ Return $arrayNew }

然后,您只需要添加一個例外帳戶列表即可不進行標記,或者添加一些邏輯或類似內容。 坦白地說,您的代碼應該做一點點語法修復就可以完成您想做的所有事情。 這是基於您的腳本的,它會輸出該組的所有成員,並標記所有不是名稱為“ Administrator”的本地帳戶,並且不是列出為“ OK”的域帳戶(在“ BEGIN部分中定義,當前為“ Domain管理員”或“工作站管理員”)。

function get-localgroupmember {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$True,HelpMessage="Enter PC")]
    [string[]]$computername
  )

  BEGIN {
    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
    $OKAccounts = ("Workstation Admin","Domain Admins" | ForEach{[regex]::Escape($_)}) -join "|"
  }

  PROCESS{
    foreach ($computer in $computername) {
      If (Test-Connection -ComputerName $computer -Quiet -Count 1) {
        try {
          $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $computer
          $idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
          $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $idtype, 'Administrators')

          $group.Members | select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName, @{N='Flag';E={If(!(($_.Context.Name -eq $Computer -and $_.samaccountname -match "Administrator") -or ($_.context.name -ne $Computer -and $_.samaccountname -match $OKAccounts))){"X"}}}

        } catch {
          [pscustomobject] @{
            Server = $computer
            Domain = "Error"
            SamAccountName = "Error"
            Flag = ''
          }
        }
      } else {
          [pscustomobject] @{
            Server = $computer
            Domain = "Off-Line"
            SamAccountName = "Off-Line"
            Flag = ''
          }
      } 

    } # end foreach
  } # end PROCESS

}

$date = [DateTime]::Today.AddDays(-1)

$allComputers = Get-ADComputer -Filter  'PasswordLastSet -ge $date' -properties PasswordLastSet | select -Expand Name
#$allComputers = $env:COMPUTERNAME
get-localgroupmember -computername $allComputers | Out-GridView

那應該給你輸出類似:

Server         Domain                     SamAccountName             Flag
------         ------                     --------------             ----
TMTsLab        TMTsLab                    Administrator                  
TMTsLab        TMTsTacoTruck.com          Domain Admins                  
TMTsLab        TMTsTacoTruck.com          SomeAcct1                  X   
TMTsLab        TMTsTacoTruck.com          SomeAcct2                  X   
TMTsLab        TMTsTacoTruck.com          TMTech                     X 

可能更好的辦法是過濾掉不需要的帳戶,而不是僅不標記它們。 因此,更改@{N='Flag';E={If(!(($_.Context.Name -eq $Computer -and $_.samaccountname -match "Administrator") -or ($_.context.name -ne $Computer -and $_.samaccountname -match $OKAccounts))){"X"}}}位到Where語句,因此該行應為:

          $group.Members | select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName | Where { !(($_.Server -eq $_.Domain -and $_.samaccountname -match "Administrator") -or ($_.Server -ne $_.Domain -and $_.samaccountname -match $OKAccounts)) }

您還需要從CatchElse腳本塊中刪除Flag = ''行。 然后代碼僅返回如下內容:

Server         Domain                     SamAccountName            
------         ------                     --------------            
TMTsLab        TMTsTacoTruck.com          SomeAcct1                   
TMTsLab        TMTsTacoTruck.com          SomeAcct2
TMTsLab        TMTsTacoTruck.com          TMTech  

此時的完整功能代碼:

function get-localgroupmember {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$True,HelpMessage="Enter PC")]
    [string[]]$computername
  )

  BEGIN {
    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
    $OKAccounts = ("Workstation Admin","Domain Admins" | ForEach{[regex]::Escape($_)}) -join "|"
  }

  PROCESS{
    foreach ($computer in $computername) {
      If (Test-Connection -ComputerName $computer -Quiet -Count 1) {
        try {
          $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $computer
          $idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
          $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $idtype, 'Administrators')

          $group.Members | select @{N='Server'; E={$computer}}, @{N='Domain'; E={$_.Context.Name}}, samaccountName | Where{ !(($_.Server -ieq $_.Domain -and $_.samaccountname -match "Administrator") -or ($_.Server -ne $_.Domain -and $_.samaccountname -match $OKAccounts)) }

        } catch {
          [pscustomobject] @{
            Server = $computer
            Domain = "Error"
            Account = "Error"
          }
        }
      } else {
          [pscustomobject] @{
            Server = $computer
            Domain = "Off-Line"
            Account = "Off-Line"
          }
      } 

    } # end foreach
  } # end PROCESS

}

暫無
暫無

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

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