Hornedowl.nethttps://hornedowl.net
Blogging about Cloud, PowerShell, and LifeWed, 01 May 2019 15:05:40 +0000en-US
hourly
1 https://wordpress.org/?v=5.2.3https://i1.wp.com/hornedowl.net/wp-content/uploads/2019/03/cropped-Bubo_virginianus_06.jpg?fit=32%2C32&ssl=1Hornedowl.nethttps://hornedowl.net
3232160018241HBoPS #8: Automatic variables in PowerShellhttps://hornedowl.net/2019/05/06/hbops-8-automatic-variables-in-powershell/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-8-automatic-variables-in-powershell
https://hornedowl.net/2019/05/06/hbops-8-automatic-variables-in-powershell/#respondMon, 06 May 2019 07:08:24 +0000http://hornedowl.net/?p=212So over the years I've worked with a few variables I took for granted, and I figured it was time to learn more about them! As always, I share that knowledge with you, my dear reader (now get me a muffin!).

]]>So over the years I’ve worked with a few variables I took for granted, and I figured it was time to learn more about them! As always, I share that knowledge with you, my dear reader (now get me a muffin!).

What are automatic variables?

Automatic variables are variables (!SURPRISE!) that store state information for PowerShell. You do not need to do anything to get information in to these variables, it’s PowerShell that creates and maintains them.

$_ or $PSItem

You’ll probably have worked with this one before (notably if you’re running a | Where-object {$_ <something>} command). This is simply the current object in the pipeline, and allows for lots of nifty filtering and manipulations

$Error

This lovely variable contains all the error objects, or rather the most recent error objects that occurred. If you want to see the most recent error, use $Error[0].Do note that if you use an ErrorAction parameter of Ignore, any error received will not be added to the $error object.

$IsLinux, $isMacOS, $IsWindows, $IsCoreCLR

Lovely things that return a Boolean response depending on if you’re running PowerShell on Linux, MacOS, Windows, or if you’re running on the .NET Core Runtime.

$PID

Having struggled with different PowerShell tools running simultaneously and how to manage them (Kalvin, if you’re reading this, you know what I’m talking about!) $PID have offered a great deal of help with that. It contains the process identitfier of the process hosting the current PowerShell session.

This gives you a means to track PowerShell sessions, if you so desire.

$PSBoundParameters

This one is actually my most recent discovery and a very nifty one! Ever added parameters to a function and then needed to do a check to see if they were used? You probably did something like this:

So the major downside with this approach is that, if you’ve used the variable $Switch somewhere else (aka it exists in the session), you’re not going to have a pleasant day. Having to keep track of all those variables in large projects gets confusing. As it turns out, there is a better way…

You see, $PSBoundParameters contains key/value pairs of the parameters that are passed to your functions (scripts too!). This allows you to keep using common parameters, without having to worry about a randomly floating thing somewhere! There’s 3 different ways you can go about using this:

]]>https://hornedowl.net/2019/05/06/hbops-8-automatic-variables-in-powershell/feed/0212HBoPS #7: Begin, Process, Endhttps://hornedowl.net/2019/05/03/hbops-7-begin-process-end/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-7-begin-process-end
https://hornedowl.net/2019/05/03/hbops-7-begin-process-end/#respondFri, 03 May 2019 08:06:53 +0000http://hornedowl.net/?p=204Imagine the day where you start writing advanced functions. That's the day you implement Begin, Process, and End. A beautifully, simple, concept that brings structure to the chaos of our minds!

]]>Imagine the day where you start writing advanced functions. That’s the day you implement Begin, Process, and End. A beautifully, simple, concept that brings structure to the chaos of our minds!

What is an advanced function?

An advanced function is, simply put, a way to allow you to write functions that behave similar to the Microsoft cmdlets.

It is as simple as adding [CmdletBinding()] right above you Param() declaration in your function.

So what’s up with this Begin, Process, End?

Begin, Process, and End are 3 different blocks to separate your code in to logical blocks. They help you prepare your function, execute the tasks that it needs to do, and end the function in the expected way.

Begin

When you are writing a function, typically you begin by specifying variables, object, or arrays that you will use throughout the function. The BEGIN block is where you would place this code.

The begin block will only run once per call of the function, consider it being pre-processing, setup, or ‘preparing’ your function. It’s important to note that it is NOT required to use the BEGIN block if you want to use PROCESS or END.

Process

The process block is where the meat of your function is. It carves and shapes whatever it is you want to do, and does so very neatly. You can also use it without the BEGIN or END blocks. But ask yourself a few questions

Does this function take a single value as a parameter, or can it take an array of values?

Is this function going to accept pipeline input? (And if it doesn’t, why not?!)

It is quite important that you ask yourself these questions, because the PROCESS block has a nifty little thing it does. You see, if you pass a single value to your function, the PROCESS block is going to run once. But when you pass multiple values, the PROCESS block is going to run once for every value you pass to the function!

Now that last bit is neat, but it needs some more explanation. Let’s take this function as an example:

End

Finally the END block. This is where we do the cleanup of our variables, close anything out that needs to be closed out, so general housekeeping.

Returning objects

One last thing… In advanced functions you shouldn’t use the return keyword to return objects, but rather just run a ‘New-Object’ command. Nor should you place the return anywhere but in the PROCESS block. Otherwise it defeats the purpose of using the pipeline…

]]>https://hornedowl.net/2019/05/03/hbops-7-begin-process-end/feed/0204HBoPS #6: Handling Credentialshttps://hornedowl.net/2019/04/29/hbops-6-handling-credentials/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-6-handling-credentials
https://hornedowl.net/2019/04/29/hbops-6-handling-credentials/#respondMon, 29 Apr 2019 08:08:39 +0000http://hornedowl.net/?p=202So if there is one thing that just annoys me, it's when I have to handle credentials in PowerShell. Mind you, not the simple "call, use, discard" type of handling... Oh No... That's easy! It's when there's a need to save credentials that things get tricky!

]]>So if there is one thing that just annoys me, it’s when I have to handle credentials in PowerShell. Mind you, not the simple “call, use, discard” type of handling… Oh No… That’s easy! It’s when there’s a need to save credentials that things get tricky!

You see, I don’t like putting credentials anywhere. Because no matter what you do, you’re going to run in to issues. Which issue is acceptable, and how to make our code as secure as possible, is something we have to decide upon in a case-by-case basis.

Wait… What are you on about?

I just hear John’s voice (good old Irish buddy and former colleague of mine) whenever I utter these words.

The thing is that there are multiple ways of handling credentials when you’re writing PowerShell tools or controllers. Each of them have their limitations. Some you should never, ever do. And I do mean NEVER!

Well what are my options then?

I think we can summarize the options we have for handling credentials very simply:

Store the credentials in the script itself (I will find you and hunt you down if you do this)

Ask for credentials every time we perform an action that requires credentials

Use Integrated Windows Authentication.

Create an ACL protected file with our credentials

Encrypt a file that contains our credentials

Obviously option 1 should be avoided at all cost… As I like to tell all my customers: “When listing your options, list all of them!”. Even doing nothing is an option. Not a good option, but an option none the less…

Using Integrated Windows Authentication

By far the most secure method of dealing with credentials is using IWA. Try to always use IWA where possibly. Also, I like the way IWA sounds….

The downside to using IWA is that it only is going to work if our resource is Active Directory aware, and in the same (or a trusting) Active Directory Domain. And it’s something that is more typically used with web services…

Creating password hash files

Storing credentials securely on disk is neat, and you can choose from 2 main methods when it comes to “encrypting” your credentials: AES and DPAPI

Now both AES and DPAPI have native suport in PowerShell, which means that it’s relatively easy to use both ways.

DPAPI

DPAPI encrypted data can only be decrypted by the same host (and same user profile) that encrypted it. This raises our confidentiality perspective, but lowers our usability since the data is not portable between machines. So any tasks that would require you to reuse the same set of credentials on multiple machines is going to require you to save the credentials before executing tasks.

How to do it

First of all we will need to retrieve our credentials:

$creds = get-credential

Our variable $Creds now contains a username (stored in clear text…) and a Password (stores as a Sytem.Security.SecureString).

Now you cannot go and export this Password to a file just yet. You have to convert the SecureString object to an Encrypted Standard String first!

Obviously this is not going to stop people who know what they’re doing in their tracks. It is better than storing your password in plain text, and that is something already…

Toolkits exist to decrypt DPAPI encrypted items, and they are freely available. Adding ACL to the file makes things a bit harder, but stil…

AES

AES on the other hand can be extremely portable, as you’ll be encrypting the password with a key you define. That does mean that it is also more vulnerable than DPAPI. You lose access to the key, you lose functionality. And even worse, someone gains access to the key, they can now decrypt your credentials! So properly secure this key and guard it with your life.

]]>https://hornedowl.net/2019/04/29/hbops-6-handling-credentials/feed/0202HBoPS #5: Reduce, Reuse, Recyclehttps://hornedowl.net/2019/04/26/hbops-5-reduce-reuse-recycle/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-5-reduce-reuse-recycle
https://hornedowl.net/2019/04/26/hbops-5-reduce-reuse-recycle/#respondFri, 26 Apr 2019 08:35:19 +0000http://hornedowl.net/?p=200Although more commonly associated with "waste management", this can also be applied to your PowerShell code! In the end, you don't want to continuously write the same code. You want to create functions and optimize the code in those functions to be adaptable...

]]>Although more commonly associated with “waste management”, this can also be applied to your PowerShell code! In the end, you don’t want to continuously write the same code. You want to create functions and optimize the code in those functions to be adaptable…

So what is it you are trying to achieve?

In general we can categorize code written in PowerShell in 2 big factions: Tools and Controllers…

Tools are single issue, problem solving, specialists. For example deploying a Virtual Machine in your environment…

All of this is highly reusable, and each of these steps can be created in separate functions.

Controllers would use the tools you’ve created, calling them in the proper order, and either log to the screen, a log file, or both.

So when we’re creating a possible solution to a business problem (or automating a process), we first need to think of what it is we’re trying to achieve, and what we’re going to write…

Be consistent, be modular!

Try to make your tools as modular as you can! Only accept input through parameters, only provide output through the pipeline.

Try to use the verb-noun cmdlet naming as you see in all of the Microsoft cmdlets. One of the things that makes things so darned easy in using PowerShell is that you can look at the name of a cmdlet, and pretty much understand what it is going to do from looking at the name of the cmdlet.

That neat thing you wrote? It’s built in already…

Once you get to a point where you’re solving problems which have already been solved in the default set of cmdlets provided by Microsoft you’re pretty much stealing from yourself. Sure, sometimes it’s fun writing a new ping functions, but the reality is that you might have just wasted your own time, as you could have just used Test-connection.

There are the exceptions to this, of course, but as with everything, the exception doesn’t make the rule…

Find a bug, report a bug

There are many a smart people working at Microsoft that create cmdlets. And as with all software that gets developed, bugs will creep their way in to the code. So if a cmdlet doesn’t work as expected, do report it on connect.microsoft.com. Not only are you helping yourself (the bug might actually get fixed!), but you’re helping the community by lending your voice to it.

Sometimes PowerShell native isn’t the best way to go…

There are tools that are vastly superior to the native, built-in cmdlets. In those cases it’s quite alright to call them in your code, but you should account for them! Comment as to why you’re using these tools. Document it somewhere. Create prerequisite checks so your code handles that specific tool not existing.

The amount of times I’ve had to dig my way through code, only to find some obscure tool was being called without mentioning it in the documentation, or providing error handling for it not being in it’s hard coded path (I just started twitching) has made me slightly frustrated!

]]>https://hornedowl.net/2019/04/26/hbops-5-reduce-reuse-recycle/feed/0200HBoPS #4: Variables, Parameters, and BattleStar Galacticahttps://hornedowl.net/2019/04/24/hbops-4-variables-parameters-and-battlestar-galactica/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-4-variables-parameters-and-battlestar-galactica
https://hornedowl.net/2019/04/24/hbops-4-variables-parameters-and-battlestar-galactica/#respondWed, 24 Apr 2019 08:31:46 +0000http://hornedowl.net/?p=189When it comes to variables and parameters, I've seen some strange, horrible things. there is only one thing more annoying than someone cycling through the alphabet for variables, and that's reusing the same variable in the entire script. Even with proper error handling that's just a recipe for disaster!

]]>When it comes to variables and parameters, I’ve seen some strange, horrible things. there is only one thing more annoying than someone cycling through the alphabet for variables, and that’s reusing the same variable in the entire script. Even with proper error handling that’s just a recipe for disaster!

Use meaningful names

When creating variables, please use meaningful names. For example, if you’re retrieving all users in active directory, don’t call use $x to store the output in, but rather use something like $AllUsers.

The general recommendation is to use Pascal Case. For example, it’s easier to read $ThisVariableContainsAllUsers than $thisvariablecontainsallusers. Something with the human psyche just messes with you when you try to read the latter variable name.

User-defined variables

Place any user-defined variables at the top of the script where possible. Usually this is something you’d do near the end of your dev cycle. Reasoning behind this is simple, it avoids others to hunt for variables that might need to be changed.

Whilst there are no concise rules around this, so when you’re in doubt whether you should move a variable to the top, ask yourself: “Might I, or someone else running this script, need to change this variable in the future?”, and secondly “Will moving this to the top break anything?”

Avoid unnecessary data output and/or retrieval

It happens to the best of us, sometimes we read data multiple times from disk in a single script. Most of the times that happens when we’re adding on functionality later and forgot we already had it in memory. Other times we might just have too much blood in our caffeine…

Remember when you read from disk instead of using the memory, you’re incurring a file system write and read I/O action. This will slow down the execution of your script. Whilst most of the times this will not be noticeable (nano vs milliseconds), it is still recommended to keep track of what you have in memory, and reuse as much as possible.

Parameters

Parameters can be divided up in to 2 distinctly different sorts: Static, and Dynamic parameters.

]]>https://hornedowl.net/2019/04/24/hbops-4-variables-parameters-and-battlestar-galactica/feed/0189HBoPS #3: Avoid using write-hosthttps://hornedowl.net/2019/04/22/hbops-3-avoid-using-write-host/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-3-avoid-using-write-host
https://hornedowl.net/2019/04/22/hbops-3-avoid-using-write-host/#respondMon, 22 Apr 2019 08:38:38 +0000http://hornedowl.net/?p=186It once was said to avoid using write-host in any script, since every time you use it, a puppy dies. In this article we explore the limitations of write-host, and a better way to put text on the console...

What is write-host?

Write-host is one of those easy cmdlets to tell the user what is going on in a script. Kind of funny, isn’t it? We’re writing scripts to automate things, but we still want people to know what is going on…

One of the major issues with write-host before PowerShell 5 is that it simly puts a text on the console. There is no way for the end-user to save, redirect, or ignore it.

So in essence you would not be able to pass the text you’re writing on to any other pipelines, making write-host just a very dumb tool that does not fit the general flexible environment of PowerShell.

Write-output

A better alternative to using write-host is write-output. It is able to be saved, redirected, or ignored if so desired by the end-user, and generally is better at handling objects!

The downside, of course there always has to be a downside, is that it doesn’t allow you to write beautifully colored messages… Then again, there are ways around that

write-output and colored messages

One way (I’m certain there are more!) would be to change the $host.UI.RawUI.ForegroundColor property to the color you want displayed. Alas, this changes the setting for the entire console, so you would have to set it back to the previous color after running your write-output command.

]]>https://hornedowl.net/2019/04/22/hbops-3-avoid-using-write-host/feed/0186HBoPS #2: Error Handling and you!https://hornedowl.net/2019/04/17/hbops-2-error-handling-and-you/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-2-error-handling-and-you
https://hornedowl.net/2019/04/17/hbops-2-error-handling-and-you/#respondWed, 17 Apr 2019 08:14:34 +0000https://hornedowl.net/?p=169Proper error handling is important... Knowing what happens matters! That is why we can use the Try{}Catch{} statements to deal with things that go wrong...

Proper error handling is important… Knowing what happens matters! That is why we can use the Try{}Catch{} statements to deal with things that go wrong…

Setting Error Action Preference to Silently Continue

Consider the block below… It has error handling (the try/catch), but since the $ErrorActionPreference is set to SilentlyContinue, it won’t show an error. You might be left wondering why no information was returned, and no warning was given!

Terminating non-terminating errors

Although we see an error in the previous image, it’s not the action we specified in the Catch block. And that’s because get-item is not generating a terminating error. If we want the action in our catch block to be generated, we need to add an error action:

There she blows! We now get our catch statement activated and displaying our warning message..

Some people argue that setting $ErrorActionPreference to Stop at the beginning of your script make you write better code. It’s not something I have done ever. If you do go that route, remember to set the $ErrorActionPreference back to Continue at the end! That preference is a global preference, and you’d mess up someones day if you don’t

Returning error to the end-user

So we’ve been able to trigger our warning! But what was the exact error? With the following block of code we can show that to our end-user:

Exception information, and how to access it

Within a catch block you can access the current error using $_. I’ve used this in an example above, and it’s a pretty nifty way to give more information.

Standard error handling structure

So with all of the above information, the following “standard” error handling structure emerges:

Try{<# This block is where we are going to do something. Our first action is going to be to set the error action preference to STOP, catching all those pesky non-terminating errors get picked up. Secondly, the executing code will be added Thirdly we report back #># Setting the error action preference to catch non-terminating error $ErrorActionPreference = 'Stop'

}Catch{<# This block is our final catch block. Catches for speficic error should be added before this one in the following format: Catch[error type to catch]{

} #>

Write-warning ('Oops... Something went wrong. Looks like we encountered an unintended error of the type: ' + $_.Exception.GetType().FullName) Write-warning $_

}Finally{<# Our Final block in the process is used for cleanup, in our case setting the error action preference back to 'Continue', since we don't want to leave it at 'Stop' #># Setting the error action preference back to the default value $ErrorActionPreference = 'Continue'}

A quick run through the code shows us that we split our handling up in 3 parts: Try, Catch, and Finally. Typically we try and catch every error we can think of (and test) in the catch blocks, but it is always good to leave a ‘catch all’ for those weird things you didn’t think of. And although I said never to change the error action preference setting, we are doing it here, so we don’t have to remember to add on an erroraction parameter to each cmdlet (work smarter). Anyway, we’re setting it back in our Finally block, which always runs.

]]>https://hornedowl.net/2019/04/17/hbops-2-error-handling-and-you/feed/0169HBoPS #1: Use a proper editor!https://hornedowl.net/2019/04/15/hbops-1-use-a-proper-editor/?utm_source=rss&utm_medium=rss&utm_campaign=hbops-1-use-a-proper-editor
https://hornedowl.net/2019/04/15/hbops-1-use-a-proper-editor/#respondMon, 15 Apr 2019 11:05:17 +0000http://hornedowl.net/?p=181All thing begin at the editor. Or you know, right after you discovered something you want to automate :). So using an editor for writing PowerShell code that helps you develop better code is neat!

]]>All thing begin at the editor. Or you know, right after you discovered something you want to automate :). So using an editor for writing PowerShell code that helps you develop better code is neat!

Not that I have any hate on Notepad, or even Notepad++, but for writing anything other than a very short script, I rely on something that helps me create better and faster!

What to look for?

When you’re looking to use an editor that provides you more functionality than Notepad, it’s fairly important to know what functionality Notepad does not provide:

Syntax highlighting: Notepad will not tell you when you write a cmdlet wrong

Collapse blocks: Handy when you can collapse regions, code blocs, or comments!

Clean indentation: This makes your code easier to read. Sure you can do this with notepad manually, but it’s a pain…

Line numbers: Nothing like getting an error in your 1000+ line script and having to count lines in notepad…

Auto complete: Most editors focused on PowerShell will offer you the Auto complete. This saves you time, and reduces the possibility of creating a ‘spelling mistake ‘ in a cmdlet or its parameters.

Which editor to use?!

Let’s face it… If you go randomly looking at editors which exist on the internet, you’ll find more than you know what to do with.

PowerShell ISE

The default editor for PowerShell scripts, modules, and all things related… For the longest time this has been the official editor from Microsoft. It’s installed by default on Windows platforms, and is a handy tool to start with. Unfortunately it does not support Powershell Core, nor is it cross-platform, so it has been replaced by Visual Studio Code as the official editor.

Visual Studio Code

As I just mentioned, this is the new ‘Official’ PowerShell editor from Microsoft. It’s free, cross-platform, and has a lot of features. I haven’t really worked with it, but with all the rave from my peers, I’m going to give it a whirl, just to see what it is about.

]]>https://hornedowl.net/2019/04/15/hbops-1-use-a-proper-editor/feed/0181Invoke-ColorOutputhttps://hornedowl.net/2019/04/15/invoke-coloroutput/?utm_source=rss&utm_medium=rss&utm_campaign=invoke-coloroutput
https://hornedowl.net/2019/04/15/invoke-coloroutput/#respondMon, 15 Apr 2019 08:47:37 +0000http://hornedowl.net/?p=191Born out of the need to avoid write-host, but still wanting pretty colors, Invoke-ColorOutput was born! This function allows you to write output to the screen in a beautiful colorized way, and not have to worry about killing puppies… Github: https://github.com/Toasterlabs/PSCommon/blob/master/Public/Logging%20and%20Console/invoke-coloroutput.ps1 Parameters Object Aliases: Message, msgThis is the meat of the function, the text we […]

]]>Born out of the need to avoid write-host, but still wanting pretty colors, Invoke-ColorOutput was born! This function allows you to write output to the screen in a beautiful colorized way, and not have to worry about killing puppies…

Ah PowerShell… My favorite tool in the toolbox. One of the few tools that can do nearly everything, and make me look cool in the process.Unfortunately I’ve been seeing quite a bit of hate and frustration from people on PowerShell. “It’s not a programming language”, “the formatting is horrible”, “It’s too forgiving”, etc.

Most of these frustrations stem from trying to pull apart code of other people. Quite honestly, I can find this task equally frustrating. Reading other peoples code is never fun. But it can be made easier if we all follow the same principles, taking in to account that most of us who use it are not “real” programmers (cause that’s not the group what PowerShell is aimed at!).

I’m going to try and lay out some of the things I try to do in my scripts and modules, and you’re free to comment, critisize, or suggest improvements. Together we can write “The Holy book of Powershell practices“!