April 22, 2015

STACK of PowerShell usefulness

Grumpy Admin here, understands this core concept of IT.  A secret I shall now share with you, well I don’t think it so much of a secret so much as a truth.

In IT there are often many way of doing and achieving the same thing. You can use a GUI or Cmdline tool. Multiple methods of configuring the same options. There really is no right or wrong way if it gets the job done. Some ways might be better and more efficent and should just be the way things are done.  I get very grumpy when people do things the most inefficient and slow way! I bet you do too!

The pipe line is a god send in the PowerShell world. It is great and can be used for great effect, to make life much easier!

For example,

$filelist=gci

0..($filelist.count-1) |%{write-host $filelist.Get($_).fullname}

1

This is good, and works to display the fullname of every file and directory using get-childitem, but don’t we get the same results with this code below?

gci |%{$_.FullName}

Both example use the pipeline to great effect.  If the sole aim is just to get the list of fullnames then the bottom one is more efficient. However, if you need to work with the objects later in your script storing the GCI results in a object makes sense. The same outcome initially.  So sometimes doing things a longer way while achieveing the short term aim, makes it better and more future proof. At the end of the day. We only ever want to script something once. We should always try to make functions that do one thing. Then combine functions with a bit of logic to make working scripts.

This is just an example of how you can do most things in different ways, in PowerShell, we have a lot of flexibility. .net and WMI etc

We all know grumpy admin is lazy so will always choose the path of least resistance, sometime this means writing bad scripts and cheating.

The pipeline gives people a great method of using iterations through objects with foreach loops. I believe it because of this iteration abilities we don’t see people using the following features and data types – stacks and queues frequently in PowerShell Scripts.

Stacks and Queues have some nice built in methods to handle addition and removal from the stack of queue.  Both of these classes, Stacks and Queues all sit under the System.Collections namespace in the .net framework and as such are easily accessible to PowerShell!

Check out this link to MSDN for more information on these useful classes.

https://msdn.microsoft.com/en-us/library/System.Collections(v=vs.110).aspx

I am going to focus on the simple stack class here just to demo it to you, we have to give it some love you know! You never know when it might form part of your core logic in a script some time! Doubt it but, if you don’t know about it you can’t use it right!

It is typical that when you try to show a feature or something off and it very hard to find real world examples where you would use such code. So I’m just going to show the stack by using get-childitem and the returning objects from that!

One usage I did think about was using a stack to establish a method of backtracking operations. Lets say you have a configurations script, that checks the state of a VM build process. If certain conditions are met it does certain configuration steps.  Now if a step is complete, but it on to a history stack. That way you have a ordered list of operations and you can then just iterate through the stack to undo operations.

What is a stack really, working in computers you would have heard the term stack quite often. It  is a common term and normally is used to define a LIFO last in first out queue of objects.  You hear lots of security noise about ”NOP Sleds down the stack!”.

If you want to do a FIFO type queue you can use the queue class. This will perhaps be the most common queue method you might use. But for me, I am going to use a LIFO stack… well because I just love to have a POP at something like this! he he he

I like to think of the LIFO as a in-tray – the paper you just put on the top gets processed first whereas FIFO is like a helpdesk ticketing system – where you process the tickets in succession of when they arrived starting with the first ticket! (Prioritisation and classification not with-standing of course). Would it be great if the Post-Office used LIFO!

On our example all I want to do is to simply display the fullname of the object on the stack, which will be the results from the GCI

So first we need to create our object

$filelist =new-object system.collections.stack

2

Now we have our stack object – we need to know how to populate it with items! Before we do that lets have a quick look at what methods the system.collections.stack class provides us

[system.collections.stack].GetMethods() | fl -Property Name

3

The three main methods for dealing with stack objects in PowerShell and .net are :-

  1. PEEK() – Look at the top item on the stack

  2. PUSH() – put an item on to the stack

  3. POP() – remove the top item from the stack

Yeah, I always have fond memories of spending ages typing in code to get a game working or the likes. Does this mean grumpy admin is both old and grumpy! Who knows!!! Answers below please!!!

So we already decided that we are going to be using the get-childitem in the c:\windows\system32 path! So let do this GCI and pipe each item’s object that is returned from the GCI on to the stack we called $filelist!

GCi |%{$filelist.PUSH($_)}

4

So from the above line, I have now demonstrated had to add items/objects on to the stack! As you see it is using the PUSH() method.

As you know Grumpy admin always likes to confirm his work – especially the first time!  We can do

$filelist

5

And as $filelist is an object itself there are properties and methods we can call on it to help us out. For example we can do a

$filelist.count

6

Ok so what is the big deal? Well we have all the files objects on a stack now and we can process them one at a time in order of LIFO! Like I said, it might be hard to find example where you would use this but better to know and have it in your armoury just in case right?

Now – What does PEEK do? Well it does what it says – it peeks at the object on top of the stack, without removing it from the stack.

$filelist.peek()

7

As this returns the object on top of the stack, we can access element of the this object in the normal way.

$filelist.peek().fullname

8

Excellent, we are getting somewhere – so how do I use the object and remove it off the stack. So that I may process the next object in the stack, easy we can POP() it! I just love that….

So we can do a command that looks something like this

$filelist.pop().fullname

9

Let’s do that again just to prove that it returns the next object in the stack and it did remove the top item. There we have a working LIFO stack.  So this gives you an easy way to iterate through a list of items or objects perhaps with a bit more control than just using the pipeline.

This can be a lot easier to deal with when your scripts and iterations/actions are quite complex. It is a useful trick – you might never need to use a stack but now you can 🙂

0..($filelist.count-1) |%{write-host $filelist.pop().fullname}

10

As you can see from the wonderful prepared screenshot, the first to items we poped off the stack ( zipfldr.dll and xwtpw32.dll) are no longer in the stack.

To finally prove that we emptied the stack and processed all the objects/items let’s do another

$filelist.count

11

So while I can’t find a good example that would be easy to demonstrate without a lot of code and effort this as something useful, it is a great core skill. If you guys have a script that uses a stack somewhere, let me know.

Hazzy