Win32_ACE

The class Win32_ACE specifies an access control entry (ACE). An ACE grants access permission to files and other resources.

Win32_ACE represents a single Access Control Entry (ACE) which works like a key in a keyring: each ACE defines a security principal (like a user account or security group) and a set of permission flags. This ACE (“key”) can then be added to a Access Control List (ACL, “key ring”) which is part of a Win32_SecurityDescriptor. Security descriptors can then be attached to securable objects such as files, folders, shares, or other items that have a Access Control List (ACL).

Because of this, it makes absolutely no sense to query for instances of this class. This always yields nothing. Instances of Win32_ACE are not freely floating around.

Instead, most securable objects provide the methods GetSecurityDescriptor() and SetSecurityDescriptor() to read and write security descriptors.

When you read a security descriptor, you can examine its properties DACL (Discretionary Access Control List, Permissions) and SACL (Security Access Control List, Auditing). Both are arrays of Win32_ACE.

To write or change permissions, get the original security descriptor and add or remove instances of Win32_ACE in DACL or SACL. To add new instances of Win32_ACE, you need to create new instances via New-CimInstance.

The following item types can be secured via WMI and Win32_ACE:

  • Registry Keys: Windows Registry information is accessible via static methods of the class StdRegProv. This class also provides GetSecurityDescriptor() and SetSecurityDescriptor().
  • Printers: Printers are represented by Win32_Printer instances. These instances come with GetSecurityDescriptor() and SetSecurityDescriptor().
  • Services: Services are represented by Win32_Service. These instances come with GetSecurityDescriptor() and SetSecurityDescriptor().
  • Files: File and folder access security is controlled by instances of Win32_LogicalFileSecuritySetting rather than CIM_DataFile or Win32_Directory. You can access these class instances via associations from an instance of CIM_DataFile or Win32_Directory.
  • Shares: Network share access security is controlled by instances of Win32_LogicalShareSecuritySetting rather than Win32_Share. You can access these class instances via associations from an instance of Win32_Share.

In addition, there are a few internal areas that can be secured via Win32_ACE (however this is rather uncommon):

  • WMI Namespaces: Access to WMI namespaces can be secured via instances of __SystemSecurity classes. These classes have a GetSecurityDescriptor() and SetSecurityDescriptor() methods. Securing WMI namespace is not a common scenario, though.
  • DCOM Applications: DCOM (Distributed COM) is a remoting technique that was replaced by the more secure and simple WsMan but is still being used in many environments. DCOM applications are represented by instances of Win32_DCOMApplicationSetting. There are methods to read and write the various security descriptors used by DCOM applications, such as GetAccessSecurityDescriptor, GetConfigurationSecurityDescriptor and GetLaunchSecurityDescriptor.

Methods

Win32_ACE has no methods.

Properties

Win32_ACE returns 7 properties:

'AccessMask','AceFlags','AceType','GuidInheritedObjectType','GuidObjectType',
'TIME_CREATED','Trustee'

Unless explicitly marked as WRITEABLE, all properties are read-only.

AccessMask

WRITEABLE UINT32

Bit flags that indicate rights granted or denied to the trustee.

AccessMask returns a numeric value. To translate it into a meaningful text, use any of the following approaches:

Use Update-Type

Update-Type tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:

Update-TypeData -MemberName AccessMask -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_ace" -MemberType ScriptProperty  -Value {
  [Flags()] Enum EnumAccessMask
  {
    READDATA_LISTDIRECTORY   = 1
    WRITEDATA_ADDFILE        = 2
    APPENDDATA_ADDSUBDIR     = 4
    READEA                   = 8
    WRITEEA                  = 16
    EXECUTE_TRAVERSE         = 32
    DELETECHILD              = 64
    READATTRIBUTES           = 128
    WRITEATTRIBUTES          = 256
    UNKNOWN512               = 512
    UNKNOWN1024              = 1024
    UNKNOWN2048              = 2048
    UNKNOWN4196              = 4096
    UNKNOWN8192              = 8192
    UNKNOWN16384             = 16384
    UNKNOWN32768             = 32768
    DELETE                   = 65536
    READCONTROL              = 131072
    WRITEDAC                 = 262144
    WRITEOWNER               = 524288
    SYNCHRONIZE              = 1048576
    UNKNOWN2097152           = 2097152
    UNKNOWN4194304           = 4194304
    UNKNOWN8388608           = 8388608
  }

  [EnumAccessMask]($this.PSBase.CimInstanceProperties['AccessMask'].Value)
} -Force

Get-CimInstance -ClassName Win32_ACE | Select-Object -Property AccessMask
Use Select-Object

Select-Object supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:

$AccessMask = @{
  Name = 'AccessMaskText'
  Expression = {
    [Flags()] Enum EnumAccessMask
    {
      READDATA_LISTDIRECTORY   = 1
      WRITEDATA_ADDFILE        = 2
      APPENDDATA_ADDSUBDIR     = 4
      READEA                   = 8
      WRITEEA                  = 16
      EXECUTE_TRAVERSE         = 32
      DELETECHILD              = 64
      READATTRIBUTES           = 128
      WRITEATTRIBUTES          = 256
      UNKNOWN512               = 512
      UNKNOWN1024              = 1024
      UNKNOWN2048              = 2048
      UNKNOWN4196              = 4096
      UNKNOWN8192              = 8192
      UNKNOWN16384             = 16384
      UNKNOWN32768             = 32768
      DELETE                   = 65536
      READCONTROL              = 131072
      WRITEDAC                 = 262144
      WRITEOWNER               = 524288
      SYNCHRONIZE              = 1048576
      UNKNOWN2097152           = 2097152
      UNKNOWN4194304           = 4194304
      UNKNOWN8388608           = 8388608
    }
    
    [EnumAccessMask][int]$_.AccessMask
  }  
}

Get-CimInstance -ClassName Win32_ACE | Select-Object -Property Caption, AccessMask, $AccessMask
Use a PowerShell Hashtable

You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:

$AccessMask_map = @{
      1 = 'READDATA_LISTDIRECTORY'
      2 = 'WRITEDATA_ADDFILE'
      4 = 'APPENDDATA_ADDSUBDIR'
      8 = 'READEA'
     16 = 'WRITEEA'
     32 = 'EXECUTE_TRAVERSE'
     64 = 'DELETECHILD'
    128 = 'READATTRIBUTES'
    256 = 'WRITEATTRIBUTES'
    512 = 'UNKNOWN512'
   1024 = 'UNKNOWN1024'
   2048 = 'UNKNOWN2048'
   4096 = 'UNKNOWN4196'
   8192 = 'UNKNOWN8192'
  16384 = 'UNKNOWN16384'
  32768 = 'UNKNOWN32768'
  65536 = 'DELETE'
 131072 = 'READCONTROL'
 262144 = 'WRITEDAC'
 524288 = 'WRITEOWNER'
1048576 = 'SYNCHRONIZE'
2097152 = 'UNKNOWN2097152'
4194304 = 'UNKNOWN4194304'
8388608 = 'UNKNOWN8388608'
}
Use Enum structure

You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:

[Flags()] Enum EnumAccessMask
{
  READDATA_LISTDIRECTORY   = 1
  WRITEDATA_ADDFILE        = 2
  APPENDDATA_ADDSUBDIR     = 4
  READEA                   = 8
  WRITEEA                  = 16
  EXECUTE_TRAVERSE         = 32
  DELETECHILD              = 64
  READATTRIBUTES           = 128
  WRITEATTRIBUTES          = 256
  UNKNOWN512               = 512
  UNKNOWN1024              = 1024
  UNKNOWN2048              = 2048
  UNKNOWN4196              = 4096
  UNKNOWN8192              = 8192
  UNKNOWN16384             = 16384
  UNKNOWN32768             = 32768
  DELETE                   = 65536
  READCONTROL              = 131072
  WRITEDAC                 = 262144
  WRITEOWNER               = 524288
  SYNCHRONIZE              = 1048576
  UNKNOWN2097152           = 2097152
  UNKNOWN4194304           = 4194304
  UNKNOWN8388608           = 8388608
}

AceFlags

WRITEABLE UINT32

Bit flags that specify inheritance of the ACE.

AceFlags returns a numeric value. To translate it into a meaningful text, use any of the following approaches:

Use Update-Type

Update-Type tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:

Update-TypeData -MemberName AceFlags -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_ace" -MemberType ScriptProperty  -Value {
  [Flags()] Enum EnumAceFlags
  {
    OBJECT_INHERIT         = 1
    CONTAINER_INHERIT      = 2
    NO_PROPAGATE_INHERIT   = 4
    ACE_ONLY_INHERIT       = 8
    INHERITED              = 16
    RESERVED_32            = 32
    SUCCESSFUL_ACCESS      = 64
    FAILED_ACCESS          = 128
  }

  [EnumAceFlags]($this.PSBase.CimInstanceProperties['AceFlags'].Value)
} -Force

Get-CimInstance -ClassName Win32_ACE | Select-Object -Property AceFlags
Use Select-Object

Select-Object supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:

$AceFlags = @{
  Name = 'AceFlagsText'
  Expression = {
    [Flags()] Enum EnumAceFlags
    {
      OBJECT_INHERIT         = 1
      CONTAINER_INHERIT      = 2
      NO_PROPAGATE_INHERIT   = 4
      ACE_ONLY_INHERIT       = 8
      INHERITED              = 16
      RESERVED_32            = 32
      SUCCESSFUL_ACCESS      = 64
      FAILED_ACCESS          = 128
    }
    
    [EnumAceFlags][int]$_.AceFlags
  }  
}

Get-CimInstance -ClassName Win32_ACE | Select-Object -Property Caption, AceFlags, $AceFlags
Use a PowerShell Hashtable

You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:

$AceFlags_map = @{
      1 = 'OBJECT_INHERIT'
      2 = 'CONTAINER_INHERIT'
      4 = 'NO_PROPAGATE_INHERIT'
      8 = 'ACE_ONLY_INHERIT'
     16 = 'INHERITED'
     32 = 'RESERVED_32'
     64 = 'SUCCESSFUL_ACCESS'
    128 = 'FAILED_ACCESS'
}
Use Enum structure

You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:

[Flags()] Enum EnumAceFlags
{
  OBJECT_INHERIT         = 1
  CONTAINER_INHERIT      = 2
  NO_PROPAGATE_INHERIT   = 4
  ACE_ONLY_INHERIT       = 8
  INHERITED              = 16
  RESERVED_32            = 32
  SUCCESSFUL_ACCESS      = 64
  FAILED_ACCESS          = 128
}

AceType

WRITEABLE UINT32

Type of ACE.

AceType returns a numeric value. To translate it into a meaningful text, use any of the following approaches:

Use Update-Type

Update-Type tells PowerShell how to interpret the property. This command needs to be executed only once per PowerShell session:

Update-TypeData -MemberName AceType -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_ace" -MemberType ScriptProperty  -Value {
  Enum EnumAceType
  {
    Access_Allowed   = 0
    Access_Denied    = 1
    Audit            = 2
  }

  [EnumAceType]($this.PSBase.CimInstanceProperties['AceType'].Value)
} -Force

Get-CimInstance -ClassName Win32_ACE | Select-Object -Property AceType
Use Select-Object

Select-Object supports calculated properties. When you submit a hashtable, PowerShell dynamically calculates the result:

$AceType = @{
  Name = 'AceTypeText'
  Expression = {
    $value = $_.AceType
    
    switch([int]$value)
      {
        0          {'Access Allowed'}
        1          {'Access Denied'}
        2          {'Audit'}
        default    {"$value"}
      }
      
  }  
}

Get-CimInstance -ClassName Win32_ACE | Select-Object -Property Caption, AceType, $AceType
Use a PowerShell Hashtable

You can use a PowerShell hashtable to decode numeric values. Use a hashtable like this one:

$AceType_map = @{
      0 = 'Access Allowed'
      1 = 'Access Denied'
      2 = 'Audit'
}
Use Enum structure

You can cast the raw property values to a new enum type to translate raw numeric values into friendly text. Use an enum like this one:

Enum EnumAceType
{
  Access_Allowed   = 0
  Access_Denied    = 1
  Audit            = 2
}

GuidInheritedObjectType

WRITEABLE STRING

Globally unique identifier (GUID) associated with the parent of the object to which these rights apply.

GuidObjectType

WRITEABLE STRING

GUID associated with the type of object to which these rights apply.

TIME_CREATED

UINT64

The time, in the CIM_DATETIME format, when the security descriptor was created.

Trustee

WRITEABLE MANAGEMENTBASEOBJECT

Object representing the user account, group account, or logon session to which an ACE applies.

CDXML Definition

You can turn this WMI class and its methods into PowerShell cmdlets by importing below CDXML file (Cmdlet Definition XML) as a module.

Create Win32_ACE.cdxml
$folder = "c:\wmi\Win32_ACE"
$cdxmlPath = Join-Path -Path $folder -ChildPath "Win32_ACE.cdxml"

# create folder if not present:
$exists = Test-Path -Path $folder
if (!$exists) { $null = New-Item -Path $folder -ItemType Directory }

# write file
$content = @'
<?xml version="1.0" encoding="utf-8"?>


<!--
This file is licensed under 'Attribution 4.0 International' license (https://creativecommons.org/licenses/by/4.0/).

You can free of charge use this code in commercial and non-commercial code, and you can freely modify and adjust the code 
as long as you give appropriate credit to the original author Dr. Tobias Weltner.

This material was published and is maintained here: 

https://powershell.one/wmi/root/cimv2/win32_ace#cdxml-definition
-->


<PowerShellMetadata xmlns="http://schemas.microsoft.com/cmdlets-over-objects/2009/11">
  <!--referencing the WMI class this cdxml uses-->
  <Class ClassName="Root/CIMV2\Win32_ACE" ClassVersion="2.0">
    <Version>1.0</Version>
    <!--default noun used by Get-cmdlets and when no other noun is specified. By convention, we use the prefix "WMI" and the base name of the WMI class involved. This way, you can easily identify the underlying WMI class.-->
    <DefaultNoun>WmiACE</DefaultNoun>
    <!--define the cmdlets that work with class instances.-->
    <InstanceCmdlets>
      <!--query parameters to select instances. This is typically empty for classes that provide only one instance-->
      <GetCmdletParameters />
      <!--defining additional cmdlets that modifies instance properties-->
      <!--Set-ACE: modifying instance properties-->
      <Cmdlet>
        <!--defining the ConfirmImpact which indicates how severe the changes are that this cmdlet performs-->
        <CmdletMetadata Verb="Set" ConfirmImpact="Low" />
        <!--using internal method to modify instance:-->
        <Method MethodName="cim:ModifyInstance">
          <!--defining the parameters of this cmdlet:-->
          <Parameters>
            <Parameter ParameterName="AccessMask">
              <!--the underlying parameter type is uint32 which really is the enumeration [Win32_ACE.AccessMask] that is defined below in the Enums node:-->
              <Type PSType="Win32_ACE.AccessMask" />
              <CmdletParameterMetadata IsMandatory="false">
                <ValidateNotNull />
                <ValidateNotNullOrEmpty />
              </CmdletParameterMetadata>
            </Parameter>
            <Parameter ParameterName="AceFlags">
              <!--the underlying parameter type is uint32 which really is the enumeration [Win32_ACE.AceFlags] that is defined below in the Enums node:-->
              <Type PSType="Win32_ACE.AceFlags" />
              <CmdletParameterMetadata IsMandatory="false">
                <ValidateNotNull />
                <ValidateNotNullOrEmpty />
              </CmdletParameterMetadata>
            </Parameter>
            <Parameter ParameterName="AceType">
              <!--the underlying parameter type is uint32 which really is the enumeration [Win32_ACE.AceType] that is defined below in the Enums node:-->
              <Type PSType="Win32_ACE.AceType" />
              <CmdletParameterMetadata IsMandatory="false">
                <ValidateNotNull />
                <ValidateNotNullOrEmpty />
              </CmdletParameterMetadata>
            </Parameter>
            <Parameter ParameterName="GuidInheritedObjectType">
              <!--the underlying parameter type is string which corresponds to the PowerShell .NET type [system.string]-->
              <Type PSType="system.string" />
              <CmdletParameterMetadata IsMandatory="false">
                <ValidateNotNull />
                <ValidateNotNullOrEmpty />
              </CmdletParameterMetadata>
            </Parameter>
            <Parameter ParameterName="GuidObjectType">
              <!--the underlying parameter type is string which corresponds to the PowerShell .NET type [system.string]-->
              <Type PSType="system.string" />
              <CmdletParameterMetadata IsMandatory="false">
                <ValidateNotNull />
                <ValidateNotNullOrEmpty />
              </CmdletParameterMetadata>
            </Parameter>
            <Parameter ParameterName="Trustee">
              <!--the underlying parameter type is Win32_Trustee which corresponds to the PowerShell .NET type [System.Management.ManagementBaseObject]-->
              <Type PSType="System.Management.ManagementBaseObject" />
              <CmdletParameterMetadata IsMandatory="false">
                <ValidateNotNull />
                <ValidateNotNullOrEmpty />
              </CmdletParameterMetadata>
            </Parameter>
          </Parameters>
        </Method>
      </Cmdlet>
    </InstanceCmdlets>
  </Class>
  <!--defining enumerations-->
  <Enums>
    <Enum EnumName="Win32_ACE.AccessMask" UnderlyingType="system.uint32" BitwiseFlags="true">
      <Value Name="READDATALISTDIRECTORY" Value="1" />
      <Value Name="WRITEDATAADDFILE" Value="2" />
      <Value Name="APPENDDATAADDSUBDIR" Value="4" />
      <Value Name="READEA" Value="8" />
      <Value Name="WRITEEA" Value="16" />
      <Value Name="EXECUTETRAVERSE" Value="32" />
      <Value Name="DELETECHILD" Value="64" />
      <Value Name="READATTRIBUTES" Value="128" />
      <Value Name="WRITEATTRIBUTES" Value="256" />
      <Value Name="UNKNOWN512" Value="512" />
      <Value Name="UNKNOWN1024" Value="1024" />
      <Value Name="UNKNOWN2048" Value="2048" />
      <Value Name="UNKNOWN4196" Value="4096" />
      <Value Name="UNKNOWN8192" Value="8192" />
      <Value Name="UNKNOWN16384" Value="16384" />
      <Value Name="UNKNOWN32768" Value="32768" />
      <Value Name="DELETE" Value="65536" />
      <Value Name="READCONTROL" Value="131072" />
      <Value Name="WRITEDAC" Value="262144" />
      <Value Name="WRITEOWNER" Value="524288" />
      <Value Name="SYNCHRONIZE" Value="1048576" />
      <Value Name="UNKNOWN2097152" Value="2097152" />
      <Value Name="UNKNOWN4194304" Value="4194304" />
      <Value Name="UNKNOWN8388608" Value="8388608" />
    </Enum>
    <Enum EnumName="Win32_ACE.AceFlags" UnderlyingType="system.uint32" BitwiseFlags="true">
      <Value Name="OBJECTINHERIT" Value="1" />
      <Value Name="CONTAINERINHERIT" Value="2" />
      <Value Name="NOPROPAGATEINHERIT" Value="4" />
      <Value Name="ACEONLYINHERIT" Value="8" />
      <Value Name="INHERITED" Value="16" />
      <Value Name="RESERVED32" Value="32" />
      <Value Name="SUCCESSFULACCESS" Value="64" />
      <Value Name="FAILEDACCESS" Value="128" />
    </Enum>
    <Enum EnumName="Win32_ACE.AceType" UnderlyingType="system.uint32">
      <Value Name="AccessAllowed" Value="0" />
      <Value Name="AccessDenied" Value="1" />
      <Value Name="Audit" Value="2" />
    </Enum>
  </Enums>
</PowerShellMetadata>
'@ | Set-Content -LiteralPath $cdxmlPath -Encoding UTF8

# import module
Import-Module -Name $cdxmlPath -Force -Verbose

# list new cmdlets
Get-Command -Module "Win32_ACE"

See here for more information on CDXML and CDXML-based PowerShell modules.

Type Extensions for PowerShell

You can automatically improve properties of class instances by using a types.ps1xml file.

Create Win32_ACE.Types.ps1xml
$folder = "c:\wmi\Win32_ACE"
$typesPath = Join-Path -Path $folder -ChildPath "Win32_ACE.Types.ps1xml"

# create folder if not present:
$exists = Test-Path -Path $folder
if (!$exists) { $null = New-Item -Path $folder -ItemType Directory }

# write file
$content = @'
<?xml version="1.0" encoding="utf-8"?>


<!--
This file is licensed under 'Attribution 4.0 International' license (https://creativecommons.org/licenses/by/4.0/).

You can free of charge use this code in commercial and non-commercial code, and you can freely modify and adjust the code 
as long as you give appropriate credit to the original author Dr. Tobias Weltner.

This material was published and is maintained here: 

https://powershell.one/wmi/root/cimv2/win32_ace#typesps1xml-file
-->


<Types>
  <Type>
    <[email protected]

            Applicable type. This type is produced by Get-CimInstance. 
            To extend instances produced by Get-WmiObject, change the type name to: 

            System.Management.ManagementObject#root/cimv2\Win32_ACE

        @-->
    <Name>Microsoft.Management.Infrastructure.CimInstance#Root/CIMV2/Win32_ACE</Name>
    <Members>
      <ScriptProperty>
        <Name>AccessMask</Name>
        <!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
        <GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_ACE.AccessMask]($this.PSBase.CimInstanceProperties['AccessMask'].Value)</GetScriptBlock>
      </ScriptProperty>
      <ScriptProperty>
        <Name>AceType</Name>
        <!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
        <GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_ACE.AceType]($this.PSBase.CimInstanceProperties['AceType'].Value)</GetScriptBlock>
      </ScriptProperty>
      <ScriptProperty>
        <Name>AceFlags</Name>
        <!--casting raw content to a enum. This translates numeric values to friendly text while leaving the original property value untouched:-->
        <GetScriptBlock>[Microsoft.PowerShell.Cmdletization.GeneratedTypes.Win32_ACE.AceFlags]($this.PSBase.CimInstanceProperties['AceFlags'].Value)</GetScriptBlock>
      </ScriptProperty>
    </Members>
  </Type>
</Types>
'@ | Set-Content -LiteralPath $typesPath -Encoding UTF8

# import type definition
Update-TypeData -PrependPath $typesPath

Note: Win32_ACE.Types.ps1xml is using enumerations defined in ClassName.cdxml which are available only when you imported the .cdxml file via Import-Module.

Or, you can manually update the PowerShell type database using Update-TypeData.

View Update-TypeData commands for Win32_ACE properties
Update-TypeData -MemberName AccessMask -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_ace" -MemberType ScriptProperty  -Value {
  [Flags()] Enum EnumAccessMask
  {
    READDATA_LISTDIRECTORY   = 1
    WRITEDATA_ADDFILE        = 2
    APPENDDATA_ADDSUBDIR     = 4
    READEA                   = 8
    WRITEEA                  = 16
    EXECUTE_TRAVERSE         = 32
    DELETECHILD              = 64
    READATTRIBUTES           = 128
    WRITEATTRIBUTES          = 256
    UNKNOWN512               = 512
    UNKNOWN1024              = 1024
    UNKNOWN2048              = 2048
    UNKNOWN4196              = 4096
    UNKNOWN8192              = 8192
    UNKNOWN16384             = 16384
    UNKNOWN32768             = 32768
    DELETE                   = 65536
    READCONTROL              = 131072
    WRITEDAC                 = 262144
    WRITEOWNER               = 524288
    SYNCHRONIZE              = 1048576
    UNKNOWN2097152           = 2097152
    UNKNOWN4194304           = 4194304
    UNKNOWN8388608           = 8388608
  }

  [EnumAccessMask]($this.PSBase.CimInstanceProperties['AccessMask'].Value)
} -Force

Update-TypeData -MemberName AceFlags -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_ace" -MemberType ScriptProperty  -Value {
  [Flags()] Enum EnumAceFlags
  {
    OBJECT_INHERIT         = 1
    CONTAINER_INHERIT      = 2
    NO_PROPAGATE_INHERIT   = 4
    ACE_ONLY_INHERIT       = 8
    INHERITED              = 16
    RESERVED_32            = 32
    SUCCESSFUL_ACCESS      = 64
    FAILED_ACCESS          = 128
  }

  [EnumAceFlags]($this.PSBase.CimInstanceProperties['AceFlags'].Value)
} -Force

Update-TypeData -MemberName AceType -TypeName "Microsoft.Management.Infrastructure.CimInstance#root/cimv2/win32_ace" -MemberType ScriptProperty  -Value {
  Enum EnumAceType
  {
    Access_Allowed   = 0
    Access_Denied    = 1
    Audit            = 2
  }

  [EnumAceType]($this.PSBase.CimInstanceProperties['AceType'].Value)
} -Force

Requirements

To use Win32_ACE, the following requirements apply:

PowerShell

Get-CimInstance was introduced with PowerShell Version 3.0, which in turn was introduced on clients with Windows 8 and on servers with Windows Server 2012.

If necessary, update Windows PowerShell to Windows PowerShell 5.1, or install PowerShell 7 side-by-side.

Operating System

Win32_ACE was introduced on clients with Windows Vista and on servers with Windows Server 2008.

Namespace

Win32_ACE lives in the namespace root/cimv2. This is the default namespace. There is no need to use the -Namespace parameter in Get-CimInstance.

Implementation

Win32_ACE is implemented in CIMWin32.dll and defined in Secrcw32.mof. Both files are located in the folder C:\Windows\system32\wbem:

explorer $env:windir\system32\wbem
notepad $env:windir\system32\wbem\Secrcw32.mof