我将使用 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
答案 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-Parallel
或 Invoke-Parallel
,这是在多台机器上运行一个命令的两种不同选项.
但是您将需要处理远程状态,例如担心如果远程机器处于离线状态该怎么办,或者担心当您尝试联系机器时无法访问该机器时该怎么办。
你已经有了一个环境,好吧,让我们想想其他方法来实现同样的目标。
您可以改为使用组策略在每台机器上本地运行此命令作为登录脚本。然后,机器可以将它们的输出写入某个中央共享中的 Json
或 Csv
文件,如果有的话,可能是 ADFS。
您还可以使用已安装在机器上的任何远程代理,例如 System Center Configuration Manager、Shalvik 或您可能拥有的任何其他应用。
因此,总结一下我的答案,您可以使用 PowerShell Remoting 来执行此操作,但听起来这会给您带来问题,您可能需要考虑使用其他系统分发作业。
来源:多年来一直担任系统管理员和自动化工程师。我可能不会像这样使用 PowerShell 远程处理。