Documentation states:
Adds a user-defined custom member to
an instance of a Windows PowerShell
object.
What "Windows PowerShell object" stands for?
This works fine:
$obj = new-object system.object
$obj | add-member -membertype noteproperty -name Name -value "OK"
$obj.name
But this does not:
$obj = @{}
Actually, I am trying to add property to $error[0].
PowerShell has what's called a PSObject that is a wrapper around any .NET object (or it can be a totally custom object) and when you call Add-Member, PowerShell is implicitly wrapping the real .NET object with a PSObject.
The way Add-Member works depends on whether or not you started with a PSObject. If you did not start with a PSObject, Add-Member will wrap the input in a PSObject and you'll need to re-assign the variable in order to see the adapted object.
So for example:
$x = [Environment]::OSVersion
$x | Add-Member NoteProperty IsVista $true
$x | Format-List # does not show the new property
This is because OSVersion is not wrapped is a PSObject. Add-Member does wrap it but that wrapper is lost because you're not re-assigning $x to the wrapped object. Contrast with this behavior:
$x = New-Object OperatingSystem ('Win32NT', '6.0')
$x | Add-Member NoteProperty IsVista $true
$x | Format-List # DOES show the new property
This is because New-Object implicitly wraps the new instance in a PSObject. So your Add-Member call is adding members to the existing wrapper.
Going back to the first example, you can make it work as expected by changing it to:
$x = [Environment]::OSVersion
$x = $x | Add-Member NoteProperty IsVista $true -PassThru
$x | Format-List # DOES show the new property
Now after all that, the reason that the Hashtable doesn't work the way you expect is because Hashtables are treated special by PowerShell and basically the adapter for Hashtables uses the keys as properties (kinda) and Add-Member won't work as expected with this kind of object.