6

J'utilise le code suivant pour déterminer les membres du groupe local Administrateurs:groupe local Membres 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" 

Ce code fonctionne dans PowerShell 2,0 - 4,0. Cependant, sur mon ordinateur Windows 10 avec PowerShell 5.0, il casse. Pour chaque compte local qui est un membre du groupe local Administrateurs, il jette l'erreur suivante:

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 

Pour les comptes de domaine qui sont membres des administrateurs, à aucune erreur. La chose qui me laisse perplexe est GetType() est un membre de l'objet (j'ai tracé la commande à la main), donc je ne suis pas sûr pourquoi il fait erreur.

J'ai regardé le changelog pour PowerShell 5.0 et n'ai rien vu qui puisse expliquer ce comportement.

Pourquoi cela se produit-il? Y a-t-il une meilleure façon d'imprimer les membres d'un groupe local dans PowerShell 5.0?

Répondre

10

a couru dans cette question moi-même et un palliatif (testé dans Windows 10 et 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

Cela l'a corrigé. Testé sous XP (PowerShell 2.0), Windows 7 (PowerShell 4.0) et Windows 10 (PowerShell 5.0). –

1

Vous souhaiterez peut-être publier le bogue here car quelqu'un pourrait avoir une solution de contournement disponible.

+0

Il a déjà été affiché: https://connect.microsoft.com/PowerShell/feedback/details/1437366/powershell-5-bug- in-gettype-for-com-objects-iadsuser –

2

réponse de Jamie était parfaite pour votre problème spécifique, mais j'ai besoin d'obtenir plusieurs propriétés des membres . J'ai trouvé que vous pouvez résoudre ce problème sans autrement changer votre code en appelant Invoke contre GetType avant d'appeler le InvokeMember. Notez que GetType n'a plus () après dans le code ci-dessous:

$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" 

Ce fut mon cas d'utilisation qui fournit plus d'informations sur les membres du groupe. Cela nécessite PowerShell 4.0 en raison de l'utilisation de la commande Resolve-DNS:

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

Nice! J'avais besoin de ça!

La façon .net était aussi un by-pass (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