Установите тип запуска службы на “Автоматически (с отложенным запуском)” с помощью PowerShell.

Вопрос или проблема

Я пытаюсь написать скрипт, изменяющий для определённых сервисов тип запуска на “Automatic (DelayedStart)”. Когда я передаю сервисы в Set-CimInstance, возникает ошибка, что “невозможно изменить только для чтения свойство ‘StartMode'”. Когда я передаю их в Invoke-CimMethod, скрипт выполняется без ошибок (и возвращает 21), но ничего не меняется. Что я делаю не так и где можно получить список возвращаемых значений?

ForEach ($Server in $Servers) {
    $Services = @("MSSQL", "MSSQLSERVER", "SQLAgent")

    $Before = @()
    ForEach ($Service in $Services) {
        $Before += Get-CimInstance -ComputerName $Server -ClassName 'Win32_Service' -Property * | Where-Object -Property Name -like "*$Service*"
        }

    $Before | Format-Table -Property PSComputerName, Name, StartMode, DelayedAutoStart, State, StartName -AutoSize

    ForEach ($Item in $Before.Name) {
        Get-CimInstance -ClassName Win32_Service -ComputerName $Server -Filter "Name="$($Item)"" | Invoke-CimMethod -MethodName Change -Arguments @{StartMode = "AutomaticDelayedStart"}
        # Get-CimInstance -ClassName Win32_Service -ComputerName $Server -Filter "Name="$($Item)"" | Set-CimInstance -Property @{StartMode = "AutomaticDelayedStart"}
        ### Error is: Set-CimInstance : Could not modify readonly property 'StartMode' of object 'Win32_Service: <Caption> <Name>
        }

    $After = @()
    ForEach ($Service in $Services) {
        $After += Get-CimInstance -ComputerName $Server -ClassName 'Win32_Service' -Property * | Where-Object -Property Name -like "*$Service*"
        }

    $After | Format-Table -Property PSComputerName, Name, StartMode, DelayedAutoStart, State, StartName -AutoSize
    }

Я думаю, что главная проблема в том, что AutomaticDelayedStart не является доступным режимом запуска для SQL Server:

Sql Server Configuration Manager

Вы можете запросить у CIM список доступных режимов запуска с помощью следующего кода:

$c = Get-CimClass -ClassName Win32_Service
$p = $c.CimClassMethods | Where-Object Name -eq ChangeStartMode | Select-Object -ExpandProperty Parameters
$s = $p | Where-Object Name -eq StartMode
$v = $s.Qualifiers | Where-Object Name -eq ValueMap | Select-Object -ExpandProperty Value
Write-Host "Available StartModes: $($v -join ',')"
# Available StartModes: Boot,System,Automatic,Manual,Disabled

(Не знаю, почему Boot или System указаны там и не пробовал их использовать.)

Также можно более эффективно обновлять и заново получать объекты CIM, просто передавая их в соответствующий cmdlet. Следующий код работал у меня на локальной машине:

#Requires -RunAsAdministrator
$Servers   = @(...)
$Services  = @("MSSQL", "MSSQLSERVER", "SQLAgent")
$StartMode="Automatic"
ForEach ($Server in $Servers) 
{
    $Before = @()
    ForEach ($Service in $Services) 
    {
        $Before += Get-CimInstance -ComputerName $Server -ClassName 'Win32_Service' -Filter "Name="$Service""
    }

    $Before | Format-Table -Property PSComputerName, Name, StartMode, DelayedAutoStart, State, StartName -AutoSize

    $After = @()
    ForEach ($Item in $Before) 
    {
        $Item | Invoke-CimMethod -MethodName Change -Arguments @{StartMode = "$StartMode"}
        $After += $Item | Get-CimInstance 
    }

    $After | Format-Table -Property PSComputerName, Name, StartMode, DelayedAutoStart, State, StartName -AutoSize
}

Ответ или решение

Когда дело доходит до автоматизации управления службами посредством PowerShell, особенно в случае настройки типа запуска службы как «Автоматически (с задержкой)», необходимо учитывать множество нюансов. Использование PowerShell для таких задач позволяет качественно и эффективно управлять инфраструктурой IT, однако требует детального подхода и понимания функционирования каждой команды и методов, которые задействованы в вашем скрипте.

Теория: Понимание StartMode и DelayedAutoStart

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

Важно понимать, что AutomaticDelayedStart не является допустимым значением непосредственно для StartMode. Вместо этого, комбинация StartMode равным "Automatic" и свойством DelayedAutoStart, установленным в True, обеспечит отложенный старт.

Пример: Проблемы с использованием Set-CimInstance и Invoke-CimMethod

В представленном примере были совершены некоторые ошибки, которые привели к недееспособности скрипта. Следует учитывать, что…

  1. Invoke-CimMethod для изменения типа запуска использует метод ChangeStartMode и не поддерживает параметр DelayedAutoStart напрямую, так как это ограничение Invoke-CimMethod.

  2. Set-CimInstance выдает ошибку о том, что StartMode является свойством только для чтения в классе Win32_Service. Это объясняется спецификой реализации этого класса в Windows.

Применение: Реализация правильной стратегии

Для корректного выполнения задачи на основе PowerShell, требуется комбинированное использование Set-Service и Set-ItemProperty через WMI и стандартные PowerShell-команды.

#Комплект переменных
$Servers = @(...) # ваш список серверов
$Services = @("MSSQL", "MSSQLSERVER", "SQLAgent")

ForEach ($Server in $Servers) {
    # Подключение к удаленному серверу
    Invoke-Command -ComputerName $Server -ScriptBlock {
        Param($Services)

        ForEach ($Service in $Services) {
            # Профессиональный подход: Изменение StartMode на Automatic
            Set-Service -Name $Service -StartupType Automatic

            # Используем WMI для установки DelayedAutoStart в True
            $serviceObj = Get-WmiObject -Class Win32_Service -Filter "Name='$Service'"
            $serviceObj.ChangeStartMode("Automatic")
            $null = Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$($Service)" -Name DelayedAutostart -Value 1

            # Вывод текущих статусов служб
            Get-Service -Name $Service | Select-Object DisplayName, Status, StartType | Format-Table -AutoSize
        }
    } -ArgumentList ($Services)
}

Заключение и дополнительные соображения

Предложенный подход сочетает в себе использование как PowerShell, так и WMI-команд, обеспечивая должный контроль за службами с возможностью откладывания их запуска. Важно всегда тестировать такие скрипты в контролируемой среде, чтобы избежать неожиданных последствий на производственных серверах.

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

Оцените материал
Добавить комментарий

Капча загружается...