Useful Powershell commands

Commands and usage

Autocompletion (tab and ctrl + space ing)

Autocompletion is your friend when it comes to using Powershell. For example, if I want to see a list of running services on my machine I can execute Get-Service but what if I only wanted to see a list subset of that filtered by some property? How would I know what properties I can filter by? ctrl + space to the rescue!

Enter Get-Service | Where-Object -Property followed by a ctrl + space this will pull up a list of properties you can filter by

> Get-Service  | Where-Object -Property CanPauseAndContinue
CanPauseAndContinue  DisplayName          ServiceHandle        StartType
CanShutdown          MachineName          ServiceName          Status
CanStop              Name                 ServicesDependedOn   ToString
Container            PSStandardMembers    ServiceType
DependentServices    RequiredServices     Site

Now say I want to see any "Hyper V" related services running on my machine I can simply type

> Get-service | Where-Object -Property DisplayName -like *hyper* | Format-Table -AutoSize

Status  Name               DisplayName
------  ----               -----------
Running vmcompute          Hyper-V Host Compute Service
Stopped vmicguestinterface Hyper-V Guest Service Interface
Stopped vmicheartbeat      Hyper-V Heartbeat Service
Stopped vmickvpexchange    Hyper-V Data Exchange Service
Stopped vmicrdv            Hyper-V Remote Desktop Virtualization Service
Stopped vmicshutdown       Hyper-V Guest Shutdown Service
Stopped vmictimesync       Hyper-V Time Synchronization Service
Stopped vmicvmsession      Hyper-V PowerShell Direct Service
Stopped vmicvss            Hyper-V Volume Shadow Copy Requestor
Running vmms               Hyper-V Virtual Machine Management

Where-Object, Sort-Object, Select-Object, "Distinct", Group-Object

Where-Object or just where allows us to filter a list of input objects based on the input object's properties in a conditional manner. There are two ways/formats in which the conditional can be expressed. One is using a script block and the other is using a comparison statement format.

Get-Service | Where-Object {$_.Status -eq "Stopped"}
Get-Service | where Status -eq "Stopped"

The two produce the same results so question is why have two formats?

The answer lies in situations where we want to use logical operators such as AND / OR.

> Get-Module -ListAvailable `
   | where {($_.Name -notlike "Microsoft*" -and $_.Name -notlike "PS*") `
   -and $_.HelpInfoUri} 

Sort-Object or just sort allows us to sort a list of inputs by a certain property

Get-ChildItem | Sort-Object LastAccessTime
gci | sort LastAccessTime

Select-Object or just select allows us to choose which properties to project and how many "rows" to return.

# Display the name, directory and last access time of files in the current directory
gci | select Name, Directory, LastAccessTime

# Only return the first 5 records from previous result
gci | select Name, Directory, LastAccessTime -First 5

Another useful feature is finding a "Distinct" of a property from a list, this can be performed by using the -Unique switch. For example, the following command returns a distinct list of DisplayGroups in our computer's list of firewall rules

Get-NetFirewallRule | Sort-Object -Property DisplayGroup -Unique | Select DisplayGroup

Let's test this worked

> (Get-NetFirewallRule | Select DisplayGroup).Count
562

> (Get-NetFirewallRule | Sort-Object -Property DisplayGroup -Unique | Select DisplayGroup).Count
115

Notice how the counts are different?

Now if we wanted to group the objects by a certain property we can use the Group-Object command.

> Get-NetFirewallRule | Group-Object DisplayGroup | Select -first 5 | ft -AutoSize

Searching for files and directories

Say we just installed Git but we don't know where it is installed

# Look for directories containing pattern *git*
gci c:\ -Filter *git* -Recurse -ErrorAction SilentlyContinue | select Directory -Unique

# Look for files and directories containing pattern *git*
gci c:\ -Filter *git* -Recurse -ErrorAction SilentlyContinue | select FullName

Appending text to a file and "tail" it

There are times where we want to simply append a line of text to a file and there other times when we want to just read n number of rows off a file. This could be writing logs and reading logs.

Let's test this

# Create a file with a line of text
echo "This is line 1" > myfile.txt

# Append to a file
Add-Content myfile.txt "This is line 2"

# Begin "tail" on myfile.txt
Get-Content myfile.txt -Wait

Now open up a separate powershell session and add more lines to myfile.txt

Add-Content myfile.txt "This is line 3"

Now check the previous powershell session and check that This is line 3 is printed on the output.

Powershell remoting

This is only a guide for remoting when the two computers are part of the same workgroup in the same network that has network profiles set to private


# Checking which workgroup the current user belongs to
(Get-WmiObject -Class Win32_ComputerSystem).Workgroup

# On target computer
Enable-PSRemoting -Force

# Trust all hosts (cannot do this in production environments)
# On both target and current computers 
Set-Item wsman:\localhost\client\trustedhosts *

# Restart the WinRM service to let new settings kick in
Restart-Service WinRM

# Set start mode to automatic (default is manual)
Set-Service WinRM -StartMode Automatic

# Verify start mode and state - it should be running
Get-WmiObject -Class win32_service | Where-Object {$_.name -like "WinRM"}

# Test whether WinRM service is running on remote computer
Test-WSMan TargetComputer

# Start a new powershell session on the target computer
Enter-PSSession -ComputerName TargetComputer -Credential Administrator

Networking

Say we wanted to view the "Network Connections" sections in our control panel, I can usually see this by running ncpa.cpl but how to view details like this in Powershell?

Get-NetConnectionProfile

Or if you want to see adapter related information

Get-NetAdapter | ft -AutoSize

Using SSH Client and SSH Server

SSH has finally came to Windows 10 and Windows Server 2016. Read this blog from the Powershell Team for more information.

Here's how to install

Look for the capabilities matching ssh

Get-WindowsCapability -Online | Where-Object -property "name" -like "*ssh*" 
Name  : OpenSSH.Client~~~~0.0.1.0
State : NotPresent

Name  : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

Installing the SSH Client

Add-WindowsCapability -Online -Name "OpenSSH.Client~~~~0.0.1.0" 

Installing the SSH Server

Add-WindowsCapability -Online -Name "OpenSSH.Server~~~~0.0.1.0"

Favourite Aliases

gps -> Get-Process

> gps | select -First 4

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    236       8     5080       6788       0.67   4900   0 AdminService
    168      10     2200       7788       0.13  11208   0 aesm_service
    252      19    13516      20944       0.09  16296   1 AlienFusionController
    295      28    28668      28652       2.95   3856   0 AlienFusionService

gsv -> Get-Service

> gsv | select -first 4

Status   Name               DisplayName
------   ----               -----------
Running  AdobeARMservice    Adobe Acrobat Update Service
Running  AESMService        Intel® SGX AESM
Stopped  AJRouter           AllJoyn Router Service
Stopped  ALG                Application Layer Gateway Service

gcm -> Get-Command

> gcm git | ft -AutoSize

CommandType Name    Version  Source
----------- ----    -------  ------
Application git.exe 2.16.2.1 C:\Program Files\Git\cmd\git.exe

http://powershell-guru.com/powershell-tip-63-check-if-a-computer-is-member-of-a-domain-or-workgroup/
https://blog.netspi.com/powershell-remoting-cheatsheet/
https://serverfault.com/questions/639088/how-do-i-make-a-connection-private-on-windows-server-2012-r2

comments powered by Disqus