I am still working with Microsoft SharePoint 2010. In the process, I am also becoming more closely acquinted with PowerShell, and I am increasingly impressed.

Tonight, I had to find a way to delete a hidden SharePoint column. It turns out that this can be accomplished rather easily from PowerShell, using some advanced functionality.

The main trick is that it is necessary to unset the Hidden property, but it cannot be done directly, because Hidden is read-only; instead, the System.Reflection namespace must be used.

First though, you need to find your column, which may not be trivial if its internal name has been generated automagically, perhaps using a nasty resource string. (If the field is added programmatically, one may use the C# syntax list.Fields.AddFieldAsXml(strXML, false, SPAddFieldOptions.AddFieldInternalNameHint) to prevent SharePoint from using the DisplayName property to generate the internal name. But, I digress.)

So here are a few lines of PowerShell code that list the internal names of all fields, in this case, in the Shared Documents library of a subsite named MLSite:

$web = Get-SPWeb http://localhost/
$list = $web.GetList("/MLSite/Shared Documents")
$list.Fields | ForEach-Object { $_.InternalName }

Continuing, suppose the column name has been found and it is "MyColumn". The following lines unset the Hidden property:

$field = $list.Fields.GetFieldByInternalName("MyColumn")
$type = $field.GetType()
$mi = $type.GetMethod("SetFieldBoolValue",
[System.Reflection.BindingFlags]$([System.Reflection.BindingFlags]::NonPublic -bor
[System.Reflection.BindingFlags]::Instance))
$mi.Invoke($field, @("CanToggleHidden",$true))
$field.Hidden=$false
$field.Update()

Now to delete the column, it is necessary to reload the list:

$list = $web.GetList("/MLSite/Shared Documents")
$field = $list.Fields.GetFieldByInternalName("MyColumn")
$field.Delete()

That's it, we're done. Note that if you need to delete another column, it is necessary to reload the list again.

And I am not sure if it is necessary, but it may help if PowerShell is being run with Administrator privileges.

Incidentally, this little exercise also demonstrates the use of ForEach-Object to iterate through a collection; the use of enumerated types; type casting in PowerShell; and object arrays.