如何通过WMI从域控制器获取域用户信息?含脚本及C#需求
PowerShell脚本修复与C#实现方案
PowerShell修复方案
方案1:使用Active Directory模块(推荐)
此方案依赖RSAT-AD-PowerShell组件(需提前安装),专门针对AD用户管理,属性获取更直接:
# 配置域控制器与凭据 $domainController = "myController" $username = "myUser@my.domain" $password = ConvertTo-SecureString "MyP@ssw03d!*" -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($username, $password) # 查询域用户并提取所需属性 Get-ADUser -Server $domainController -Credential $credential -Filter * -Properties Name, LockedOut, LastLogonDate | Select-Object SamAccountName, Name, LockedOut, @{Name='IsLoggedIn'; Expression={$null -ne $_.LastLogonDate -and $_.LastLogonDate -gt (Get-Date).AddHours(-1)}}
SamAccountName:域用户名Name:用户全名LockedOut:账号锁定状态(布尔值)IsLoggedIn:通过最近1小时内的登录记录判断登录状态(可自行调整时间阈值)
方案2:修复原WMI脚本(无AD模块依赖)
原脚本问题在于错误输出了$_.Properties类型对象,且Win32_LogonSession仅返回登录会话,需关联用户账号才能获取属性:
$domainController = "myController" $username = "myUser@my.domain" $password = ConvertTo-SecureString "MyP@ssw03d!*" -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential($username, $password) # 获取所有登录会话 $sessionQuery = Get-WmiObject -Class Win32_LogonSession -ComputerName $domainController -Credential $credential $sessionQuery | ForEach-Object { # 关联会话对应的用户账号 $user = Get-WmiObject -ComputerName $domainController -Credential $credential ` -Query "ASSOCIATORS OF {Win32_LogonSession.LogonId=$($_.LogonId)} WHERE ResultClass=Win32_UserAccount" if ($user) { # 查询用户锁定状态 $loginProfile = Get-WmiObject -Class Win32_NetworkLoginProfile -ComputerName $domainController -Credential $credential ` -Filter "Name='$($user.Name)'" Write-Host "用户名: $($user.SamAccountName)" Write-Host "全名: $($user.FullName)" Write-Host "锁定状态: $($loginProfile?.LockedOut)" Write-Host "登录状态: 已登录" Write-Host "----------------------" } }
- 移除了原脚本中多余的
Write-Host $_.Properties,避免输出类型名称 - 通过WMI关联查询获取用户账号信息
- 登录状态通过存在有效登录会话判断
C#实现参考
方案1:使用System.DirectoryServices.AccountManagement(推荐,.NET内置)
该命名空间专为AD身份管理设计,无需额外依赖:
using System; using System.DirectoryServices.AccountManagement; using System.Linq; public class DomainUserService { public static void RetrieveDomainUsers(string domainController, string adminUser, string adminPass) { var contextOptions = ContextOptions.Negotiate | ContextOptions.SecureSocketLayer; using (var adContext = new PrincipalContext(ContextType.Domain, domainController, adminUser, adminPass, contextOptions)) { using (var userPrincipal = new UserPrincipal(adContext)) using (var searcher = new PrincipalSearcher(userPrincipal)) { foreach (var result in searcher.FindAll().OfType<UserPrincipal>()) { bool isLoggedIn = result.LastLogon.HasValue && result.LastLogon.Value > DateTime.Now.AddHours(-1); Console.WriteLine($"用户名: {result.SamAccountName}"); Console.WriteLine($"全名: {result.DisplayName}"); Console.WriteLine($"锁定状态: {result.IsAccountLockedOut()}"); Console.WriteLine($"登录状态: {(isLoggedIn ? "已登录" : "未登录")}"); Console.WriteLine("----------------------"); } } } } // 调用示例 static void Main() { RetrieveDomainUsers("myController", "myUser@my.domain", "MyP@ssw03d!*"); } }
方案2:使用WMI(对应PowerShell的WMI逻辑)
如果需要基于WMI实现,可参考以下代码:
using System; using System.Management; using System.Linq; public class WmiDomainUserHelper { public static void GetUserSessionInfo(string domainController, string adminUser, string adminPass) { var connOptions = new ConnectionOptions { Username = adminUser, Password = adminPass, Authority = $"ntlmdomain:{domainController.Split('.')[0]}" }; var scope = new ManagementScope($"\\\\{domainController}\\root\\cimv2", connOptions); scope.Connect(); // 查询所有登录会话 var sessionQuery = new ObjectQuery("SELECT * FROM Win32_LogonSession"); using (var sessionSearcher = new ManagementObjectSearcher(scope, sessionQuery)) { foreach (var session in sessionSearcher.Get()) { string logonId = session["LogonId"].ToString(); // 关联用户账号 var userQuery = new ObjectQuery($"ASSOCIATORS OF {{Win32_LogonSession.LogonId={logonId}}} WHERE ResultClass=Win32_UserAccount"); using (var userSearcher = new ManagementObjectSearcher(scope, userQuery)) { foreach (var user in userSearcher.Get()) { string samAccount = user["SamAccountName"].ToString(); // 查询锁定状态 var profileQuery = new ObjectQuery($"SELECT * FROM Win32_NetworkLoginProfile WHERE Name='{user["Name"]}'"); using (var profileSearcher = new ManagementObjectSearcher(scope, profileQuery)) { var profile = profileSearcher.Get().Cast<ManagementObject>().FirstOrDefault(); bool isLocked = profile != null && (bool)profile["LockedOut"]; Console.WriteLine($"用户名: {samAccount}"); Console.WriteLine($"全名: {user["FullName"]}"); Console.WriteLine($"锁定状态: {isLocked}"); Console.WriteLine($"登录状态: 已登录"); Console.WriteLine("----------------------"); } } } } } } }
内容的提问来源于stack exchange,提问作者Geoff
相关产品推荐
相关产品推荐

