Reputation: 155
I am trying to get the output of a powershell command into an array, but it seems not to work. In fact I want to address the output with a row and a column index. e.g.
$a=Get-Service
With output (part)
Status Name DisplayName
------ ---- -----------
Stopped AeLookupSvc Application Experience
Stopped ALG Application Layer Gateway Service
Stopped AppIDSvc Application Identity
Running Appinfo Application Information
Stopped AppMgmt Application Management
I want to address for the second line the DisplayName, e.g.
$a[2][2]
And it should give then
Application Layer Gateway Service
But this does not seem to work.
Can anybody help?
Upvotes: 9
Views: 66858
Reputation: 19818
To follow on from the answers that mention using property names:
To discover the property names of the objects coming out of the pipeline, pipe the output of the cmdlet into Get-Member
. For example:
Get-Service | Get-Member
This will give you the type of the objects coming out of the pipeline, as well as a list of the properties, methods and events of those objects. If you're only interested in the property names of the objects you can filter the output of Get-Member
using Get-Member -MemberType Property, AliasProperty
.
For example:
> Get-Service | Get-Member -MemberType Property, AliasProperty
TypeName: System.Service.ServiceController#StartupType
Name MemberType Definition
---- ---------- ----------
Name AliasProperty Name = ServiceName
RequiredServices AliasProperty RequiredServices = ServicesDependedOn
BinaryPathName Property System.String {get;set;}
CanPauseAndContinue Property bool CanPauseAndContinue {get;}
CanShutdown Property bool CanShutdown {get;}
CanStop Property bool CanStop {get;}
Container Property System.ComponentModel.IContainer Container {get;}
DelayedAutoStart Property System.Boolean {get;set;}
DependentServices Property System.ServiceProcess.ServiceController[] DependentServices {get;}
Description Property System.String {get;set;}
DisplayName Property string DisplayName {get;set;}
MachineName Property string MachineName {get;set;}
ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;}
ServiceName Property string ServiceName {get;set;}
ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn {get;}
ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
StartType Property System.ServiceProcess.ServiceStartMode StartType {get;}
StartupType Property Microsoft.PowerShell.Commands.ServiceStartupType {get;set;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}
UserName Property System.String {get;set;}
Note that Get-Member
gives details of each object coming through the pipeline, not of the whole collection of objects. So, in the output displayed from Get-Service
, Get-Member
gives details of the object representing a single service installed on the machine. It does not represent the collection of all services.
You can then use these property names with the Select-Object
cmdlet to specify which properties you want to display.
For example:
> Get-Service | Select-Object ServiceName, Status, StartType
ServiceName Status StartType
----------- ------ ---------
ALG Stopped Manual
AppHostSvc Running Automatic
AppIDSvc Stopped Manual
Appinfo Running Manual
AppMgmt Stopped Manual
Upvotes: 0
Reputation: 13567
This type of question makes me think that you're probably coming from a Unix background, and are accustomed to having to deal with indicies and column index, that sort of thing.
Fundamentally, PowerShell is an object-oriented scripting language. You simply don't need to do what you're asking about here.
For instance, if you want to capture the results, then grab a property for one of the objects, here's how that's done.
First, capture the output.
$a=Get-Service
Now, you want a particular property of a particular entity. To get that, index into the object you want.
>$a[2]
Status Name DisplayName
------ ---- -----------
Stopped AJRouter AllJoyn Router Service
To select the .DisplayName
, all you have to do is append that to the end of your previous command.
> $a[2].DisplayName
AllJoyn Router Service
If you want to select multiple values, you could use this approach instead.
#Select multiple values from one entity
$a[2] | select DisplayName, Status
>DisplayName Status
----------- ------
Application Layer Gateway Service Stopped
#Select multiple values from each in the array
$a | select DisplayName, Status
>DisplayName Status
----------- ------
Adobe Acrobat Update Service Running
AllJoyn Router Service Stopped
Application Layer Gateway Service Stopped
Application Identity Stopped
Upvotes: 23
Reputation: 13237
The output from Get-Service
that you see in the Console may look like an array (as it is formatted as a table when sent to the Console), but it is actually an 'System.ServiceProcess.ServiceController' object.
Rather than using row and column designations, you need to use the name of the property to retrieve it, so for your example:
$a[2].DisplayName
will return Application Layer Gateway Service
Upvotes: 5
Reputation: 354874
This is not possible without a mapping from property names to array indices. Note that what you see in the output is just a partial list of properties (defined in an XML file somewhere). So there isn't even an easy way to convert those to array indices.
However, I also don't quite understand your need here. You can get the second service with $a[1]
, as expected. And then you can get its DisplayName
property value with $a[1].DisplayName
. PowerShell uses objects throughout. There is simply no need to fall back to text parsing or cryptic column indices just to get your data. There's an easier way.
Upvotes: 7