2015-08-01 3 views
0

Я пытаюсь получить имя пользователя пользователей домена в сценарии входа в PowerShell. Любое количество разных пользователей может зайти на компьютеры, о которых идет речь.Запрос PowerShell WMI не возвращает имя пользователя в сценарии входа

Локальная учетная запись пользователя (назовем ее «syscheck») настроена на клиентских доменах Win7/Win8 для запуска сценария PS (PS 2.0/3.0); сценарий находится локально и запускается планировщиком заданий при входе пользователя в систему. Сценарий должен получить имя пользователя, домена, журналирования в

Я пытался сделать это с помощью WMI:.

Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty UserName

, но это ничего не возвращает при выполнении сценария.

Если я пытаюсь это:

$env:USERNAME

Имя пользователя, от '' syscheck локальной учетной записи возвращается.

Является ли имя пользователя домена еще недоступным, когда скрипт работает при входе в систему?

Возможно, есть способ сделать это с .NET? Другие варианты?

***** UPDATE 8 августа *****

Я проверил с раствором при условии (спасибо Александру!), Но до сих пор не может получить имя пользователя, вошедшего в систему пользователя. Я считаю, что это связано с тем, что, как упоминалось выше, это скрипт входа в систему, запущенный 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 Class получает свои данные?

Другие варианты?

Вот предыдущие методы, которые я пробовал - все возвращают имя пользователя принципала задачи, запускающей скрипт (или пустую строку, что и возвращает 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) 
+0

Вопрос: Вы говорите, что '$ env: USERNAME' возвращает ожидаемое, правильное значение в сценарии входа в Powershell? Что именно скрипт не читает? – paulsm4

+0

Я ищу имя пользователя, регистрирующегося на компьютере. '$ env: USERNAME' возвращает имя учетной записи, на которой запущен скрипт, который запускается при входе в систему любого пользователя домена. В этой ситуации можно ожидать поведения '$ env: USERNAME'; Я включил его здесь, чтобы помочь проиллюстрировать проблему. – jott19

+0

$ uA = $ ([System.Security.Principal.WindowsIdentity] :: GetCurrent(). Name); $ uB = $ (whoami); $ uC = $ ($ env: USERNAME); $ uD = $ (Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty UserName); $ uE = $ ([Environment] :: UserName); Write-Host "A = $ uA"; Write-Host "B = $ uB"; Write-Host "C = $ uC" Write-Host "D = $ uD"; Write-Host "E = $ uE"; опубликует результаты позже – jott19

ответ

0

Проблема была не с кодом WMI, а с состоянием машины, на которой он запускался. Оказывается, когда пользователи подключаются VPN к своим машинам (почти всегда благодаря функции автоматического повторного подключения VPN-клиента) или имеют некоторую стороннюю утилиту (например, некоторые службы облачного резервного копирования), существует несколько логинов и «вход» в систему пользователь неоднозначен.

На данный момент это работает довольно хорошо:

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 не может быть обнаружен (существует несколько входов в систему), или когда никто не вошел в систему.

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 и более ранних версиях.


Что касается фактического решения, я бы рекомендовал использовать какие-то явные уведомления. Например, вы можете использовать события. Подпишитесь на событие, а затем выпустите событие из обычного сценария входа пользователя.

+0

WMI снова сохраняет этот день! Похоже, что мне нужно. Будет опубликован после тестирования. Обратите внимание, что сеансы RDP могут создавать ложные срабатывания. – jott19

+0

RDP-логины LogonType 10 - это не проблема. – jott19

+0

На самом деле я не думаю, что это _really_ отличается от запроса 'Win32_ComputerSystem'.) Я предполагаю, что ваш скрипт syscheck просто запускает бит «слишком рано» - до того, как WMI получит уведомление о входе в систему. В этом случае что-то вроде «Start-Sleep -Seconds 5» должно помочь. –

Смежные вопросы