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