Training
Get a free hour of SANS training

Experience SANS training through course previews.

Learn More
Learning Paths
Can't find what you are looking for?

Let us help.

Contact us
Resources
Join the SANS Community

Become a member for instant access to our free resources.

Sign Up
For Organizations
Interested in developing a training plan to fit your organization’s needs?

We're here to help.

Contact Us
Talk with an expert

Month of PowerShell: Getting Object Properties for Windows Service Dependencies

Something I always have to look up are commands for object properties. Fortunately, PowerShell makes this pretty easy. Let's take a look.

Authored byJoshua Wright
Joshua Wright

#monthofpowershell

As I learn PowerShell, I quickly get overwhelmed with the number of commands available. I try to anticipate the Verb/Noun syntax, and command completion helps a lot.

I can rattle off PowerShell commands for lots of things, but something I always have to look up are the object properties. Fortunately, PowerShell makes this pretty easy. Let me explain by posing a question:

What are the dependent services for the Windows EventLog service?

The first part of this is pretty easy: [code]Get-Service[/code] will enumerate the services. We can specify the service name as an unnamed argument, or following [code]-Name[/code]:

PS C:\WINDOWS\system32> Get-Service eventlog

Status   Name               DisplayName
------   ----               -----------
Running  eventlog           Windows Event Log


PS C:\WINDOWS\system32> Get-Service -Name EventLog

Status   Name               DisplayName
------   ----               -----------
Running  EventLog           Windows Event Log

In PowerShell, the pipeline allows us to process the objects that are returned from the command. If objects seems vague, it's intentionally so: objects can be properties, code, scripts, alias, events, and more. Often, we're interested in the properties, displayed as columns of information.

To identify the available properties, we have some options. The first is to send the output of [code]Get-Service[/code] to [code]Get-Member[/code]:

PS C:\WINDOWS\system32> Get-Service | Get-Member


   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType    Definition
----                      ----------    ----------
Name                      AliasProperty Name = ServiceName
RequiredServices          AliasProperty RequiredServices = ServicesDependedOn
Disposed                  Event         System.EventHandler Disposed(System.Object, System.EventArgs)
Close                     Method        void Close()
Continue                  Method        void Continue()
CreateObjRef              Method        System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose                   Method        void Dispose(), void IDisposable.Dispose()
Equals                    Method        bool Equals(System.Object obj)
ExecuteCommand            Method        void ExecuteCommand(int command)
GetHashCode               Method        int GetHashCode()
GetLifetimeService        Method        System.Object GetLifetimeService()
GetType                   Method        type GetType()
InitializeLifetimeService Method        System.Object InitializeLifetimeService()
Pause                     Method        void Pause()
Refresh                   Method        void Refresh()
Start                     Method        void Start(), void Start(string[] args)
Stop                      Method        void Stop()
WaitForStatus             Method        void WaitForStatus(System.ServiceProcess.ServiceControllerStatus desiredSt...
CanPauseAndContinue       Property      bool CanPauseAndContinue {get;}
CanShutdown               Property      bool CanShutdown {get;}
CanStop                   Property      bool CanStop {get;}
Container                 Property      System.ComponentModel.IContainer Container {get;}
DependentServices         Property      System.ServiceProcess.ServiceController[] DependentServices {get;}
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;}
Status                    Property      System.ServiceProcess.ServiceControllerStatus Status {get;}
ToString                  ScriptMethod  System.Object ToString();

This is a lot of output, and for our purposes we are mostly interested in properties, so we can refine our pipeline adding [code]-MemberType Property[/code]:

PS C:\WINDOWS\system32> Get-Service | Get-Member -MemberType Property


   TypeName: System.ServiceProcess.ServiceController

Name                MemberType Definition
----                ---------- ----------
CanPauseAndContinue Property   bool CanPauseAndContinue {get;}
CanShutdown         Property   bool CanShutdown {get;}
CanStop             Property   bool CanStop {get;}
Container           Property   System.ComponentModel.IContainer Container {get;}
DependentServices   Property   System.ServiceProcess.ServiceController[] DependentServices {get;}
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;}
Status              Property   System.ServiceProcess.ServiceControllerStatus Status {get;}

In this output we see all of the properties available in the object sent to the pipeline from [code]Get-Service[/code]. This is useful, but the definition column doesn't always offer intuitive insight. Our second option is to use [code]Select-Object[/code] instead:

PS C:\WINDOWS\system32> Get-Service | Select-Object -First 1 -Property *


Name                : AarSvc_23e54
RequiredServices    : {}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : True
DisplayName         : AarSvc_23e54
DependentServices   : {}
MachineName         : .
ServiceName         : AarSvc_23e54
ServicesDependedOn  : {}
ServiceHandle       : SafeServiceHandle
Status              : Running
ServiceType         : 240
StartType           : Manual
Site                :
Container           :

We see the same property names, but sometimes seeing the property name in the context of a sample value can be more useful than the [code]Get-Member[/code] output.

Note: Using [code]-First 1[/code] in the [code]Select-Object[/code] command limits the output to just a single property list; omitting [code]-First 1[/code] would return the properties for all objects, which may be more than you really want to read though.

In the output of [code]Get-Member[/code] and [code]Select-Object[/code], we see the property [code]DependentServices[/code]. Let's take a look for the [code]EventLog[/code] service:

PS C:\WINDOWS\system32> Get-Service EventLog | Select-Object -Property DependentServices

DependentServices
-----------------
{Wecsvc, uhssvc, NcdAutoSetup, AppVClient...}

Fantastic! We have the list of dependent services for EventLog. However, Notice the ellipsis at the end of the dependent services list, and the curly braces surrounding the values? This indicates that the output is an object that is truncated.

To get the complete list, we have to backtrack a bit. When we use the [code]Select-Object[/code] cmdlet in a pipeline, it will change the output object to a custom  [[code]PSObject[/code]](https://msdn.microsoft.com/en-us/library/system.management.automation.psobject%28v=vs.85%29.aspx) class. That is, it's a wrapper that provides alternate ways of viewing the available member objects. Instead of working with the [code]Select-Object[/code] output, we can return right to [code]Get-Service[/code], declaring the output as a variable:

PS C:\WINDOWS\system32> $eventlogsvc = Get-Service EventLog
PS C:\WINDOWS\system32>

With the variable [code]$eventlogsvc[/code], we can access the member object [code]DependentServices[/code] using dot notation:

PS C:\WINDOWS\system32> $eventlogsvc.DependentServices

Status   Name               DisplayName
------   ----               -----------
Stopped  Wecsvc             Windows Event Collector
Running  uhssvc             Microsoft Update Health Service
Stopped  NcdAutoSetup       Network Connected Devices Auto-Setup
Stopped  AppVClient         Microsoft App-V Client
Running  netprofm           Network List Service
Running  NlaSvc             Network Location Awareness

To get the complete list of dependent service names, we can use [code]Select-Object[/code] again to access just the [code]Name[/code] property:

PS C:\WINDOWS\system32> $eventlogsvc.DependentServices | Select-Object -Property Name

Name
----
Wecsvc
uhssvc
NcdAutoSetup
AppVClient
netprofm
NlaSvc

PowerShell purists will point out that declaring a variable is not necessary, since you can enclose the [code]Get-Service[/code] command in parenthesis to accomplish the same goal: [code](Get-Service EventLog).DependentServices | Select-Object -Property name[/code]. While this is true, I think declaring the [code]$eventlogsvc[/code] is worth the memory required for the enhanced legibility. YMMV.

PowerShell often feels like a safe form of what I imagine spelunking is like. There's lots of twists and turns, and sometimes you have to backtrack quite a bit, but eventually you find your way, or you give up trying.

-Joshua Wright

Return to Getting Started With PowerShell


Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.

Month of PowerShell: Getting Object Properties for Windows Service Dependencies | SANS Institute