繁体   English   中英

PowerShell WMI查询无法在登录脚本中返回用户名

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM