<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: TheInfraDev</title>
    <description>The latest articles on DEV Community by TheInfraDev (@theinfradev).</description>
    <link>https://dev.to/theinfradev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F112183%2F6d08f95d-8d62-4853-8e12-146f142ae9b3.png</url>
      <title>DEV Community: TheInfraDev</title>
      <link>https://dev.to/theinfradev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/theinfradev"/>
    <language>en</language>
    <item>
      <title>Powershell: Build Configuration Objects - part 2 of 3</title>
      <dc:creator>TheInfraDev</dc:creator>
      <pubDate>Sat, 16 Feb 2019 04:38:30 +0000</pubDate>
      <link>https://dev.to/theinfradev/powershell-build-configuration-objects---part-2-of-3-11pn</link>
      <guid>https://dev.to/theinfradev/powershell-build-configuration-objects---part-2-of-3-11pn</guid>
      <description>&lt;h1&gt;&lt;b&gt; PowerShell Functions and Classes Pt 2 - Build Configuration Objects&lt;/b&gt;&lt;/h1&gt;
&lt;p&gt;
Note: This is part two of a three part series on PowerShell Classes and Functions.
&lt;/p&gt;

&lt;p&gt;
In part one we looked at how we can create a class to hold our configuration object. We then created a constructor to create some automation in our config. In the second part I want to look into how we can use methods to generate our objects.

For example, lets take our last example of a TV Gaming PC.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
Class PCSystem
{
        [string]$CPU
        [string]$Mainboard   = 'MSI B450M Mortar Titanium'
        [string]$Case        = 'Thermaltake Level 20 VT Chassis'
        [string]$PowerSupply = 'SeaSonic FocusPlus Gold 650W'
        [string]$RAM         = 'Team Delta RGB - 16 GB DDR3000'
        [string]$Storage     = 'Samsung 970 EVO 500 GB'
        [string]$GPU
}
&lt;/code&gt;&lt;/pre&gt;
We have deliberately left the CPU and GPU options available to be tweaked as these are the main configuration changes we can make to our performance. I would like to be able to configure it with the following options:

&lt;li&gt;1 :  CPU = 'AMD Ryzen 5 2400G' | GPU = 'No GPU'&lt;/li&gt;
&lt;li&gt;2 :  CPU = 'AMD Ryzen 3 2200G' | GPU = 'EVGA - GeForce GTX 2070'&lt;/li&gt;
&lt;li&gt;3 :  CPU = 'AMD Ryzen 5 2400G' | GPU = 'EVGA - GeForce GTX 2070'&lt;/li&gt;
&lt;p&gt;
How do we do this? Well we could just instantiate the object and add these configurations in the body of the script. This is certainly common, but i think it makes the script hard to read. It is always preferable to make the script read like a narrative. Alternatively, we can create a constructor that takes an argument, say an integer like "1", "2" or "3".&lt;/p&gt;
&lt;p&gt;
This seems cleaner to me and allows us to clean up our later code, while also creating discrete configurations that can be later appended or added to easily, because we are housing all our configs in one spot. 
&lt;/p&gt;

&lt;h1&gt;&lt;b&gt;Lets create our class to build specific types of computers. &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt; Good to see you are finally adding a GPU to this crappy build. &lt;/i&gt;&lt;/h3&gt;

&lt;p&gt;In my previous article I took the CPU name as the input to our constructor, this time all we are going to do is take a single integer. (i.e. 1,2 or 3) &lt;/p&gt;
&lt;p&gt;&lt;br&gt;
So lets see how this is done.&lt;/p&gt;



&lt;pre&gt;&lt;code&gt;
Class PCSystem
{
    $CPU; $Mainboard; $Case; $PowerSupply; $RAM; $Storage; $GPU
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt; First you can see we created our class with the declarations of what properties our class is going to house.&lt;/ul&gt;

&lt;pre&gt;&lt;code&gt;
    PCSystem([int32]$Option)
    {
        [string]$this.Mainboard     = 'MSI B450M Mortar Titanium'
        [string]$this.Case          = 'Thermaltake Level 20 VT Chassis'
        [string]$this.PowerSupply   = 'SeaSonic FocusPlus Gold 650W'
        [string]$this.RAM           = 'Team Delta RGB - 16 GB DDR3000'
        [string]$this.Storage       = 'Samsung 970 EVO 500 GB'
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt; Now we create our constructor. You can see we are taking the parameter '$Option' as our input to tell the constructor what to do. Now while we want to be able to change the CPU/GPU the rest don't change so rather than repeatedly declare the rest of the properties for each configuration - we are going to set the other properties now. 


&lt;/ul&gt;

&lt;pre&gt;&lt;code&gt;
        switch($Option)
        {
            1{
                [string]$this.CPU  = 'AMD Ryzen 5 2400G'
                [string]$this.GPU  = ''
             }
            2{
                [string]$this.CPU  = 'AMD Ryzen 3 2400G'
                [string]$this.GPU  = 'EVGA - GeForce GTX 2070'  
             }
            3{
                [string]$this.CPU  = 'AMD Ryzen 5 2400G'
                [string]$this.GPU  = 'EVGA - GeForce GTX 2070'
             }
Default 
         {
                [string]$this.CPU  = 'Invalid configuration'
                [string]$this.GPU  = ''
             }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt; Lastly, we have done the most interesting bit, and using a switch statement we set the CPU/GPU properties based on which option the constructor is provided. (a bad input to $option will return the 'default' of "invalid configuration").&lt;/ul&gt;

&lt;p&gt;And there it is, we now have a way of creating this complex object in our script by simply calling it with an integer. Just to see what that looks like we might as well call option 3:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
&amp;gt;_ [PCSystem]::new(3)

CPU          : AMD Ryzen 5 2400G
Mainboard    : MSI B450M Mortar Titanium
Case         : Thermaltake Level 20 VT Chassis
PowerSupply  : SeaSonic FocusPlus Gold 650W
RAM          : Team Delta RGB - 16 GB DDR3000
Storage      : Samsung 970 EVO 500 GB
GPU          : EVGA - GeForce GTX 2070
&lt;/code&gt;&lt;/pre&gt;


&lt;h1&gt;&lt;b&gt; Can you think of other configurations this could apply too? &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt;Why don’t you, I am tired from reading the millions of words&lt;/i&gt;&lt;/h3&gt;


&lt;p&gt;&lt;br&gt;
This configuration builder approach is a great way of dealing with building PowerShell objects. Importantly it also takes this configuration step out of your main logic, "separating the concern". For many dev's this is a pretty standard approach but for the System Engineer this may be a brand-new way of thinking about things. If you asking yourself, why should I do this, maybe hang in there for the next post when i wrap this up, but just offhand I have found this is great for structuring your scripts into discrete sections, it cleans up your configuration while putting it all in one place which any engineer could find. We have now a clear understanding of what each object needs, because the totality of it is defined at the start of the class and if we want to add a configuration we are using composition to include new configurations in the constructor which will then filter down through the whole script. Just some of the objects for which I have used this configuration class include: Virtual Machines, Network Adapter, and AD User/Computer configurations.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
In the final part of this 3 part series, I will look at how to use this configuration object in a Function providing a full implementation and, you know - actually doing something with this class object that I have spent so long demonstrating.&lt;/p&gt;



&lt;p&gt;&lt;br&gt;
If you can think of another type of configuration you could use this for, leave it in the comments below because I am always looking for new ideas.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Cheers,&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
The Infra Dev&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;i&gt;To get updates on my new articles, follow me on Twitter &lt;a href="https://twitter.com/theinfradev" rel="noopener"&gt;@theinfradev&lt;/a&gt; &lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Photo by Philipp Katzenberger on Unsplash&lt;/p&gt;

</description>
      <category>powershell</category>
      <category>posh</category>
      <category>devops</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Powershell: Keeping it Classy and Functional - Part 1of3</title>
      <dc:creator>TheInfraDev</dc:creator>
      <pubDate>Mon, 21 Jan 2019 14:32:26 +0000</pubDate>
      <link>https://dev.to/theinfradev/powershell-keeping-it-classy-and-functional---part-1of3-3272</link>
      <guid>https://dev.to/theinfradev/powershell-keeping-it-classy-and-functional---part-1of3-3272</guid>
      <description>&lt;h1&gt;&lt;b&gt; Let’s keep it Classy &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt;"48 hrs to... Oh, Shutup!"&lt;/i&gt;&lt;/h3&gt;

&lt;p&gt;In PowerShell 5.0 Microsoft introduced proper Classes giving us a very powerful capability that to the average system admin probably went unused.&lt;br&gt;
In fact, the greatness of classes is in how we can combine their data and functional capabilities with our standard PowerShell functions to create much cleaner code, with well-defined configurations and output. &lt;/p&gt;



&lt;blockquote&gt;
If you have never created a Class in PowerShell or... ever, I suggest trying it out seperately. I won’t go into all the specifics as this is less about how to create a class, and more about what we can do with them, once we are comfortable. I suggest this guy’s blog as a good primer, or at least to bookmark for later.&lt;p&gt;
&lt;a href="https://xainey.github.io/2016/powershell-classes-and-concepts/"&gt;Powershell Classes and Concepts &lt;/a&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;
In this first post I will create our first data classes by emulating a physical process. In this case we are going to build a configuration for a little Gaming PC to hook up to the TV. The main build is not particularly powerful using only an AMD integrated GPU however it should be able to get decent performance for couch games such as Rocket League on medium settings at 1080p. Because of our use of classes we can later extend this configuration to make it (our PC configuration) more powerful.
&lt;/p&gt;



&lt;h1&gt;&lt;b&gt;Let’s create our first class to store our configuration&lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt; Can’t we just buy an Xbox or PS4? Seems easier. &lt;/i&gt;&lt;/h3&gt;

&lt;p&gt;Ok, so let’s define the parts we want in our little TV gaming box. We will need the following as our base config:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Mainboard: MSI B450M Mortar Titanium ($105)
&lt;/li&gt;
&lt;li&gt; RAM: Team Delta RGB - 16 GB DDR3000 ($135)
&lt;/li&gt;
&lt;li&gt; Storage: Samsung 970 EVO 500 GB ($128)
&lt;/li&gt;
&lt;li&gt; Case: Thermaltake Level 20 VT Chassis ($105)
&lt;/li&gt;
&lt;li&gt; PSU: SeaSonic FocusPlus Gold 650W ($90)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are going to standardize around this platform allowing use to make slight changes to CPU, GPU if we want to beef up the processing power.&lt;/p&gt;



&lt;blockquote&gt;
I don’t particularly want to go into the reasons why I have chosen AMD over INTEL or 16GB over 8GB but suffice to say If you build this computer it should all work.
&lt;/blockquote&gt;
&lt;p&gt;
So how do we do this as a class in Powershell. Well the first thing to know is PowerShell makes this super easy and we can essentially just list our items and PowerShell will worry about how to construct the object. This is the simplest way we can create our configuration. &lt;/p&gt;

&lt;pre&gt;
Class PCSystem
{
   [string]$CPU
   [string]$Mainboard   = 'MSI B450M Mortar Titanium'
   [string]$Case        = 'Thermaltake Level 20 VT Chassis'
   [string]$PowerSupply = 'SeaSonic FocusPlus Gold 650W'
   [string]$RAM         = 'Team Delta RGB - 16 GB DDR3000'
   [string]$Storage     = 'Samsung 970 EVO 500 GB'
   [string]$GPU
}
&lt;/pre&gt;
&lt;p&gt;
In the above example we can see that we have declared the variable type and then the variable name. For some that is all we have declared, however for others we have declared a default value. This means when this object is instantiated later, we already have these values keyed in. Because I want to keep our options open I have kept our CPU/GPU options as undeclared values.
&lt;/p&gt;

&lt;p&gt;
Now we have this base class we can instantiate it.
&lt;/p&gt;
&lt;pre&gt;
$TVPC =  [PCSystem]::new()
&lt;/pre&gt;
Now I am going to add a little gem of a Processer, an APU (CPU + GPU) from AMD that will give our box some great processing capacity and due to the integrated GPU gives us a low end gaming system for very little money. (USD$158) 
&lt;pre&gt;
$TVPC.CPU = 'AMD Ryzen 5 2400G'
&lt;/pre&gt;
Now our CPU is added, we have our base system. If we print this to console we get:  
&lt;pre&gt;
CPU         : AMD Ryzen 5 2400G
Mainboard   : MSI B450M Mortar Titanium
Case        : Thermaltake Level 20 VT Chassis
PowerSupply : SeaSonic FocusPlus Gold 650W 
RAM         : Team Delta RGB - 16 GB DDR3000 
Storage     : Samsung 970 EVO 500 GB 
GPU         :
&lt;/pre&gt;
Perfect, now we have a simple object which describes our configuration which we can pass around between functions as we like. Later if we decide we need extra storage or any other attributes we can just add them to our class, and they will automatically be instantiated, so we have a very extensible config.



&lt;h1&gt;&lt;b&gt; Let’s make our own Class constructors! &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt;I thought we were going to let PowerShell do that for us? &lt;/i&gt;&lt;/h3&gt;

&lt;p&gt;
You are probably thinking, that’s kind of cool, Job done! Well, yes it is. But we can do it better. &lt;/p&gt;

&lt;p&gt;The great thing about classes is that unlike say a hash table - we can add behaviour(methods) to a class via a constructor.&lt;/p&gt;


&lt;blockquote&gt; Quick primer: A constructor tells the language engine how to build the Class object.
&lt;/blockquote&gt;
&lt;p&gt;
We can give the class logic so that if the class is not provided input on creation - it will be the default class, or alternatively create a more custom version of the class if provided a configuration option. 
&lt;/p&gt;

&lt;p&gt;Let’s have a look at what the constructor looks like. (I am going to compress the variable declarations at the top because it looks neater).
&lt;/p&gt;
&lt;pre&gt;
Class PCSystem
{
   $CPU; $Mainboard; $Case; $PowerSupply; $RAM; $Storage; $GPU
   PCSystem([string]$CPU)
   {
       [string]$this.CPU           = $CPU 
       [string]$this.Mainboard     = 'MSI B450M Mortar Titanium' 
       [string]$this.Case          = 'Thermaltake Level 20 VT Chassis'
       [string]$this.PowerSupply   = 'SeaSonic FocusPlus Gold 650W'
       [string]$this.RAM           = 'Team Delta RGB - 16 GB DDR3000'
       [string]$this.Storage       = 'Samsung 970 EVO 500 GB'
    }
}
&lt;/pre&gt;
So what is the difference here? Well, now we have made a constructor method that has the same name as the class (this is important). PowerShell will now treat this method as its constructor and knows that when an instance of this object is created it must follow the rules provided in this method:
&lt;ul&gt;
&lt;li&gt; First, instead of declaring the defaults when we create the variables we are doing it in the constructor, this allows us to make this decision depending on the constructor rather than just by default.
&lt;/li&gt;
&lt;li&gt;Second, we are requiring that on creation, a value be given for the CPU. This way we are requiring the decision early, but ultimately saying - without this we cannot proceed.
&lt;/li&gt;
&lt;li&gt;Third, in this particular case you will note the GPU is ignored. This particular configuration doesn’t care about GPU so we don’t need to specify it. However the GPU attribute will still be created because it is referenced at the top of the class.



&lt;blockquote&gt;
Note: Like many other languages when you refer to a variable of the class, (like CPU for example) we need to call it "$This.CPU". The ‘this’ part of the parameter is the way .NET handles talking about the actual instances of the object rather than the abstract class we are working from here. In our example earlier where we created the $TVPC object, "$this.CPU" is an analogy for writing "$TVPC.CPU".
&lt;/blockquote&gt;

&lt;p&gt;
Due to this constructor, we can now define our CPU on creating the variable, shrinking our code from 2 lines to 1 and making sure the object is at a minimum spec from the beginning.&lt;/p&gt;
&lt;p&gt;We can now create it, like so: &lt;/p&gt;



&lt;pre&gt;
$TVPC =  [PCSystem]::new('AMD Ryzen 5 2400G')
&lt;/pre&gt;



&lt;h1&gt;&lt;b&gt; What’s Next? &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt;Wait, you were saying stuff? Sorry I was busy downloading Red Dead Redemption 2 on my PS4 that I just bought.&lt;/i&gt;&lt;/h3&gt;

&lt;p&gt;I hope that while I am using a real world physical object here, you could see how this could be used to describe configuration of any complex function. And by using a simple constructor we could create minor variations of our configuration which we can call depending on circumstance. Say for example, you want to create a fleet of VMs and you have 2 different memory configurations. By having these constructors you can save a lot of time and duplicated code by just changing the input to the constructor from one config to the other, and PowerShell will take care of the rest.&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;OK, that is it for this post, In my next post I will look at how we can use constructors further as well as general class methods to build a script into a more complex yet maintainable bit of software.&lt;br&gt;
&lt;br&gt;
Cheers,&lt;/p&gt;
&lt;p&gt; &lt;br&gt;
TheInfraDev&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
&lt;i&gt;To get updates on my new articles, follow me on Twitter &lt;a href="https://twitter.com/theinfradev" rel="noopener"&gt;@theinfradev&lt;/a&gt; &lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Photo by Heng Films on Unsplash&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>powershell</category>
      <category>posh</category>
      <category>devops</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>How To Not Write A Blog Post</title>
      <dc:creator>TheInfraDev</dc:creator>
      <pubDate>Sun, 23 Dec 2018 10:48:27 +0000</pubDate>
      <link>https://dev.to/theinfradev/how-to-not-write-a-blog-post-59bk</link>
      <guid>https://dev.to/theinfradev/how-to-not-write-a-blog-post-59bk</guid>
      <description>&lt;h1&gt;&lt;b&gt;Thoughts on writing a blog&lt;/b&gt;&lt;/h1&gt;
&lt;p&gt;
My phone buzzes, it is an alarm that goes off every 2 weeks on a Friday.&lt;/p&gt;

&lt;blockquote&gt;
"You have 48 hrs to write a blog post."
&lt;/blockquote&gt;
&lt;p&gt;
It is meant to be a motivating reminder, yet it is received more like a kidnapper’s ransom demand. A forceful reminder that it is time to get two weeks of random thoughts compressed onto the page, ready for review by my beautiful wife (to make sure I didn’t make any horrendous errors, like using there instead of their, or trying to figure out if it is accept or except). Ready for publishing to the world, ready for the glare of the dazzling lights of my own hubris, by next Wednesday* at the latest.
&lt;/p&gt;

&lt;p&gt;I open my standard blog template, with markdown ready to go.&lt;/p&gt;
&lt;p&gt;
...The cursor blinks forlornly. A call to action if I ever did see one.
&lt;/p&gt;

&lt;p&gt;
"You brought this on yourself", I mutter under my breath.
&lt;/p&gt;


&lt;h1&gt;&lt;b&gt;I have a headline idea but there are all these stupid questions in my way...&lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;&lt;i&gt;I thought this was a blog about writing shitty scripts? I think you have a bad case of "Gone Meta"&lt;/i&gt;&lt;/h3&gt;

&lt;p&gt; It goes something like this.&lt;/p&gt;

&lt;p&gt; For my next blog I have a grand idea, how to use classes in PowerShell to aid the building of a great script. But I don’t like extremely long blog posts. I want to keep it at about 600-1000 words. And with that in mind, how do you condense everything that is great about encapsulation and composition and polymorphism to that size - to an audience that may or may not know what those things are? How do you NOT start at the beginning? I don’t want to start at the beginning, better developers than I have done that, and I should only refer to their esteemed work rather than stumble over it badly.&lt;/p&gt;

&lt;p&gt;
But in the meantime I do have something important to say about classes, about POPO’s (Plain Old PowerShell Objects. Get it? Well if you aren't a dev - probably not. haha... ahem.). There’s the stuff about using classes to hide your implementation of methods and lastly how you can then use those building blocks to make really cool functions that work 95% of the time, every time.
Shit, how do you explain interfaces...?&lt;/p&gt;

&lt;p&gt;

I am only like 5 blog posts in, the first couple were more "about the mission" a.k.a. why I want to do this. Whereas this stuff, this is the good stuff. This is what people actually want to learn and this is what I have to give. And yet, can the 6th post instead be a meta description of blogging? Does everyone feel like this? Do all the people who - with good intention - set out to write a little about what they know and love, stumble upon this road where the possibilities are infinite, the likelihood of sounding like a gibbering mess is high and... really, please forgive me, I meant well... Oh dear.
&lt;/p&gt;


&lt;h1&gt;&lt;b&gt; Let’s take a step back&lt;/b&gt;&lt;/h1&gt;
&lt;h3&gt;&lt;i&gt;For that, do you not have to take a step forward first?&lt;/i&gt;&lt;/h3&gt;
&lt;p&gt;
The cursor blinks forlornly. I look up, I have an idea. I’ll make it a three-part series. Yeah, that’s it. The first part is about creating simple classes to pass around data, then the methods, finally I’ll wrap it all in a nice function. Brilliant, pat on the back. Now, what will I use as my example?
...
ah nuts...
The cursor blinks forlornly. 
How does it do that? How can a cursor be forlorn? &lt;/p&gt;

&lt;p&gt;Bastard.
&lt;/p&gt;


&lt;h1&gt;&lt;b&gt; Let me leave you with something useful!&lt;/b&gt;&lt;/h1&gt;
&lt;h3&gt;&lt;i&gt;It’s really the least you can do after this rambling mess&lt;/i&gt;&lt;/h3&gt;
&lt;p&gt;
As the Holiday season is basically now and (you might have guessed) I have postponed the first of the all! Important! Three! Part! Series! till January, let me leave you with a gift. Something that I have can write by heart now. How to write a simple but effective logging function in PowerShell. This will always be a good idea to implement near the start of your fun little scripts, I promise.
&lt;/p&gt;

&lt;p&gt;
First declare an environmental variable at the start of your script with the log location like so:
&lt;/p&gt;
&lt;blockquote&gt;
$env:Logfile = "$AppPath\logs\$(get-date -format 'dd-MM-yyyy') - Application log"&lt;p&gt; #The get-date temporary variable here will make sure to add the date to the file name so you don’t end up with one giant 100MB log.
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;
Then we will write the function itself. &lt;/p&gt;

&lt;blockquote&gt;
Function Write-Log &lt;p&gt;
{&lt;/p&gt;


&lt;ul&gt;
    Param([string]$LogEntry,[string]$Logpath,[string]$Color) 
&lt;ul&gt;# We define our inputs #&lt;/ul&gt;
&lt;p&gt;
    $DateTime = Get-Date -format 'dd/MM/yyyy HH:mm:ss' ; if ($Color -notmatch "\w"){$Color = 'Gray'} &lt;/p&gt;

&lt;ul&gt;# Then we get the current date/time, and make sure we have a color choice (Gray as a default) #&lt;/ul&gt;
&lt;p&gt;
    $log = "$env:Computername : $DateTime : $LogEntry"  &lt;/p&gt;

&lt;ul&gt;# Now we create our full log entry # &lt;/ul&gt;
&lt;p&gt;
    Out-File -InputObject $log -FilePath $LogPath -Append -NoClobber  &lt;/p&gt;

&lt;ul&gt;# This is how we write it to a file #&lt;/ul&gt;
&lt;p&gt;
    Write-host $Log -ForegroundColor $Color  &lt;/p&gt;

&lt;ul&gt;Finally we write it to the console so we can debug as we write the app.&lt;/ul&gt;
&lt;/ul&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;br&gt;
&lt;/blockquote&gt;
&lt;br&gt;
So what have we created? Well if we run the function like so:
&lt;blockquote&gt;
&lt;br&gt;
Write-Log -LogEntry "I wrote a nice log file" -Logpath $env:Logfile -color 'blue'&lt;br&gt;
&lt;/blockquote&gt;
&lt;br&gt;
We will likely now have a new log at the desired location and a nice message on the console in blue like this:
&lt;blockquote&gt;
&lt;br&gt;
Computer01 : 19/12/2018 06:48:02 : I wrote a nice log file &lt;br&gt;
&lt;/blockquote&gt;
&lt;br&gt;
I hope this helps, and if you use it - that you enjoy having nicely formatted logs! Have a Merry Christmas and/or Happy Holidays.&lt;br&gt;
See you next year for my amazing three-part series on PowerShell Classes and Functions and why they are so awesome together...

&lt;p&gt;
The InfraDev
&lt;/p&gt;

&lt;p&gt;&lt;i&gt;To get updates on my new articles, follow me on Twitter &lt;a href="https://twitter.com/theinfradev" rel="noopener"&gt;@theinfradev&lt;/a&gt; &lt;/i&gt;&lt;/p&gt;

</description>
      <category>powershell</category>
      <category>posh</category>
      <category>devops</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>How to write great PowerShell functions!</title>
      <dc:creator>TheInfraDev</dc:creator>
      <pubDate>Wed, 12 Dec 2018 12:08:32 +0000</pubDate>
      <link>https://dev.to/theinfradev/how-to-write-great-powershell-functions-110g</link>
      <guid>https://dev.to/theinfradev/how-to-write-great-powershell-functions-110g</guid>
      <description>&lt;p&gt;So far I have talked about the &lt;a href="https://theinfradev.pro/01-whatisaninfradev.html" rel="noopener noreferrer"&gt;InfraDev's mission&lt;/a&gt;, and what languages and tools you might use, so now I think it is time to look at some concrete examples of how people commonly write PowerShell functions, and then how to improve them to be more stable, readable, and maintainable while living up to the standards of the Powershell community. One of the key skills in an InfraDev’s life, is the ability to write functions. Functions allow us to: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Re-use and share code by making standard implementations.
&lt;/li&gt;
&lt;li&gt; Encapsulate and therefore hide our implementation (not for security, but readability).
&lt;/li&gt;
&lt;li&gt; Make clear Entry and Exit points to different behaviours.
&lt;/li&gt;
&lt;li&gt; Change a swiss army knife into a hammer
&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;&lt;b&gt;Let's start with a common way people write functions &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;I have heard it is good to start at the beginning&lt;/h3&gt;

&lt;p&gt;I have chosen a rather simple and common form of a function. We are going to provide config data (Computername) and then return services data narrowed down to just the Name and Status properties.
&lt;/p&gt;

&lt;blockquote&gt;
$GLOBAL:ComputerName = 'Server01' &lt;p&gt;
Function Get-ServiceData &lt;/p&gt;


&lt;ul&gt;{&lt;ul&gt;Get-Service -ComputerName $ComputerName | Select-Object -Properties Name,Status&lt;/ul&gt;}&lt;/ul&gt;

&lt;p&gt;Get-ServiceData&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;

&lt;p&gt; So what are the key features of this Function?
    &lt;/p&gt;
&lt;li&gt; $Computername is out of scope and so is declared as a Global variable. This is a very fragile and just all-round bad practice. Bad Coder! Bad!
    &lt;/li&gt;
&lt;li&gt; The data we are returning is instead printed to the console (sometimes called Stdout). This is bad for the purposes of extending the use of the function. In fact our function is not returning any data.
    &lt;/li&gt;
&lt;li&gt; If get-service fails for any reason - we get an error, but nothing returns to our console (std out). Worse, because we were using write-host, we have no way of checking what happened! This is not good if we ever want to use this as a chain of functions or check programmatically whether the function succeeded or failed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt; 
Things you might not know: "What is StdIn / StdOut?" (Linux information project definition)
Standard output, sometimes abbreviated stdout, refers to the standardized streams of data that are produced by command line programs (i.e., all-text mode programs) in Linux and other Unix-like operating systems. These standardized streams, which consist of plain text, make it very easy for the output from such programs to be sent to a devices (e.g., display monitors or printers) or to be further processed by other programs." &lt;a href="http://www.linfo.org/standard_output.html" rel="noopener noreferrer"&gt;more...&lt;/a&gt;


&lt;/blockquote&gt; 



&lt;h1&gt;&lt;b&gt;Let's make this function better&lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt;It's time to get technical?&lt;/h3&gt;


&lt;blockquote&gt;
$ComputerName = 'Server01'&lt;p&gt;
Function Get-ServiceData ($ComputerName) &lt;/p&gt;


&lt;ul&gt;{&lt;ul&gt;$Service = Get-Service -ComputerName $Computername
    &lt;p&gt;Return $Service&lt;/p&gt;
&lt;/ul&gt;}&lt;/ul&gt;
$RemoteServices = Get-ServiceData -ComputerName $ComputerName
&lt;/blockquote&gt;

&lt;ul&gt;
        &lt;li&gt; $ComputerName is in scope as we are passing it into this function as a parameter. This not only stops the global variable issue, but also means that other people using this function don’t have to magically know that they must declare this variable first.
        &lt;/li&gt;
&lt;li&gt; The Get-Service data is now added to a variable and is properly returned as output of this function. This provides for re-use of the output.
    &lt;/li&gt;
&lt;li&gt; Further, we are also capturing the Return of our function in the $RemoteServices variable which we can then either evaluate and use further or just write to the console.
        &lt;/li&gt;
&lt;li&gt; We haven’t fixed all the flaws, because If Get-Service fails for any reason - we still return nothing and anything relying on the return of this function is out of luck.
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Is this best implementation? No, this is still a fragile implementation, but we have resolved some issues around returning the data and passing in data&lt;/p&gt;



&lt;h1&gt;&lt;b&gt;Let's go all the way to stable, maintainable code&lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt; This won’t be javascript then j/k ;)&lt;/h3&gt;


&lt;blockquote&gt;
$ComputerName = 'Server01'&lt;p&gt;
$RemoteServices = "No data"&lt;/p&gt;
&lt;p&gt;
Function Get-ServiceData&lt;/p&gt;

&lt;ul&gt;{
&lt;ul&gt;[CmdletBinding(SupportsShouldProcess)] Param([string]$ComputerName)

&lt;p&gt;$Service = "Unable to retrieve data"&lt;/p&gt;
&lt;p&gt;
$Service = Get-Service -ComputerName $Computername &lt;/p&gt;
&lt;p&gt;
Return $Service &lt;/p&gt;

&lt;/ul&gt;

&lt;p&gt;}&lt;br&gt;
&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;
$RemoteServices = Get-ServiceData -ComputerName $ComputerName
&lt;/p&gt;


&lt;/blockquote&gt;


&lt;ul&gt;
    &lt;li&gt; $Computername is in scope as we are passing it as a parameter into this function. 


&lt;/li&gt;

&lt;li&gt; We have also given ourselves extra PowerShell cmdlts such as -whatif and -confirm through using the &lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_cmdletbindingattribute?view=powershell-6" rel="noopener noreferrer"&gt;[CmdletBinding(SupportsShouldProcess)]&lt;/a&gt; syntax. Rather than the () we used before, now we are using best practice and changing our function into a proper 1st class PowerShell cmdlet. 




&lt;/li&gt;

&lt;li&gt; We declared that the input data is a string. This provides a type check to make sure we are giving the right type of variable and if not, it will cast it as a string anyway. While the function may fail to provide us the data we want, it will provide data.
    &lt;/li&gt;

&lt;li&gt; Get-Service data is added to a variable that is already initialised. If Get-Service fails to retrieve any data, our original data will be kept. If it succeeds our data will be overwritten by the object returned.
    &lt;/li&gt;

&lt;li&gt; If Get-Service fails for any reason - we get an error message.
    &lt;/li&gt;

&lt;li&gt; Finally $RemoteServices is also initialised as a string 'No data' which is no longer a null or undefined variable. This also means if Get-Service fails we will then have our error declared and ready to be returned. Therefore, we know that if we get this back as the return, the Get-Service cmdlet failed.
&lt;/li&gt;

&lt;/ul&gt;



&lt;h1&gt;&lt;b&gt; Let’s wrap this up &lt;/b&gt;&lt;/h1&gt;

&lt;h3&gt; Finally, some good news! &lt;/h3&gt;

&lt;p&gt;
Each of these implementations would have worked and without rigorous testing we might have even considered them working functions. Up until they didn't, and the wrong data was fed in, or the wrong data came back. What I have tried to show here is how we can use a couple of key principles to provide stability to our functions. &lt;/p&gt;

&lt;p&gt;
Yes, the function is longer, and yes we have also nailed down a few concrete details such as variable types which is perhaps not in the dynamic nature of PowerShell - but by doing this we have made this function safer in the overall context and we have also made sure our hypothetical tool wouldn't error out due to nulls or failures in the implementation itself. Instead when we get bad data, we can recognise and refactor to compensate. &lt;/p&gt;

&lt;p&gt; 
In further posts I will go into how to apply the same techniques in different styles of functions and start working with classes and objects. For now I hope the takeaway is that with a few changes to writing style we can create more stable code, that still provides the same data in an easy to read format.
&lt;/p&gt;


&lt;h4&gt;
To get updates on my new articles, follow me on Twitter &lt;a href="https://twitter.com/theinfradev" rel="noopener noreferrer"&gt;@theinfradev&lt;/a&gt; &lt;/h4&gt;

</description>
      <category>powershell</category>
      <category>posh</category>
      <category>devops</category>
      <category>sysadmin</category>
    </item>
  </channel>
</rss>
