获取本地组成员:与版本无关

时间:2018-09-16 21:20:02

标签: powershell

我发现this线程提供了两种获取本地组成员的基本方法。

这适用于所有版本的Powershell,但取决于使用旧的NET命令行实用程序。

function Get-LocalGroupMembers() {
  param ([string]$groupName = $(throw "Need a name") )
  $lines = net localgroup $groupName
  $found = $false
  for ($i = 0; $i -lt $lines.Length; $i++ ) {
    if ( $found ) {
      if ( -not $lines[$i].StartsWith("The command completed")) {
        $lines[$i]
      }
    } elseif ( $lines[$i] -match "^----" ) {
      $found = $true;
    }
  }
}

这在PowerShell 2.0中对我有效,但在PS5.0中使用Error while invoking GetType. Could not find member.的barfs 它只会在某些组(包括管理员)中f之以鼻,我认为这是某种安全功能,例如要求提升特权才能真正在脚本中拥有管理员权限。

Function Get-LocalGroupMembers
{
    Param(
        [string]
        $server = "."
    )
    Try
    {
        $computer = [ADSI]"WinNT://$( $Server ),computer"
        $computer.psbase.children | 
            where { 
                $_.psbase.schemaClassName -eq 'group' 
            } |
                ForEach {
                    $GroupName = $_.Name.ToString()
                    $group =[ADSI]$_.psbase.Path
                    $group.psbase.Invoke("Members") |
                        foreach {
                            $memberName = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) -replace "WinNT:", ""

                            $props = @{
                                "LocalGroup" = $GroupName
                                "MemberName" = $memberName
                            }

                            $obj = New-Object -TypeName psobject -Property $props
                            Write-Output $obj
                        } # foreach members
                } # foreach group
    }
    Catch
    {
        Throw
    }
}

我想我在某处读到PS5.1最终具有本机CMDlet。但是我不能依赖特定版本的PS,我需要支持Win7中PS2.0的所有功能。也就是说,是否有不依赖命令行实用程序kludge的单一版本不可知解决方案?还是我需要根据运行的PS版本使用旧的hack或新的CMDlet的代码?

2 个答案:

答案 0 :(得分:0)

因此,我很乐意使用此解决方案。

$hostname = (Get-WmiObject -computerName:'.' -class:Win32_ComputerSystem).name 
$wmiQuery = Get-WmiObject -computerName:'.' -query:"SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$Hostname',Name='$group'`"" 
if ($wmiQuery -ne $null) {  
    :searchLoop foreach ($item in $wmiQuery) {  
       if (((($item.PartComponent -split "\,")[1] -split "=")[1]).trim('"') -eq $user) {
           $localGroup = $true
           break :searchLoop
        }
    }  
 }

我不确定我是否喜欢那种过于复杂的IF和一些变量,但是它的功能已经存在并且可以在所有版本的PS上正常工作,而这并不求助于命令行混乱。 请注意,如果用户是该组的成员,则只返回true,这就是我所需要的。我发布的其他代码将提供成员列表,这是进行检查的基础,而我只是没有修改它以显示真正的最终目标,因为问题没有这个表现出来。

答案 1 :(得分:0)

相反:

$memberName = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) -replace "WinNT:", ""

您可以尝试以下方法:

$memberName = ([ADSI]$_).InvokeGet("Name")