Подтвердить что ты не робот

Как увеличить максимальное количество дочерних процессов, которые могут быть вызваны службой Windows - ограничения рабочей области рабочего стола

В: У меня есть служба Windows, которая порождает множество дочерних процессов. Кажется, что существует некоторый предел, около 100, где процесс не может быть запущен. Вызов CreateProcess() возвращается с pid, но тогда процесс просто не реализуется. Если вместо этого я запустил наш сервер в качестве консольного приложения, этот лимит исчезнет. Кроме того, если я установил флаг DETACHED_PROCESS, этот предел более чем удваивается. Однако я получаю сбои, если я устанавливаю DETACHED_PROCESS и вызываю CreateProcesssWithLogonW().

4b9b3361

Ответ 1

Это проблема "куча рабочего стола". Очень хорошее обсуждение можно найти здесь:

Обзор кучи рабочего стола

Обратите внимание, что это относится только к программам, которые работают как сервисы, потому что размер кучи рабочего стола по умолчанию для служб намного меньше, чем для приложений.

В нашем случае мы смогли запустить около 100 дочерних процессов до исчерпания ресурсов без изменений. С изменением это число может быть значительно увеличено.

Это ответ, который мы предоставили нашим конечным пользователям на нашей базе знаний:

ПРЕДУПРЕЖДЕНИЕ: это влияет на кучу рабочего стола всех служб! Не делайте это больше, чем необходимо, или вы будете вынуждать систему потреблять больше ресурсов, и вы можете столкнуться с проблемами в общем размере кучи рабочего стола.

Если вы обнаружите, что не можете открыть более 100 проектов, даже на очень большом сервере RAM, возможно, вы столкнулись с ограничением размера "кучи рабочего стола Windows".

Проблема заключается в том, что сеансы служб под окнами (где запущены службы) имеют меньше этого "рабочего пространства" для создания окон.

Короткий вариант:

  • Службы получают небольшие кучи рабочего стола, чем интерактивные сеансы.

  • Размер рабочей кучи рабочего стола ограничивает количество окон

  • Каждый подсервер создает одно или несколько "окон", даже если мы не видим их.

Решение:

  • Резервное копирование реестра перед внесением любых изменений!

  • Запустите regedit.exe как администратор

  • Изменить значение реестра:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows
    
  • Вы увидите строку типа:

    %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
    

Критический бит:

SharedSection=1024,20480,768

Второе число (20480) - это размер для интерактивных сеансов. Третье число (768) - это размер неинтерактивных (сервисных) сеансов. Обратите внимание, как третье число на 26 раз меньше второго. Экспериментально мы обнаружили, что это изменение:

SharedSection=1024,20480,2048

Увеличен предел проекта от 106 до 270, почти идеально масштабируется с размером кучи. Выберите значение, которое отражает максимальное количество проектов, которые вы ожидаете открыть одновременно всеми пользователями в системе. Не делайте это значение больше необходимого, и не больше 8192, так как каждая служба в вашей системе будет потреблять больше драгоценного ресурса.

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

Ответ 2

У нас было много серверов удаленного рабочего стола, которые нам нужно было протестировать, поэтому мы написали powershell script для запроса AD для наших RD-серверов, а затем применили это изменение реестра. Наслаждайтесь

   $newValue = "%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,2048 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16"
$origValue = "%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16"

if ($update) {
    Clear-Variable update
}

$updateConfirm= [System.Windows.Forms.MessageBox]::Show("Update Desktop Heap Limitation to 2048?" , "Status" , 4) 
if ($updateConfirm -eq "YES" ) {
    $update = $true
} else { 
    $revertConfirm= [System.Windows.Forms.MessageBox]::Show("Revert Desktop Heap Limitation to 768?" , "Status" , 4) 
    if ($revertConfirm -eq "YES" ) {
        $update = $false
    } 
}

if (($updateConfirm -ne "YES") -and ($revertConfirm -ne "YES")) {
    Write-Host "User did not specify whether to update or revert Desktop Heap Limitation. Exiting Setup."
    Read-Host "Press Enter to exit."
    break
}

#Import Active Directory PowerShell module
if (Test-Path C:\Users\${env:USERNAME}\Documents\WindowsPowerShell\Modules\ActiveDirectory\ActiveDirectory.psm1) {
    Import-Module ActiveDirectory -prefix AD
} else {
    $s = New-PSSession -computerName DC01WDC01
    Invoke-command { import-module ActiveDirectory } -session $s
    Export-PSSession -session $s -commandname *-AD* -outputmodule ActiveDirectory -allowclobber
    Import-Module ActiveDirectory -prefix AD
    Remove-PSSession -session $s
}

$servers =  Get-ADADComputer -Filter {(Name -Like "RDS*")}  | Select -Expand Name

foreach ($server in $servers) {
    Write-Host "Working on $server" -ForegroundColor Magenta
    if(!(Test-Connection -ComputerName $server -Count 1 -quiet)) {
        Write-Warning "$server : Offline"
        Continue
    }

    if ($update -eq $true) {
        Invoke-Command -ComputerName $server -ArgumentList $newValue -ScriptBlock {
            Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" -Name "Windows" -Value $args[0]
            $result = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" | SELECT Windows
            if ($result.Windows -like "*SharedSection=1024,20480,2048*") {
                Write-Host "Successfully reverted Desktop Heap Limit to 2048" -ForegroundColor Green
            } else {
                Write-Warning "Update to registry value unsuccessful on $env:ComputerName" 
            }              
        }
    } elseif ($update -eq $false) {
        Invoke-Command -ComputerName $server -ArgumentList $origValue -ScriptBlock {
            Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" -Name "Windows" -Value $args[0]
            $result = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" | SELECT Windows    
            if ($result.Windows -like "*SharedSection=1024,20480,768*") {
                Write-Host "Successfully reverted Desktop Heap Limit to 768" -ForegroundColor Green
            } else {
                Write-Warning "Update to registry value unsuccessful on $env:ComputerName" 
            }       
        }
    }
}