Suppress error for one line

Hi there,
I have a script that will contact all servers in AD and then see if they are Virtual Machines. for any server that doesn’t have the appropriate registry value an error is returned. Here are the relevant lines:

$RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Server)
 $VMHostName = $RegBase.OpenSubKey("SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\$_").GetValue('PhysicalHostName')

The error returned is “You cannot call a method on a null-valued expression.”
-erroraction silently continue is not supported here, and I know that I can set $ErrorActionPreference= ‘silentlycontinue’ to stop all errors, but really I want to see any other genuine errors.
So, is there a way to stop errors that only show when the above registry key does not exist?
Thanks

You can use try/catch, or temporarily change $ErrorActionPreference; those are really the only two opetions, when you’re calling a .NET method directly.

try
{
    $VMHostName = $RegBase.OpenSubKey("SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\$_").GetValue('PhysicalHostName')
}
catch
{
    $VMHostName = ''
    # Or whatever other error handling action you want to take
}

Awesome! The Try/Catch worked perfectly.
Thanks for that.

In fact both answers worked for me. Just to check I understood you correctly I changed the line to:

$ErrorActionPreference= 'silentlycontinue' 
$VMHostName = $RegBase.OpenSubKey("SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\$_").GetValue('PhysicalHostName')
$ErrorActionPreference= 'continue' 

Mind blown - would never have thought of changing system variables mid-script.

Thanks again.
Kieran.

Just a note on changing the $ErrorActionPreference since it MIGHT not be set to ‘Continue’ before you changed it the first time I would recommend saving the old value before, like this:

$OriginalErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference= 'silentlycontinue' 
$VMHostName = $RegBase.OpenSubKey("SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\$_").GetValue('PhysicalHostName')
$ErrorActionPreference = $OriginalErrorActionPreference

Yes indeed, good idea. Thanks for the tip!
Kieran.

Kieran and Simon,

I might be completely wrong but changing the ErrorActionPreference variable back and forth does not have any effect around your .NET method calls. Dave showed the correct approach with try/catch if you want to continue to use the .NET method calls. Alternatives are to use PowerShell Remoting if your servers are enabled for it and the Get-ItemProperty cmdlet or the WMI Registry provider. Just search a bit more using your favourite search engine and browse the TechNet Script Center (also available via the Script Browser add-on for the PowerShell ISE).

try
{
   $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Server)
   $VMHostName = $RegBase.OpenSubKey("SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\$_").GetValue('PhysicalHostName')
}
catch
{
    $VMHostName = "
    # Or whatever other error handling action you want to take
}

The documentation doesn’t say so, but changing $ErrorActionPreference does have some effect on terminating errors. They’ll still abort a pipeline, but when the error is raised to your current scope, your $ErrorActionPreference variable kicks in. So if you’ve set it to SilentlyContinue, nothing winds up getting displayed at the console. It’s one of the little quirks that I included in the Error Handling ebook.

You might consider suppressing just the single exception. Not all possible exceptions.

$RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Server)
try
{
	$VMHostName = $RegBase.OpenSubKey("SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters\$_").GetValue('PhysicalHostName')
}
catch [Management.Automation.RuntimeException]
{
	if ($_.FullyQualifiedErrorId -ne "InvokeMethodOnNull")
	{
		throw $_
	}
}