6

Ich verwende den folgenden Code Mitglieder der lokalen Administrator-Gruppe zu bestimmen:Print Lokale Gruppenmitglieder in Powershell 5.0

$obj_group = [ADSI]"WinNT://localhost/Administrators,group" 
[email protected]($obj_group.Invoke("Members"))|foreach{$_.GetType().InvokeMember("Name","GetProperty",$null,$_,$null)} 
Write-Output "Current local Administrators: $members" 

Dieser Code funktioniert in Powershell 2,0-4,0. Auf meinem Windows 10-Computer mit PowerShell 5.0 bricht es jedoch. Für jedes lokale Konto, das ein Mitglied der lokalen Administrator-Gruppe ist, wirft es die folgenden Fehler:

Error while invoking GetType. Could not find member. 
At line:2 char:54 
+ ... "))|foreach{$_.GetType().InvokeMember("Name","GetProperty",$null,$_,$ ... 
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : OperationStopped: (:) [], MissingMemberException 
    + FullyQualifiedErrorId : System.MissingMemberException 

für Domänenkonten, die ein Mitglied der Administratoren sind, wird kein Fehler erzeugt.

Die Sache, die mich verwirrt, ist GetType() ist ein Mitglied des Objekts (ich führte den Befehl von Hand), so dass ich nicht sicher bin, warum es aus Fehler.

Ich schaute auf das Änderungsprotokoll für PowerShell 5.0 und sah nichts, das dieses Verhalten offensichtlich erklären würde.

Warum passiert das? Gibt es eine bessere Möglichkeit zum Drucken von Mitgliedern einer lokalen Gruppe in PowerShell 5.0?

Antwort

10

Liefen in diese Frage selbst und eine Abhilfe heraus (getestet in Windows 10 und 8,1)

$obj_group = [ADSI]"WinNT://localhost/Administrators,group" 
$members= @($obj_group.psbase.Invoke("Members")) | foreach{([ADSI]$_).InvokeGet("Name")} 
Write-Output "Current local Administrators: $members" 
+0

Das hat es behoben. Getestet in XP (PowerShell 2.0), Windows 7 (PowerShell 4.0) und Windows 10 (PowerShell 5.0). –

1

Sie könnten den Fehler here als jemand eine Problemumgehung verfügbar haben möchten.

+0

Es wurde bereits gebucht: https://connect.microsoft.com/PowerShell/feedback/details/1437366/powershell-5-bug- in-gettype-for-com-Objekte-iadsuser –

2

Jamie Antwort für Ihr spezifisches Problem war perfekt, aber ich habe eine Notwendigkeit, mehrere Eigenschaften von den Mitgliedern zu bekommen . Ich habe festgestellt, dass Sie dieses Problem beheben können, ohne Ihren Code zu ändern, indem Sie Invoke gegen GetType anrufen, bevor Sie InvokeMember dagegen aufrufen. Beachten Sie, dass GetType nicht mehr (), nachdem es in dem unten stehenden Code:

$obj_group = [ADSI]"WinNT://localhost/Administrators,group" 
[email protected]($obj_group.Invoke("Members"))|foreach{$_.GetType.Invoke().InvokeMember("Name","GetProperty",$null,$_,$null)} 
Write-Output "Current local Administrators: $members" 

Das ist mein Anwendungsfall war, die mehr Informationen über die Gruppenmitglieder zur Verfügung stellt. Dies erfordert PowerShell 4.0 aufgrund der Verwendung des Resolve-DNS-Befehls:

function Get-LocalGroupMembers { 
<# 
.Synopsis 
    Get the group membership of a local group on the local or a remote computer 
.EXAMPLE 
    Defaults to collecting the members of the local Administrators group 

    PS C:\> Get-LocalGroupMembers | ft -AutoSize 

    ComputerName ParentGroup Nesting Name   Domain  Class 
    ------------ ----------- ------- ----   ------  ----- 
    EricsComputer     0 Administrator EricsComp User 
    EricsComputer     0 eric   EricsComp User 
    EricsComputer     0 Domain Admins DomainName Group 
.EXAMPLE 
    Query a remote computer (that is known not to respond to a ping) and a targeted group 

    PS C:\> Get-LocalGroupMembers -computerName EricsComputer -localgroupName Users -pingToEstablishUpDown $false 

    ComputerName ParentGroup Nesting Name   Domain  Class 
    ------------ ----------- ------- ----   ------  ----- 
    EricsComputer     0 SomeOtherGuy EricsComp User 

.NOTES 
    The ParentGroup and Nesting attributes in the output are present to allow 
    the output of this function to be combined with the output of 
    Get-ADNestedGroupMembers. They serve no purpose otherwise. 
#> 
    Param(
     $computerName = $env:computername, 
     $localgroupName = "Administrators", 
     $pingToEstablishUpDown = $true 
    ) 
    $requestedComputerName = $computerName 
    if ($computername = Resolve-DnsName $computername) { 
     $computername = ($computername | where querytype -eq A).Name 
     if ($computername -ne $requestedComputerName) { 
      Write-Warning "Using name $computerName for $requestedComputerName" 
     } 
    } else { 
     Write-Warning "Unable to resolve $requestedComputerName in DNS" 
     return "" | select @{label="ComputerName";Expression={$requestedComputerName}}, 
             @{label="ParentGroup";Expression={""}}, 
             @{label="Nesting";Expression={""}}, 
             @{Label="Name";Expression={"ComputerName did not resolve in DNS"}}, 
             @{Label="Domain";Expression={"ComputerName did not resolve in DNS"}}, 
             @{Label="Class";Expression={"ComputerName did not resolve in DNS"}} 
    } 
    if ($pingToEstablishUpDown) { 
     if (-not (Test-Connection -count 1 $computerName)) { 
      Write-Warning "Unable to ping $computerName, aborting ADSI connection attempt" 
      return "" | select @{label="ComputerName";Expression={$requestedComputerName}}, 
             @{label="ParentGroup";Expression={""}}, 
             @{label="Nesting";Expression={""}}, 
             @{Label="Name";Expression={"Not available to query"}}, 
             @{Label="Domain";Expression={"Not available to query"}}, 
             @{Label="Class";Expression={"Not available to query"}} 
     } 
    } 
    try { 
     if([ADSI]::Exists("WinNT://$computerName/$localGroupName,group")) {  
      $group = [ADSI]("WinNT://$computerName/$localGroupName,group") 
      $members = @() 
      $Group.Members() | foreach { 
       $AdsPath = $_.GetType.Invoke().InvokeMember("Adspath", 'GetProperty', $null, $_, $null) 
       # Domain members will have an ADSPath like WinNT://DomainName/UserName. 
       # Local accounts will have a value like WinNT://DomainName/ComputerName/UserName. 
       $a = $AdsPath.split('/',[StringSplitOptions]::RemoveEmptyEntries) 
       $name = $a[-1] 
       $domain = $a[-2] 
       $class = $_.GetType.Invoke().InvokeMember("Class", 'GetProperty', $null, $_, $null) 

       $members += "" | select @{label="ComputerName";Expression={$computerName}}, 
             @{label="ParentGroup";Expression={""}}, 
             @{label="Nesting";Expression={0}}, 
             @{Label="Name";Expression={$name}}, 
             @{Label="Domain";Expression={$domain}}, 
             @{Label="Class";Expression={$class}} 
      }  
     } 
     else { 
      Write-Warning "Local group '$localGroupName' doesn't exist on computer '$computerName'" 
     } 
    } 
    catch { 
     Write-Warning "Unable to connect to computer $computerName with ADSI" 
     return $false } 
    return ,$members 
} 
1

Nizza! Brauchte das!

Die .net Weg war auch ein Bypass (http://blogs.technet.com/b/heyscriptingguy/archive/2013/10/27/the-admin-s-first-steps-local-group-membership.aspx)

Add-Type -AssemblyName System.DirectoryServices.AccountManagement 
$ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine 
$computer = $env: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