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

时间:2015-08-01 01:11:37

标签: powershell authentication wmi

我试图在PowerShell登录脚本中获取域用户的用户名。任何数量的不同用户都可能登录到相关计算机。

在Win7 / Win8域客户端上配置本地用户帐户(让我们称之为“syscheck'”)以运行PS脚本(PS 2.0 / 3.0);该脚本驻留在本地,由任务计划程序在用户登录时启动。该脚本需要获取登录的域用户的用户名。

我试图用WMI做到这一点:

Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty UserName

但是当脚本运行时,这不会返回任何内容。

如果我试试这个:

$env:USERNAME

' syscheck'的用户名返回本地帐户。

当脚本在登录时运行时,域用户名是否仍然不可用?

也许有办法用.NET做到这一点?其他选择?

***** 8月8日更新*****

我已经使用提供的解决方案进行了测试(感谢Alexander!)但仍无法检索已登录用户的用户名。我相信这是因为,如上所述,这是Task Scheduler启动的登录脚本。启动脚本的Task的主体是本地帐户。出于某种原因,尝试获取域用户名的所有方法都失败了。

这是最新的尝试:

首先,这是我调用函数的方式:

$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)

2 个答案:

答案 0 :(得分:0)

您可以采取哪些措施来了解正在发生的事情:

$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和早期版本中的本地控制台登录。

至于实际解决方案,我建议使用某种显式通知。例如,您可以使用事件。订阅一个事件,然后从用户的常规登录脚本中发出事件。

答案 1 :(得分:0)

问题不在于WMI代码,而在于运行它的机器的状态。事实证明,当用户被VPN连接到他们的机器中时(几乎总是归功于VPN客户端的自动重新连接功能),或者安装了一些第三方实用程序(例如某些云备份服务),有多个登录和& #34;所述"登录用户不明确。

目前这种方法运作良好:

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(存在多个登录)或没有人登录时,我必须编写附加代码来解决这些情况。