Book Image

Mastering Windows PowerShell Scripting (Second Edition) - Second Edition

By : Brenton J.W. Blawat
Book Image

Mastering Windows PowerShell Scripting (Second Edition) - Second Edition

By: Brenton J.W. Blawat

Overview of this book

PowerShell scripts offer a handy way to automate various chores. Working with these scripts effectively can be a difficult task. This comprehensive guide starts from scratch and covers advanced-level topics to make you a PowerShell expert. The first module, PowerShell Fundamentals, begins with new features, installing PowerShell on Linux, working with parameters and objects, and also how you can work with .NET classes from within PowerShell. In the next module, you’ll see how to efficiently manage large amounts of data and interact with other services using PowerShell. You’ll be able to make the most of PowerShell’s powerful automation feature, where you will have different methods to parse and manipulate data, regular expressions, and WMI. After automation, you will enter the Extending PowerShell module, which covers topics such as asynchronous processing and, creating modules. The final step is to secure your PowerShell, so you will land in the last module, Securing and Debugging PowerShell, which covers PowerShell execution policies, error handling techniques, and testing. By the end of the book, you will be an expert in using the PowerShell language.
Table of Contents (24 chapters)
Title Page
Credits
About the Authors
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

PowerShell on Linux


PowerShell for Linux is, at least at the time of writing, in alpha. The current release is still worth installing even if only to see what having a unified shell may look like.

Note

What about Cygwin? PowerShell is not the first to give a hint of a single shell across different operating systems. However, until PowerShell matured, it was a serious challenge to manage Windows and Microsoft-based systems from the command line alone.

Some familiarity with Linux is assumed during this process.

Installing PowerShell

This installation is based on PowerShell 6, alpha 12 as the latest at the time of writing. The package can be downloaded from GitHub with yum, which will also install the dependencies (https://github.com/PowerShell/PowerShell/releases/latest):

  1. The following command will install PowerShell and any dependencies (libicu, libunwind, and uuid):
sudo yum install https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.12/powershell-6.0.0_alpha.12-1.el7.centos.x86_64.rpm

alpha 12 is the latest release but it may not be when you read this.

  1. PowerShell can be immediately started by running the following command:
powershell
  1. Create a few files in the home directory as a test:
Set-Location ~ 
1..10 | ForEach-Object { New-Item $_ -ItemType File }
  1. The previous command creates 10 empty files named 1 to 10 (with no file extension). Ensure that the new files are now visible using Get-ChildItem:
Get-ChildItem

Note

ls versus Get-ChildItem: On Windows, ls (list) in PowerShell is an alias for Get-ChildItem. On Linux, ls is the original command. See Get-Alias -Definition Get-ChildItem to view what still is.

Where are the PowerShell files?

Several of the following used paths are specific to the installed release (in this case, alpha 12).

As with PowerShell on Windows, the PSHOME variable shows where PowerShell itself has been installed:

PS> $PSHOME 
/opt/microsoft/powershell/6.0.0-alpha.12

The paths for module installation may be viewed using the environment variables:

PS> $env:PSMODULEPATH -split ':' 
/home/psuser/.local/share/powershell/Modules 
/usr/local/share/powershell/Modules 
/opt/microsoft/powershell/6.0.0-alpha.12/Modules

Note

Case sensitivity Linux has a much higher regard for case than Windows. Environment variables, file paths, executables, and so on, are case sensitive. The previously used variable name must be written in uppercase. Use Get-ChildItem to list all of the environment variables using the following command:Get-ChildItem env:

Changing the shell

Once installed, PowerShell is visible in the list of available shells:

chsh -l

Set PowerShell as the default shell for the current user:

chsh 
New shell [/bin/bash]: /usr/bin/powershell

Profiles

The current user profile on Linux resides under the home directory:

~/.config/powershell

Two profiles can be created: CurrentUserCurrentHost (Microsoft.PowerShell_profile.ps1) and Current User (profile.ps1). Inspecting the automatic variable, $PROFILE shows the first of these:

  1. The directory will need to be created prior to use; the following command creates it:
New-Item ~/.config/powershell -ItemType Directory 
  1. Create a simple profile file by sending a string to a file:
‘Write-Host “Welcome to PowerShell” -ForegroundColor Green’ |
    Out-File .config/powershell/profile.ps1
  1. The AllUser profile may be created under PowerShell's installation directory, in this case, alpha 12, as this is the version I have installed:
/opt/microsoft/powershell/6.0.0-alpha.12 
  1. Writing to this area of the filesystem requires the root privileges:
sudo vi /opt/microsoft/powershell/6.0.0-alpha.12/profile.ps1 
  1. Inside vi, press i to enter insert mode and then type the following:
Write-Host 'This is the system profile' -ForegroundColor Yellow
  1. Once completed, press Esc, then type :wq to save and quit vi.
  2. As with PowerShell on Windows, this will be executed before a user-level profile that shows the following in the console when the shell is started:
This is the system profile 
Welcome to PowerShell

Multiplatform scripting

PowerShell on Linux (and macOS) has a long way to go to reach maturity. Our experience writing for these systems has to make a similar journey.

One of the most important facets is that Linux and macOS run PowerShell Core. It lacks some features we may have become used to when writing for Windows.

Line endings

Windows editors, including ISE, tend to use a carriage return followed by linefeed (\r\n or `r`n) at the end of each line. Linux editors use linefeed only (\n or `n).

Line endings are less important if the only thing reading the file is PowerShell (on any platform). However, if a script is set to executable on Linux, a sha-bang must be included and the line-ending character used must be linefeed only.

For example, a created as follows named test.ps1 must use \n to end lines:

#!/usr/bin/env powershell 
Get-Process

The first line is the sha-bang and lets Linux know which parser to use when executing the shell script.

Once created, chmod may be used to make the script executable outside of PowerShell:

chmod +x test.ps1

After being made executable, the script may be executed from bash with the full path or a relative path:

./test.ps1

Note

Editor defaults PowerShell ISE uses carriage return followed by line feed (\r\n). This behavior is by design and cannot be changed. Visual Studio Code uses \r\n for line endings by default. This may be changed in User Settings by adding the following command:"files.eol": "\n"

File encoding

Windows editors, including ISE, tend to save files using what is commonly known as ANSI encoding; this is more correctly known as Windows-1252.

As Windows-1252 is a Microsoft native format, it may be more appropriate to save files in a universally accepted format such as UTF8.

Note

Editor defaults PowerShell ISE defaults to saving files in UTF8 with a Byte Order Mark (BOM). Visual Studio Code saves files using UTF8 (without a BOM) by default. The setting may be changed in User Settings by adding "files.encoding": "utf8bom".

Path separator

Testing shows that PowerShell on Linux is forgiving about path separators; that is, Microsoft Windows uses the backslash (\), where Linux uses a forward slash (/).

If anything outside of PowerShell (including native commands) is to be used, a correct separator should be chosen.

The Join-Path command will merge path elements using the correct separator for each platform. Manual path construction (based on merging strings) should be avoided.

Example

The following function uses the System.Net.NetworkInformation namespace to discover IPv4 address information. This allows us to return the same thing whether it is run on Windows or Linux.

If it were Windows only, we might have used WMI or the Get-NetIPConfiguration command. Creating something to work on both operating systems is more challenging:

function Get-IPConfig { 
    [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | ForEach-Object { 
        $ipProperties = $_.GetIPProperties() 
             
        $addresses = $ipProperties.UnicastAddresses | 
            Where-Object { 
                $_.Address.AddressFamily -eq 'InterNetwork' 
            } | ForEach-Object { 
                "$($_.Address) $($_.IPv4Mask)" 
            } 
 
        $gateway = $ipProperties.GatewayAddresses.Address | 
            Where-Object { 
                $_.AddressFamily -eq 'InterNetwork' -and  
                $_ -ne '0.0.0.0' 
            } 
 
        [PSCustomObject]@{ 
            Name      = $_.Name 
            Id        = $_.Id 
            Addresses = $addresses 
            Gateway   = $gateway 
        } 
    } | Where-Object { $_.Addresses } 
} 
Get-IPConfig