14

I have a two-dimensional array of property names and values, which I need to add to a PowerShell object.

I have NO issues creating and displaying an object like this using New-Object and Add-Member:

$obj = New-Object PSObject
$obj | Add-Member NoteProperty IName($fiel.IName)
$obj | Add-Member NoteProperty SName($fiel.SName)
$obj | Add-Member NoteProperty Taggy($fiel.Taggy)
$obj | Add-Member NoteProperty Title($fiel.Title)

Write-Output $obj

Enter image description here

But when I try something like this:

for ($k=0; $k -lt $fieldsArray.Count; $k++)
{
    $itemobj | Add-Member –MemberType NoteProperty –Name $fieldsArray[$k].InternalName –Value $itemki[$j][$fieldsArray[$k].InternalName]
    #Write-Host $k
    #Write-Host $fieldsArray[$k].InternalName.ToString()
    #Write-Host $itemki[$j][$fieldsArray[$k].InternalName]
}

Write-Output $itemobj

The Write-Output $itemobj will return only one property member that should be added without any neat column names.
The commented out parts were added for testing purposes and return correct values for all items.

I also tried

$itemobj | Add-Member NoteProperty $fieldsArray[$k].InternalName.ToString()($fieldsArray[$k].InternalName)

without any improvement.

Why are the other property members not added?

I have the data I need. If I write:

for ($k=0; $k -lt $fieldsArray.Count; $k++)
{
    Write-Host $k
    Write-Host $fieldsArray[$k].InternalName.ToString()
    Write-Host $itemki[$j][$fieldsArray[$k].InternalName]
}

I get:

0 ID 1
1 ContentTypeId 0x0108007345CD807822EA4E85691E5C642F3A27
2 ContentType
3 Title Task0
4 Modified 11/24/2014 12:29:30 PM

And these are exactly the values that I expect and want. The problem is adding them as properties to an object. I think I cannot have a variable as a NotePropertyName, but it's a wild guess based on the results I am getting.

Some of the values in $itemki[$j][$fieldsArray[$k].InternalName] are empty - could it be it?

Forget all the arrays. They were just for the context:

Write-Host $fieldsArray[$k].InternalName.ToString() # Writes out the correct value
Write-Host $itemki[$j][$fieldsArray[$k].InternalName] # writes out the correct value
$itemobj | Add-Member NoteProperty $fieldsArray[$k].InternalName.ToString()($fieldsArray[$k].InternalName) # The values/property are not added

The question is: WHY NOT? Are there any restrictions in Add-Member on passing values as variables? Empty values?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
grisha
  • 389
  • 1
  • 8
  • 22
  • 3
    The code snippets lack data, so it is hard to see what you are trying to achieve. Please consider posting a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – vonPryz Jan 08 '15 at 18:47
  • This appears to be an issue in that you are using different parameter sets. In the first example you are using `NotePropertySingleMemberSet` but in the second you are using `MemberSet`. – Matt Jan 08 '15 at 18:55
  • If we had some sample data sure we could tell you what is wrong. You don't show us where `$j` or `$itemobj` are declared but I suppose we could guess – Matt Jan 08 '15 at 19:10
  • I will admit that I am still confused about this question. It is clear the information here is from SharePoint but the first example does not appear related to the second. In the first you are using custom functions `IName`,`SName`... that, according to the picture, don't have all the expected output that you show from your edit. In your second example `$fieldsarray` looks like this: `="ID","ContentTypeID","ContentType","Title","Modified"`? Also the structure of `$itemki` is making me have to guess the data that is in there. Not getting this without more information. Could just be me. – Matt Jan 08 '15 at 21:10

3 Answers3

15

I am still not sure completely, but if you are just focusing on the Add-Member then consider the following.

$fieldsarray = "ID", "ContentTypeID", "ContentType", "Title", "Modified"
$itemki = "1", "0x0108007345CD807822EA4E85691E5C642F3A27", "", "Task0", "11/24/2014 12:29:30 PM"
$itemobj = New-Object pscustomobject
for($k=0;$k -lt $fieldsArray.Count ; $k++)
{
    $itemobj | Add-Member NoteProperty $fieldsarray[$k] $itemki[$k]
}

$itemobj

Notice the empty string entry in the array $itemki. This would generate the output.

ID            : 1
ContentTypeID : 0x0108007345CD807822EA4E85691E5C642F3A27
ContentType   :
Title         : Task0
Modified      : 11/24/2014 12:29:30 PM

Change the "" to an empty element: "1","0x0108007345CD807822EA4E85691E5C642F3A27",,"Task0","11/24/2014 12:29:30 PM", and you get this output:

ID            : 1
ContentTypeID : 0x0108007345CD807822EA4E85691E5C642F3A27
ContentType   : {Task0}
Title         : 11/24/2014 12:29:30 PM
Modified      :

Which is wrong. Then if you change the empty element to $null your output looks much like the first:

ID            : 1
ContentTypeID : 0x0108007345CD807822EA4E85691E5C642F3A27
ContentType   :
Title         : Task0
Modified      : 11/24/2014 12:29:30 PM

Concerning your output

You say you only get the last element when you do $itemobj outside the loop. What does $itemobj look like after each pass? for(;;){} loops don't send data to the output stream in the same way that a ForEach-Object{} would which is worth mentioning.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matt
  • 45,022
  • 8
  • 78
  • 119
  • 3
    I hope you leave a comment as to what your resolution was. I did't think this was a good answer... at least not yet. – Matt Jan 09 '15 at 18:38
9

Don't do a For loop, do a ForEach-Object loop. Something like:

$Object = New-Object PSObject
$Array | ForEach{
    Add-Member -InputObject $Object -NotePropertyName $_[0] -NotePropertyValue $_[1]
}

That should do what you're looking for I think.

TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
  • 2
    upvoted,because even though it doesn't solve the issue, it does improve the quality of the code – grisha Jan 08 '15 at 19:31
  • Shouldn't there be "`ForEach-Object`" in the sample code? – Peter Mortensen Feb 08 '16 at 10:47
  • OK, according to [the documentation for ForEach-Object](https://technet.microsoft.com/en-us/library/hh849731.aspx), ForEach (and "`%`") is an alias, so it should not make any difference. But why do you say "Don't do a ForEach loop, do a ForEach-Object loop" then? – Peter Mortensen Feb 08 '16 at 15:41
  • Sorry, I'm so used to typing `ForEach` that I put that instead of just `For`. I have updated my answer. – TheMadTechnician Feb 08 '16 at 17:22
8

You could use a hash table instead of two arrays. It's very easy to create an object from a hash table. Here's an example:

$hash = @{
    ID            = '1'
    ContentTypeID = '0x0108007345CD807822EA4E85691E5C642F3A27'
    ContentType   = ''
    Title         = 'Task0'
    Modified      = '11/24/2014 12:29:30 PM'
}

$Object = New-Object PSObject -Property $hash
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
campbell.rw
  • 1,366
  • 12
  • 22