Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

A Classy PowerShell Christmas

Posted on December 19, 2016December 19, 2016

Well it's that time of year again to have some holiday fun with PowerShell. This year I thought I'd give you a classy present. Or more accurately, a class-based PowerShell toy. Classes were introduced in PowerShell 5.0, primarily with DSC resources in mind, but you can use classes for all sorts of things.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

In simple terms, a class is a definition of some type of object. In PowerShell you can now define a class in a simple PowerShell script file. The basic outline looks like this:

Class theClassName {

#define properties

#define methods (optional)

#define constructors (optional

}

The constructor is a block of code that can create an instance of your class or object. It is completely optional as you can create an instance of your class using either of these statements:

[theClassname]::New()
New-Object theClassname

But perhaps I  should just let you unwrap my class present.

#requires -version 5.0

<#
ChristmasClass.ps1
A demo PowerShell class
#>

Enum ListStatus {
    Naughty
    Nice
}

Enum Present {
    Socks
    Barbie
    Elmo
    XBox
    GIJoe
    Underwear
    HotWheels
    EZBakeOven
    Walkman
    PS4
    Pajamas
    Stratego
    GinzuKnives
    ChiaPet
    Tie
    Mittens
    Bicycle
    Pony
    Battleship
    CabbagePatchDoll
}

Class myChristmas {

#class properties
[string]$Greeting
[string]$ElfName
[ListStatus]$List
[int]$DaysRemaining
[string]$CountDown

#class methods
[string]GetGreeting() {
  $texts = @("Merry Christmas","Happy Holidays","HO-HO-HO","Vrolijk Kerstfeest",
  "Joyeux Noël","Frohe Weihnachten","Hyvää Joulua","Glædelig Jul","Kala Christouyenna",
  "Mele Kalikimaka","Buon Natale","Merry Xmas","Merry Christmas & A Happy New Year",
  "Meri Kuri","God Jul","Nollaig Chridheil","Feliz Navidad",
  "Schöni Wiehnachte","Mutlu Noeller","Nadolig Llawen","toDwI'ma' qoS yItIvqu'"
   )
  $text = $texts | Get-Random
  return $text
}

[string]GetElfName() {

    $first = "Toby","Bernard","Princess","Harvey","Chuck","Doris","Elsa",
    "Snookums","Honey","Norm","Coco","Sven","Inga","Boris",
    "Benedict","Sunshine","Kiki","Nutmeg","Humperdink","Jack",
    "Bertha","Matilda","Clarice","Dwight","Hermey","Rupert","Lady",
    "Izzy"

    $mod = "Ginger","Glitter","Frosty","Sugar","Sour","Pepper",
    "Minty","Crazy","Spicy","Pickle","Twinkle","Sparkle","Disco","Red",
    "Green","Little","Big","Tiny","Glow","Shimmer","Dazzle","Winter","Jingle",
    "Puffy","Fluffy","Saucy","Crinkle"
    
    $last = "pants","toes","bottom","beard","nose","puss","lips",
    "ears","socks","stockings","belly","cheeks","bells","chin",
    "mctush","sticks","fish","whisker","boots","slippers","knicker",
    "knocker"

    $name = "{0} {1}{2}" -f (Get-Random $first),(Get-Random $mod),(Get-Random $last)
    return $name
}

[void]Refresh() {
 #calculate christmas for the current year that should be culture aware
 $Christmas = [datetime]::new( (Get-Date).Year,12,25)
 $span = $Christmas - (Get-Date)
 $this.DaysRemaining = $span.totalDays
 #strip off milliseconds
 $timestring = $span.ToString()
 $this.CountDown = $timestring.Substring(0,$timestring.LastIndexOf("."))
 
 $this.Greeting = $this.GetGreeting()
}

#overloaded method
[Present]GetPresent() {
  $presents = [enum]::GetNames([present]) | Get-Random
  return $presents
}

[Present[]]GetPresent([int]$Count) {
  $presents = [enum]::GetNames([present]) | Get-Random -count $Count
  return $presents
}

[void]Play() {
  #The first number is the reciprocal of the duration and the rest is the 
#note and octave (which we use for getting the frequency).  
#For example, 4A4 is a quarter A note

#first verse only
$notes =  write 4A4 4A4 2A4        4A4 4A4 2A4        4A4 4C4 4F3 8G3             1A4 `
  4Bb4 4Bb4 4Bb4 8Bb4     4Bb4 4A4 4A4 8A4 8A4    4A4 4G3 4G3 4A4    2G3 2C4 `
  4A4 4A4 2A4       4A4 4A4 2A4    4A4 4C4 4F3 4G3     1A4        4Bb4 4Bb4 4Bb4 4Bb4 `
  4Bb4 4A4 4A4 8A4 8A4    4C4 4C4 4Bb4 4G3     1F3  

function Play([int] $freq, [int] $duration)
{
  [console]::Beep($freq, $duration);
}

 
#
# Note is given by fn=f0 * (a)^n
# a is the twelth root of 2
# n is the number of half steps from f0, positive or negative.
# f0 used here is A4 at 440 Hz
#
$f0 = 440;
$a = [math]::pow(2,(1/12)); # Twelth root of 2
function GetNoteFreq([string]$note)
{
  # n is the number of half steps from the fixed note.
  $note -match '([A-G#]{1,2})(\d+)' | out-null
  $octave = ([int] $matches[2]) - 4;
  $n = $octave * 12 + ( GetHalfStepsFromA $matches[1] );
  $freq = $f0 * [math]::Pow($a, $n);

  return $freq;
}

 
function GetHalfStepsFromA([string] $note)
{
  switch($note)
  {
    'A'  { 0 }
    'A#' { 1 }
    'Bb' { 1 }
    'B'  { 2 }
    'C'  { 3 }
    'C#' { 4 }
    'Db' { 4 }
    'D'  { 5 }
    'D#' { 6 }
    'Eb' { 6 }
    'E'  { 7 }
    'F'  { 8 }
    'F#' { 9 }
    'Gb' { 9 }
    'G'  { 10 }
    'G#' { 11 }
    'Ab' { 11 }
  }
}


$StandardDuration = 1000;
foreach($note in $notes)
{

  $note -match '(\d)(.+)' | out-null
  $duration = $StandardDuration / ([int] $matches[1]);
  $playNote = $matches[2];
  $freq = GetNoteFreq $playNote;

  #write-host $playNote $freq $duration;
 Play $freq $duration
  start-sleep -milli 50
}

}

[void]Show() {
  cls

$Msg1 =
@"
.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:.
.     *                                       .
.    /.\        Merry Christmas               .
.   /..'\            from all of us           .
.   /'.'\                in PowerShell        .
.  /.''.'\                                    .
.  /.'.'.\                                    .
. /'.''.'.\                                   .
. ^^^[_]^^^                                   .
.                                             .
.                                             .
.                                          .
.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:.
"@


$Msg2 =
@"
                    _...
              o_.-"`    `\
       .--.  _ `'-._.-'""-;     _
     .'    \`_\_  {_.-a"a-}  _ / \
   _/     .-'  '. {c-._o_.){\|`  |
  (@`-._ /       \{    ^  } \\ _/
   `~\  '-._      /'.     }  \}  .-.
     |>:<   '-.__/   '._,} \_/  / ())  
     |     >:<   `'---. ____'-.|(`"`
     \            >:<  \\_\\_\ | ;
      \                 \\-{}-\/  \
       \                 '._\\'   /)
        '.                       /(
          `-._ _____ _ _____ __.'\ \
            / \     / \     / \   \ \ 
         _.'/^\'._.'/^\'._.'/^\'.__) \
     ,=='  `---`   '---'   '---'      )
     `"""""""""""""""""""""""""""""""`
"@

$msg3 = 
@"
               ___
             /`   `'.
            /   _..---;
            |  /__..._/  .--.-.
            |.'  e e | ___\_|/____
           (_)'--.o.--|    | |    |
          .-( `-' = `-|____| |____|
         /  (         |____   ____|
         |   (        |_   | |  __|
         |    '-.--';/'/__ | | (  `|
         |      '.   \    )"";--`\ /
         \        ;   |--'    `;.-'
         |`-.__ ..-'--'`;..--'`
"@

$msg4 = 
@"
           *             ,
                       _/^\_
                      <     >
     *                 /.-.\         *
              *        `/&\`                   *
                      ,@.*;@,
                     /_o.I %_\    *
        *           (`'--:o(_@;
                   /`;--.,__ `')             *
                  ;@`o % O,*`'`&\ 
            *    (`'--)_@ ;o %'()\      *
                 /`;--._`''--._O'@;
                /&*,()~o`;-.,_ `""`)
     *          /`,@ ;+& () o*`;-';\
               (`""--.,_0 +% @' &()\
               /-.,_    ``''--....-'`)  *
          *    /@%;o`:;'--,.__   __.'\
              ;*,&(); @ % &^;~`"`o;@();         *
              /(); o^~; & ().o@*&`;&%O\
              `"="==""==,,,.,="=="==="`
           __.----.(\-''#####---...___...-----._
         '`         \)_`"""""`
                 .--' ')
               o(  )_-\
                 `"""` `
 
"@

$msg5 =
@"
                        .--------.
   *               .    |________|        .          *
                        |      __|/\
             *        .-'======\_\o/.
                     /___________<>__\
               ||||||  /  (o) (o)  \
               |||||| |   _  O  _   |          .
     .         |||||| |  (_)   (_)  |
               ||||||  \   '---'   /    *
               \====/   [~~~~~~~~~]
                \\//  _/~||~`|~~~~~\_
                _||-'`/  ||  |      \`'-._       *
        *    .-` )|  ;   ||  |)      ;    '. 
            /    `--.|   ||  |       |      `\
           |         \   |||||)      |-,      \         .
            \       .;       _       ; |_,    |
             `'''||` ,\     (_)     /,    `.__/
                 ||.`  '.         .'  `.             *
      *          ||       ` ' ' `       \
                 ||                      ;
   .          *  ||                      |    .
                 ||                      |              *
                 ||                      |
 .__.-""-.__.-"""||                      ;.-"""-.__.-""-.__.
                 ||                     /
                 ||'.                 .'
                 ||  '-._  _ _  _ _.-'
                `""`       
"@
$msg6 =
@"
                                  _
                               .-(_)
                              / _/
                           .-'   \
                          /       '.
                        ,-~--~-~-~-~-,
                       {__.._...__..._}             ,888,
       ,888,          /\##"  6  6  "##/\          ,88' `88,
     ,88' '88,__     |(\`    (__)    `/)|     __,88'     `88
    ,88'   .8(_ \_____\_    '----'    _/_____/ _)8.       8'
    88    (___)\ \      '-.__    __.-'      / /(___)
    88    (___)88 |          '--'          | 88(___)
    8'      (__)88,___/                \___,88(__)
              __`88,_/__________________\_,88`__
             /    `88,       |88|       ,88'    \
            /        `88,    |88|    ,88'        \
           /____________`88,_\88/_,88`____________\
          /88888888888888888;8888;88888888888888888\
         /^^^^^^^^^^^^^^^^^^`/88\\^^^^^^^^^^^^^^^^^^\
        /                    |88| \============,     \
       /_  __  __  __   _ __ |88|_|^  MERRY    | _ ___\
       |;:.                  |88| | CHRISTMAS! |      |
       |;;:.                 |88| '============'      |
       |;;:.                 |88|                     |
       |::.                  |88|                     |
       |;;:'                 |88|                     |
       |:;,                  |88|                     |
       '---------------------""""---------------------'
"@

$i = Get-Random -Minimum 1 -Maximum 6

$selected = ($msg1,$msg2,$msg3,$msg4,$msg5,$msg6 | Get-Random)
If([bool]!($i%2)) {
	Write-Host -ForegroundColor Green -Object $selected
        
	} else {
	Write-Host -ForegroundColor Red -Object $selected
	}


}

#class constructor
myChristmas() {
 $this.ElfName = $this.GetElfName()

 if ( (Get-Date).Second%2) {
    $this.List = [ListStatus]::Naughty
 }
 else {
    $this.List = [ListStatus]::Nice
 }
 
 #set the rest of the properties by invoking the defined
 #Refresh() method

 $this.Refresh()
}

}

[myChristmas]::new()

You will need PowerShell 5.0 or later to run this file.  The script defines the class and then creates an instance of it so I'll run the script and save the results to a variable.

image

The properties are defined in the class. When I invoke the New() method to create an instance of the object, the code in the constructor session is executed. The $this object will refer to the new instance. In my case I am invoking an internal method called GetElfName() to set the ElfName property.  If you look at that method you'll see that it is prefaced with an object time (string). When using a method in a PowerShell class you must specify what type of object it will return, or use [void] to return nothing. Also note that if your method writes an object to the pipeline you must use the return keyword.

The List property is set from an enumeration. This is a way of creating a pre-determined array of possible values. In my case, Naughty or Nice, which is more or less randomly assigned.

The remaining properties are set by invoking the internal Refresh() method which calculates how many days are left until Christmas.  If you pipe the object to Get-Member you will see how the object matches up to the class definition.

image

I don't want to spoil all the surprises so I'll let you play with some of the methods. But let me at least point out the GetPresent() method. If you look at the screen shot you'll see that there are two ways to run it. This is referred to as an overload. If you look at the code in the class definition, you'll see multiple entries for the method, with different parameter options.

image

By the way, the method is merely returning one or several randomly selected items from another enumeration for presents. Hopefully you will get something you like.

Enjoy my gift and I wish you all the best for the holiday season and a terrific 2017.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “A Classy PowerShell Christmas”

  1. Jeffery Hicks says:
    December 20, 2016 at 10:44 am

    Checkout this update: http://bit.ly/2gYjXUc

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d