Powershell: Get-ItemPropertyValue ignores ErrorAction SilentlyContinue if registry key does not exist

Created on 15 Jan 2018  路  12Comments  路  Source: PowerShell/PowerShell

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.

Steps to reproduce

Get-ItemPropertyValue -Path 'HKCU:\' -Name xyzzy -ErrorAction SilentlyContinue

Expected behavior

No error to be displayed

Actual behavior

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

Environment data

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
Area-Cmdlets-Management Issue-Discussion

Most helpful comment

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.

All 12 comments

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:

  • Re contrasting -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).

  • Re case at hand:

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.

Was this page helpful?
0 / 5 - 0 ratings