Вопрос или проблема
У меня есть следующий код, и я ожидаю, что моя мини-программа отобразит значение номер один, остановит сервис, а затем отобразит значение номер два.
Я проверил документацию здесь, и она подтверждает, что следующая команда должна выполняться после выполнения истинного/ложного условия из оператора IF.
https://www.pdq.com/blog/how-to-use-if-statements-in-powershell/
$AccServiceName="AccountLoaderService"
$AccService = Get-service $AccServiceName
if ($AccService.Status -eq 'Running')
{
Write-Host '1'
Stop-Service $AccServiceName
}
Start-Sleep -Seconds 20
if ($AccService.Status -eq 'Stopped')
{
Write-Host '2'
}
На самом деле происходит следующее: отображается номер один, но номер два никогда не отображается.
Сервис определенно останавливается в течение 20 секунд, указанных в коде, и если я запускаю команду снова сразу после этого, без включенной команды ожидания, она возвращает значение номер два.
Надеюсь, это имеет смысл, любая помощь будет очень полезна.
$AccServiceName="AccountLoaderService"
$AccService = Get-Service $AccServiceName
if ($AccService.Status -eq 'Running') {
Write-Host '1'
Stop-Service $AccServiceName
}
Start-Sleep -Seconds 20
# Обновите статус сервиса
$AccService = Get-Service $AccServiceName
if ($AccService.Status -eq 'Stopped') {
Write-Host '2'
}
Добавив $AccService = Get-Service $AccServiceName после команды Start-Sleep, вы гарантируете, что статус сервиса обновляется перед повторной проверкой. Это должно позволить вашему скрипту отображать ‘2’, как и ожидалось.
Ответ или решение
Разбор проблемы с циклом IF в PowerShell
Введение
Ваша проблема заключается в том, что после выполнения команды Stop-Service
сервис не обновляет свое состояние перед тем, как вы проверяете его статус в следующем условии. Это распространенное недоразумение при работе с объектами в PowerShell, особенно с сервисами, которые могут обновляться асинхронно.
Описание проблемы
В вашем коде:
- Определение переменных: Вы устанавливаете имя сервиса и получаете его статус.
- Первое условие IF: Если сервис запущен, вы выводите "1" и останавливаете сервис.
- Засыпание: После этого вы включаете задержку на 20 секунд.
- Второе условие IF: Следующая проверка состояния сервиса ожидает, что его статус обновится автоматически.
На самом деле, после остановки сервиса PowerShell не обновляет переменную $AccService
автоматически. Поэтому, когда вы проверяете статус сервиса через 20 секунд, вы все еще получаете устаревший статус.
Решение
Для того чтобы ваш код работал правильно и позволял проверять текущее состояние сервиса после его остановки, вам нужно будет получить его статус заново после сна. Добавьте команду Get-Service
после вызова Start-Sleep
. Вот исправленный вариант вашего кода:
$AccServiceName = "AccountLoaderService"
$AccService = Get-Service $AccServiceName
if ($AccService.Status -eq 'Running') {
Write-Host '1'
Stop-Service $AccServiceName
}
Start-Sleep -Seconds 20
# Обновите статус сервиса
$AccService = Get-Service $AccServiceName
if ($AccService.Status -eq 'Stopped') {
Write-Host '2'
}
Объяснение исправлений
-
Обновление статуса сервиса: После команды
Start-Sleep
вы добавили строкуGet-Service
, что позволяет обновить данные о статусе сервиса. Это важно, поскольку PowerShell работает с копиями объектов, и изменения, сделанные в службах, не отражены в ранее полученных объектах автоматически. -
Проверка статуса: Теперь после ожидания вы корректно проверяете актуальный статус сервиса, что и приводит к ожидаемому выводу "2", если сервис действительно остановлен.
Заключение
Проблемы, подобные вашей, часто встречаются при работе в PowerShell, и знание о том, как PowerShell управляет объектами и состоянием, критически важно для написания корректных и стабильных скриптов. Убедитесь, что вы всегда обновляете состояния объектов после выполнения команд, влияющих на их статус. Это не только улучшит ваши скрипты, но и сделает их более предсказуемыми.
Если у вас возникнут дополнительные вопросы или понадобятся разъяснения, не стесняйтесь задавать их!