@ -97,6 +97,31 @@ The format is based on
`FileNotFoundException` . A volume that is mounted into a folder, and a
junction or symbolic link to another volume, probably fail the same way.
Use a path that starts at the root of the volume
- **Breaking:** match `Get-ChildItem2 -Filter` once, in the cmdlet, with the
wildcard rules that `Get-ChildItem -Filter` applies in Windows PowerShell
5.1, in both editions, and on the real name of an item, not its 8.3 short
name. `Report.*` also returns `Report` , which has no dot; a pattern that
ends in a dot, such as `Report.` or `*.` , returns the names without a dot;
`*.*.*` returns every item; and a question mark also matches nothing at
the end of a name and before a dot, so `a?` also returns `a` . An empty
`-Filter` returns every item, like `*` , instead of nothing, and a pattern
of more than 32,767 characters is a parameter error. In PowerShell 7,
`Get-ChildItem2` deliberately differs from its own `Get-ChildItem -Filter`
for a pattern that ends in a dot, unless an asterisk comes right before the
dot, and for a pattern of an asterisk, a dot, and one or two question marks
- **Breaking:** write a non-terminating error in `Get-NTFSOrphanedAccess` for
an item that it can't read for a reason other than a denied access, and
continue with the next item: `ReadSecurityError` with the category
`OpenError` ; it wrote a warning. A script that reads the failure with
`-WarningVariable` needs `-ErrorVariable` , and `-ErrorAction Stop` now
stops at it
- Take `-SecurityDescriptor` of `Set-NTFSSecurityDescriptor` at position 1,
like the first positional parameter of the other cmdlets; it was at
position 2. A positional call isn't affected, because it is the only
positional parameter
- Document that `Get-NTFSEffectiveAccess` writes the error "Access is denied"
for a user account of the domain when the user who runs the cmdlet has no
domain credentials, such as a local standard user
### Deprecated
@ -121,6 +146,32 @@ The format is based on
- Compare boxed privilege output values by their privilege and attributes;
the object overload rejected privilege values and recursively compared
an attributes enum instead
- Convert a `FileSecurity` or a `DirectorySecurity` object to
`FileSystemSecurity2` in the .NET API of `Security2.dll` : the conversions
ignored the descriptor and threw an exception for an empty path. The result
wraps the descriptor and has no item: `FullName` and `Name` are `$null` ,
`Write()` throws an `InvalidOperationException` , and the entries, the
owner, the inheritance, and the effective access can be read; an inherited
entry has no source. PowerShell uses the conversion to bind
`-SecurityDescriptor` , so the cmdlets now accept the object that `Get-Acl`
returns, where they stopped with a parameter binding error. Such a
descriptor can't be written, so `Set-NTFSSecurityDescriptor` writes a
`WriteSdError` for it, and the audit cmdlets write a `ReadSecurityError`
for one that has no audit entries
- **Breaking:** fix `RemoveFileSystemAccessRuleAll` and
`RemoveFileSystemAuditRuleAll` of the .NET API, which ignored the list of
accounts and removed every explicit entry; they remove only the entries of
the listed accounts, and an empty list removes none
- **Breaking:** fix the overloads of `AddFileSystemAccessRule` and
`AddFileSystemAuditRule` of the .NET API that take a path and a list of
accounts, which did nothing until the caller enumerated the result; they
write at once, and an exception reaches the caller of the method
- Fix a module setting `EnablePrivileges` that is missing or not `$true` or
`$false` , for example after
`(Get-Module NTFSSecurity).PrivateData['EnablePrivileges'] = 'false'` : the
cmdlets that use privileges failed with an `InvalidCastException` or a
`NullReferenceException` ; they stop with one error,
`EnablePrivilegesSettingInvalid` , which names the setting
- Fix `Clear-NTFSAccess -DisableInheritance` and `Set-NTFSSecurityDescriptor` ,
which reported a `RestoreOwnerError` for an owner that had not changed:
after they took ownership of an item that the user owned already and left a
@ -150,6 +201,15 @@ The format is based on
exception of a later command when that command took the debug message
after the enabling, for example with `5>&1 | Select-Object -First 2` ; they
now disable the privilege and pass the exception on
- Fix the 17 cmdlets that take ownership of an item to retry a denied read or
change and then set the previous owner back: the `Add-` , `Remove-` , and
`Clear-` cmdlets for access and audit entries, `Get-NTFSAccess` ,
`Get-NTFSOrphanedAccess` , `Get-NTFSEffectiveAccess` , the six inheritance
cmdlets, `Get-FileHash2` , and `Set-NTFSSecurityDescriptor` . When a later
command in the pipeline threw at the `RestoreOwnerError` that setting the
owner back can write, they reported the exception as the error of the item
and went on with the next one, so that the caller never saw it; they now
pass it on
- Fix `Get-ChildItem2 -Filter` , which read a bracket as the start of a
character class, so that it did not return a file with brackets in its name,
such as `Report[1].txt` , for that name; only `*` and `?` are wildcards. A
@ -251,14 +311,40 @@ The format is based on
object that has `AppliesTo` and `InheritanceFlags` or `PropagationFlags`
now fails with `AmbiguousParameterSet` , like the same parameters on the
command line, and so does an object that has both `Path` and
`SecurityDescriptor` , where the path won before. An `AppliesTo` that is
`$null` fails to bind for that object (a row of a CSV file that has fewer
fields than its header gives `$null` ). A value that PowerShell can't
`SecurityDescriptor` , where the path won before. The empty cell of a CSV
file, `$null` , and `DBNull` count as a value of the other group here,
because PowerShell binds them to the parameters of both groups: a file
that has columns of both groups fails for a row that leaves one of them
empty, so give such a file the columns of one group only. An `AppliesTo`
that is `$null` fails to bind for that object (a row of a CSV file that has
fewer fields than its header gives `$null` ). A value that PowerShell can't
convert to a scope, such as the empty cell of a CSV file or a misspelled
name, is ignored, and the object is handled as one without `AppliesTo` : it
gets its own flags, or the default scope if it has none. A call with
name, is an error for that object, see the next entry. A call with
neither `-Path` nor `-SecurityDescriptor` now fails with
`AmbiguousParameterSet` instead of a missing-parameter error for `-Path`
- Fix `Add-NTFSAccess` , `Remove-NTFSAccess` , `Add-NTFSAudit` , and
`Remove-NTFSAudit` , which silently used the default when a piped object had
a value of `AccessType` (`AuditFlags` for the audit cmdlets),
`InheritanceFlags` , `PropagationFlags` , or `AppliesTo` that PowerShell
could not convert, such as a misspelled name or the empty cell of a CSV
file: a typo for `Deny` created an `Allow` entry, and a misspelled scope
used the default scope, without a message. The cmdlets now write the
non-terminating error `InvalidParameterValue` for that object, change
nothing for it, and go on with the next one; a blank value is such an
error too, where it used the default. **Breaking:** the five parameters
have the type `Object` , because the cmdlets convert the values themselves.
A bad value that you name on the command line, and a named `$null` , still
stop the command, but with the error id `InvalidParameterValue` , not the id
of a parameter binding error. A script block, such as
`-AccessType { 'Deny' }` , is no longer evaluated for every piped object and
is a bad value. `Get-Help` shows the type `Object` , and tab completion
still offers the valid names
- Fix `Add-NTFSAccess` , `Remove-NTFSAccess` , `Add-NTFSAudit` , and
`Remove-NTFSAudit` with `-SecurityDescriptor` , which ended the whole
command with a terminating error when the change of one descriptor failed,
such as for a deny entry without rights; they write the non-terminating
error `AddAceError` or `RemoveAceError` for that descriptor and go on with
the next one, as they do for a path
- Fix `Get-NTFSEffectiveAccess` : `-ExcludeNoneAccessEntries` now leaves out
items without access, the cmdlet uses the current location when `-Path`
is omitted, and `-SecurityDescriptor` returns the effective access of the