10

次のコードを使用して、ローカルの Administrators グループのメンバーを特定します。

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

このコードは、PowerShell 2.0 ~ 4.0 で機能します。ただし、PowerShell 5.0 を搭載した Windows 10 マシンでは、壊れます。ローカルの Administrators グループのメンバーであるローカルアカウントごとに、次のエラーがスローされます。

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

Administrators のメンバーであるドメイン アカウントの場合、エラーは生成されません。

私を困惑させているGetType()のは、オブジェクトのメンバーであるため (コマンドを手でトレースしたため)、エラーが発生する理由がわかりません。

PowerShell 5.0 の変更ログを調べましたが、この動作を明確に説明するものは何も見つかりませんでした。

なぜこうなった?PowerShell 5.0 でローカル グループのメンバーを出力するより良い方法があれば教えてください。

4

4 に答える 4

12

自分でこの問題に遭遇し、回避策を見つけました(Windows 10および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"
于 2015-08-20T14:40:09.610 に答える
5

ジェイミーの答えはあなたの特定の問題にぴったりでしたが、メンバーから複数のプロパティを取得する必要があります. コードを変更せずにこの問題に対処できることがわかりました。コードを呼び出すInvokeGetTypeに、コードを呼び出しますInvokeMember()以下のコードでは、GetType の後にそれがないことに注意してください。

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

これは、グループ メンバーに関する詳細情報を提供する私のユース ケースです。これには、Resolve-DNS コマンドを使用するため、PowerShell 4.0 が必要です。

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
}
于 2015-12-29T18:28:04.897 に答える
1

誰かが利用可能な回避策を持っている可能性があるため、ここにバグを投稿することをお勧めします。

于 2015-08-12T01:30:05.690 に答える