Menu

Get into Powershell

7. Juni 2018 - Allgemein

It took a while until I got into Powershell. At a first glance, I was discouraged by the strange syntax of variables and commands. It didn’t feel natural at the beginning. I didn’t know what cmdlets are and how to pipe them together. There was also this strange $_ variable, used in filter commands. And how should I know which attributes an object offers to me. So I decided to keep up with the Linux bash (in a VM), to do my daily work. Offer time I mentioned that Powershell was still there in Win7, and also in Win7, and also in Win10. So, it can’t a bad thing. I played a little bit around and was still confused about how to use and chain the different cmdlets (= PowerShell commands).

After googling around, for tutorials I found this excellent MVA link, where two topmost of my questions, like:

were answered.

What convinced me to use Powershell?

The help system

The Powershell help system is awesome. Get-Help is the cmdlet you should know. Want to know which cmdlet can help you to get information about processes? Use Get-Help *process* and the help system dumps all cmdlets regarding processes.

Sample output:

> get-help *process*

Name                              Category  Module                    Synopsis
----                              --------  ------                    --------
Enter-PSHostProcess               Cmdlet    Microsoft.PowerShell.Core ...
Exit-PSHostProcess                Cmdlet    Microsoft.PowerShell.Core ...
Get-PSHostProcessInfo             Cmdlet    Microsoft.PowerShell.Core ...
Stop-Process                      Cmdlet    Microsoft.PowerShell.M... Stop-Process...
Start-Process                     Cmdlet    Microsoft.PowerShell.M... Start-Process...
Wait-Process                      Cmdlet    Microsoft.PowerShell.M... Wait-Process...
Get-Process                       Cmdlet    Microsoft.PowerShell.M... Get-Process...
Debug-Process                     Cmdlet    Microsoft.PowerShell.M... Debug-Process...
Get-AppvVirtualProcess            Function  AppvClient                ...
Start-AppvVirtualProcess          Function  AppvClient                ...
Get-ComputeProcess                Cmdlet    HostComputeService        Get-ComputeProcess...
Stop-ComputeProcess               Cmdlet    HostComputeService        Stop-ComputeProcess...
Get-VMProcessor                   Cmdlet    Hyper-V                   Get-VMProcessor...
Set-VMProcessor                   Cmdlet    Hyper-V                   Set-VMProcessor...
ConvertTo-ProcessMitigationPolicy Cmdlet    ProcessMitigations        ConvertTo-ProcessMitigationPolicy...
Get-ProcessMitigation             Cmdlet    ProcessMitigations        Get-ProcessMitigation...
Set-ProcessMitigation             Cmdlet    ProcessMitigations        Set-ProcessMitigation...

 

Hmm… but how do I know how to use e.g. Get-Process?

Use Get-Help with its -Examples attribute. It may be the case that Get-Help won’t dump anything example related. Here, your local help might be outdated. You’ve two options to get the most actual help info.

Example output for Get-Help Get-Process -Examples:

> Get-Help Get-Process -Examples

NAME
Get-Process

SYNOPSIS
Gets the processes that are running on the local computer or a remote computer.


Example 1: Get a list of all active processes on the local computer

PS C:\>Get-Process

This command gets a list of all active processes running on the local computer. For a definition of each column, see the "Additional Notes" section of the Help topic for Get-Help.
Example 2: Get all available data about one or more processes

PS C:\>Get-Process winword, explorer | Format-List *

This command gets all available data about the Winword and Explorer processes on the computer. It uses the Name parameter to specify the processes, but it omits the optional parameter name. The pipeline operator (|) passes the data
to the Format-List cmdlet, which displays all available properties (*) of the Winword and Explorer process objects.

As an alternative to Get-Help you also type help or man.

Objects

Compared to other shells Powershell cmdlets will return the output in form of an object. Based on that you can use object attributes, for e.g. filtering, compared to other shells where you’ve to work with strings.

How do you know which attributes are available on a given object?

Here the Get-Member cmdlet starts to shine. How to use Get-Member? Correct, via Get-Help:

 

> Get-Help Get-Member -Examples

NAME
Get-Member

SYNOPSIS
Gets the properties and methods of objects.


Example 1: Get the members of process objects

PS C:\>Get-Service | Get-Member
TypeName: System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
Name AliasProperty Name = ServiceName
Close Method System.Void Close()
Continue Method System.Void Continue()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType)
Dispose Method System.Void Dispose()
Equals Method System.Boolean Equals(Object obj)
ExecuteCommand Method System.Void ExecuteCommand(Int32 command)
GetHashCode Method System.Int32 GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method System.Type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Pause Method System.Void Pause()
Refresh Method System.Void Refresh()
Start Method System.Void Start(), System.Void Start(String[] args)
Stop Method System.Void Stop()
ToString Method System.String ToString()
WaitForStatus Method System.Void WaitForStatus(ServiceControllerStatus desiredStatus), System.Voi...
CanPauseAndContinue Property System.Boolean CanPauseAndContinue {get;}
CanShutdown Property System.Boolean CanShutdown {get;}
CanStop Property System.Boolean CanStop {get;}
Container Property System.ComponentModel.IContainer Container {get;}
DependentServices Property System.ServiceProcess.ServiceController[] DependentServices {get;}
DisplayName Property System.String DisplayName {get;set;}
MachineName Property System.String MachineName {get;set;}
ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;}
ServiceName Property System.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;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}

This command displays the properties and methods of the process objects (System.ServiceProcess.ServiceController) that are generated by the Get-Service cmdlet.

The command uses the pipeline operator (|) to send the output of a Get-Service command to Get-Member.

Because the Get-Member part of the command does not have any parameters, it uses all of the default values. As such, it gets all member types, but it does not get static members and does not display intrinsic members.

If you check example 1 of the Get-Help output, you’ll see how Get-Member is used to retrieve information about the object Get-Service returns. We see that Get-Service returns a System.ServiceProcess.ServiceController object. The MemberType column tells us that the object offers methods and properties, like the service status (which if of type System.ServiceProcess.ServiceControllerStatus), or the service display name (which is of type string).

Why do we care about this information? Because of two things:

  1. Cmdlet chaining, via the pipeline operator |
  2. Filtering given objects on specific attributes.

Chain cmdlets together

Powershell allows us to chain several cmdlets together. For example we can write:

> Get-Service -name "winrm" | Stop-Service -WhatIf
What if: Performing the operation "Stop-Service" on target "Windows Remote Management (WS-Management) (winrm)".

Above example retrieves all services named „winrm“ and forwards them via the pipeline to the Stop-Service cmdlet (which, of course will stop the piped serivces). Get-Service also allows wildcard filtering via the *-operator:

 

> Get-Service *win*

Status   Name               DisplayName
------   ----               -----------
Running  WinDefend          Windows Defender Antivirus Service
Running  WinHttpAutoProx... WinHTTP Web Proxy Auto-Discovery Se...
Running  Winmgmt            Windows Management Instrumentation
Stopped  WinRM              Windows Remote Management (WS-Manag...

 

In combination with the Where-Object cmdlet we can perform more detailed filtering before stopping services:

> Get-Service *win* | Where-Object { $_.Status -like "Running" } | Stop-Service -WhatIf
What if: Performing the operation "Stop-Service" on target "Windows Defender Antivirus Service (WinDefend)".
What if: Performing the operation "Stop-Service" on target "WinHTTP Web Proxy Auto-Discovery Service (WinHttpAutoProxySvc)".
What if: Performing the operation "Stop-Service" on target "Windows Management Instrumentation (Winmgmt)".

Via $_ or $PSITEM you can refer to the actual object in the pipeline.

If I want some more information about the service matching the „*win*“ filter I can use the Foreach-Object cmdlet and build a more complex chain:

> Get-Service *win* | foreach-Object { Write-Host "$($_.Displayname) - $($_.Status) - $($_.Starttype)"} | where-object { $_.Status -like "Running" } | Stop-Service -WhatIf
Windows Defender Antivirus Service - Running - Automatic
WinHTTP Web Proxy Auto-Discovery Service - Running - Manual
Windows Management Instrumentation - Running - Automatic
Windows Remote Management (WS-Management) - Stopped - Manual

How do we know which cmdlets can be chained together. This MSDN link gives a detailed explanation about it. Short explanation: Lets check this simple example:

Get-Process notepad | Stop-Process

Get-Process returns one or more System.Diagnostics.Process objects. These objects are passed down the pipeline. Powershell now has to check if the Stop-Process cmdlet accepts the given object type. For this task Powershell checks, if Stop-Process has an parameter that

How can we get to this information? Via Get-Help.

 

> Get-Help Stop-Process -Parameter *
...
-Id <Int32[]>
    Specifies the process IDs of the processes to stop. To specify multiple IDs, use commas to separate the IDs. To find the PID of a process, type `Get-Process`.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false


-InputObject <Process[]>
    Specifies the process objects to stop. Enter a variable that contains the objects, or type a command or expression that gets the objects.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByValue)
    Accept wildcard characters?  false


-Name <String[]>
    Specifies the process names of the processes to stop. You can type multiple process names, separated by commas, or use wildcard characters.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false

...

 

First of all we’ve to check if any given parameter accepts pipeline input -> „Accept pipeline input? True„. If so, we have to check the value in the following brackets. This might be ByValue or ByPropertyName. For values Stop-Process supports the following types (received from the pipeline):

If Stop-Process receives other object types than the above two, it will check if the given object has a Name parameter. If so, it will accept this as input.

 

Based on that mechanism it is super easy to build complex chains. There are also some cmdlets that take nearly every object type as pipeline input-parameter. Some of the cmdlets are:

 

Based on that we can build a complex chain like:

> Get-Service *win* | Where-Object { $_.Status -like "running"} | ForEach-Object -Begin { Write-host "Found services:"} -Process { Write-Host "$($_.DisplayName), $($_.Status)"; $_} | Stop-Service -WhatIf
Found services:
Windows Defender Antivirus Service, Running
What if: Performing the operation "Stop-Service" on target "Windows Defender Antivirus Service (WinDefend)".
WinHTTP Web Proxy Auto-Discovery Service, Running
What if: Performing the operation "Stop-Service" on target "WinHTTP Web Proxy Auto-Discovery Service (WinHttpAutoProxySvc)".
Windows Management Instrumentation, Running
What if: Performing the operation "Stop-Service" on target "Windows Management Instrumentation (Winmgmt)".

 

Get-Service returns a bunch System.ServiceProcess.ServiceController-objects. Each of the objects is sent to the pipeline on after another. That means that the first object is sent to Where-Object, afterwards to ForEach-Object, and finally to Stop-Service. After that, the second object is sent to the pipeline. We can also see this behavior in above console output, where „Windows Defender Antivirus Service“-service state is printed. Right after that the WhatIf output of Stop-Service is printed. In the next line of the console output the state of „WinHTTP Web Proxy Auto-Discovery Service“-service is printed,…

 

Hope above descriptions makes it a bit easier for you to get into Powershell.

 

 

 

 

 

 

 

 

 

 

 

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*

code