Работа с числовыми значениями enum в PowerShell: полное руководство

Если вы когда-нибудь сталкивались с ошибками в PowerShell из-за локализации системы, вы знаете, как это раздражает. Строки вроде Enabled или Disabled могут внезапно превратиться в Включено на русском или Activé на французском – и ваш скрипт сломается. Но есть способ обойти эту проблему, работая с числовыми значениями (enum) вместо текстовых статусов. Давайте разберёмся, как это сделать без головной боли.

Почему enum надёжнее строк (и как это работает)

Числовые значения – это универсальный язык. Даже если система переведена на другой язык, код 4 всегда будет означать одно и то же. Например, статус службы Running в PowerShell соответствует числу 4, и это значение не зависит от локализации. Но где взять эти магические числа?

Вот пример: когда вы получаете статус службы через (Get-Service ‘WinDefend’).Status, PowerShell возвращает объект типа ServiceControllerStatus. Чтобы увидеть его числовое значение, используйте свойство value__:

$service = Get-Service 'WinDefend'  
$service.Status.value__  # Вернёт 4 для состояния 'Running'  

Проблема в том, что не все объекты так очевидны. Например, при работе с функцией Get-WindowsOptionalFeature, её свойство State возвращает строки вроде Disabled или Enabled, но их числовые эквиваленты не документированы явно.

Совет: Если вы видите свойство с текстовым значением, проверьте его тип через Get-Member. Это поможет найти связанный enum.

Как получить список enum-значений для любого свойства

Допустим, вы работаете с Get-WindowsOptionalFeature и хотите узнать, какие числа скрываются за State. Вот пошаговый алгоритм:

1. Получите объект для анализа:

$feature = Get-WindowsOptionalFeature -Online | Select-Object -First 1  

2. Определите тип свойства State:

$feature.State | Get-Member  

В первой строке вывода вы увидите что-то вроде:

TypeName: Microsoft.Dism.Commands.FeatureState

3. Извлеките все возможные значения enum:

[enum]::GetValues([Microsoft.Dism.Commands.FeatureState])  

Это вернёт массив:

Disabled  
DisablePending  
Enabled  
EnablePending  
...  

4. Используйте числовые индексы:

Каждому элементу массива соответствует число, начиная с 0. Например:

Get-WindowsOptionalFeature -Online | Where-Object { $_.State -eq 0 }  # Найдёт все отключённые функции  

Но есть нюанс: если enum определён в сборке, которая не загружена в текущую сессию, PowerShell выдаст ошибку. В таком случае попробуйте явно импортировать модуль, например:

Import-Module Dism  

Кстати, иногда разработчики забывают документировать enum. Если [enum]::GetValues() не работает, проверьте, не является ли свойство простой строкой без привязки к перечислению.

СостояниеЧисловое значение
Disabled0
DisablePending1
Enabled2

Частые ошибки и как их избежать

– Ошибка: «Не удаётся найти тип [Microsoft.Dism.Commands.FeatureState]».
– Решение: Убедитесь, что модуль Dism загружен. Выполните Import-Module Dism перед использованием enum.

– Ошибка: Числовые значения не совпадают с ожидаемыми.
– Причина: Некоторые enums начинаются с 1 вместо 0. Всегда проверяйте вывод [enum]::GetValues().

– Лайфхак: Если не хочется запоминать числа, используйте сам enum в сравнениях:

Get-WindowsOptionalFeature -Online | Where-Object {  
    $_.State -eq [Microsoft.Dism.Commands.FeatureState]::Enabled  
}  

Этот код будет работать даже при смене числовых значений в будущих версиях Windows (хотя такое случается редко).

И напоследок: не все свойства в PowerShell используют enum. Если Get-Member показывает тип string, придётся мириться с рисками локализации – или искать альтернативные API. Но в 90% случаев метод с enum сработает, сделав ваши скрипты надёжнее.

P.S. Если вдруг застряли – посмотрите документацию .NET. Многие enum-ы из PowerShell берутся именно оттуда (например, System.ServiceProcess.ServiceControllerStatus). Просто введите в Google «<название_свойства> enum dotnet», и вы найдёте нужную таблицу.

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

Все поля обязательны к заполнению. Ваш адрес email не будет виден никому.

Новое
Интересное