2015-05-12 5 views
1
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 

То, что я хочу, это выход, чтобы выглядеть следующим образом, и я хочу, чтобы пометить пользователей в группу администраторов, которые не являются частью нашей стандартной установки. На самом деле я хочу игнорировать учетные записи SAM, являющиеся учетными записями домена, но помечая их на данный момент. То, что происходит, - это цикл через учетные записи SAM для создания этого вывода. Однако, когда машина отключена, я тоже должен это отметить.Список всех учетных записей локальных администраторов за исключением администратора домена и локального администратора

EXample Output

Я также не хочу использовать ValueFromPipeline, а получить список имен компьютеров из этой команды $allComputers = Get-ADComputer -Filter 'PasswordLastSet -ge $date' -properties PasswordLastSet | select Name и затем использовать эту переменную в качестве источника проходным.

Это мой пересмотренный код, но у меня возникают проблемы, создающие пользовательский объект, чтобы добавить в массив, когда, кажется, зацикливание в $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 
+0

@ Ansgar-Wiechers спасибо за форматирование исходного! Как ты это сделал? Я сейчас и только учился. –

+2

Код для него: ''. Кажется, нравится иметь пустую строку, отделяющую ее от чего-либо еще, поэтому я бы поставил ее наверху, поместил пробел под нее, а затем сделал свой пост. '' тоже должен работать, но я только начал использовать первый, когда это необходимо. – TheMadTechnician

+0

В последнее время мне пришлось сделать что-то почти такое, для проверки лицензии на программное обеспечение. Позвольте мне посмотреть, могу ли я просеять его, чтобы подстроить одну вещь для того, что вы хотите видеть. – ssaviers

ответ

2

Честно говоря, я бы не стал выведите объект массива, как вы. В этом нет необходимости. Просто создайте каждый объект по мере необходимости и позвольте ему выводить напрямую (вам действительно не нужно использовать return, так как функция будет пропускать любой вывод по конвейеру, если вы конкретно не указали это иначе, с чем-то вроде или Out-File). Кроме того, похоже, что ваш вход требует объекта (это довольно неопределенно), но вы затем пытаетесь пропустить этот объект и использовать каждую запись в качестве имени ПК, поэтому то, что вы действительно хотите для ввода, - это массив строк , В этом случае измените свой тип от [object] до [string[]]. Наконец, хороший бит вашего кода можно упростить, если вы просто расширяете свойство Name при создании переменной $AllComputers. О, я соврал, это последнее ... Ваш оператор return не находится в допустимом разделе вашей функции. Это должно быть что-то вроде END{ Return $arrayNew }

Тогда вам просто нужно добавить список исключенных учетных записей, чтобы не помечать или добавлять какую-либо логику или что-то в этом роде. Честно говоря, ваш код должен делать почти все, что вы хотите, чтобы сделать это с помощью небольшого синтаксиса. Ниже приведен пример вашего сценария, в котором он выводит всех членов группы и флаги, которые не являются локальной учетной записью с именем «Администратор», и не являются учетной записью домена, указанной в ОК (определенной в разделе BEGIN, в настоящее время «Домен» Админы "или" Администратор рабочей станции ").

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)) } 

Вы также хотите удалить Flag = '' строки из ваших Catch и Else scriptblocks, а также.Какие то код возвращает только что-то вроде:

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 

} 
+0

Опять же с tacos – Matt

+0

Что, вам не нравятся тако? Хорошо, в следующий раз я изменю его на TMTsChinchillaFarm.com только для вас. Matt = P – TheMadTechnician