about_Enum

简短说明

语句 enum 声明枚举。 枚举是一种非重复类型,它由一组名为枚举器列表的命名标签组成。

长说明

语句 enum 允许创建一组强类型标签。 可以在代码中使用该枚举,而无需分析或检查拼写错误。

枚举在内部表示为整数值类型,起始值为零。 默认情况下,PowerShell 枚举使用 System.Int32 ([int]) 作为基础类型。 默认情况下,PowerShell 为列表中的第一个标签分配值零。 默认情况下,PowerShell 使用连续整数分配剩余的标签。

在定义中,可以为标签提供任何整数值。 未分配值的标签采用下一个整数值。

语法

枚举使用以下语法:

整数枚举定义语法

[[<attribute>]...] enum <enum-name> {
    <label> [= <int-value>]
    ...
}

特定基础类型枚举定义语法

[[<attribute>]...] enum <enum-name> : <underlying-type-name> {
    <label> [= <int-value>]
    ...
}

标志枚举定义语法

[[<attribute>]...] [Flag()] enum <enum-name>[ : <underlying-type-name>] {
    <label 0> [= 1]
    <label 1> [= 2]
    <label 2> [= 4]
    <label 3> [= 8]
    ...
    ...
}

枚举访问语法

[<enum-name>]::<label>

示例

示例 1 - 最小枚举

以下代码块定义了带有三个标签的 MarkdownUnorderedListCharacter 枚举。 它不会向任何标签分配显式值。

enum MarkdownUnorderedListCharacter {
    Asterisk
    Dash
    Plus
}

下一个代码块显示当强制转换为枚举类型时整数值和字符串值的行为方式。

$ValuesToConvert = @(0, 'Asterisk', 1, 'Dash', 2, 'Plus')
foreach ($Value in $ValuesToConvert) {
    [MarkdownUnorderedListCharacter]$EnumValue = $Value

    [pscustomobject]@{
        AssignedValue = $Value
        Enumeration   = $EnumValue
        AreEqual      = $Value -eq $EnumValue
    }
}
AssignedValue Enumeration AreEqual
------------- ----------- --------
            0    Asterisk     True
     Asterisk    Asterisk     True
            1        Dash     True
         Dash        Dash     True
            2        Plus     True
         Plus        Plus     True

强制转换等于枚举值的整数将返回该枚举。 与枚举的标签相同的强制转换字符串将返回该枚举。

示例 2 - 显式和同义词枚举值

下面的示例演示与媒体文件关联的 对象的枚举。 定义将显式值分配给 、、 picturevideo的基础值music。 紧跟在显式赋值之后的标签将获取下一个整数值。 可以通过将相同的值分配给另一个标签来创建同义词;请参阅的构造值:oggogamogg、 或 jpgjpeg、 或 mpgmpeg

enum MediaTypes {
    unknown
    music   = 10
    mp3
    aac
    ogg     = 15
    oga     = 15
    mogg    = 15
    picture = 20
    jpg
    jpeg    = 21
    png
    video   = 40
    mpg
    mpeg    = 41
    avi
    m4v
}

方法 GetEnumNames() 返回 枚举的标签列表。

[MediaTypes].GetEnumNames()
unknown
music
mp3
aac
ogg
oga
mogg
picture
jpg
jpeg
png
video
mpg
mpeg
avi
m4v

方法 GetEnumValues() 返回 枚举的值列表。

[MediaTypes].GetEnumValues()
unknown
music
mp3
aac
ogg
ogg
ogg
picture
jpg
jpg
png
video
mpg
mpg
avi
m4v

注意

GetEnumNames()GetEnumValues() 似乎返回相同的结果;命名值的列表。 但是,在内部枚举 GetEnumValues() 值,然后将值映射到名称中。 仔细阅读列表,你会注意到 oggogamogg 显示在 的 GetEnumNames()输出中,但 的 GetEnumValues() 输出仅显示 ogg。 、jpeg、 和 mpg会发生mpeg同样的情况jpg。 PowerShell 为同义词值返回的名称不是确定性的。

可以使用 GetEnumName() 方法获取与特定值关联的名称。 如果有多个与值关联的名称,该方法将返回第一个定义的名称。

[MediaTypes].GetEnumName(15)
ogg

以下示例演示如何将每个名称映射到其值。

[MediaTypes].GetEnumNames() | ForEach-Object {
  [pscustomobject]@{
    Name = $_
    Value = [int]([MediaTypes]::$_)
  }
}
Name    Value
----    -----
unknown     0
music      10
mp3        11
aac        12
ogg        15
oga        15
mogg       15
picture    20
jpg        21
jpeg       21
png        22
video      40
mpg        41
mpeg       41
avi        42
m4v        43

可以使用语法 [<enum-name>]::<label>指定单个枚举值的标签。

[MediaTypes]::png
[MediaTypes]::png -eq 22
png
True

示例 3 - 枚举作为标志

以下代码块将 FileAttributes 枚举创建为一组位标志。 每个标签的值是前一个标签值的两倍。

[Flags()] enum FileAttributes {
    Archive    = 1
    Compressed = 2
    Device     = 4
    Directory  = 8
    Encrypted  = 16
    Hidden     = 32
}

[FileAttributes]$file1 =  [FileAttributes]::Archive
[FileAttributes]$file1 += [FileAttributes]::Compressed
[FileAttributes]$file1 += [FileAttributes]::Device
"file1 attributes are: $file1"

[FileAttributes]$file2 = [FileAttributes]28 ## => 16 + 8 + 4
"file2 attributes are: $file2"
file1 attributes are: Archive, Compressed, Device
file2 attributes are: Device, Directory, Encrypted

若要测试是否设置了特定标志,可以使用二进制比较运算符 -band。 此示例测试 值$file2中的 DeviceArchive 属性。

PS > ($file2 -band [FileAttributes]::Device) -eq [FileAttributes]::Device
True

PS > ($file2 -band [FileAttributes]::Archive) -eq [FileAttributes]::Archive
False

还可以使用 HasFlag() 方法测试是否设置了特定标志。 此示例测试 的值$file1中的 DeviceHidden 属性。

PS > $file1.HasFlag([FileAttributes]::Device)
True

PS > $file1.HasFlag([FileAttributes]::Hidden)
False

示例 4 - 作为参数的枚举

在以下示例中, 函数ConvertTo-LineEndingRegex定义了类型为 EndOfLineInputObject 参数。

enum EndOfLine {
    CR   = 1
    LF   = 2
    CRLF = 3
}

function ConvertTo-LineEndingRegex {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline)]
        [EndOfLine[]]$InputObject
    )

    process {
        switch ($InputObject) {
            CR   {  '\r'  }
            LF   {  '\n'  }
            CRLF { '\r\n' }
        }
    }
}

[EndOfLine]::CR | ConvertTo-LineEndingRegex

'CRLF' | ConvertTo-LineEndingRegex

ConvertTo-LineEndingRegex 2
\r

\r\n

\n

在此示例中,调用 ConvertTo-LineEndingRegex 的第一个语句传递 的 CR枚举值。 第二个语句传递字符串 ,该字符串 'CRLF'将强制转换为 LineEnding。 第三个语句指定参数的值 2 ,该值映射到 LF 标签。

可以通过在 PowerShell 提示符中键入以下文本来查看参数完成选项:

ConvertTo-LineEndingRegex -InputObject <Tab>

为参数指定无效的标签名称或数值时,函数将引发错误。

ConvertTo-LineEndingRegex -InputObject 0
ConvertTo-LineEndingRegex: Cannot process argument transformation on
parameter 'InputObject'. Cannot convert value "0" to type "EndOfLine" due
to enumeration values that are not valid. Specify one of the following
enumeration values and try again. The possible enumeration values are
"CR,LF,CRLF".

示例 5 - 具有特定基础类型的枚举

从 PowerShell 6.2 开始,可以使用特定的基础类型定义枚举。 此示例显示枚举的有效基础类型。

第一个代码块将两个变量初始化为数组。 $EnumTypes 是一个空数组,用于保存动态创建的类型。 $IntegralTypes 是包含枚举的有效基础类型的数组。

$EnumTypes     = @()
$IntegralTypes = @(
    'byte', 'sbyte', 'short', 'ushort', 'int', 'uint', 'long', 'ulong'
)

下一个代码块定义用于动态创建枚举定义的模板。 将 {0} 格式占位符替换为整型类型名称时,模板将创建一个脚本块,该脚本块可:

  1. 定义名为 的 <type>Enum枚举,如 byteEnum。 定义的枚举使用指定的整型类型作为基础值类型。

    枚举的定义是将 Min 值设置为整型类型的最小值。 它定义 Max 设置为整型类型的最大值的值。

  2. 返回新定义的类型。

$DefinitionTemplate = @"
enum {0}Enum : {0} {{
    Min = [{0}]::MinValue
    Max = [{0}]::MaxValue
}}

[{0}Enum]
"@

下一个代码块使用模板在当前范围内创建和调用 scriptblock。 它将返回的类型定义添加到 数组中 $EnumTypes

foreach ($IntegralType in $IntegralTypes) {
    $Definition  = $DefinitionTemplate -f $IntegralType
    $ScriptBlock = [scriptblock]::Create($Definition)
    $EnumTypes  += . $ScriptBlock
}

最后一个代码块循环访问枚举类型,使用 GetEnumValuesAsUnderlyingType() 方法将值列为基础类型。 循环为每个值创建一个新的 对象,显示枚举类型、值类型、标签和实际值。

foreach ($EnumType in $EnumTypes) {
    $EnumType.GetEnumValuesAsUnderlyingType() | ForEach-Object {
        [pscustomobject]@{
            EnumType  = $EnumType.FullName
            ValueType = $_.GetType().FullName
            Label     = $EnumType.GetEnumName($_)
            Value     = $_
        }
    }
}
EnumType   ValueType     Label                Value
--------   ---------     -----                -----
byteEnum   System.Byte   Min                      0
byteEnum   System.Byte   Max                    255
sbyteEnum  System.SByte  Max                    127
sbyteEnum  System.SByte  Min                   -128
shortEnum  System.Int16  Max                  32767
shortEnum  System.Int16  Min                 -32768
ushortEnum System.UInt16 Min                      0
ushortEnum System.UInt16 Max                  65535
intEnum    System.Int32  Max             2147483647
intEnum    System.Int32  Min            -2147483648
uintEnum   System.UInt32 Min                      0
uintEnum   System.UInt32 Max             4294967295
longEnum   System.Int64  Max    9223372036854775807
longEnum   System.Int64  Min   -9223372036854775808
ulongEnum  System.UInt64 Min                      0
ulongEnum  System.UInt64 Max   18446744073709551615

枚举方法

以下列表包括可用于 PowerShell 中的枚举的有用方法以及如何使用它们。

格式

静态 Format() 方法返回给定枚举类型、枚举值和格式字符串的格式化字符串输出。 输出与对具有指定格式字符串的值调用 ToString 方法相同。

可以对 System.Enum 基类类型或特定枚举类型使用静态方法。

[System.Enum]::format([<enum-name>], <value>, <format-string>)
[<enum-name>]::format([<enum-name>], <value>, <format-string>)

有效的格式字符串是 GgXdxDF 或 。f 有关详细信息,请参阅 枚举格式字符串

以下示例使用每个受支持的枚举格式字符串将 TaskState 枚举的每个值转换为其字符串表示形式。

enum TaskState {
    ToDo
    Doing
    Done
}

# String format template for the statements
$Statement = "[System.Enum]::Format([TaskState], {0}, '{1}')"

foreach ($Format in @('G', 'D', 'X', 'F')) {
    $StatementToDo  = $Statement -f 0, $Format
    $StatementDoing = $Statement -f "([TaskState]'Doing')", $Format
    $StatementDone  = $Statement -f '[TaskState]::Done', $Format
    $FormattedToDo  = [System.Enum]::Format(
      [TaskState], 0, $Format
    )
    $FormattedDoing = [System.Enum]::Format(
        [TaskState], ([TaskState]'Doing'), $Format
    )
    $FormattedDone  = [System.Enum]::Format(
      [TaskState], [TaskState]::Done, $Format
    )

    "{0,-62} => {1}" -f $StatementToDo,  $FormattedToDo
    "{0,-62} => {1}" -f $StatementDoing, $FormattedDoing
    "{0,-62} => {1}" -f $StatementDone,  $FormattedDone
}
[System.Enum]::Format([TaskState], 0, 'G')                     => ToDo
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'G')  => Doing
[System.Enum]::Format([TaskState], [TaskState]::Done, 'G')     => Done
[System.Enum]::Format([TaskState], 0, 'D')                     => 0
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'D')  => 1
[System.Enum]::Format([TaskState], [TaskState]::Done, 'D')     => 2
[System.Enum]::Format([TaskState], 0, 'X')                     => 00000000
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'X')  => 00000001
[System.Enum]::Format([TaskState], [TaskState]::Done, 'X')     => 00000002
[System.Enum]::Format([TaskState], 0, 'F')                     => ToDo
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'F')  => Doing
[System.Enum]::Format([TaskState], [TaskState]::Done, 'F')     => Done

GetEnumName

反射 GetEnumName() 方法返回特定枚举值的名称。 输入值必须是枚举的有效基础类型,如整数或枚举值。 如果有多个与值关联的名称,该方法将返回第一个定义的名称。

[<enum-name>].GetEnumName(<value>)
enum GateState {
    Unknown
    Open
    Opening
    Closing
    Closed
}

foreach ($Value in 0..4) {
    [pscustomobject]@{
      IntegerValue = $Value
      EnumName     = [GateState].GetEnumName($Value)
    }
}
IntegerValue EnumName
------------ --------
           0 Unknown
           1 Open
           2 Opening
           3 Closing
           4 Closed

GetEnumNames

反射 GetEnumNames() 方法将每个枚举值的名称作为字符串返回。 输出包含同义词。

[<enum-name>].GetEnumNames()
enum Season {
    Unknown
    Spring
    Summer
    Autumn
    Winter
    Fall   = 3
}

[Season].GetEnumNames()
Unknown
Spring
Summer
Fall
Autumn
Winter

GetEnumUnderlyingType

反射 GetEnumUnderlyingType() 方法返回枚举值的基础类型。

[<enum-name>].GetEnumUnderlyingType()
enum IntBasedEnum {
    Zero
    One
    Two
}
enum ShortBasedEnum : short {
    Zero
    One
    Two
}

foreach ($EnumType in @([IntBasedEnum], [ShortBasedEnum])) {
    [pscustomobject]@{
        EnumType = $EnumType
        ValueType = $EnumType.GetEnumUnderlyingType()
    }
}
EnumType       ValueType
--------       ---------
IntBasedEnum   System.Int32
ShortBasedEnum System.Int16

GetEnumValues

反射 GetEnumValues() 方法返回枚举的每个已定义值。

[<enum-name>].GetEnumValues()
enum Season {
    Unknown
    Spring
    Summer
    Autumn
    Winter
    Fall   = 3
}

[Season].GetEnumValues()
Unknown
Spring
Summer
Fall
Fall
Winter

GetEnumValuesAsUnderlyingType

反射 GetEnumValuesAsUnderlyingType() 方法将枚举的每个定义值作为基础类型返回。

[<enum-name>].GetEnumValuesAsUnderlyingType()
enum IntBasedEnum {
    Zero
    One
    Two
}
enum ShortBasedEnum : short {
    Zero
    One
    Two
}

foreach ($EnumType in @([IntBasedEnum], [ShortBasedEnum])) {
    [pscustomobject]@{
        EnumType = $EnumType
        ValueType = $EnumType.GetEnumValuesAsUnderlyingType()[0].GetType()
    }
}
EnumType       ValueType
--------       ---------
IntBasedEnum   System.Int32
ShortBasedEnum System.Int16

HasFlag

实例 HasFlag 方法确定是否为标志枚举值设置位标志。 与执行二进制比较和等效性检查相比,使用此方法更短且更易于阅读。

<enum-value>.HasFlag(<enum-flag-value>)

以下示例定义 ModuleFeatures 标志枚举,并显示值 39 具有哪些标志。

[Flags()] enum ModuleFeatures {
    Commands  = 1
    Classes   = 2
    Enums     = 4
    Types     = 8
    Formats   = 16
    Variables = 32
}

$Features = [ModuleFeatures]39

foreach ($Feature in [ModuleFeatures].GetEnumValues()) {
    "Has flag {0,-12}: {1}" -f "'$Feature'", ($Features.HasFlag($Feature))
}
Has flag 'Commands'  : True
Has flag 'Classes'   : True
Has flag 'Enums'     : True
Has flag 'Types'     : False
Has flag 'Formats'   : False
Has flag 'Variables' : True

IsDefined

如果为 枚举定义了输入值,则 IsDefined() 静态方法返回 $true ;否则 $false返回 。 使用此方法可检查值是否对枚举有效,而无需处理无效参数错误。

可以对 System.Enum 基类类型或特定枚举类型使用静态方法。

[System.Enum]::IsDefined([<enum-name>], <value>)
[<enum-name>]::IsDefined([<enum-name>], <value>)
enum Season {
    Unknown
    Spring
    Summer
    Autumn
    Winter
    Fall   = 3
}

foreach ($Value in 0..5) {
    $IsValid   = [Season]::IsDefined([Season], $Value)
    $EnumValue = if ($IsValid) { [Season]$Value }

    [pscustomobject] @{
        InputValue = $Value
        IsValid    = $IsValid
        EnumValue  = $EnumValue
    }
}
InputValue IsValid EnumValue
---------- ------- ---------
         0    True   Unknown
         1    True    Spring
         2    True    Summer
         3    True      Fall
         4    True    Winter
         5   False

ToString

实例 ToString() 方法返回枚举值的标签。 此方法也是枚举值如何显示为输出的默认视图。 (可选)可以指定格式字符串来控制值显示方式。 有关格式设置的详细信息,请参阅 设置枚举值的格式

注意

对于为特定值定义同义词的枚举,不要编写依赖于 输出的代码 ToString()。 方法可以返回值的任何有效名称。

<enum-value>.ToString([<format-string>])

以下示例将 Shade 枚举 Gray 定义为 的 Grey同义词。 然后,它输出对象,这些对象显示实际枚举值,枚举显示为字符串,枚举显示为整数。

enum Shade {
    White
    Grey
    Gray = 1
    Black
}

[Shade].GetEnumValues() | Foreach-Object -Process {
    [pscustomobject]@{
        EnumValue    = $_
        StringValue  = $_.ToString()
        IntegerValue = [int]$_
    }
}
numValue StringValue IntegerValue
--------- ----------- ------------
    White White                  0
     Grey Grey                   1
     Grey Grey                   1
    Black Black                  2

枚举值同义词

可以定义为同一整数值提供不同名称的枚举。 执行此操作时,指向相同基础值的名称称为 同义词。 具有同义词的枚举使用户能够为同一值指定不同的名称。

使用同义词定义枚举时,不要编写依赖于转换为特定名称的同义词值的代码。 可以可靠地编写将同义词字符串转换为枚举值的代码。 使用枚举值本身时,始终将其作为枚举值或其基础类型而不是字符串进行比较。

以下代码块使用 GreyGray 作为同义词定义 Shade 枚举。

enum Shade {
    White
    Grey
    Gray = 1
    Black
}

[Shade]'Grey' -eq [Shade]::Gray
[Shade]::Grey -eq 1
[Shade]'Gray' -eq 1
True
True
True

枚举作为标志

枚举的一个常见用途是表示一组互斥值。 例如, ArrivalStatus 实例的值可以是 Early、OnTime 或 Late。 一个 ArrivalStatus 实例的值反映多个枚举常量是没有意义的。

但是,在其他情况下,枚举对象的值可以包含多个枚举成员,并且每个成员表示枚举值中的一个位字段。 可以使用 FlagsAttribute 指示枚举由位字段组成,作为用户可以组合的标志。

要使作为标志的枚举正常工作,必须将每个标签的整数值设置为 2 的幂。 如果未为标签指定值,PowerShell 会将该值设置为比上一个标签高一个值。

可以定义常用标志组合的值,使用户能够更轻松地同时指定一组标志。 值的名称应为标志的组合名称。 整数值应为标志值之和。

若要确定是否为值设置了特定标志,请对值使用 HasFlag() 方法或使用二进制比较运算符 -band

有关演示如何使用标志枚举和检查是否设置标志的示例,请参阅示例 3

枚举作为参数

可以定义使用枚举作为其类型的 cmdlet 参数。 将枚举指定为参数的类型时,用户会自动完成该参数的值并验证该参数的值。 参数完成建议枚举的有效标签列表。

当参数具有枚举作为其类型时,可以指定以下任一项:

  • 枚举,例如 [<EnumType>]::<Label>
  • 字符串格式的枚举标签
  • 枚举的数值

有关显示枚举类型参数行为的示例,请参阅 示例 4

具有特定基础类型的枚举

从 PowerShell 6.2 开始,可以使用特定的基础类型定义枚举。 定义不带特定基础类型的枚举时,PowerShell 会创建 (System.Int32) 作为基础类型的枚举[int]

枚举的基础类型必须是 整型数值类型。 以下列表包含具有短名称和完整类型名称的有效类型:

  • byte - System.Byte
  • sbyte - System.SByte
  • short - System.Int16
  • ushort - System.UInt16
  • int - System.Int32
  • uint - System.UInt32
  • long - System.Int64
  • ulong - System.UInt64

可以将枚举的特定基础类型定义为短名称或完整类型名称。 以下定义在功能上是相同的。 只有用于基础类型的名称不同。

enum LongValueEnum : long {
    Zero
    One
    Two
}
enum LongValueEnum : System.Int64 {
    Zero
    One
    Two
}

设置枚举值的格式

可以通过调用静态 Format 方法以及实例 ToString 方法的重载,将枚举值转换为其字符串表示形式。 可以使用格式字符串来控制枚举值以字符串形式表示的精确方式。 有关详细信息,请参阅 枚举格式字符串

以下示例使用每个受支持的枚举格式字符串 (GXgdDFxf ) 将 TaskState 枚举的每个成员转换为其字符串表示形式。

enum TaskState {
    ToDo
    Doing
    Done
}

[TaskState].GetEnumValues() | ForEach-Object {
    [pscustomobject]@{
        "ToString('G')" = $_.ToString('G')
        "ToString('D')" = $_.ToString('D')
        "ToString('X')" = $_.ToString('X')
        "ToString('F')" = $_.ToString('F')
    }
}
ToString('G') ToString('D') ToString('X') ToString('F')
------------- ------------- ------------- -------------
ToDo          0             00000000      ToDo
Doing         1             00000001      Doing
Done          2             00000002      Done

以下示例将格式字符串用于标志枚举的值。

[Flags()] enum FlagEnum {
    A = 1
    B = 2
    C = 4
}

$FlagValues = @(
    [FlagEnum]::A                                 # 1
    [FlagEnum]::B                                 # 2
    [FlagEnum]::A + [FlagEnum]::B                 # 3
    [FlagEnum]::C                                 # 4
    [FlagEnum]::C + [FlagEnum]::A                 # 5
    [FlagEnum]::C + [FlagEnum]::B                 # 6
    [FlagEnum]::C + [FlagEnum]::A + [FlagEnum]::B # 7
    [FlagEnum]::C + [FlagEnum]::C                 # 8
)

foreach ($Value in $FlagValues) {
    [pscustomobject]@{
        "ToString('G')" = $Value.ToString('G')
        "ToString('D')" = $Value.ToString('D')
        "ToString('X')" = $Value.ToString('X')
        "ToString('F')" = $Value.ToString('F')
    }
}
ToString('G') ToString('D') ToString('X') ToString('F')
------------- ------------- ------------- -------------
A             1             00000001      A
B             2             00000002      B
A, B          3             00000003      A, B
C             4             00000004      C
A, C          5             00000005      A, C
B, C          6             00000006      B, C
A, B, C       7             00000007      A, B, C
8             8             00000008      8

请注意,对于标志枚举, GF 格式字符串显示用逗号分隔的值的集标志列表。 最后一个值 8不会列出任何标志,因为它实际上不是有效的标志集。 如果不复制至少一个标志,则不能组合枚举标志来获取 的总 8 和。

使用 Update-TypeData 定义扩展方法

不能在声明中为枚举定义方法。 若要扩展枚举的功能,可以使用 Update-TypeData cmdlet 定义 ScriptMethod 枚举的成员。

以下示例使用 Update-TypeData cmdlet 将方法添加到 GetFlags()FileAttributes 标志枚举。 它返回为值设置的标志的数组。

[Flags()] enum FileAttributes {
    Archive    = 1
    Compressed = 2
    Device     = 4
    Directory  = 8
    Encrypted  = 16
    Hidden     = 32
}

$MemberDefinition = @{
    TypeName   = 'FileAttributes'
    MemberName = 'GetFlags'
    MemberType = 'ScriptMethod'
    Value      = {
        foreach ($Flag in $this.GetType().GetEnumValues()) {
          if ($this.HasFlag($Flag)) { $Flag }
        }
    }
}

Update-TypeData @MemberDefinition

$File = [FileAttributes]28

$File.GetFlags()
Device
Directory
Encrypted

使用类型加速器导出枚举

默认情况下,PowerShell 模块不会自动导出 PowerShell 中定义的类和枚举。 如果不调用 using module 语句,自定义类型在模块外部不可用。

但是,如果模块添加了类型加速器,则用户导入模块后,这些类型加速器将立即在会话中可用。

注意

将类型加速器添加到会话使用内部 (而不是公共) API。 使用此 API 可能会导致冲突。 如果导入模块时已存在同名的类型加速器,则下面所述的模式将引发错误。 从会话中删除模块时,它还会删除类型加速器。

此模式可确保这些类型在会话中可用。 在 VS Code 中创作脚本文件时,它不会影响 IntelliSense 或完成。 若要获取 VS Code 中自定义类型的 IntelliSense 和完成建议,需要在脚本顶部添加 语句 using module

以下模式演示如何在模块中将 PowerShell 类和枚举注册为类型加速器。 将代码片段添加到根脚本模块的任何类型定义之后。 请确保变量 $ExportableTypes 包含要在用户导入模块时提供给用户的每个类型。 其他代码不需要任何编辑。

# Define the types to export with type accelerators.
$ExportableTypes =@(
    [DefinedTypeName]
)
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [psobject].Assembly.GetType(
    'System.Management.Automation.TypeAccelerators'
)
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
    if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
        $Message = @(
            "Unable to register type accelerator '$($Type.FullName)'"
            'Accelerator already exists.'
        ) -join ' - '

        throw [System.Management.Automation.ErrorRecord]::new(
            [System.InvalidOperationException]::new($Message),
            'TypeAcceleratorAlreadyExists',
            [System.Management.Automation.ErrorCategory]::InvalidOperation,
            $Type.FullName
        )
    }
}
# Add type accelerators for every exportable type.
foreach ($Type in $ExportableTypes) {
    $TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
# Remove type accelerators when the module is removed.
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
    foreach($Type in $ExportableTypes) {
        $TypeAcceleratorsClass::Remove($Type.FullName)
    }
}.GetNewClosure()

当用户导入模块时,添加到会话的类型加速器的任何类型都立即可用于 IntelliSense 和完成。 删除模块时,类型加速器也是如此。

从 PowerShell 模块手动导入枚举

Import-Module#requires和 语句仅导入模块定义的模块函数、别名和变量。 不导入枚举。

如果模块定义类和枚举,但未为这些类型添加类型加速器,请使用 using module 语句导入它们。

语句 using module 从根模块导入类和枚举, (ModuleToProcess 脚本模块或二进制模块的) 。 它不会一致地将嵌套模块中定义的类或脚本中定义的点源类导入根模块。 定义希望直接在根模块中供模块外部用户使用的类。

有关 语句 using 的详细信息,请参阅 about_Using

在开发期间加载新更改的代码

在脚本模块开发期间,通常会更改代码,然后使用 Force 参数加载新版本的模块Import-Module。 这仅适用于对根模块中函数的更改。 Import-Module 不会重新加载任何嵌套模块。 此外,无法加载任何更新的类。

若要确保运行最新版本,必须启动新会话。 无法在 PowerShell 中定义并使用 语句导入 using 的类和枚举进行卸载。

另一种常见的开发做法是将代码分成不同的文件。 如果一个文件中的函数使用在另一个模块中定义的枚举,则应使用 using module 语句来确保函数具有所需的枚举定义。

限制

  • 不能使用属性修饰 PowerShell 中定义的枚举值。 只能修饰枚举声明本身,如用于将枚举定义为一组位标志的 FlagsAttribute 一样。

    解决方法:无

  • 不能在枚举定义中定义方法,并且 PowerShell 不支持定义 [扩展方法] (如 C#)。

    解决方法:使用 Update-TypeData cmdlet 定义 ScriptMethod 枚举的成员。