Logoff remoto de usuários no Windows com o PowerShell + SONAR

<#
.SYNOPSIS
    Logs off user(s) specified. You can't log off a user from the console session.
.DESCRIPTION
    Logs off user(s) specified. You can't log off a user from the console session.
.EXAMPLE
     -User "Administrator"
    Logs off Administrator user.
.EXAMPLE
     -User "Administrator","Guest"
    Logs off Administrator and Guest users.
.EXAMPLE
    PS C:> Logoff-User.ps1 -User "Administrator","Guest"
    Logs off Administrator and Guest users.
.OUTPUTS
    String[]
.NOTES
    Minimum OS Architecture Supported: Windows 10, Windows Server 2016
    Release Notes:
#>

[CmdletBinding(SupportsShouldProcess = $True)]
param (
    # User name(s) to log off
    [Parameter(Mandatory = $true)]
    [String[]]
    $User
)

begin {
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
        { Write-Output $true }
        else
        { Write-Output $false }
    }
    Function Get-QueryUser() {
        Param()
        # Replaces all occurrences of 2 or more spaces in a row with a single comma
        $Lines = @(query.exe user).foreach({ $(($_) -replace ('s{2,}', ',')) })
        $Header = $($Lines[0].split(',').trim())
        for ($i = 1; $i -lt $($Lines.Count); $i++) {
            $Line = $($Lines[$i].split(',')).foreach({ $_.trim().trim('>') })
            # Accounts for disconnected users
            if ($Line.count -eq 5) {
                $Line = @($Line[0], "$($null)", $Line[1], $Line[2], $Line[3], $Line[4] )
            }
            $CurUser = [PSCustomObject]::new()
            for ($j = 0; $j -lt $($Line.count); $j++) {
                $CurUser | Add-Member -MemberType NoteProperty -Name $Header[$j] -Value $Line[$j]
            }
            $CurUser
        }
    }
}
process {
    if (-not (Test-IsElevated)) {
        Write-Error -Message "Access Denied. Please run with Administrator privileges."
        exit 1
    }
    # Get a list of users logged on from query.exe, format it for powershell to process
    $QueryResults = Get-QueryUser
    # Accounts for only one user logged in
    $QueryTest = $($QueryResults | Select-Object -First 1)
    if (
        $QueryResults.Count -or
        (
            $QueryTest.USERNAME -is [String] -and
            -not [String]::IsNullOrEmpty($QueryTest.USERNAME) -and
            -not [String]::IsNullOrWhiteSpace($QueryTest.USERNAME)
        )
    ) {
        $script:HasError = $false
        $QueryResults | Where-Object {
    
            # For each session filter out the user that weren't specified in $User
            $_.UserName -in $User
    
        } | ForEach-Object {
            Write-Host "Found Logged In User: $($_.UserName)"
            if ($_.SessionName -like "console") {
                # We can't log out a user that is at the console.
                # We could do this logic in the Where-Object code block, but then there isn't an output of what was skipped.
                # https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/logoff#remarks
                # "You can't log off a user from the console session."
                Write-Host "Skipping user, can't log off a user($($_.UserName)) from the $($_.SessionName) session."
            }
            else {
                # Log off the user session with a matching ID
                logoff.exe $_.Id
                if ($LASTEXITCODE -gt 0) {
                    $script:HasError = $true
                    Write-Error "logoff.exe $($_.Id) returned exit code: $LASTEXITCODE"
                }
                else {
                    Write-Host "Logged Off User: $($_.UserName)"
                }
            }
        }
        if ($script:HasError) {
            exit 1
        }
    }
    else {
        Write-Output "No Users Logged In"
        exit 2
    }
}
end {}

Análise detalhada

  • Inicialização : O script começa com uma série de comentários, ou '.SYNOPSIS', '.DESCRIPTION' e '.EXEMPLE', que fornecem uma visão geral, uma descrição detalhada e exemplos de uso, respectivamente.

  • Parâmetros : O bloco param define que o script requer uma entrada ( $User ), que é o(s) nome(s) de usuário(s) para fazer logoff.

  • Funções : Duas funções principais são definidas:

  • Test-IsElevated : determina se o script é executado com privilégios de administrador.

  • Get-QueryUser : Obtém uma lista de usuários conectados usando o comando do Windows query.exe user e, em seguida, formata essa saída para facilitar o consumo pelo PowerShell.

  • Bloco de Processo : As principais operações ocorrem aqui:

  • Verificação de permissão : verifica se o script está sendo executado com privilégios administrativos usando Test-IsElevated .

  • Consulta de sessão : recupera todos os usuários conectados via Get-QueryUser .

  • Término de Sessão : Itera pela lista de usuários conectados. Se o nome de usuário corresponder ao parâmetro $User fornecido e não for uma sessão de console, ele desconecta esse usuário usando logoff.exe .

Atualizado

Isto foi útil?