This seems to be a bug in Windows PowerShell 5.1 so I figured I would see if it was resolved in 6.0.0 but it's still there.
Get-ItemPropertyValue -Path 'HKCU:\' -Name xyzzy -ErrorAction SilentlyContinue
No error to be displayed
PS C:\Program Files\PowerShell\6.0.0> Get-ItemPropertyValue -Path 'HKCU:\' -Name xyzzy -ErrorAction SilentlyContinue
Get-ItemPropertyValue : Property xyzzy does not exist at path HKEY_CURRENT_USER\.
At line:1 char:1
+ Get-ItemPropertyValue -Path 'HKCU:\' -Name xyzzy -ErrorAction Silentl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ItemPropertyValue], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.GetItemPropertyValueCommand
Name Value
---- -----
PSVersion 6.0.0
PSEdition Core
GitCommitId v6.0.0
OS Microsoft Windows 6.1.7601 S
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
As a 5.1 issue and yesterdays blog mentioning the Consider-WindowsPowerShell51 label is it worth adding that label to this issue?
@SwarfegaGit This is a terminating error. Terminating errors are not suppressed by -ErrorAction SilentlyContinue
.
@markekraus so this is a non-terminating error?
PS C:\Program Files\PowerShell\6.0.0> Get-ItemProperty -Path 'HKCU:\' -Name xyzzy -ErrorAction SilentlyContinue
PS C:\Program Files\PowerShell\6.0.0> Get-ItemProperty -Path 'HKCU:\' -Name xyzzy
Get-ItemProperty : Property xyzzy does not exist at path HKEY_CURRENT_USER\.
At line:1 char:1
+ Get-ItemProperty -Path 'HKCU:\' -Name xyzzy
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (xyzzy:String) [Get-ItemProperty], PSArgumentException
+ FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
Any reason it should differ?
The difference being, IMO, that Get-ItemPropertyValue
depends on the existence of the property. if it didn't terminate when the property didn't exist, the result between the property being unset would be the same as the property not existing at all. With a terminating error you can test for the existence of the property at the same time as getting its value if it has one.
if it didn't terminate when the property didn't exist, the result between the property being unset would be the same as the property not existing at all.
If we needed to make that distinction, the error record should give us the info that we need. It feels like there is a terminating error here when there does not need to be.
As I take a look at this cmdlet, it is inconsistent in how it handles this. I can suppress a bad path, but not a bad property.
PS> Get-ItemPropertyValue -Path safsdfsfdf -name sdfasfa -ErrorAction SilentlyContinue
PS> Get-ItemPropertyValue -Path 'HKCU:\bad\to\the\bone' -Name xyzzy -ErrorAction SilentlyContinue
PS> Get-ItemPropertyValue -Path 'HKCU:\' -Name xyzzy -ErrorAction SilentlyContinue
Get-ItemPropertyValue : Property xyzzy does not exist at path HKEY_CURRENT_USER\.
At line:3 char:5
+ Get-ItemPropertyValue -Path 'HKCU:\' -Name xyzzy -ErrorAction Sil ...
As a scripter, I expect to be able to suppress both without using try/catch.
This seems like an oversight, and should not be a terminating error. We use try/catch to grab errors and report up the thread but this terminating takes control away from the coder.
Anyways... I am getting around it in my case by using:
Get-ItemProperty -Path $KeyPath | Select-Object $KeyName -ExpandProperty $KeyName
Which will spit out the value if there is one and do a non-terminating if there is no value found.
Great analysis, @KevinMarquette, and agreed, @CoreyChaplan:
From https://docs.microsoft.com/en-us/powershell/developer/cmdlet/cmdlet-error-reporting:
Does the error condition prevent your cmdlet from successfully processing any further input objects? If so, this is a terminating error.
Is the error condition related to a specific input object or a subset of input objects? If so, this is a nonterminating error.
Does the cmdlet accept multiple input objects, such that processing may succeed on another input object? If so, this is a nonterminating error.
Therefore, the error at hand should _not_ be a terminating error, given that Get-ItemPropertyValue
accepts _multiple_ paths via the pipeline.
An aside re your workaround:
~
Get-ItemProperty -Path $KeyPath | Select-Object -ExpandProperty $KeyName
~
is sufficient - also including [-Property] $KeyName
is not just unnecessary, it actually _decorates_ the output object with an ETS property of that name.
Depending on your strict-mode settings, even (Get-ItemProperty -Path $KeyPath).$KeyName
may do.
Thanks for @KevinMarquette and @CoreyChaplan for their observation. Here is a third angle from me:
We already know that the following generates an error:
PowerShell
Get-ItemPropertyValue -Path "C:\Windows" -Name "SomethingInvalid" -ErrorAction SilentlyContinue
However, the following does not:
PowerShell
$ErrorActionPreference="SilentlyContinue"
Get-ItemPropertyValue -Path "C:\Windows" -Name "SomethingInvalid"
$ErrorActionPreference="Continue"
I am afraid I don't find the logic of our esteemed @markekraus applicable here.
@skycommand:
Re contrasting -ErrorAction SilentlyContinue
with $ErrorActionPreference="SilentlyContinue"
:
That is a _fundamental_ (problematic) behavioral distinction in PowerShell:
-ErrorAction
only acts on _non-terminating_ errors, whereas $ErrorActionPreference= ...
acts on _all_ errors.
In the case at hand, $ErrorActionPreference="SilentlyContinue"
therefore manages to suppress the _statement-terminating_ error that Get-ItemPropertyValue
emits, whereas -ErrorAction SilentlyContinue
doesn't.
The bottom line is: Get-ItemPropertyValue
should emit a _non-terminating error_ here, not a (statement-)terminating one.
(Never mind)
@skycommand:
-ErrorAction SilentlyContinue
with $ErrorActionPreference="SilentlyContinue"
:I was pointing out that you were referring to a _fundamental problem_ with PowerShell's error handling and that, as such, it is _incidental to the problem at hand_ - it applies whether or not use of a terminating error is justified.
(If you want to learn about all related warts, read this).
I was pointing out that there is _indeed a problem_ with Get-ItemPropertyValue
that _should be fixed_: The error that is reported when a value (property) by a given name isn't found should be a _non-terminating error_ (PSCmdlet.WriteError()
), not a (statement-)terminating one (PSCmdlet.ThrowTerminatingError()
).
From what I can tell, the only one _not_ in agreement with this in this thread is @markekraus.
@mklement0 Really? That's what you wanted to say? Alright. I'm fine with that. I apologize for misunderstanding it. And as a gesture of goodwill, I strike my original reply.
But I emphasize that your original message did not sound like what you are writing now and still does not. You see, you took your time to write what I had already discovered on my own, and reported in a prior post. So, naturally, I'd assume your purpose was something besides informing me, i.e. going from a premise to a conclusion.
Most helpful comment
If we needed to make that distinction, the error record should give us the info that we need. It feels like there is a terminating error here when there does not need to be.
As I take a look at this cmdlet, it is inconsistent in how it handles this. I can suppress a bad path, but not a bad property.
As a scripter, I expect to be able to suppress both without using try/catch.