Powershell: How to use select-object to get a dynamic set of properties?
Solution 1
I would suggest taking in the paramters as a normal string[]
(Array) parameter, and use it to create an array of hashtables (custom expressions for Select-Object
). Then supply the hashtable with Select-Object
. Ex:
param (
[String[]]$Fields
)
#Create property-array for Select-Object
$props = @()
#Add mandatory displayname property
$props += @{n="DisplayName";e=([Scriptblock]::Create("`$_.DisplayName"))}
#Add user-defined fields
foreach ($field in $Fields) {
$props += @{n=$field;e=([Scriptblock]::Create("`$_.Item($field)"))}
}
#Later in code
$web.Lists | foreach{
$lib = $_
if($lib.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary `
-and $lib.BaseTemplate -eq [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary)
{
$lib.Items | Select-Object -Property $props
}
}
#Usage: .\psextractor -Fields "Type", "Name", "User", "Desc"
#This will list all fields specified after '-Fields'
Solution 2
You can try like this:
param([object[]]$fields)
$fields += "DisplayName"
$web.Lists | foreach{
$lib = $_
if($lib.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary
-and $lib.BaseTemplate -eq [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary){
$lib.Items | Select-Object -property $fields
}
}
call your function like this:
myfunction.ps1 -fields Type,name,User,Description
Related videos on Youtube
Realistic
Updated on June 25, 2022Comments
-
Realistic almost 2 years
I am using powershell in conjunction with sharepoint 07 to list some stuff out. I am trying to allow a (power) user to specify which Fields they want to display.
For example, I could run my code as follows:
.\psextractor -fields "Type|name|User Desc
After doing this I would get a list of files displaying the fields listed above. Currently I am using the Select-Object identifier and I was wondering if this was possible. If not, is there a way to do this without using the create-object cmdlet?
My code:#$Args if($Args[0] -eq "-fields" -and $Args.Count -ge 2){ $flds = $Args[1].split("|") } #Later in code $web.Lists | foreach{ $lib = $_ if($lib.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary -and $lib.BaseTemplate -eq [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary){ $lib.Items | Select-Object DisplayName, @{n=$flds[0];e={$_.Item($flds[0])}} , @{n=$flds[1];e={$_.Item($flds[1])}} #, etc, etc } }
EDIT: I used Graimer's solution below with a few tweaks
SOLUTION:
param([object[]]$flds) $props=@() #globally declared since some of this is done in functions later $mflds = $("Author","Created","Modified","Modified By") #mandatory fields $mflds | foreach{ if($flds -notcontains $_){ $flds += $_ } } #had to use regular for loop because the $_ identifier was conflicting for ($i =0; $i -lt $flds.Count; $i++) { $props += @{n=$flds[$i];e=([Scriptblock]::Create("`$_[`$flds[$i]]"))} } #other mandatory custom fields #the create method could have been used here $props += @{n="FileName";e={"$($_.Item('Name'))"}} $props += @{n="Url";e={"$wburl/$($_.Url)"}} #Later in code $web.Lists | foreach{ $lib = $_ if($lib.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary -and $lib.BaseTemplate -eq [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary){ $lib.Items | Select-Object -property $props } }
-
Realistic about 11 yearsThis does not work because the properties are stored within the object that is being selected. That is why I had to use $_.Item("Field I need"). Similarly they can be accessed like so: $itm = $_; $itm["Field I need"]. I'm not sure how SP did this but its a pain :(
-
Frode F. about 11 yearsBtw, if people are going to downvote my answers, I would very much appreciate a comment specifying what I should improve. This is a community, we're supposed to help each other to get better.
-
Realistic about 11 yearsI hope I didn't accidentally down vote you because your post was definitely helpful. However, as I stated on the other answer, you cannot get these properties in this manner. The only way they can be accessed is via a method or by using hashing ie: @{$_["my fields"]} or @{$_get("My Field")}. The syntax is pseudo but I hope you get the point. If you have any suggestions for this please share.
-
Realistic about 11 yearsI have figured it out! the $_ was conflicting but besides that this was perfect. See the edit to my post which includes a full solution.
-
Frode F. about 11 yearsit's good it worked out :) however I can't see your problem. my foreachloop did not use a
$_
that would conflict anywhere. My references to it was escaped with a backtick(in the create scriptblock part). As long as theItem
object you want to extract from supports aItem(string)
method it should work. If it is a normal hashtable, a change to..=([Scriptblock]::Create("'$_[($field)]"))
should be enough (where ' infront of$_
is a backtick). :-)