1

I want to create an object in powershell that stores information about the state of a script. I can do this:

$myScriptObject = 
    @("status", "Selected Operation(s):", "None"), 
     ("status", "Current Operation:", "None"), 
     ("status", "Current Step:", "Prompting for Script Action" ),
     ("test", "This is just for testing", "1,2,3") `
    | ForEach-Object {[pscustomobject]@{kind = $_[0]; name = $_[1]; value 
= $_[2]}}

And that works:

$myScriptObject

kind   name                     value                      
----   ----                     -----                      
status Selected Operation(s):   None                       
status Current Operation:       None                       
status Current Step:            Prompting for Script Action
test   This is just for testing 1,2,3 

...and I can even do this:

foreach($myObject in $myScriptObject) {
    if ($myObject.kind -eq 'status') {
        Write-Host $myObject.name $myObject.value
    }
}

which outputs this:

Selected Operation(s): None
Current Operation: None
Current Step: Prompting for Script Action

My questions are: 1. how do I add something like the following to $myScriptObject:

-kind "ActionMenuChoice" -Name "Do This" -Value 1
-kind "ActionMenuChoice" -Name "Do That" -Value 2
  1. How do I change items already in the object?

    status Current Step: Prompting for Script Action

to

status Current Step:            Prompting for Login

Or am I going about it all wrong? The idea came from the difficulty in returning numerous variables back from a function, and I read using objects is much better to pass back and forth in functions, and found using objects to be much easier to keep track of and to a certain extent manipulate.

Cheers!

2
  • 3
    you seem to have an array of objects. so to make one that has the format in your question [1], simply create a new object and add it to the array. ///// for question [2] - to change a property in an object in an array, use $Collection[$Index].PropertyName = 'New Value'. Commented May 9, 2019 at 14:56
  • 1
    Calling your array of custom objects an object is confusing. Please clarify what you mean by add something like ... - do you want to be able to append new elements to your array using argument syntax? If so, you'll have to write a function. Instead of an array, consider using a hashtable keyed by your custom objects' .Name property, which makes updating existing objects easier. Commented May 9, 2019 at 14:57

2 Answers 2

3

If we are keeping your current object array structure, you can create $myScriptObject as an generic list type by casting [collections.generic.list[object]]. Then you can use the .Add() method to add items to your collection.

[collections.generic.list[object]]$myScriptObject = 
    @("status", "Selected Operation(s):", "None"), 
     ("status", "Current Operation:", "None"), 
     ("status", "Current Step:", "Prompting for Script Action" ),
     ("test", "This is just for testing", "1,2,3") |
        ForEach-Object {[pscustomobject]@{kind = $_[0]; name = $_[1]; value = $_[2]}}

[void]$myScriptObject.add([pscustomobject]@{"Kind" = "ActionMenuChoice"; "Name" = "Do This"; "Value" = 1})
[void]$myScriptObject.add([pscustomobject]@{"Kind" = "ActionMenuChoice"; "Name" = "Do That"; "Value" = 2})

If you want to update an item property in that collection, you will first need to find the object/item within the collection and then access the property you want to update.

($myScriptObject | Where-Object {$_.name -eq 'Current Step:'}).value = "Prompting for Login"

Where-Object can provide the condition needed to locate the target object. Then you can use the object.property syntax to access the property. With PowerShell objects, you can do direct assignment syntax (object.property = value) to update the property value.

Sign up to request clarification or add additional context in comments.

6 Comments

the [ordered] stuff aint needed if you are applying the hashtable immediately to the [PSCustomObject] call. i would remove those. [grin] ///// the arraylist type is deprecated in favor of generic.list. plus, the 2nd of those does NOT produce the silly "did something" output that usually needs to be suppressed. i would change that, also ... [grin] ///// for the use case the OP made, there is no apparent reason to use anything other than a standard array ... or did i miss something again?
@Lee_Dailey I applied your recommendations.
kool! thank you for that ... it was bugging me somewhat more than it really otta. [grin]
Succinct, elegant, and to the point, thanks you! Tested all your solution and it works a charm. If I might impose on your good graces once more, I have a strategic and tactical question around all this.
If I might impose on you once more, I'll be getting Azure objects, and later some REST api responses - strategically, should I store these other two types of information in a pair of separate objects, or lump them in myScriptObject? And this tactical one is around getting my object back from functions - use the dreaded return $myScriptObject, simply state $myScriptObject or, when calling the function, asssign it i.e. $myScriptObject = Get-ScriptChoice($myScriptObject)
|
1

I would use a datatable instead:

Add-Type -AssemblyName System.Collections

$dt = New-Object system.Data.DataTable
[void]$dt.Columns.Add('kind',[string]::empty.GetType() )
[void]$dt.Columns.Add('name',[string]::empty.GetType() )
[void]$dt.Columns.Add('value',[string]::empty.GetType() )


# Add new rows:
$newRow = $dt.NewRow()
$newRow.kind = 'status'
$newRow.name = 'Selected Operation(s):'
$newRow.value = 'None'

[void]$dt.Rows.Add( $newRow )

$newRow = $dt.NewRow()
$newRow.kind = 'status'
$newRow.name = 'Selected'
$newRow.value = 'None'

[void]$dt.Rows.Add( $newRow )


# Find row(s):
$rows = $dt.Select("kind = 'status'")
"Found:"
$dt

# Change first row by condition:
$rows = $dt.Select("kind = 'status'")
$rows[0].value = 'test'
[void]$dt.AcceptChanges()
"Changed one row:"
$dt

# Change all rows:
$rows = $dt.Select("")
$rows | % { $_.value = 'new' }
[void]$dt.AcceptChanges()
"Changed all:"
$dt

# Change all rows by condition:
$rows = $dt.Select("name = 'Selected'")
$rows | % { $_.value = 'newer' }
[void]$dt.AcceptChanges()
"Changed by condition:"
$dt

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.