LLMA-dot / Get-Clue

Collection of various links and other useful things that I am currently learning. Maybe helpful to others.
0 stars 0 forks source link

[Repeat] Learn PowerShell Scripting in a Month of Lunches #3

Open LLMA-dot opened 1 year ago

LLMA-dot commented 1 year ago

Learn PowerShell Scripting in a Month of Lunches teaches you how to expand your command-line PowerShell skills into effective scripts and tools. In 27 bite-size lessons, you'll discover instantly useful techniques for writing efficient code, finding and squashing bugs, organizing your scripts into libraries, and much more. Advanced scripters will even learn to access the .NET Framework, store data long-term, and create nice user interfaces.

Part 3. Grown-up Scripting

Part 2. Building a PowerShell script

Part 1. Introduction to Scripting

Complete 1 chapter (+ DIY) to reset. Complete 1 section to reset x2. Complete the book to add another book to Todo.

LLMA-dot commented 1 year ago

Removed and put into header.

LLMA-dot commented 1 year ago

Notes Chapter 5:

Wildcards:

The IF Construct

If (expression>) {
    #code
} ElseIf (<expression>) {
    #code
} ElseIf (<expression>) {
    #code
} Else {
    #code
}

An expression is any Powershell expression that will result in either $True or $False.

Only the script block of the first expression that is True will run.

Note: If things aren't lining up properly, here's a trick: Highliught the affected region (or your entire script document), right-click and select Format Selection.

The ForEach Construct

Best Practice: In a script, we greatly prefer the use of ForEach over the ForEach-Object command. But with large collections of arrays, the construct can force you to use more memory, because the entire array or collection must be in a single variable to start with. When you use the command Foreach-Object, objects can be piped in one at a time.

There is some confusion about ForEach because the alias for the ForEach-Object is ForEach, although it works differently than the ForEach CONSTRUCT. The construct, which is what we're teaching here, always has the (x$ in $y) syntax right after it.

The Switch Construct

switch (:principal:) {
    :candidate: {script block}
    :candidate: {script block}
    :candidate: {script block}
default {script block {
}

The principal is usually a variable containing a single value or object.

Each matching candidate will execute

Be sure to read about_switch .

The Do-While Construct

Variant 1:

While ( :condition:) {
#code
}

Variant 2:

Do {
#code
} while (:condition:)

Break

LLMA-dot commented 1 year ago

Chapter 6 Notes

This chapter deals with the theory of tools vs. controller scripts.

Tools have some important characteristics:

Different kinds of tools

Thought exercise 1

Image that you have some LOB application that tracks customer records. You've been asked to write a script that will generate a list of customers whose records have gone for a year or more without any activity. That list is to be formatted in a CSV file that can be fed to other processes, and in an HTML report that can be posted on the company intranet.

How many tools do you need to write? You have to start thinking of the discrete tasks involved, and see what tasks are already solved by Powershell.

My shot at this: I only need to write one tool.

  1. Write Get-Customer Records.
  2. Where-Object less than 365 days since last "interacted"
  3. Export to CSV
  4. Convert to HTML

What the book thinks:

  1. You'll have to write a Get-CustomerRecord tool.
  2. You'll need a way to filter the results of Get-CustomerRecord (Where-Object)
  3. You'll need to convert those results to CSV and save to a file (Export-CSV)
  4. You'll also need a way to make an HTML report.
    • [ ] Check out ConvertTo-EnhancedHTML from EnhancedHTML2 (PowerShell Gallery)

Thinking about controllers

Whereas tools are generic and lack context, controllers are all about contect.

For example, CreateStaleCustomerHTMLReport.ps1 is the script we might create to generate that HTML report of customers who've been inactiver for a year or more.

Get-CustomerRecord |
Where-Object {$_LastActivity -lt (Get-Date).AddDays(-365)} |
ConvertTo-HTML |
Out-File \\intranet\www\reports\inactive-customers.html

Like tools, controllers have some specific characteristics:

Comparing tools and controllers

Tools Controllers
Do one thing and one thing only. Connect multiple tools.
Accept input on parameters. May have hardcoded input, and may use tools to retrieve date that will be fed to other tools
Produce data as objects. May produce any kind of output, including formatted data, special files, and so on.
Complete a task. Solve a problem or meet a need.
Are often useless or minimally useful on their own. Are self-contained.
Are useable across a variety of situations. Are used for a specific situation.

Thought exercise 2

Send a quick email reminder to users whose passwords are about to expire in a day or two.

My take:

  1. Get all users whose passwords will expire (Get-ADUser / Where-Object) - No tool necessary
  2. Write them a mail - Tool necessary (probably PS Gallery)

Book:

  1. Get non-expiring user accounts.
  2. Get password expiration date.
  3. Filter accounts based on number of days.
  4. Send email.
  5. Create audit trail.

If you did it right, your controller script may look like this:

Get-EnabledNonExpiringUser | 
Add-ExpiryDataToUser |
Where-Object {$_.DaystoExpire -lt 2} |
Send-PasswordExpiryMessageToUser |
Export-CSV report.csv

Provisioning new Users

This is our classic "tools versus controllers" example. Think about what goes into provisioning a new user in your organization. You probably have to set up an account, mailbox-enable it, set up a home folder somewhere, maybe add them to something in Sharepoint, and so on. Each of these is obviously a discrete task within the process, and each of those tasks should be a tools.

There's an opportunity to be clver here, too. For example where do you set up the new home folder? What's your normal business logic? "Well, we look at the existing file servers, and we usually don't put more than 1000 Users per home folder file server. So we find a server with less than 1000 home folders already, and use that one. But if the server we pick has less than 75 Gb free, then we leave it alone and pick another one." That's a TASK, and it's one you could automate. Perhaps you'd create a Select-UserHomeFolderFileServer tool athat does all the analysis and returns a list of eligible servers, and then a New-UserHomeFolder tool that uses the first eligible server to create the new user's home folder on. Those are two discrete tasks and should be two discrete tools.

Let the verb be your guide

We always start at the official PS-Verb list, which has the official, allowed verbs for command names.

You'll only have trouble finding the right VERB if you're doing too much in one script.

Listening to PowerShell's verbs, and honoring their intent, can help you make better toolmaking decisions.

Hard truth: If you don't know much about how things you want to automate work you're going to have a hard time automating it in PowerShell.

Thought Exercise 3

Imagine that, for compliance purposes, you must create a report for each server in your domain from the MSInfo32.exe cmd tool. What tools might you need to use? Perhaps Get-ADComputer from the AD module to get the computer accounts. You might want to ping the computer first with Test-Connection and then, if the computer is online, run the MSInfo32 command. Your boss could even ask that you record the server names that aren't online in a seperate text file. In the end, you might not need to create any new tools, but rather a controller script to pull together this collection of PowerShell and non-PowerShell tools.

May look like this:

#Get-ComplianceInfo.ps1
Get-ADComputer -filter * | foreach {
    if (Test-Connection $_.name -quiet) {
        msinfo32 /computer "\\$($_.name)" /report "C:\work\$($_.name)-msinfo.txt"
    }
    else {
        $_.name | out-file C:\logs\offline.txt -Append
    }
}