通过 WMI 查询获取帐户状态

时间:2021-03-28 07:29:49

标签: powershell

我将使用 WMI 查询管理员组成员身份的服务器。我的问题是:我也想通过 WMI 查询获取帐户状态。 顺便说一句,没有必要的组状态,例如域管理员等。

我想要的输出:

"UserName","Fullname","Machinename","DomainName","Account Status"
"localuser","MACHINE\localuser","MACHINE","MACHINE","OK"
"Domain Admins","CONTOSO\Domain Admins","MACHINE","CONTOSO"
"domain_user_01","CONTOSO\domain_user_01","MACHINE","CONTOSO","Degraded"

脚本:

function get-localadministrators {
    param ([string]$computername=$env:computername)

    $computername = $computername.toupper()
    $ADMINS = get-wmiobject -computername $computername -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}

    foreach ($ADMIN in $ADMINS) {
                $admin = $admin.replace("\\$computername\root\cimv2:Win32_UserAccount.Domain=","") # trims the results for a user
                $admin = $admin.replace("\\$computername\root\cimv2:Win32_Group.Domain=","") # trims the results for a group
                $admin = $admin.replace('",Name="',"\")
                $admin = $admin.REPLACE("""","")#strips the last "

                $objOutput = New-Object PSObject -Property @{
                    Machinename = $computername
                    
                    Fullname = ($admin)
                    DomainName  =$admin.split("\")[0]
                    UserName = $admin.split("\")[1]
                }#end object

    $objreport+=@($objoutput)
    }#end for

    return $objreport
}#end function

2 个答案:

答案 0 :(得分:2)

继续我的评论。

您可以使用 WMI 或 ADSI 来执行此操作,但 PowerShell v5 及更高版本已经具有用于此用例的 cmdlet。

以下所有内容都使用类中的原始属性名称。当然,如果您想要不同的名称,可以使用哈希表、PSCustomObject 或计算属性来实现。

Get-Command  -Module '*local*' | 
Format-Table -AutoSize
# Results
<#
CommandType     Name                                               Version    Source                                                                             
-----------     ----                                               -------    ------                                                                             
Cmdlet          Add-LocalGroupMember                               1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Disable-LocalUser                                  1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Enable-LocalUser                                   1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Get-LocalGroup                                     1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Get-LocalGroupMember                               1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Get-LocalUser                                      1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          New-LocalGroup                                     1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          New-LocalUser                                      1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Remove-LocalGroup                                  1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Remove-LocalGroupMember                            1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Remove-LocalUser                                   1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Rename-LocalGroup                                  1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Rename-LocalUser                                   1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Set-LocalGroup                                     1.0.0.0    Microsoft.PowerShell.LocalAccounts                                                 
Cmdlet          Set-LocalUser                                      1.0.0.0    Microsoft.PowerShell.LocalAccounts
#>

如果您使用的是默认情况下没有此功能的 PSVersion,您可以在此处获取:

Find-Module -Name '*local*' | 
Format-Table -AutoSize
# Results
<#
Version Name                                                     Repository Description                                                                          
------- ----                                                     ---------- -----------                                                                          
...
1.6     localaccount                                             PSGallery  A Simple module to allow the management of local users and groups on a computer      
1.0.0.0 Microsoft.PowerShell.LocalAccounts                       PSGallery  Provides cmdlets to work with local users and local groups                           
3.0     LocalUserManagement                                      PSGallery  a module that performs various local user management functions                       
1.3     LocalMachine                                             PSGallery  Simple management functions for accounts and settings on a local machine.            
0.1.1   LocalAccountManagement                                   PSGallery  Manage local and remote user accounts and profiles                                   
...
1.0.1   cLocalGroup                                              PSGallery  The cLocalGroup module contains the cLocalGroup DSC resource that provides a mecha...
2.1.0   ECS.LocalGPO                                             PSGallery  This Windows PowerShell module contains functions used for working with Windows lo...
...
#>

如果您坚持使用 WMI,那么...

发现您必须使用的内容以及任何相关的类关系

# Group Detail
Clear-Host
((Get-WmiObject -Class Win32_Group) -match 'Administrators')[0] |
Select-Object -Property '*'
<#
PSComputerName   : 570A5E12-BA93-4
Status           : OK
Name             : Administrators
__GENUS          : 2
__CLASS          : Win32_Group
__SUPERCLASS     : Win32_Account
__DYNASTY        : CIM_ManagedSystemElement
__RELPATH        : Win32_Group.Domain="570A5E12-BA93-4",Name="Administrators"
__PROPERTY_COUNT : 9
__DERIVATION     : {Win32_Account, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER         : 570A5E12-BA93-4
__NAMESPACE      : root\cimv2
__PATH           : \\570A5E12-BA93-4\root\cimv2:Win32_Group.Domain="570A5E12-BA93-4",Name="Administrators"
Caption          : 570A5E12-BA93-4\Administrators
Description      : Administrators have complete and unrestricted access to the computer/domain
Domain           : 570A5E12-BA93-4
InstallDate      : 
LocalAccount     : True
SID              : S-1-5-32-544
SIDType          : 4
... 
#>

Get-WmiObject -Class Win32_Group | 
Select-Object -Property Name, SIDType
# Results
<#
Name                                SIDType
----                                -------
...
Administrators                            4
...
Guests                                    4
...
Users                                     4
#>

# User Detail
Clear-Host
(Get-WmiObject -Class Win32_Account)[0] | 
Select-Object -Property '*'
<#
PSComputerName     : 570A5E12-BA93-4
Status             : Degraded
Caption            : 570A5E12-BA93-4\Administrator
PasswordExpires    : False
__GENUS            : 2
__CLASS            : Win32_UserAccount
__SUPERCLASS       : Win32_Account
__DYNASTY          : CIM_ManagedSystemElement
__RELPATH          : Win32_UserAccount.Domain="570A5E12-BA93-4",Name="Administrator"
__PROPERTY_COUNT   : 16
__DERIVATION       : {Win32_Account, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER           : 570A5E12-BA93-4
__NAMESPACE        : root\cimv2
__PATH             : \\570A5E12-BA93-4\root\cimv2:Win32_UserAccount.Domain="570A5E12-BA93-4",Name="Administrator"
AccountType        : 512
Description        : Built-in account for administering the computer/domain
Disabled           : True
Domain             : 570A5E12-BA93-4
FullName           : 
InstallDate        : 
LocalAccount       : True
Lockout            : False
Name               : Administrator
PasswordChangeable : True
PasswordRequired   : True
SID                : S-1-5-21-2047949552-857980807-821054962-500
SIDType            : 1
...
#>


Get-WmiObject -Class Win32_Account | 
Select-Object -Property Name, SIDType
# Results
<#
Name                                SIDType
----                                -------
Administrator                             1
DefaultAccount                            1
Guest                                     1
WDAGUtilityAccount                        1
Everyone                                  5
...
BUILTIN                                   3
...
Administrators                            4
...
Guests                                    4
...
Users                                     4
#>

下面将通过首先选择用户来为您提供所有用户和所属组,这就是您在帖子中显示的内容,但实际上是短路逻辑,因为您只在您的在管理员中查询。那么,这...

仅选择您需要的内容。注意 SIDType 代码作为过滤器的重点

Clear-Host
Get-WmiObject -Class Win32_Account | 
Where-Object -Property SIDType -eq 1 |
Select-Object -Property PSComputerName, Name, Status, 
@{
    Name       = 'Groups'
    Expression = {($PSItem).GetRelated('Win32_Group').Name}
} | 
Format-Table -AutoSize
# Results
<#

PSComputerName  Name               Status   Groups                                
--------------  ----               ------   ------                                
570A5E12-BA93-4 Administrator      Degraded Administrators                        
570A5E12-BA93-4 DefaultAccount     Degraded System Managed Accounts Group         
570A5E12-BA93-4 Guest              Degraded Guests                                
570A5E12-BA93-4 WDAGUtilityAccount OK       {Administrators, Remote Desktop Users}
#>

当然,如果您愿意,您可以使用 RegEx 来摆脱大括号。最后,删除 Where-Object 行和 SIDType 过滤器,您就可以完成所有操作。

Clear-Host
Get-WmiObject -Class Win32_Account | 
Select-Object -Property PSComputerName, Name, Status, 
@{
    Name       = 'Groups'
    Expression = {($PSItem).GetRelated('Win32_Group').Name}
} | 
Format-Table -AutoSize
# Results
<#
PSComputerName  Name                                Status   Groups                                
--------------  ----                                ------   ------                                
570A5E12-BA93-4 Administrator                       Degraded Administrators                        
570A5E12-BA93-4 DefaultAccount                      Degraded System Managed Accounts Group         
570A5E12-BA93-4 Guest                               Degraded Guests                                
570A5E12-BA93-4 WDAGUtilityAccount                  OK       {Administrators, Remote Desktop Users}
570A5E12-BA93-4 Everyone                            OK                                             
...                                         
570A5E12-BA93-4 NETWORK                             OK                                             
570A5E12-BA93-4 BATCH                               OK                                             
570A5E12-BA93-4 INTERACTIVE                         OK       Users                                 
...                                          
570A5E12-BA93-4 SELF                                OK                                             
570A5E12-BA93-4 Authenticated Users                 OK       Users                                 
570A5E12-BA93-4 RESTRICTED                          OK                                             
...                                           
570A5E12-BA93-4 IUSR                                OK       IIS_IUSRS                             
...    
#>

反向请求---只选择你需要的,不需要SIDType。

Clear-Host
Get-WmiObject -Class Win32_Group | 
Select-Object -Property PSComputerName, Name, Status, 
@{
    Name       = 'GroupMembers'
    Expression = {
        (
            Get-WmiObject -Class win32_group | 
            Where Name -eq $PSItem.Name).GetRelated('Win32_UserAccount'
        ).Name
    }
} | 
Format-Table -AutoSize
# Results
<#
PSComputerName  Name                                Status GroupMembers                       
--------------  ----                                ------ ------------                       
570A5E12-BA93-4 Access Control Assistance Operators OK                                        
570A5E12-BA93-4 Administrators                      OK     {Administrator, WDAGUtilityAccount}
570A5E12-BA93-4 Backup Operators                    OK                                        
570A5E12-BA93-4 Cryptographic Operators             OK                                        
570A5E12-BA93-4 Device Owners                       OK                                        
570A5E12-BA93-4 Distributed COM Users               OK                                        
570A5E12-BA93-4 Event Log Readers                   OK                                        
570A5E12-BA93-4 Guests                              OK     Guest                              
570A5E12-BA93-4 Hyper-V Administrators              OK                                        
570A5E12-BA93-4 IIS_IUSRS                           OK                                        
570A5E12-BA93-4 Network Configuration Operators     OK                                        
570A5E12-BA93-4 Performance Log Users               OK                                        
570A5E12-BA93-4 Performance Monitor Users           OK                                        
570A5E12-BA93-4 Power Users                         OK                                        
570A5E12-BA93-4 Remote Desktop Users                OK     WDAGUtilityAccount                 
570A5E12-BA93-4 Remote Management Users             OK                                        
570A5E12-BA93-4 Replicator                          OK                                        
570A5E12-BA93-4 System Managed Accounts Group       OK     DefaultAccount                     
570A5E12-BA93-4 Users                               OK                                        
#>

如果正确设置 PSRemoting(域或工作组模式),则访问远程系统很简单。

# Target a remote computer
Clear-Host
Import-Csv -Path 'D:\Temp\ComputerList.csv' | 
ForEach-Object {
    Get-WmiObject -Class Win32_Account -ComputerName $PSitem.Name -Credential (Get-Credential -Credential WDAGUtilityAccount) | 
    Where-Object -Property SIDType -eq 1 |
    Select-Object -Property PSComputerName, Name, Status, 
    @{
        Name       = 'Groups'
        Expression = {($PSItem).GetRelated('Win32_Group').Name}
    }
} | 
Format-Table -AutoSize
# Results
<#
PSComputerName  Name               Status   Groups                                
--------------  ----               ------   ------                                
570A5E12-BA93-4 Administrator      Degraded Administrators                                    
570A5E12-BA93-4 DefaultAccount     Degraded System Managed Accounts Group         
570A5E12-BA93-4 Guest              Degraded Guests                                
570A5E12-BA93-4 TestUser           OK       Users                                 
570A5E12-BA93-4 WDAGUtilityAccount OK       {Administrators, Remote Desktop Users}
#>

至于您的详细信息

<#
"UserName","Fullname","Machinename","DomainName","Account Status"
"localuser","MACHINE\localuser","MACHINE","MACHINE","OK"
"Domain Admins","CONTOSO\Domain Admins","MACHINE","CONTOSO"
"domain_user_01","CONTOSO\domain_user_01","MACHINE","CONTOSO","Degraded"
#>


# Only the administrators group
Clear-Host
Get-WmiObject -Class Win32_Account | 
Where-Object -Property SIDType -eq 1 |
Select-Object -Property Name, Caption, PSComputerName, Domain, Status, 
@{
    Name       = 'Groups'
    Expression = {($PSItem).GetRelated('Win32_Group').Name}
} | 
Where-Object -Property Groups -EQ 'Administrators'| 
Format-Table -AutoSize
# Results
<#
Name               Caption                            PSComputerName  Domain          Status   Groups                                
----               -------                            --------------  ------          ------   ------                                
Administrator      570A5E12-BA93-4\Administrator      570A5E12-BA93-4 570A5E12-BA93-4 Degraded Administrators                        
WDAGUtilityAccount 570A5E12-BA93-4\WDAGUtilityAccount 570A5E12-BA93-4 570A5E12-BA93-4 OK       {Administrators, Remote Desktop Users}
#>


Clear-Host
Get-WmiObject -Class Win32_Group | 
Select-Object -Property Name, Caption, PSComputerName, Domain, Status, 
@{
    Name       = 'GroupMembers'
    Expression = {
        (
            Get-WmiObject -Class win32_group | 
            Where Name -eq $PSItem.Name).GetRelated('Win32_UserAccount'
        ).Name
    }
} | 
Format-Table -AutoSize
# Results
<#
Name                                Caption                                             PSComputerName  Domain          Status GroupMembers                       
----                                -------                                             --------------  ------          ------ ------------                       
Access Control Assistance Operators 570A5E12-BA93-4\Access Control Assistance Operators 570A5E12-BA93-4 570A5E12-BA93-4 OK                                        
Administrators                      570A5E12-BA93-4\Administrators                      570A5E12-BA93-4 570A5E12-BA93-4 OK     {Administrator, WDAGUtilityAccount}
...                       
#>


# Only the administrators group
Clear-Host
Get-WmiObject -Class Win32_Group | 
Where-Object -Property Name -eq 'Administrators' | 
Select-Object -Property Name, Caption, PSComputerName, Domain, Status, 
@{
    Name       = 'GroupMembers'
    Expression = {
        (
            Get-WmiObject -Class win32_group | 
            Where Name -eq $PSItem.Name).GetRelated('Win32_UserAccount'
        ).Name
    }
}  | 
Format-Table -AutoSize 
# Results
<#
Name           Caption                        PSComputerName  Domain          Status GroupMembers                       
----           -------                        --------------  ------          ------ ------------                       
Administrators 570A5E12-BA93-4\Administrators 570A5E12-BA93-4 570A5E12-BA93-4 OK     {Administrator, WDAGUtilityAccount}
#>

根据您的评论进行更新。

至于这个...

<块引用>

我可以通过 directoryservices .NET 类而不是 WMI 来编写吗

当然可以,详见此处...

<块引用>

https://devblogs.microsoft.com/scripting/the-admins-first-steps-local-group-membership

...但使用它不会返回您列出的输出。

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-Object -Property '*' -First 1
# Results
<#
GivenName                         : 
MiddleName                        : 
Surname                           : 
EmailAddress                      : 
VoiceTelephoneNumber              : 
EmployeeId                        : 
AdvancedSearchFilter              : System.DirectoryServices.AccountManagement.AdvancedFilters
Enabled                           : False
AccountLockoutTime                : 
LastLogon                         : 
PermittedWorkstations             : {}
PermittedLogonTimes               : {255, 255, 255, 255...}
AccountExpirationDate             : 
SmartcardLogonRequired            : False
DelegationPermitted               : True
BadLogonCount                     : 0
HomeDirectory                     : 
HomeDrive                         : 
ScriptPath                        : 
LastPasswordSet                   : 3/28/2021 10:20:29 AM
LastBadPasswordAttempt            : 
PasswordNotRequired               : False
PasswordNeverExpires              : True
UserCannotChangePassword          : False
AllowReversiblePasswordEncryption : False
Certificates                      : {}
Context                           : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType                       : Machine
Description                       : Built-in account for administering the computer/domain
DisplayName                       : 
SamAccountName                    : Administrator
UserPrincipalName                 : 
Sid                               : S-1-5-21-2047949552-857980807-821054962-500
Guid                              : 
DistinguishedName                 : 
StructuralObjectClass             : 
Name                              : Administrator
#>

答案 1 :(得分:0)

要回答您的评论...

你说

<块引用>

如何优化这个脚本,有200台机器,需要一个世纪...

<块引用>

...那么,我如何通过 directoryservices .NET 类而不是 WMI 进行编写?是否有可能?你有这方面的信息吗? – Arbelac 6 小时前

如果您确实需要在大量机器上运行一个命令并且您具有远程访问权限,则可以查看 ForEach-ParallelInvoke-Parallel,这是在多台机器上运行一个命令的两种不同选项.

但是您将需要处理远程状态,例如担心如果远程机器处于离线状态该怎么办,或者担心当您尝试联系机器时无法访问该机器时该怎么办。

更简单的选择

你已经有了一个环境,好吧,让我们想想其他方法来实现同样的目标。

您可以改为使用组策略在每台机器上本地运行此命令作为登录脚本。然后,机器可以将它们的输出写入某个中央共享中的 JsonCsv 文件,如果有的话,可能是 ADFS。

您还可以使用已安装在机器上的任何远程代理,例如 System Center Configuration Manager、Shalvik 或您可能拥有的任何其他应用。

因此,总结一下我的答案,您可以使用 PowerShell Remoting 来执行此操作,但听起来这会给您带来问题,您可能需要考虑使用其他系统分发作业。

来源:多年来一直担任系统管理员和自动化工程师。我可能不会像这样使用 PowerShell 远程处理。

相关问题