© Adam Bertram 2020
A. BertramBuilding Better PowerShell Codehttps://doi.org/10.1007/978-1-4842-6388-4_19

19. Miscellaneous Tips

Adam Bertram1  
(1)
Evansville, IN, USA
 

There will inevitably be tips that don’t fit the mold. Tips that don’t necessarily fit in a chapter and not enough of them were found to create a chapter will be here.

In this chapter, you will find a smorgasbord of tips ranging from string and array best practices, interactive prompting, creating PowerShell script shortcuts, and more.

Write for Cross-Platform

At one time, PowerShell was called Windows PowerShell. PowerShell only existed on Windows. Not anymore. Nowadays, PowerShell is available on just about every platform out there. As a result, scripts are being run on Windows, Linux, macOS, and other platforms every day.

If you’re writing PowerShell for the community or others in your organization, it’s a good idea to ensure those scripts are cross-platform compatible. IT workloads are constantly moving around on-prem and to/from the cloud on different operating systems. A web server can just as easily run on nGinx as it can on IIS. You should write scripts to account for this potential change even though there are no plans to run on another platform.

Even though the Microsoft PowerShell Team has taken every effort to maintain complete parity between Windows PowerShell and PowerShell, there will be differences, especially across different operating systems. If you believe your script may run on both versions, be sure to write and test for both.

There is an endless number of examples of following this tip, but to solidify things, let’s use an example. Perhaps you have a script that works with an API. This script queries a REST API and performs some tasks based on the result of various API calls. In one line of your code, the script reads a directory. You usually work on Windows and you’ve been getting a bit lazy lately with how you code. You decide to save a few keystrokes use the alias ls to list files in a directory. This code works just fine in Windows.
ls -Path 'C:SomeFolder' | ForEach-Object { $_.Encrypt() }

Now let’s say you’ve been working hard on this script and want to share it with others. This script doesn’t necessarily need to be run on Windows. There is no dependency on Windows because perhaps you’re querying an API with the Invoke-RestMethod cmdlet that’s available cross-platform.

Someone else runs this script on macOS and it fails. Why? There are two reasons:
  1. 1.

    ls is a shell command in macOS. However, on Windows, ls is an alias to the Get-ChildItem cmdlet. You’re running two separate commands expecting both to have the same functionality.

     
  2. 2.

    The Encrypt() method is not available on macOS. It’s only available in Windows. If you need to encrypt the files, you need to find a cross-platform way to do it.

     

You don’t have to always write code to be cross-platform but it can never hurt!

Tip Source: https://twitter.com/migreene

Further Learning

Don’t Query the Win32_Product CIM Class

One common use for PowerShell is to find installed software on a Windows machine. Installed software can be found in various places in both WMI, the registry and the file system.

One place that installed software is located is within the Win32_Product CIM class. It may be tempting to use Get-CimInstance to query this class but don’t! This class is special and forces Windows to run external processes behind the scenes. It’s slower to respond and will instruct Windows to run msiexec for each instance when you don’t expect it.

If you need to find what software is installed on a Windows computer, don’t do this or anything like it:
Get-CimInstance -Class Win32_Product
If so, you’ll find the performance is extremely slow. If you dig in a bit to figure out why, you’ll find that you’re filling up the Windows Application event log with messages as shown in Figure 19-1.
../images/501963_1_En_19_Chapter/501963_1_En_19_Fig1_HTML.jpg
Figure 19-1

MsiInstaller event log messages

Instead of querying the WMI Win32_Product class, use the registry. You can query the registry yourself, but to save time, check out the PSSoftware community module or any other that queries the registry instead.

Further Learning

Create a Shortcut to Run PowerShell As Administrator

Much of the time, you need to run PowerShell “as administrator” in Windows. Doing so allows you to perform many system tasks you wouldn’t typically have access to.

To run any command “as administrator,” you can right-click the program and click Run as administrator as shown in Figure 19-2. But this is too much work!
../images/501963_1_En_19_Chapter/501963_1_En_19_Fig2_HTML.jpg
Figure 19-2

Manually running PowerShell “as administrator”

Instead of navigating to a program in a menu, you can’t save a few seconds by creating a shortcut that always opens up PowerShell “as administrator.” To make this happen, create a Windows shortcut on your desktop or another place on disk using the following command. This command starts PowerShell and then immediately invokes a child Windows PowerShell process “as administrator.”
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -Verb Runas}"

Replace Start-Process PowerShell with Start-Process pwsh to launch PowerShell Core “as administrator”

Tip Source: https://www.reddit.com/user/Wugz/

Further Learning

Store “Formattable” Strings for Later Use

You can store “formattable” strings without actually using them until you need to. What’s a “formattable” string? As mentioned in the “Write for the Next Person” chapter, PowerShell allows you to create placeholders in strings to replace via the -f operator.

As shown in the following code snippet and result in Figure 19-3, using string formatting with the -f operator, you can replace a value inside of another string by using an incrementing placeholder:
'Hi, I am {0} {1}' -f 'Adam','Bertram'
../images/501963_1_En_19_Chapter/501963_1_En_19_Fig3_HTML.jpg
Figure 19-3

Replacing placeholders with values in a string

You can use this feature to your advantage by also storing the entire string with placeholders in a variable and then replacing those placeholders with a variable. For example, perhaps you need to store a common SQL query in code but one value in that query will change. You could create the string with placeholders, assign it to a variable, and invoke the code later.

The following code snippet is storing the SQL query string with a placeholder as $FString. It’s then using a pipeline variable ($_) as the value to replace which is a variable. You can see that the “formattable” string’s placeholder is getting replaced by different values.
$FString = "SELECT * FROM some.dbo WHERE Hostname = '{0}'"
"comp1","comp2" | ForEach-Object {
    Invoke-SQLcmd -Query ($FString -f $_)
}

Tip Source: https://www.reddit.com/user/Vortex100/

Further Learning

Use Out-GridView for GUI-Based Sorting and Filtering

Sometimes the command line isn’t enough. Whether you’re feeling mouse-happy or you’re giving a script to a user that needs a GUI, you can easily display objects using a cmdlet called Out-GridView . The Out-GridView cmdlet takes one or more objects as input and then displays them in a window with a grid. You can then filter, sort, and click around the rows as much as you’d like.

Maybe you’d like to present a list of Windows services to a user. Just pipe Get-Service to Out-GridView. You’ll get a nice window as shown in Figure 19-4.
Get-Service | Out-GridView
../images/501963_1_En_19_Chapter/501963_1_En_19_Fig4_HTML.jpg
Figure 19-4

Viewing Windows services in a GUI-based grid layout

Not only can you create a nice, grid layout of objects, you can also provide input to other commands via the grid by passing selected objects using the PassThru parameter.

Perhaps you need to restart some Window services but want to select them via nice, grid layout you saw earlier. In that case, you’d use the PassThru parameter which would force Out-GridView to pass all selected objects to the pipeline which another command would pick up (Restart-Service in this case).
Get-Service | Out-GridView -PassThru | Restart-Service

The Out-GridView cmdlet is an easy and simple way to create an interactive, GUI-based grid layout.

Tip Source: https://www.reddit.com/user/alphanimal/

Further Learning

Don’t Make Automation Scripts Interactive

When you’re building scripts to automatically perform tasks, don’t introduce any kind of interactivity. The point of automation is complete, hands-off-the-keyboard behavior. The last thing you want to want to happen is to be woken up in the middle of the night because a mission-critical script didn’t run because it was waiting on you to type something in.

Every time a script prompts for input, it’s paused. The entire script just waits for a human to come along and type some characters on the keyboard. Don’t create this. Instead, think through the input you need to pass at runtime and automatically use that information.

Don’t define a mandatory parameter and not pass a value to that parameter:

function Do-Thing {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Foo
    )
}
PS> Do-Thing
function Do-Thing {
    [CmdletBinding()]
    param(
        [Parameter()]
        [string]$Foo
    )
    $thing = Read-Host -Prompt 'I need some input!'
    ## Do stuff with $thing
}
PS> Do-Thing
$credential = Get-Credential -Message 'Needs some love here'

The only place to prompt for anything is when someone intends to be in front of that code when it runs.

Further Learning

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.15.149