Powershell 在OU中的每台计算机上获取本地管理员帐户

Powershell 在OU中的每台计算机上获取本地管理员帐户,powershell,active-directory,admin,administrator,ou,Powershell,Active Directory,Admin,Administrator,Ou,我正在尝试获取administrators组中在其受尊敬的计算机上的所有用户帐户的列表,以及我们整个OU的列表。我发现一个脚本可以在一台计算机上显示这一点,但我想调用CSV文件以获取计算机名称,然后将结果输出到另一个CSV文件。以下是我正在使用的脚本: Function Get-LocalGroupMembership { <# .SYNOPSIS Recursively list all members of a specified Local group.

我正在尝试获取administrators组中在其受尊敬的计算机上的所有用户帐户的列表,以及我们整个OU的列表。我发现一个脚本可以在一台计算机上显示这一点,但我想调用CSV文件以获取计算机名称,然后将结果输出到另一个CSV文件。以下是我正在使用的脚本:

Function Get-LocalGroupMembership {
<#
    .SYNOPSIS
        Recursively list all members of a specified Local group.

    .DESCRIPTION
        Recursively list all members of a specified Local group. This can be run against a local or
        remote system or systems. Recursion is unlimited unless specified by the -Depth parameter.

        Alias: glgm

    .PARAMETER Computername
        Local or remote computer/s to perform the query against.

        Default value is the local system.

    .PARAMETER Group
        Name of the group to query on a system for all members.

        Default value is 'Administrators'

    .PARAMETER Depth
        Limit the recursive depth of a query. 

        Default value is 2147483647.

    .PARAMETER Throttle
        Number of concurrently running jobs to run at a time

        Default value is 10

    .NOTES
        Author: Boe Prox
        Created: 8 AUG 2013
        Version 1.0 (8 AUG 2013):
            -Initial creation

    .EXAMPLE
        Get-LocalGroupMembership

        Name              ParentGroup       isGroup Type   Computername Depth
        ----              -----------       ------- ----   ------------ -----
        Administrator     Administrators      False Domain DC1              1
        boe               Administrators      False Domain DC1              1
        testuser          Administrators      False Domain DC1              1
        bob               Administrators      False Domain DC1              1
        proxb             Administrators      False Domain DC1              1
        Enterprise Admins Administrators       True Domain DC1              1
        Sysops Admins     Enterprise Admins    True Domain DC1              2
        Domain Admins     Enterprise Admins    True Domain DC1              2
        Administrator     Enterprise Admins   False Domain DC1              2
        Domain Admins     Administrators       True Domain DC1              1
        proxb             Domain Admins       False Domain DC1              2
        Administrator     Domain Admins       False Domain DC1              2
        Sysops Admins     Administrators       True Domain DC1              1
        Org Admins        Sysops Admins        True Domain DC1              2
        Enterprise Admins Sysops Admins        True Domain DC1              2       

        Description
        -----------
        Gets all of the members of the 'Administrators' group on the local system.        

    .EXAMPLE
        Get-LocalGroupMembership -Group 'Administrators' -Depth 1

        Name              ParentGroup    isGroup Type   Computername Depth
        ----              -----------    ------- ----   ------------ -----
        Administrator     Administrators   False Domain DC1              1
        boe               Administrators   False Domain DC1              1
        testuser          Administrators   False Domain DC1              1
        bob               Administrators   False Domain DC1              1
        proxb             Administrators   False Domain DC1              1
        Enterprise Admins Administrators    True Domain DC1              1
        Domain Admins     Administrators    True Domain DC1              1
        Sysops Admins     Administrators    True Domain DC1              1   

        Description
        -----------
        Gets the members of 'Administrators' with only 1 level of recursion.         

#>
[cmdletbinding()]
Param (
    [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
    [Alias('CN','__Server','Computer','IPAddress')]
    [string[]]$Computername = $env:COMPUTERNAME,
    [parameter()]
    [string]$Group = "Administrators",
    [parameter()]
    [int]$Depth = ([int]::MaxValue),
    [parameter()]
    [Alias("MaxJobs")]
    [int]$Throttle = 10
)
Begin {
    $PSBoundParameters.GetEnumerator() | ForEach {
        Write-Verbose $_
    }
    #region Extra Configurations
    Write-Verbose ("Depth: {0}" -f $Depth)
    #endregion Extra Configurations
    #Define hash table for Get-RunspaceData function
    $runspacehash = @{}
    #Function to perform runspace job cleanup
    Function Get-RunspaceData {
        [cmdletbinding()]
        param(
            [switch]$Wait
        )
        Do {
            $more = $false         
            Foreach($runspace in $runspaces) {
                If ($runspace.Runspace.isCompleted) {
                    $runspace.powershell.EndInvoke($runspace.Runspace)
                    $runspace.powershell.dispose()
                    $runspace.Runspace = $null
                    $runspace.powershell = $null                 
                } ElseIf ($runspace.Runspace -ne $null) {
                    $more = $true
                }
            }
            If ($more -AND $PSBoundParameters['Wait']) {
                Start-Sleep -Milliseconds 100
            }   
            #Clean out unused runspace jobs
            $temphash = $runspaces.clone()
            $temphash | Where {
                $_.runspace -eq $Null
            } | ForEach {
                Write-Verbose ("Removing {0}" -f $_.computer)
                $Runspaces.remove($_)
            }             
        } while ($more -AND $PSBoundParameters['Wait'])
    }

    #region ScriptBlock
        $scriptBlock = {
        Param ($Computer,$Group,$Depth,$NetBIOSDomain,$ObjNT,$Translate)            
        $Script:Depth = $Depth
        $Script:ObjNT = $ObjNT
        $Script:Translate = $Translate
        $Script:NetBIOSDomain = $NetBIOSDomain
        Function Get-LocalGroupMember {
            [cmdletbinding()]
            Param (
                [parameter()]
                [System.DirectoryServices.DirectoryEntry]$LocalGroup
            )
            # Invoke the Members method and convert to an array of member objects.
            $Members= @($LocalGroup.psbase.Invoke("Members"))
            $Counter++
            ForEach ($Member In $Members) {                
                Try {
                    $Name = $Member.GetType().InvokeMember("Name", 'GetProperty', $Null, $Member, $Null)
                    $Path = $Member.GetType().InvokeMember("ADsPath", 'GetProperty', $Null, $Member, $Null)
                    # Check if this member is a group.
                    $isGroup = ($Member.GetType().InvokeMember("Class", 'GetProperty', $Null, $Member, $Null) -eq "group")
                    If (($Path -like "*/$Computer/*")) {
                        $Type = 'Local'
                    } Else {$Type = 'Domain'}
                    New-Object PSObject -Property @{
                        Computername = $Computer
                        Name = $Name
                        Type = $Type
                        ParentGroup = $LocalGroup.Name[0]
                        isGroup = $isGroup
                        Depth = $Counter
                    }
                    If ($isGroup) {
                        # Check if this group is local or domain.
                        #$host.ui.WriteVerboseLine("(RS)Checking if Counter: {0} is less than Depth: {1}" -f $Counter, $Depth)
                        If ($Counter -lt $Depth) {
                            If ($Type -eq 'Local') {
                                If ($Groups[$Name] -notcontains 'Local') {
                                    $host.ui.WriteVerboseLine(("{0}: Getting local group members" -f $Name))
                                    $Groups[$Name] += ,'Local'
                                    # Enumerate members of local group.
                                    Get-LocalGroupMember $Member
                                }
                            } Else {
                                If ($Groups[$Name] -notcontains 'Domain') {
                                    $host.ui.WriteVerboseLine(("{0}: Getting domain group members" -f $Name))
                                    $Groups[$Name] += ,'Domain'
                                    # Enumerate members of domain group.
                                    Get-DomainGroupMember $Member $Name $True
                                }
                            }
                        }
                    }
                } Catch {
                    $host.ui.WriteWarningLine(("GLGM{0}" -f $_.Exception.Message))
                }
            }
        }

        Function Get-DomainGroupMember {
            [cmdletbinding()]
            Param (
                [parameter()]
                $DomainGroup, 
                [parameter()]
                [string]$NTName, 
                [parameter()]
                [string]$blnNT
            )
            Try {
                If ($blnNT -eq $True) {
                    # Convert NetBIOS domain name of group to Distinguished Name.
                    $objNT.InvokeMember("Set", "InvokeMethod", $Null, $Translate, (3, ("{0}{1}" -f $NetBIOSDomain.Trim(),$NTName)))
                    $DN = $objNT.InvokeMember("Get", "InvokeMethod", $Null, $Translate, 1)
                    $ADGroup = [ADSI]"LDAP://$DN"
                } Else {
                    $DN = $DomainGroup.distinguishedName
                    $ADGroup = $DomainGroup
                }         
                $Counter++   
                ForEach ($MemberDN In $ADGroup.Member) {
                    $MemberGroup = [ADSI]("LDAP://{0}" -f ($MemberDN -replace '/','\/'))
                    New-Object PSObject -Property @{
                        Computername = $Computer
                        Name = $MemberGroup.name[0]
                        Type = 'Domain'
                        ParentGroup = $NTName
                        isGroup = ($MemberGroup.Class -eq "group")
                        Depth = $Counter
                    }
                    # Check if this member is a group.
                    If ($MemberGroup.Class -eq "group") {              
                        If ($Counter -lt $Depth) {
                            If ($Groups[$MemberGroup.name[0]] -notcontains 'Domain') {
                                Write-Verbose ("{0}: Getting domain group members" -f $MemberGroup.name[0])
                                $Groups[$MemberGroup.name[0]] += ,'Domain'
                                # Enumerate members of domain group.
                                Get-DomainGroupMember $MemberGroup $MemberGroup.Name[0] $False
                            }                                                
                        }
                    }
                }
            } Catch {
                $host.ui.WriteWarningLine(("GDGM{0}" -f $_.Exception.Message))
            }
        }
        #region Get Local Group Members
        $Script:Groups = @{}
        $Script:Counter=0
        # Bind to the group object with the WinNT provider.
        $ADSIGroup = [ADSI]"WinNT://$Computer/$Group,group"
        Write-Verbose ("Checking {0} membership for {1}" -f $Group,$Computer)
        $Groups[$Group] += ,'Local'
        Get-LocalGroupMember -LocalGroup $ADSIGroup
        #endregion Get Local Group Members
    }
    #endregion ScriptBlock
    Write-Verbose ("Checking to see if connected to a domain")
    Try {
        $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
        $Root = $Domain.GetDirectoryEntry()
        $Base = ($Root.distinguishedName)

        # Use the NameTranslate object.
        $Script:Translate = New-Object -comObject "NameTranslate"
        $Script:objNT = $Translate.GetType()

        # Initialize NameTranslate by locating the Global Catalog.
        $objNT.InvokeMember("Init", "InvokeMethod", $Null, $Translate, (3, $Null))

        # Retrieve NetBIOS name of the current domain.
        $objNT.InvokeMember("Set", "InvokeMethod", $Null, $Translate, (1, "$Base"))
        [string]$Script:NetBIOSDomain =$objNT.InvokeMember("Get", "InvokeMethod", $Null, $Translate, 3)  
    } Catch {Write-Warning ("{0}" -f $_.Exception.Message)}         

    #region Runspace Creation
    Write-Verbose ("Creating runspace pool and session states")
    $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
    $runspacepool = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
    $runspacepool.Open()  

    Write-Verbose ("Creating empty collection to hold runspace jobs")
    $Script:runspaces = New-Object System.Collections.ArrayList        
    #endregion Runspace Creation
}

Process {
    ForEach ($Computer in $Computername) {
        #Create the powershell instance and supply the scriptblock with the other parameters 
        $powershell = [powershell]::Create().AddScript($scriptBlock).AddArgument($computer).AddArgument($Group).AddArgument($Depth).AddArgument($NetBIOSDomain).AddArgument($ObjNT).AddArgument($Translate)

        #Add the runspace into the powershell instance
        $powershell.RunspacePool = $runspacepool

        #Create a temporary collection for each runspace
        $temp = "" | Select-Object PowerShell,Runspace,Computer
        $Temp.Computer = $Computer
        $temp.PowerShell = $powershell

        #Save the handle output when calling BeginInvoke() that will be used later to end the runspace
        $temp.Runspace = $powershell.BeginInvoke()
        Write-Verbose ("Adding {0} collection" -f $temp.Computer)
        $runspaces.Add($temp) | Out-Null

        Write-Verbose ("Checking status of runspace jobs")
        Get-RunspaceData @runspacehash   
    }
}
End {
    Write-Verbose ("Finish processing the remaining runspace jobs: {0}" -f (@(($runspaces | Where {$_.Runspace -ne $Null}).Count)))
    $runspacehash.Wait = $true
    Get-RunspaceData @runspacehash

    #region Cleanup Runspace
    Write-Verbose ("Closing the runspace pool")
    $runspacepool.close()  
    $runspacepool.Dispose() 
    #endregion Cleanup Runspace    
}
函数获取LocalGroupMembership{
[cmdletbinding()]
Param(
[参数(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[别名(“CN”、“服务器”、“计算机”、“IP地址”)]
[string[]$Computername=$env:Computername,
[参数()]
[string]$Group=“Administrators”,
[参数()]
[int]$Depth=([int]::MaxValue),
[参数()]
[别名(“MaxJobs”)]
[int]$Throttle=10
)
开始{
$PSBoundParameters.GetEnumerator()| ForEach{
长篇大论$_
}
#区域额外配置
详细写入(“深度:{0}”-f$Depth)
#端区额外配置
#为Get RunspaceData函数定义哈希表
$runspacehash=@{}
#用于执行运行空间作业清理的函数
函数Get RunspaceData{
[cmdletbinding()]
param(
[切换]$等待
)
做{
$more=$false
Foreach($runspace中的$runspaces){
If($runspace.runspace.isCompleted){
$runspace.powershell.EndInvoke($runspace.runspace)
$runspace.powershell.dispose()
$runspace.runspace=$null
$runspace.powershell=$null
}ElseIf($runspace.runspace-ne$null){
$more=$true
}
}
If($more-和$PSBoundParameters['Wait'])){
开始睡眠-100毫秒
}   
#清除未使用的运行空间作业
$temphash=$runspaces.clone()
$temphash |在哪里{
$\运行空间-eq$Null
}| ForEach{
详细写入(“删除{0}”-f$\计算机)
$Runspaces.remove($\ux)
}             
}而($more-和$PSBoundParameters['Wait']))
}
#区域脚本块
$scriptBlock={
参数($Computer、$Group、$Depth、$NetBIOSDomain、$ObjNT、$Translate)
$Script:Depth=$Depth
$Script:ObjNT=$ObjNT
$Script:Translate=$Translate
$Script:NetBIOSDomain=$NetBIOSDomain
函数Get LocalGroupMember{
[cmdletbinding()]
Param(
[参数()]
[System.DirectoryServices.DirectoryEntry]$LocalGroup
)
#调用Members方法并转换为成员对象数组。
$Members=@($LocalGroup.psbase.Invoke(“成员”))
美元柜台++
ForEach($Members中的成员){
试一试{
$Name=$Member.GetType().InvokeMember(“Name”、'GetProperty'、$Null、$Member、$Null)
$Path=$Member.GetType().InvokeMember(“ADsPath”、'GetProperty'、$Null、$Member、$Null)
#检查此成员是否为组。
$isGroup=($Member.GetType().InvokeMember(“类”、'GetProperty'、$Null、$Member、$Null)-eq“组”)
If(($Path-like“*/$Computer/*”){
$Type='Local'
}Else{$Type='Domain'}
新对象PSObject-属性@{
Computername=$Computer
Name=$Name
Type=$Type
ParentGroup=$LocalGroup.Name[0]
isGroup=$isGroup
深度=$计数器
}
如果($isGroup){
#检查此组是本地组还是域组。
#$host.ui.WriteEverBoseline(“(RS)检查计数器:{0}是否小于深度:{1}”-f$Counter,$Depth)
如果($计数器-lt$深度){
如果($Type-eq‘Local’){
如果($Groups[$Name]-notcontains'Local'){
$host.ui.WriteEverBoseline((“{0}:获取本地组成员”-f$Name))
$Groups[$Name]+=,“本地”
#枚举本地组的成员。
获取LocalGroupMember$Member
}
}否则{
如果($Groups[$Name]-不包含“域”){
$host.ui.WriteEverBoseline((“{0}:获取域组成员”-f$Name))
$Groups[$Name]+=,“域”
#枚举域组的成员。
获取DomainGroupMember$Member$Name$True
}
}
}
}
}抓住{
$host.ui.WriteWarningLine((((“GLGM{0}”-f$\.Exception.Message))
}
}
}
函数Get DomainGroupMember{
[cmdletbinding()]
Param(
[参数()]
$DomainGroup,
[参数()]
[字符串]$NTName,
[参数()]
[字符串]$blnNT
)
试一试{
如果($blnNT-eq$True){
#将组的NetBIOS域名转换为可分辨名称。
$objNT.InvokeMember(“Set”,“InvokeMethod”,“Null”,“Translate,(3,(“{0}{1}”-f$NetBIOSDomain.Trim(),$NTName)))
$DN=$objNT.InvokeMember(“Get”、“InvokeMethod”、$Null、$Translate,1)
$ADGroup=[ADSI]
import-csv T:\computers.csv | Get-LocalGroupMembership 
import-csv T:\computers.csv | Get-LocalGroupMembership | Where Name | Export-CSV t:\LocalAdmins.csv