I've used Invoke-Restmethod to download some data, which Powershell stores in a PSCustomObject, in a property called data.
I need to use the value of one of the items in the returned data as a variable for another command. I have managed to select-object -expand my way down to the following output from Get-Member:
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
id NoteProperty System.Int32 id=999
What I need to do is grab the value of the ID noteproperty - 999 - and pass that as part of a string to a new variable, eg:
$newVar = "sometext" + 999 + "moretext"
No amount of select-string or out-string etc is helping. Scripting is not exactly my strong point so I'm not sure I'm even articulating what I want properly - apologies if this is the case!
Any assistance much appreciated
I'm not sure exactly what your code and looks like, so I created the following static approximation from the description:
$data = New-Object PSCustomObject
$data | Add-Member -Type NoteProperty -Name Id -Value 999
$restResponse = New-Object PSCustomObject
$restResponse | Add-Member -Type NoteProperty -Name data -Value $data
Please clarify if this is not a match. You can get the Id value as follows
$restResponse.data.Id
Assign it to another variable
$newVar = "sometext" + $restResponse.data.Id + "moretext"
$newVar
And if your REST response is a collection of data objects, iterate through them
$restResponse.data | Foreach-Object { "sometext" + $_.Id + "moretext" }
I would go for for using $output | select *,#{n='test';e={[string]$_.test}} -exclude properties test
if the exclude is not active it will complain about it already exists. Mostly I use the select expression to manipulate data realtime instead of psCustomObject for such simple task
Related
I am trying to parse parameters of a Graph command to get every value and attribute name. The reason would be to use Compare-Object between the current state of an object and bodyparams added as JSON or an array in Powershell.
Or even create a simple function to compare any of the old params with the JSON for any change, and create a parms with the differences.
The conceptual idea would be to have a template for any modification without using the commands, the old object's params, to compare with a new set of params from the diff.
So far, I managed to do this :
Get-MgGroup -GroupId $GroupId | Select-Object * |Convertto-Json
Which returns :
{
"AcceptedSenders": null,
"AllowExternalSenders": null,
"AppRoleAssignments": null,
"AssignedLabels": null,
"AssignedLicenses": null,
(The whole JSON is too long to be put here, and it would be pointless. It's just attributes and objects)
Which is what I'd want. But I would want to do the same with the object itself
Definition is where the values are since this command:
Get-MgGroup -GroupId $GroupId | Select-Object * | Get-Member -MemberType NoteProperty
Returns this :
Name MemberType Definition
---- ---------- ----------
AcceptedSenders NoteProperty object AcceptedSenders=null
AdditionalProperties NoteProperty Dictionary[string,Object] AdditionalProperties=System.Collections.Generic.Dictionary`2[System.String,System.Object]
AllowExternalSenders NoteProperty object AllowExternalSenders=null
AppRoleAssignments NoteProperty object AppRoleAssignments=null
AssignedLabels NoteProperty object AssignedLabels=null
AssignedLicenses NoteProperty object AssignedLicenses=null
AutoSubscribeNewMembers NoteProperty object AutoSubscribeNewMembers=null
Calendar NoteProperty MicrosoftGraphCalendar Calendar=Microsoft.Graph.PowerShell.Models.MicrosoftGraphCalendar
CalendarView NoteProperty object CalendarView=null
Classification NoteProperty object Classification=null
Conversations NoteProperty object Conversations=null
CreatedDateTime NoteProperty datetime CreatedDateTime=04/09/2022 05:48:57
CreatedOnBehalfOf NoteProperty MicrosoftGraphDirectoryObject CreatedOnBehalfOf=Microsoft.Graph.PowerShell.Models.MicrosoftGraphDirectoryObject
DeletedDateTime NoteProperty objec
As you can see, not every value is null or a string, so I cannot just fill an empty object with an iteration of the name with null on it.
In simple terms, I would like to get from the cmd's any "NoteProperty" : the name, the type, and the value.
I figure it might be hard to grasp without context, I wrote a draft on kroki
enter image description here
The idea would have a model for any future change, but I wouldn't want to change it manually every time.
Edit :
I actuall went further and maybe that'll be more evident with the function :
function Compare-Attributes {
Get-MgGroup -GroupId $GroupId | Select-Object -Property * | ConvertTo-Json -Compress | Out-file -FilePath 'C:\Users\Currentusr\Currentdir\BodyParams.JSON'
### I change some values
$old_parms = #(Get-MgGroup -GroupId $GroupId | Select-Object -Property * | ConvertTo-Json )
$new_parms = #(Get-Content 'C:\Users\Currentusr\Currentdir\BodyParams.JSON' | Convertfrom-Json )
$new_parms = #(Get-Content 'C:\Users\YassinBousaadi\projects\Ansible\Ansible_Modules\BodyParams.JSON' | Convertfrom-Json |
Edit-LeafProperty -PassThru { if ($null -eq $_.Value) { $_.Value = 'null' } } | ConvertTo-Json)
$old_parms_obj = #( $old_parms| ConvertFrom-Json)
$new_parms_obj = #( $new_parms | ConvertFrom-Json)
echo $new_parms_obj
Compare-Object -ReferenceObject $old_parms_obj `
-DifferenceObject $new_parms_obj `
-IncludeEqual `
What it returns is actually not half bad :
InputObject
-----------
#{AcceptedSenders=null; AllowExternalSenders=null; AppRoleAssignments=null; AssignedLabels=null; AssignedLicenses=null; AutoSubscribeNewMembers=null; Calendar=; CalendarView=null; Classification=null; Conversations=null; CreatedDateTime=04/09/2022 05:48:57; CreatedOnB...
I changed the AcceptedSenders attribute as true in the JSON in between, so that value should show. but that'll be the one to show, since it's the only one that's changed, right ? I even went and changed every null value to actual null as strings in the JSON because it would otherwise return empty values
Trying to parse through an Azure parameters template from gihub and update some parameters to the file in Powershell then commit it back to github for automation purposes. I seem to be erroring out on adding the new parameters back in to the file pulled from github. I've checked and made sure the objects are both the same.
I pull the JSON file down from github fine, convert it from JSON, compile my new parameter object and when i go to add the new parameters back into the original i receive the below error:
Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'.
At line:1 char:1
+ $paramTemplate.parameters += $newparam
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Powerhell code:
#Get Content
$paramContent = (Invoke-WebRequest -Uri $parameterUri -Headers $headers -UseBasicParsing).content
$paramTemplate = $paramContent | ConvertFrom-Json
#define parameters in JSON Format
$addnewparam = #"
{
"parameters": {
"virtualMachineRG": {
"value": "$virtualMachineRG"
},
"virtualMachineName": {
"value": "$virtualMachineName"
},
"virtualMachineSize" : {
"value": "$virtualMachineSize"
},
"diagnosticsStorageAccountName": {
"value": "$diagnosticsStorageAccountName"
}
}
}
"#
$newparam = $addnewparam | ConvertFrom-JSON
$paramTemplate.parameters += $newparam
Any insight is greatly appreciated!
PS C:\GitHub\Azure> $paramtemplate.GetType()
>>
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
PS C:\GitHub\Azure> $newparam.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
I've also tried matching the NoteProperty the same for both to no avail. I'm on PSVersion 5.1.17763.771
PS C:\GitHub\Azure> $paramtemplate | get-member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
$schema NoteProperty string $schema=https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#
contentVersion NoteProperty string contentVersion=1.0.0.0
parameters NoteProperty System.Management.Automation.PSCustomObject parameters=#{subnetName=; virtualNetworkId=; virtualMachineName=; virtualMachineRG=; osDiskType=; virtualMachineSize=; admi...
PS C:\GitHub\Azure> $newparam | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
parameters NoteProperty System.Management.Automation.PSCustomObject parameters=#{virtualMachineRG=; virtualMachineName=; virtualMachineSize=; diagnosticsStorageAccountName=}
You can do the following if you want to update $paramtemplate.parameters property values with values from $newparam.parameters properties.
$newparam.parameters.PSObject.Properties.Name | Foreach-Object {
$paramtemplate.parameters.$_ = $newparam.parameters.$_
}
Since you are dealing with a PSCustomObject type in .parameters, .PSObject.Properties will return all of its properties. The .Name property returns the string name of the properties. $_ is the current object being processed within Foreach-Object { } script block.
You could do this slightly differently, which is uglier (IMO) but could be negligibly more performant.
$newparam.parameters.PSObject.Properties | Foreach-Object {
$paramtemplate.parameters.$($_.Name) = $_.Value
}
Note: If $newparam contains properties that $paramtemplate does not have, then we will have to add more logic to handle that case.
$newparam.parameters.PSObject.Properties | Foreach-Object {
if ($paramtemplate.parameters.PSObject.Properties.Name -contains $_.Name) {
$paramtemplate.parameters.$($_.Name) = $_.Value
}
else {
$paramtemplate.parameters | Add-Member -Type NoteProperty -Name $_.Name -Value $_.Value
}
}
Regarding the error message you received, this happened because you were attempting to add a PSCustomObject to another PSCustomObject. That type of operation requires your first object to be a collection. You can convert an object to a collection using the unary operator , just before you add the next object. The syntax is as follows:
$object1 = ,$object1 + $object2
EDIT
Looking more closely at these objects, it appears that all of the properties contain another PSCustomObject with a property called Value with some value that you will have supplied. In that case, the following will work for updating the template.
$newparam.parameters.PSObject.Properties | Foreach-Object {
if ($paramtemplate.parameters.PSObject.Properties.Name -contains $_.Name) {
$paramtemplate.parameters.$($_.Name).Value = $_.Value.Value
}
else {
$paramtemplate.parameters | Add-Member -Type NoteProperty -Name $_.Name -Value ([pscustomobject]#{Value = $_.Value.Value})
}
}
Try this:
$newparam | ForEach {
$paramtemplate.parameters | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value
}
This iterates over the psobject to add and adds properties one by one.
I have a variable stored as a System.Array displayed as;
Site : https://value.sharepoint.com/
Email : value#value.co.uk
DisplayName : value
UniqueId : value
AcceptedAs : value#value.co.uk
WhenCreated : 24/01/2019 06:02:45
InvitedBy : value_value.co.uk#ext##value.onmicrosoft.com
When I try to export this variable as a file it shows in the same format. As this is not in the correct structure for a table (shown below) I am unable to use this data when I try to use it in Power BI.
Site Email ect
---- ---- ----
https://value.sharepoint.com/ value#value.co.uk ect
I need to get my data into the structure shown above. I have tried;
$Test = New-Object -TypeName PSObject -Property $ExternalUsers
However this results in the following error;
New-Object : Cannot convert 'System.Object[]' to the type 'System.Collections.IDictionary' required by parameter 'Property'. Specified method is not supported.
I then tried to loop through all of the items in the array and then create an object for each item, before adding it to a "Master Object";
foreach($var in $ExternalUsers){
$Test = New-Object -TypeName PSObject -Property $ExternalUsers
$Test | Add-Member -MemberType NoteProperty -Name Site -Value $var.Site
$Test | Add-Member -MemberType NoteProperty -Name Email -Value $var.Email
$TestObject += $Test
}
This got each item into the correct structure but when I tried to add all the items back into the one variable I got the error;
Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'.
Any ideas how I could get around this?
To me it looks like you have an array (System.Object[]) containing PSObjects with the properties Site, Email etc.
A structure like that is ideal for exporting to CSV file, which you can then import in a spreadsheed application like Excel for instance.
For that you use the cmdlet Export-Csv like this:
$ExternalUsers | Export-Csv -Path 'PATH AND FILENAME FOR THE OUTPUT CSV FILE' -NoTypeInformation
If the output you show is complete, it seems there is only one element in the array. You can check this by looking at $ExternalUsers.Count.
I'm not quite sure what you mean by "As this is not in the correct structure for a table", because you can quite easily display it as table using
$ExternalUsers | Format-Table -AutoSize
Output on console window:
Site Email DisplayName UniqueId AcceptedAs WhenCreated InvitedBy
---- ----- ----------- -------- ---------- ----------- ---------
https://value.sharepoint.com/ value#value.co.uk value value value#value.co.uk 24/01/2019 06:02:45 value_value.co.uk#ext##value.onmicrosoft.com
If what you want is less properties, just loop through the array and select the properties you want to keep from the objects in it:
$Shortened = $ExternalUsers | ForEach-Object {
$_ | Select-Object Site, Email
}
$Shortened | Format-Table -AutoSize
Will produce:
Site Email
---- -----
https://value.sharepoint.com/ value#value.co.uk
I'm not into Power BI, but remember that the Format-Table cmdlet is for display purposes on console ONLY.
It does NOT provide anything else but a view on the data.
Hope this helps
use:
$TestObject = #()
and no need to specify (-Property $ExternalUsers)
$Test = New-Object -TypeName PSObject
It occurred to me today that, after so many years of habitually passing -NoTypeInformation to Export-Csv/ConvertTo-Csv to prevent that undesirable comment line from being emitted, perhaps Import-Csv/ConvertFrom-Csv would be able to reconstruct objects with their original property types (instead of all of them being String) if only I hadn't suppressed that type information. I gave it a try...
PS> Get-Service | ConvertTo-Csv
...and, having not actually seen in a long time what gets emitted by omitting -NoTypeInformation, was reminded that it only includes the type of the input objects (just the first object, in fact), not the types of the members...
#TYPE System.ServiceProcess.ServiceController
"Name","RequiredServices","CanPauseAndContinue","CanShutdown","CanStop","DisplayName","DependentServices","MachineName","ServiceName","ServicesDependedOn","ServiceHandle","Status","ServiceType","StartType","Site","Container"
...
Comparing the result of serializing with type information and then deserializing...
PS> Get-Service | ConvertTo-Csv | ConvertFrom-Csv | Get-Member
TypeName: CSV:System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CanPauseAndContinue NoteProperty string CanPauseAndContinue=False
CanShutdown NoteProperty string CanShutdown=False
CanStop NoteProperty string CanStop=True
Container NoteProperty object Container=null
DependentServices NoteProperty string DependentServices=System.ServiceProcess.ServiceController[]
DisplayName NoteProperty string DisplayName=Adobe Acrobat Update Service
MachineName NoteProperty string MachineName=.
Name NoteProperty string Name=AdobeARMservice
RequiredServices NoteProperty string RequiredServices=System.ServiceProcess.ServiceController[]
ServiceHandle NoteProperty string ServiceHandle=
ServiceName NoteProperty string ServiceName=AdobeARMservice
ServicesDependedOn NoteProperty string ServicesDependedOn=System.ServiceProcess.ServiceController[]
ServiceType NoteProperty string ServiceType=Win32OwnProcess
Site NoteProperty string Site=
StartType NoteProperty string StartType=Automatic
Status NoteProperty string Status=Running
...to the result of serializing without type information and then deserializing...
PS> Get-Service | ConvertTo-Csv -NoTypeInformation | ConvertFrom-Csv | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CanPauseAndContinue NoteProperty string CanPauseAndContinue=False
CanShutdown NoteProperty string CanShutdown=False
CanStop NoteProperty string CanStop=True
Container NoteProperty object Container=null
DependentServices NoteProperty string DependentServices=System.ServiceProcess.ServiceController[]
DisplayName NoteProperty string DisplayName=Adobe Acrobat Update Service
MachineName NoteProperty string MachineName=.
Name NoteProperty string Name=AdobeARMservice
RequiredServices NoteProperty string RequiredServices=System.ServiceProcess.ServiceController[]
ServiceHandle NoteProperty string ServiceHandle=
ServiceName NoteProperty string ServiceName=AdobeARMservice
ServicesDependedOn NoteProperty string ServicesDependedOn=System.ServiceProcess.ServiceController[]
ServiceType NoteProperty string ServiceType=Win32OwnProcess
Site NoteProperty string Site=
StartType NoteProperty string StartType=Automatic
Status NoteProperty string Status=Running
...the only difference is that the TypeName changes from CSV:System.ServiceProcess.ServiceController (the same type specified by the #TYPE comment prefixed with CSV:) to System.Management.Automation.PSCustomObject. All the members are the same, all the properties are of type String, and in both cases you have deserialized objects that do not contain the methods of and are not in any way connected to or proxies of the original objects.
Evidently Microsoft felt that not only could it be desirable to include this type information in the CSV output, but that it should be done by default. Since I can't really ask "Why did they do this?", what I'm wondering is how could this information potentially be useful? Do the *-Csv serialization cmdlets use it for anything other than setting the TypeName of each object? Why would I ever want this type information communicated "in-band" in the CSV output as opposed to just...knowing that this file containing service information came from System.ServiceProcess.ServiceController instances, or even just not caring what the original type was as long as it has the properties I expect?
The only two use cases I can think of are if you receive a CSV file created by an unknown PowerShell script then having the type information can aide in determining what application/library/module was used to produce the data, or if you had a ridiculously general script that attempted to refresh arbitrary input based on the type information, like this...
Import-Csv ... `
| ForEach-Object -Process {
# Original type name of the first record, not necessarily this record!
$firstTypeName = $_.PSObject.TypeNames[0];
if ($firstTypeName -eq 'CSV:System.ServiceProcess.ServiceController')
{
Get-Service ...
}
elseif ('CSV:System.IO.DirectoryInfo', 'CSV:System.IO.FileInfo' -contains $firstTypeName)
{
Get-ChildItem ...
}
elseif ($firstTypeName -eq 'CSV:Microsoft.ActiveDirectory.Management.ADObject')
{
Get-ADObject ...
}
...
}
...but those aren't very compelling examples, especially considering that, as I noted, this type information was deemed so important that it is included by default. Are there other use cases I'm not thinking of? Or is this simply a case of "It's better (and cheap) to include it and not need it than to need it and not include it"?
Related: PowerShell GitHub issue with discussion about making -NoTypeInformation the default in a then-future version (6.0, according the cmdlet documentation), as well as an apparent consensus that there's no point in ever omitting -NoTypeInformation.
If you have a thing which understands the header and also knows how to construct an other thing of that type, then that first thing could conceivably create one or more those other things from the string representation. I'm not saying it's useful but I am saying that is a potential use if a .csv might be usable where a file of another type might not. I may or may not have actually done this for reasons similar to what I mention here in answer to your question.
When working in the interactive console if I define a new object and assign some property values to it like this:
$obj = New-Object System.String
$obj | Add-Member NoteProperty SomeProperty "Test"
Then when I type the name of my variable into the interactive window Powershell gives me a summary of the object properties and values:
PS C:\demo> $obj
SomeProperty
------------
Test
I basically want to do just this but from within a function in a script. The function creates an object and sets some property values and I want it to print out a summary of the object values to the Powershell window before returning. I tried using Write-Host within the function:
Write-Host $obj
But this just output the type of the object not the summary:
System.Object
How can I have my function output a summary of the object's property values to the Powershell window?
Try this:
Write-Host ($obj | Format-Table | Out-String)
or
Write-Host ($obj | Format-List | Out-String)
My solution to this problem was to use the $() sub-expression block.
Add-Type -Language CSharp #"
public class Thing{
public string Name;
}
"#;
$x = New-Object Thing
$x.Name = "Bill"
Write-Output "My name is $($x.Name)"
Write-Output "This won't work right: $x.Name"
Gives:
My name is Bill
This won't work right: Thing.Name
To print out object's properties and values in Powershell. Below examples work well for me.
$pool = Get-Item "IIS:\AppPools.NET v4.5"
$pool | Get-Member
TypeName: Microsoft.IIs.PowerShell.Framework.ConfigurationElement#system.applicationHost/applicationPools#add
Name MemberType Definition
---- ---------- ----------
Recycle CodeMethod void Recycle()
Start CodeMethod void Start()
Stop CodeMethod void Stop()
applicationPoolSid CodeProperty Microsoft.IIs.PowerShell.Framework.CodeProperty
state CodeProperty Microsoft.IIs.PowerShell.Framework.CodeProperty
ClearLocalData Method void ClearLocalData()
Copy Method void Copy(Microsoft.IIs.PowerShell.Framework.ConfigurationElement ...
Delete Method void Delete()
...
$pool | Select-Object -Property * # You can omit -Property
name : .NET v4.5
queueLength : 1000
autoStart : True
enable32BitAppOnWin64 : False
managedRuntimeVersion : v4.0
managedRuntimeLoader : webengine4.dll
enableConfigurationOverride : True
managedPipelineMode : Integrated
CLRConfigFile :
passAnonymousToken : True
startMode : OnDemand
state : Started
applicationPoolSid : S-1-5-82-271721585-897601226-2024613209-625570482-296978595
processModel : Microsoft.IIs.PowerShell.Framework.ConfigurationElement
...
Tip #1
Never use Write-Host.
Tip #12
The correct way to output information from a PowerShell cmdlet or function is to create an object that contains your data, and then to write that object to the pipeline by using Write-Output.
-Don Jones: PowerShell Master
Ideally your script would create your objects ($obj = New-Object -TypeName psobject -Property #{'SomeProperty'='Test'}) then just do a Write-Output $objects. You would pipe the output to Format-Table.
PS C:\> Run-MyScript.ps1 | Format-Table
They should really call PowerShell PowerObjectandPipingShell.
Some general notes.
$obj | Select-Object ⊆ $obj | Select-Object -Property *
The latter will show all non-intrinsic, non-compiler-generated properties. The former does not appear to (always) show all Property types (in my tests, it does appear to show the CodeProperty MemberType consistently though -- no guarantees here).
Some switches to be aware of for Get-Member
Get-Member does not get static members by default. You also cannot (directly) get them along with the non-static members. That is, using the switch causes only static members to be returned:
PS Y:\Power> $obj | Get-Member -Static
TypeName: System.IsFire.TurnUpProtocol
Name MemberType Definition
---- ---------- ----------
Equals Method static bool Equals(System.Object objA, System.Object objB)
...
Use the -Force.
The Get-Member command uses the Force parameter to add the intrinsic members and compiler-generated members of the objects to the display. Get-Member gets these members, but it hides them by default.
PS Y:\Power> $obj | Get-Member -Static
TypeName: System.IsFire.TurnUpProtocol
Name MemberType Definition
---- ---------- ----------
...
pstypenames CodeProperty System.Collections.ObjectModel.Collection...
psadapted MemberSet psadapted {AccessRightType, AccessRuleType,...
...
Use ConvertTo-Json for depth and readable "serialization"
I do not necessary recommend saving objects using JSON (use Export-Clixml instead).
However, you can get a more or less readable output from ConvertTo-Json, which also allows you to specify depth.
Note that not specifying Depth implies -Depth 2
PS Y:\Power> ConvertTo-Json $obj -Depth 1
{
"AllowSystemOverload": true,
"AllowLifeToGetInTheWay": false,
"CantAnyMore": true,
"LastResortOnly": true,
...
And if you aren't planning to read it you can -Compress it (i.e. strip whitespace)
PS Y:\Power> ConvertTo-Json $obj -Depth 420 -Compress
Use -InputObject if you can (and are willing)
99.9% of the time when using PowerShell: either the performance won't matter, or you don't care about the performance. However, it should be noted that avoiding the pipe when you don't need it can save some overhead and add some speed (piping, in general, is not super-efficient).
That is, if you all you have is a single $obj handy for printing (and aren't too lazy like me sometimes to type out -InputObject):
# select is aliased (hardcoded) to Select-Object
PS Y:\Power> select -Property * -InputObject $obj
# gm is aliased (hardcoded) to Get-Member
PS Y:\Power> gm -Force -InputObject $obj
Caveat for Get-Member -InputObject:
If $obj is a collection (e.g. System.Object[]), You end up getting information about the collection object itself:
PS Y:\Power> gm -InputObject $obj,$obj2
TypeName: System.Object[]
Name MemberType Definition
---- ---------- ----------
Count AliasProperty Count = Length
...
If you want to Get-Member for each TypeName in the collection (N.B. for each TypeName, not for each object--a collection of N objects with all the same TypeName will only print 1 table for that TypeName, not N tables for each object)......just stick with piping it in directly.
The below worked really good for me. I patched together all the above answers plus read about displaying object properties in the following link and came up with the below
short read about printing objects
add the following text to a file named print_object.ps1:
$date = New-Object System.DateTime
Write-Output $date | Get-Member
Write-Output $date | Select-Object -Property *
open powershell command prompt, go to the directory where that file exists and type the following:
powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated
Just substitute 'System.DateTime' with whatever object you wanted to print. If the object is null, nothing will print out.
# Json to object
$obj = $obj | ConvertFrom-Json
Write-host $obj.PropertyName