[英]PowerShell WMI query fails to return username in logon script
我正在尝试在PowerShell登录脚本中获取域用户的用户名。 任何数量的不同用户都可以登录相关计算机。
为了运行PS脚本(PS 2.0 / 3.0),在Win7 / Win8域客户端上配置了一个本地用户帐户(简称为“ syscheck”)。 该脚本位于本地,由Task Scheduler在用户登录时启动。 该脚本需要获取正在登录的域用户的用户名。
我试图用WMI做到这一点:
Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty UserName
但这在脚本运行时不返回任何内容。
如果我尝试这样做:
$env:USERNAME
返回“ syscheck”本地帐户的用户名。
登录时运行脚本时,域用户名是否不可用?
也许有一种方法可以使用.NET? 还有其他选择吗?
***** 8月8日更新*****
我已经使用提供的解决方案进行了测试(谢谢Alexander!),但仍然无法检索已登录用户的用户名。 我相信这是因为,如上所述,这是Task Scheduler启动的登录脚本。 启动脚本的任务的主体是本地帐户。 由于某些原因,尝试获取域用户名的所有方法都会失败。
这是最新的尝试:
首先,这就是我调用函数的方式:
$indx = 0
do {
$username = GetDomUser
if (($indx -eq 25) -or ($username.Length -ne 0)) {
Write-Output $username
Break
}
else {
Start-Sleep -Seconds 12
}
$indx++
}
while ($indx -lt 25) # 5 minutes is PLENTY of time for boot...
现在,这是函数:
Function GetDomUser {
$compname = $($env:COMPUTERNAME)
$pattern = '"MYDOMAIN",Name='
$antecedent = @(Get-WmiObject -Class Win32_LoggedOnUser -ComputerName $compname |
Where-Object { $_.Antecedent -match $pattern } | Select-Object -ExpandProperty Antecedent)
Return ([regex]::Match([string]$antecedent[0],"$pattern(.*$)").Value).Split('=')[1] -replace '"', ""
}
当然,一旦计算机启动,这在控制台上将非常有效。
是否可以刷新Win32_LoggedOnUser类从中获取其数据的任何存储?
还有其他选择吗?
这是我尝试过的以前的方法-全部返回启动脚本的Task的主体的用户名(或空字符串,D返回的内容)。
$usernameA = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
$usernameB = $(whoami)
$usernameC = $($env:USERNAME)
$usernameD = $(Get-WmiObject Win32_ComputerSystem -ComputerName $compname | Select-Object -ExpandProperty UserName)
$usernameE = $([Environment]::UserName)
您可以按照以下步骤进行操作:
$iLOGON32_LOGON_INTERACTIVE = 2
$cLogonSessions = Get-WmiObject -Class "Win32_LogonSession" `
| Where-Object { $_.LogonType -eq $iLOGON32_LOGON_INTERACTIVE }
if ($cLogonSessions -ne $null) {
$cInteractiveLogons = @()
foreach ($oLogonSession in $cLogonSessions) {
$sWmiQuery = ('ASSOCIATORS OF {{Win32_LogonSession.LogonId="{0}"}} ' `
+ 'WHERE AssocClass=Win32_LoggedOnUser') -f $oLogonSession.LogonId
$cInteractiveLogons += Get-WMIObject -Query $sWmiQuery `
| Select-Object -ExpandProperty "Caption"
}
} else {
$ex = New-Object -TypeName System.NullReferenceException(`
'$cInteractiveLogons is null.')
throw $ex
}
$cInteractiveLogons | Select-Object -Unique
当$cInterativeLogons is null
,将引发异常,这意味着没有人交互式登录(尚未),在这种情况下,您可以等待并稍后重新检查。
请注意,此代码不可靠,因为LOGON32_LOGON_INTERACTIVE
不仅限于XP和早期版本中的本地控制台登录。
至于实际的解决方案,我建议使用某种显式通知。 例如,您可以利用事件。 订阅事件,然后从用户的常规登录脚本中发出事件。
问题不在于WMI代码,而在于运行它的计算机的状态。 事实证明,将用户VPN接入他们的计算机(几乎总是要归功于VPN客户端的自动重新连接功能),或者安装了某些第三方实用程序(例如某些云备份服务)时,会有多个登录名和“ the”登录用户是模棱两可的。
目前,它运行良好:
Function GetDomainUser {
$compname = $($env:COMPUTERNAME)
$pattern = '"' + $($env:USERDOMAIN) + '"' + ',Name='
$antecedent = @(Get-WmiObject -Class Win32_LoggedOnUser -ComputerName $compname |
Where-Object { $_.Antecedent -match $pattern } |
Select-Object -ExpandProperty Antecedent | Select-Object -Unique)
Return $(([regex]::Match([string]$antecedent,$($pattern + '(".+")')).Value).Split('=')[1] -replace '"','')
}
但是我不得不编写附加代码来解决无法发现LoggedOnUser(存在多个登录)或没有人登录的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.