Назад | Перейти на главную страницу

Как закрыть потерянные сеансы PowerShell?

Я создавал скрипт, который использует несколько команд Invoke-Command -asjob на удаленном сервере, хотя при тестировании цикл While-Loop вышел из строя, и мне пришлось его остановить. Однако, когда я сейчас пытаюсь выполнить Invoke-Command -asjob на целевом сервере, он возвращает задание с ошибкой состояния. Когда я получаю задание, оно возвращается с такой ошибкой:

The WS-Management service cannot process the request. This user has exceeded the maximum number of concurrent shells allowed for this plugin. Close at least one open shell or raise the plugin quota for this user.
+ FullyQualifiedErrorId : -2144108060,PSSessionStateBroken

Когда я выполняю Get-PSSession, ничего не отображается, поэтому я не могу использовать Remove-PSSession (пока это единственное предложение Google).

Вот что он в основном выполнял:

While ($True)
    { 
    Invoke-Command -Computername $RemoteServer -AsJob {Get-ChildItem}
    }

Я вырвался из этого и сделал Get-Job | Remove-Job, который удалил все задания, но я все еще не могу запустить Invoke-Command -AsJob на удаленном сервере.

Я также перезапустил службу WSMAN на удаленном сервере (войдя в нее с помощью RDP), которая не сработала.

Удаленные задания будут выполняться под wsmprovhost.exe процесс на задание. У вас должна быть возможность завершить эти процессы грубой силой с помощью WMI или даже удаленно перезагрузить компьютер. Конечно, вы рискуете убить размещенные задания для других пользователей / действий.

Это положит конец всем wsmprovhost.exe процессы на указанном компьютере (или массив имен компьютеров):

(gwmi win32_process -ComputerName $RemoteServer) |? 
    { $_.Name -imatch "wsmprovhost.exe" } |% 
    { $_.Name; $_.Terminate() }

Я знаю, что этот пост довольно старый. @Matthew Wetmore предлагает отличное решение для удаления ВСЕ PSSession с удаленного сервера. Но у @SuHwak был следующий вопрос о том, как остановить только сеансы, созданные конкретным пользователем.

С этой целью я написал вспомогательную функцию.

function Get-PSSessionsForUser
{
    param(
        [string]$ServerName,
        [string]$UserName
    )

    begin {
        if(($UserName -eq $null) -or ($UserName -eq ""))
        { $UserName = [Environment]::UserName }
        if(($ServerName -eq $null) -or ($ServerName -eq ""))
        { $ServerName = [Environment]::MachineName }
    }

    process {
        Get-CimInstance  -ClassName Win32_Process -ComputerName $ServerName | Where-Object { 
            $_.Name -imatch "wsmprovhost.exe"
        } | Where-Object {
            $UserName -eq (Invoke-CimMethod -InputObject $_ -MethodName GetOwner).User
        }
    }
}

И, чтобы использовать это ....

#Get, but do not terminate sessions for the current user, on the local computer.
Get-PSSessionsForUser

#Terminate all sessions for for the current user, on the local computer.
(Get-PSSessionsForUser) | Invoke-CimMethod -MethodName Terminate

<####################################>

#Get, but do not terminate sessions for a specific user, on the local computer.
Get-PSSessionsForUser -UserName "custom_username"

#Terminate all sessions for a specific user, on the local computer.
(Get-PSSessionsForUser -UserName "custom_username") | Invoke-CimMethod -MethodName Terminate

<####################################>

#Get, but do not terminate sessions for the current user, on a remote server.
Get-PSSessionsForUser -ServerName "remote_server"

#Terminate all sessions for the current user, on a remote server.
(Get-PSSessionsForUser -ServerName "remote_server") | Invoke-CimMethod -MethodName Terminate

<####################################>

#Get, but do not terminate sessions for a specific user, on a remote server.
Get-PSSessionsForUser -UserName "custom_username" -ServerName "remote_server"

#Terminate all sessions for a specific user, on a remote server.
(Get-PSSessionsForUser -UserName "custom_username" -ServerName "remote_server") | Invoke-CimMethod -MethodName Terminate