如何在 PowerShell 中转换为用户对象?

How can I cast as a user object in PowerShell?

我有以下代码连接到域中的每台计算机并检查本地管理员组的成员:

Foreach ($Computer in Get-ADComputer -Filter *){
    $Path = $Computer.Path
    $Name = ([ADSI]"$Path").Name
    Write-Host $Name
    $members = [ADSI]"WinNT://$Name/Administrators"
    $members = @($members.psbase.Invoke("Members"))
    ForEach($member in $members){
        Write-Host $member.GetType().InvokeMember("Name", 'GetProperty', $null, $member, $null)
        Write-Host $member.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $member, $null)
    }
}

我正在尝试将 $member 的值存储在某种 $User 对象中,这样我就可以在没有所有疯狂的调用程序的情况下实际引用属性。

例如,在我想要的伪代码中:

$user = (User) $member;
Write-Host $user.Name
Write-Host $user.AdsPath

我是 PowerShell 的新手,但是...我不确定我是否真的了解如何转换为其中的对象类型。

您想要创建具有指定成员和值的自定义对象(或 PSObject):

Foreach ($Computer in Get-ADComputer -Filter *){
    $Path=$Computer.Path
    $Name=([ADSI]"$Path").Name
    write-host $Name
    $members =[ADSI]"WinNT://$Name/Administrators"
    $members = @($members.psbase.Invoke("Members"))
    ForEach($member in $members){
        $propsWanted = @('Name' , 'AdsPath') # An array of the properties you want
        $properties = @{} # This is an empty hashtable, or associative array, to hold the values
        foreach($prop in $propsWanted) {
            $properties[$prop] = $member.GetType().InvokeMember($prop, 'GetProperty', $null, $member, $null)
        }
        $user = New-Object PSObject -Property $properties
        $user # This is an object representing the user
    }
}

只是回顾一些变化:

  1. 我将您想要的所有 属性 名称放入一个数组 $propsWanted 中,然后对其进行迭代以调用并获取每个名称。通过在一个地方添加 属性 名称,您以后可以轻松使用更多属性。
  2. $properties哈希表将存储一对key/value,其中键是属性名称,值是属性值。
  3. 哈希表填满后,可以在创建PSObject时将其传递给New-Object-Property参数。

您应该使用您的新对象并通过测试一些东西来查看:

  • 将其通过管道传输到 Format- cmdlet 以查看各种视图:

    $user | Format-Table
    $user | Format-List
    
  • 直接查看其属性值:

    $user.Name
    $user.AdsPath
    
  • 如果你把这些对象组成一个数组,你可以过滤它们,例如:

    $user | Where-Object { $_.Name -like '*Admin' }
    

备选方案

您可以尝试使用 CIM 或 WMI,这实际上会更友好一些:

CIM

$group = Get-CimInstance -ClassName Win32_Group  -Filter "Name = 'Administrators'"

Get-CimAssociatedInstance -InputObject $group -ResultClassName Win32_UserAccount |

select -ExpandProperty Caption

Get-CimAssociatedInstance -InputObject $group -ResultClassName Win32_Group |

select -ExpandProperty Caption

WMI

$query = "ASSOCIATORS OF {Win32_Group.Domain='$($env:COMPUTERNAME)',Name='Administrators'} WHERE ResultClass = Win32_UserAccount"

Get-WmiObject -Query $query | Select -ExpandProperty Caption

$query = "ASSOCIATORS OF {Win32_Group.Domain='$($env:COMPUTERNAME)',Name='Administrators'} WHERE ResultClass = Win32_Group"

Get-WmiObject -Query $query | Select -ExpandProperty Caption

.NET 3.5 此方法需要:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement

$ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine

$context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $env:COMPUTERNAME

$idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName

$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $idtype, 'Administrators')

$group.Members |

select @{N='Domain'; E={$_.Context.Name}}, samaccountName

归因

以上所有备选方案均直接取自这篇 "Hey, Scripting Guy!" 文章,The Admin's First Steps: Local Group Membership。它详细介绍了所有这些,包括 [ADSI] 方法。值得一读。

如何实际投射

我刚刚意识到我实际上并没有回答这个问题,即使它不是您所需要的。 Classes/types 用方括号指定。事实上,当你这样做时:

[ADSI]"WinNT://$Name/Administrators"

您将 [String]" 中的字符串文字)转换为 [ADSI] 对象,该对象有效,因为 [ADSI] 知道如何处理它。

其他示例:

[int]"5"
[System.Net.IPAddress]'8.8.8.8'

由于我们不知道您正在寻找的 "user" 对象的类型(或者它甚至没有真正加载),您不能使用此方法。