3

Я пытаюсь получить в настоящее время вошли пользователей, которые имеют активный сеанс.

В диспетчере задач список предельно ясен: есть два пользовательских сеанса и один активный.

Я хочу запросить то же самое через Powershell. Я попробовал несколько доступных команд Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique который перечисляет намного больше пользователей, чем я могу видеть [компьютер, присоединенный к домену]

Я ищу запрос, который может дать результаты точно так же, как диспетчер задач.

3 ответа3

3

Проблема с Get-WmiObject Win32_LoggedOnUser | Select Antecedent -Unique , что он показывает все сеансы, даже те, которые были закрыты с момента последней перезагрузки компьютера. К сожалению, самый простой способ опроса сеансов - использовать старый исполняемый файл query.exe.

Вы можете преобразовать выходные данные query.exe в объекты, используя немного регулярных выражений:

$Computer = $env:COMPUTERNAME
$Users = query user /server:$Computer 2>&1

$Users = $Users | ForEach-Object {
    (($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1  none  $2' -replace "\s{2,}", "," -replace "none", $null))
} | ConvertFrom-Csv

foreach ($User in $Users)
{
    [PSCustomObject]@{
        ComputerName = $Computer
        Username = $User.USERNAME
        SessionState = $User.STATE.Replace("Disc", "Disconnected")
        SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
    } 
}

Который даст вам вывод, как это:

ComputerName Username SessionState SessionType
------------ -------- ------------ -----------
BSMITH-LT    bobsm    Active       console    

Возьмем это намного дальше к функции:

function Convert-QueryToObjects
{
    [CmdletBinding()]
    [Alias('QueryToObject')]
    [OutputType([PSCustomObject])]
    param
    (
        [Parameter(Mandatory = $false,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true,
                   Position = 0)]
        [Alias('ComputerName', 'Computer')]
        [string]
        $Name = $env:COMPUTERNAME
    )

    Process
    {
        Write-Verbose "Running query.exe against $Name."
        $Users = query user /server:$Name 2>&1

        if ($Users -like "*No User exists*")
        {
            # Handle no user's found returned from query.
            # Returned: 'No User exists for *'
            Write-Error "There were no users found on $Name : $Users"
            Write-Verbose "There were no users found on $Name."
        }
        elseif ($Users -like "*Error*")
        {
            # Handle errored returned by query.
            # Returned: 'Error ...<message>...'
            Write-Error "There was an error running query against $Name : $Users"
            Write-Verbose "There was an error running query against $Name."
        }
        elseif ($Users -eq $null -and $ErrorActionPreference -eq 'SilentlyContinue')
        {
            # Handdle null output called by -ErrorAction.
            Write-Verbose "Error action has supressed output from query.exe. Results were null."
        }
        else
        {
            Write-Verbose "Users found on $Name. Converting output from text."

            # Conversion logic. Handles the fact that the sessionname column may be populated or not.
            $Users = $Users | ForEach-Object {
                (($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1  none  $2' -replace "\s{2,}", "," -replace "none", $null))
            } | ConvertFrom-Csv

            Write-Verbose "Generating output for $($Users.Count) users connected to $Name."

            # Output objects.
            foreach ($User in $Users)
            {
                Write-Verbose $User
                if ($VerbosePreference -eq 'Continue')
                {
                    # Add '| Out-Host' if -Verbose is tripped.
                    [PSCustomObject]@{
                        ComputerName = $Name
                        Username = $User.USERNAME
                        SessionState = $User.STATE.Replace("Disc", "Disconnected")
                        SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
                    } | Out-Host
                }
                else
                {
                    # Standard output.
                    [PSCustomObject]@{
                        ComputerName = $Name
                        Username = $User.USERNAME
                        SessionState = $User.STATE.Replace("Disc", "Disconnected")
                        SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
                    }
                }
            }
        }
    }
}

и теперь вы можете делать такие вещи, как: Get-ADComputer -Filter {Name -like "SERVER*"} | Convert-QueryToObjects | ? {$_.SessionState -eq 'Active'}

1

Вот как я это делаю. Это не работает для сеансов RDP, хотя.

$out = query session | where {$_ -match 'console'}
$array = $out -split('\s+')
$consoleuser = $array[1]

Или же:

$consoleuser = query session | select-string console | foreach { -split $_ } | 
  select -index 1
-1

это можно сделать с помощью:

get-wmiobject -Class Win32_Computersystem | выберите имя пользователя

С уважением

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .