Get-Member for Cmdlets - powershell

I`m new to PowerShell and was looking for a way to retrieve the properties of an object. I read up on Get-Member.
However, when I tried to get the properties for an object "created" by the SharePoint Online cmdlet (Remove-SPOSitGroup) I get an error message:
"get-member : you must specify an object for the get-member cmdlet"
Moreover, in order to be even able to pipe the cmdlet to Get-Member I have to specify the required parameters "site" and "identity" for the cmdlet.
This in turn executes the command and deletes a SharePoint group.
I don`t want that. I just want to get the properties of the object that Remove-SPOSitGroup produces.
Here`s my command:
Remove-SPOSiteGroup -Site XXX -Identity XXX | Get-Member -MemberType Property
This works fine with
Get-Command | Get-Member -MemberType Property
As I mentioned this is new to me so any help is appreciated.
Thanks.

The issue what you are having is because you command is not giving any output:
Remove-SPOSiteGroup's output will pass as an Input to the next cmdlet if you are piping it. Thats what Pipe symbolizes in PS.
So, in your case the return type is nothing as a result, the next cmdlet which is Get-Member is not getting any object to give you the details of methods & properties. Hope you are clear now about get-member

Related

Determine possible values for an attribute

I'm struggling with getting the possible values for an attribute.
I want to generate a report of DTCs (Distributed Transaction Coordinators). With the help I found the cmdlet Get-DtcAdvancedSetting.
With this Get-DtcAdvancedSetting cmdlet it's possible to read the properties. The command looks like this:
$AccountName = Get-DtcAdvancedSetting -Name "AccountName" -DtcName "Local" -Subkey "Security"
This works perfectly. But to read the other properties I have to find out what Names they have.
How can I find out the possible Values for the -Name attribute of the cmdlet Get-DtcAdvancedSetting with the help of PowerShell?
I tried like this:
Get-DtcAdvancedSetting -Name "AccountName" -DtcName "Local" -Subkey "Security" |
Select Name -First 1 |
Get-Member
[Enum]::GetNames('System.String.Name')
I also tried like this:
Get-Command Get-DtcAdvancedSetting |
%{$_.Parameters.Values} |
fl name, ParameterType
[Enum]::GetNames('Microsoft.System.String')
Both ways just give me failures like:
Cannot convert argument "enumType", with value:
Is it possible the get this Values? And if yes how?
The Get-DtcAdvancedSetting cmdlet allows you to query the registry.
So in your case you are probably searching for
Get-ChildItem HKLM:\SOFTWARE\Microsoft\MSDTC | Select -ExpandProperty Property

Unexected results in Receive-Job

I noticed weird behavior when using jobs in PowerShell 5.0.
Running job that returns PSObject, also returns some hashtable.
Jobs that return strings, integers, etc work propertly.
Running
Start-Job { New-Object PSObject -Property #{ A = 1 } } |
Receive-Job -Wait -AutoRemoveJob
returns
A : 1
RunspaceId : 6921e85f-301e-4e95-8e4b-c0882fc2085f
PSSourceJobInstanceId : 2992ef77-5642-4eac-8617-f26449a87801
Running
Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob
returns
#{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
However, running
Start-Job { ,#(New-Object PSObject -Property #{ A = 1 }) } |
Receive-Job -Wait -AutoRemoveJob
returns
A
-
1
Why does Receive-Job cmdlet add that hashtable only for PSObjects?
UPDATE: Same in PowerShell 4.0.
PowerShell is not a WYSIWYG shell. Usually, "what you get" is not a text, but objects with properties and methods. And "what you see" is some text representation of them. In many cases by default PowerShell does not display all of the object's properties, but only most common ones, as defined in format files. And some objects use custom formatting, like strings and integers only display their value, but not any of its properties, and collections display their content but not collections themselves.
So, in fact, PowerShell adds extra properties to all objects received from job. But this properties not always get displayed. You can see that extra properties by passing job output to Get-Member cmdlet:
Start-Job { 1,'',#() } | Receive-Job -Wait -AutoRemoveJob | Get-Member
or to formatting cmdlet with appropriate options to force formatting primitive types and to not enumerate collection:
Start-Job { 1,'',#() } | Receive-Job -Wait -AutoRemoveJob | Format-List -Force -Expand CoreOnly
To complement PetSerAl's excellent answer with a focus on the hashtable that wasn't (a hashtable), based on PetSerAl's helpful comments:
The output from Start-Job { New-Object PSObject } | Receive-Job -Wait -AutoRemoveJob,
#{PSComputerName=localhost; RunspaceId=3e783d5f-254a-4951-bb4a-7ff6fa2812c5; PSShowComputerName=False; PSSourceJobInstanceId=1d951dec-0823-4cde-8219-4a6263550441}
only looks like a hashtable literal; in fact, it is the default output formatting for "property-less" custom objects that, in fact, do have properties, but only ones added by PowerShell itself.
This representation is suspiciously similar to a hashtable literal, but the quoting around values that would normally need it is missing - such as around localhost.
Also note that outputting an actual hashtable results in a much nicer, two-column key-value format.
Note that PS still considers a custom object that originally had no properties property-less even after PS itself has added properties to it, such as by Receive-Job here - see below for details.
In its original state (no properties added by PS yet), a property-less object's default output is empty (the empty string). (Try New-Object PSCustomObject directly at the prompt.)
Once Receive-Job has added its "meta" properties to the custom object, their existence triggers the hashtable-like output formatting.
PetSerAl has provided a link to the source code, which suggests that the "PropertyLessObject" formatting is triggered under the following conditions:
An object has no properties at all or only has properties automatically added by PowerShell in the context of remoting (which apparently also includes job-related cmdlets), as done by Receive-Object here.
To put it differently: Properties automatically added by PS aren't taken into account when deciding whether an object is propertyless.
The source-code link will tell you the specific 3-, 4-, or 5-element sets of remoting properties that may be added during remoting and trigger the formatting, but here's a minimal (3-property) example.
Again, note that the hashtable-like formatting is only triggered because the only properties that the object has are named for remoting-related, automatically added properties:
PS> [PSCustomObject] #{PSComputerName='Hi, Mom'; RunspaceId=0; PSShowComputerName=$true}
#{PSComputerName=Hi, Mom; RunspaceId=0; PSShowComputerName=False}
Note that even though a hashtable literal is involved in the command, it is merely used to construct a custom object.
You can force a normal list or table view with Format-List -Force or Format-Table -Force, but note that Boolean property PSShowComputerName never shows up and instead implicitly controls whether the associated PSComputerName property is included in the list / table.
PetSerAl also points out that you can get the hashtable-like output format on demand for any custom object ([pscustomobject]): simply invoke .PSObject.ToString() (note the crucial .PSObject part; without it, you get empty output).
PS> ([pscustomobject] #{ one = 'Hi, Mom'; two = 2 }).PSObject.ToString()
#{one=Hi, Mom; two=2}
Or, more simply, with string interpolation (which, presumably, simply calls .PSObject.ToString() behind the scenes):
PS> "$([pscustomobject] #{ one = 'Hi, Mom'; two = 2 })"
#{one=Hi, Mom; two=2}
Note that this kind of string interpolation does not work for instances of any other types (objects not of type [System.Management.Automation.PSCustomObject]):
PowerShell defers to their .ToString() method even when you invoke .PSObject.ToString().
A directly .NET-based type (e.g., as added with Add-Type) by default simply returns its full type name (both from .ToString() / .PSObject.ToString() and as default output in PS); e.g.:
PS> (Add-Type -PassThru 'namespace net.same2u { public class SomeType {} }')::New()
net.same2u.SomeType # the full type name
The same applies to instances of custom PowerShell classes (defined with class { ... }).

How to check if the output of a function is redirected?

On *nix systems I can easily detect if the program is run on tty or the output is plain stream (pipe or file) and thus adjust the output accordingly (e.g. pretty print or serialize). How to do the same in PowerShell?
I'd like my function to either output the result as object for manual processing (when executed in script or piped to other commands) or use something like Format-Table -AutoSize when invoked directly from PS prompt.
What's the proper way to achieve that in PS?
I'd recommend leaving the decision of whether or not to use formatting cmdlets to the user. If anything I'd add a default display property set to the output objects, so that PowerShell displays only a select subset of properties by default (full property set can still be displayed by calling the format cmdlet with -Property *).
$properties = 'a', 'b', ... # list of property names
$object = ... # your object
$defaultPropertySet = New-Object Management.Automation.PSPropertySet('DefaultDisplayPropertySet', [string[]]$properties)
$standardMembers = [Management.Automation.PSMemberInfo[]]#($defaultPropertySet)
$object | Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $standardMembers
Note that this requires PowerShell v3 or newer.

What is this powershell syntax doing?

I've come across the following powershell syntax:
([ADSI]"")
I realise it is something to do with active directory, but what I want is to understand exactly what the syntax is doing.
Can somebody explain it do me?
I get different results for these two:
[ADSI] | get-member
[ADSI]"" | get-member
What are those quotes doing?
ADSI on it's own is not recognized, so what are those square brackets doing?
Is the same as New-Object ADSI("")
I get different results for these two:
[ADSI] | get-member
[ADSI]"" | get-member
The first one is enumerating the member of the type ADSI. The second one is enumerating the members of an object (and instance) of type ADSI.

Why it is not called select-property in powershell?

An example
get-process | select-object vm, cpu,id | out-gridview
Here select-object actually is selecting PROPERTIES of the OBJECTS in the COLLECTION stored in memory.
Anyone knows why this cmdlet is not called select-property ?
Maybe I m asking a noob quesiton......
When you call Select-Object Blah, Blah1, Blah2, you are using the Property parameter via positional binding
Notice that the help describes a lot more than just the -Property parameter you are using:
Get-Help Select-Object -Full
<#
...
The Select-Object cmdlet selects specified properties of an object or set
of objects. It can also select unique objects, a specified number of
objects, or objects in a specified position in an array.
To select objects from a collection, use the First, Last, Unique, Skip, and
Index parameters. To select object properties, use the Property parameter.
When you select properties, Select-Object returns new objects that have
only the specified properties.
#>
Spend some time using the built in help system, there is a trove of information in there!
#Get the full help details
Get-Help Select-Object -Full
#If available, look online for help
Get-Help Select-Object -Online
#List conceptual topics
Get-Help about_*
#Read about regular expressions
Get-Help about_Regular_Expressions
Lastly, if you're talking semantics, the noun in a PowerShell command name refers to what your verb is acting upon: objects.
Cheers!