Немного переписал свою статью. Выделил функции, чтобы иметь возможность выделять в отдельные процессы как все службы, так и конкретные. Пример задачи, где мне пришлось делить группу служб, работающих в одном процессе, на несколько процессов, уже описывал.

P.S. Описываемый PowerShell модуль опубликовал в своём SVN репозитории.

Делим группу на самостоятельные процессы (по рецепту, описанному в статье):

(Get-ItemProperty `
    -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
    -name netsvcs `
).netsvcs `
| ? {Test-Path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)"} `
| % {
    $newSvcGroupKey = New-ItemProperty `
        -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
        -name "netsvc_$($_)" `
        -value ([System.String[]]@($_)) `
        -force `
    ;
    Set-ItemProperty `
        -path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)" `
        -name ImagePath `
        -value “%systemroot%\system32\svchost.exe -k netsvc_$($_)” `
        -force `
     ;
}; 

Set-ItemProperty `
    -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
    -name netsvcs `
    -value ([System.String[]]@()) `
    -force;

И собираем обратно в одну группу (один процесс):

$svcs = ($svcGroups = get-itemProperty `
    -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
) `
| get-member -memberType NoteProperty `
| ? {$_.name -match 'netsvc_(?<svc>.+)'} `
| % {
    $svc = $matches['svc'];
    invoke-expression "`$svcGroups.$($_.name)";
    Remove-ItemProperty `
        -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
        -name $_.name `
    ;
};

$svcs = `
    (Get-ItemProperty `
        -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
        -name netsvcs `
    ).netsvcs + $svcs `
    | sort -unique
;

Set-ItemProperty `
    -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
    -name netsvcs `
    -value $svcs `
    -force
;

$svcs `
| ? {Test-Path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)"} `
| % {
    Set-ItemProperty `
        -path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)" `
        -name ImagePath `
        -value “%systemroot%\system32\svchost.exe -k netsvcs” `
        -force `
    ;
}; 

Надеюсь, эти сценарии помогут Вам в отладке.

А теперь оформим приведённые выше сценарии “правильными” командлетами:

function Get-ServicesWithOwnProcess { 
    <#
    .Synopsis
            Возвращает массив идентификаторов служб, выделенных нами в отдельный процесс.
    .Description
            Возвращает массив идентификаторов служб, выделенных нами в отдельный процесс.
    .Example
        Get-ServicesWithOwnProcess `
           | Set-ServiceCommonProcess
    #>
  
    get-itemProperty `
         -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
    | get-member -memberType NoteProperty `
    | ? {$_.name -match 'netsvc_(?<svc>.+)'} `
    | % {
         $matches['svc'];
    }; 
};

function Get-ServicesWithCommonProcess { 
    <#
       .Synopsis
            Возвращает массив идентификаторов служб, использующих процесс svchost.exe (группа netsvcs).
    .Description
            Возвращает массив идентификаторов служб, использующих процесс svchost.exe (группа netsvcs).
    .Example
        Get-ServicesWithCommonProcess `
           | Set-ServiceOwnProcess
    #>
  
    (Get-ItemProperty `
        -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
        -name netsvcs `
    ).netsvcs `
    | ? {Test-Path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)"} `
    ;
};

function Set-ServiceOwnProcess { 
    <#
    .Synopsis
            Выделение для указанного сервиса собственного процесса svchost.exe.
    .Description
            Выделение для указанного сервиса собственного процесса svchost.exe.
    .Parameter service
         Идентификатор службы
    .Example
        Set-ServiceOwnProcess `
                -service 'AppMgmt' 
    #>
  
    [CmdletBinding(
        SupportsShouldProcess = $true,
        ConfirmImpact = 'Low'
    )]
    param (
        [Parameter(
            Mandatory=$true,
            Position=0,
            ValueFromPipeline=$true,
            HelpMessage="Идентификатор службы."
        )]
        [string]$service
    )

    $service `
    | ? {Test-Path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)"} `
    | ? {
        (Get-ItemProperty `
            -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
            -name netsvcs `
        ).netsvcs -contains $_ `
    } `
    | % {
        $newSvcGroupKey = New-ItemProperty `
            -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
            -name "netsvc_$($_)" `
            -value ([System.String[]]@($_)) `
            -force `
        ;
        Set-ItemProperty `
            -path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)" `
            -name ImagePath `
            -value “%systemroot%\system32\svchost.exe -k netsvc_$($_)” `
            -force `
        ;

        Set-ItemProperty `
            -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
            -name netsvcs `
            -value ( `
                (Get-ItemProperty `
                    -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
                    -name netsvcs `
                ).netsvcs -notmatch $_ `
            ) `
            -force `
        ;
    }; 
};

function Set-ServiceCommonProcess { 
    <#
        .Synopsis
            Возвращаем сервис в "групповой" процесс svchost.exe (группа netsvc).
        .Description
            Возвращаем сервис в "групповой" процесс svchost.exe (группа netsvc).
        .Parameter service
            Идентификатор службы
        .Example
            Set-ServiceCommonProcess `
                -service 'AppMgmt' 
    #>
  
    [CmdletBinding(
        SupportsShouldProcess = $true,
        ConfirmImpact = 'Low'
    )]
    param (
        [Parameter(
            Mandatory=$true,
            Position=0,
            ValueFromPipeline=$true,
            HelpMessage="Идентификатор службы."
        )]
        [string]$service
    )

    $service `
    | ? {Test-Path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)"} `
    | ? {
        (Get-ItemProperty `
            -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
            -name netsvcs `
        ).netsvcs -notcontains $_ `
    } `
    | % {
        Set-ItemProperty `
            -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
            -name netsvcs `
            -value ( `
                (Get-ItemProperty `
                    -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
                    -name netsvcs `
                ).netsvcs + $_ `
                | sort -unique `
            ) `
            -force `
        ;

        Set-ItemProperty `
            -path HKLM:"\SYSTEM\CurrentControlSet\Services\$($_)" `
            -name ImagePath `
            -value “%systemroot%\system32\svchost.exe -k netsvcs” `
            -force `
        ;

        Remove-ItemProperty `
            -path HKLM:'\Software\Microsoft\Windows NT\CurrentVersion\Svchost' `
            -name "netsvc_$($_)" `
        ;
    }; 
};

Теперь имеем возможность выделить службе свой процесс буквально одной строкой, и вернуть её обратно – также одной строкой. Модуль назвал ITG.SvcHostManagement.psm1.

Отзывы » (1)

  1. С помощью этого трюка смог найти и локализовать «виновника» утечки дескрипторов — службу Application Management. Именно в этой службе при определённом стечении обстоятельств (вся и суть в том, что не всегда это происходит) возникают утечки дескрипторов и общее количество открытых дескрипторов доходит до 44000+. При этом отваливаются сетевые ресурсы, недоступен контроллер домена, DFS ресурсы и так далее. Теперь же достаточно убить процесс, хостящий службу Application Management, и запустить её заново (она сама поднимется при очередном применении политик) — и можно работать дальше.
    Итого, рекомендую Вам указанным выше способом выдеить как минимум службу Application Management в отдельный процесс, и повесть в расписание периодический перезапуск данной службы хотя бы раз в сутки — и эту проблему таким образом мы обойдём.

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка