Weekend Scripter: Draw a Cat on a Fence Watching a Yellow Moon Using Windows PowerShell

Weekend Scripter: Draw a Cat on a Fence Watching a Yellow Moon Using Windows PowerShell

  • Comments 1
  • Likes

  

Summary: Learn how to draw a cat on a fence watching a yellow moon by using Windows PowerShell

 

Microsoft Scripting Guy Ed Wilson here. It is seven in the morning yet it seems like it could be four in the morning. It is dark outside, and the room is cool with a hint of humidity. I hang on to my cup of English Breakfast tea like a starved dog protects a bone. A soft bubbling sound emanating from the general direction of the stove assures me that my Irish steel-cut oats are continuing their slow progression to a cooked state.

A gentle but persistent breeze blows the leaves across the lawn, and the squirrels chatter with one another in the relentless pursuit of nuts and other edible foodstuffs. On such a morning as this, it seems as if almost anything is possible. On such a morning as this, I wrote my first Windows PowerShell script. On such a morning as this, I completed my first Windows PowerShell book. On such a morning as this, I had a cup of English Breakfast tea, waited for my Irish steel-cut oats to cook and wondered about such a morning as this.

While the oats are cooking, I decided to open up Windows PowerShell on the kitchen computer and play around a bit. The DrawCircleWithCatAndMoon.ps1 script is the result.

DrawCircleWithCatAndMoon.ps1

Function Test-IsIseHost
{
 <#
 .Synopsis
 Determines if you are running in the Windows PowerShell ISE
 .Description
 This function determines if you are running in the Windows Powershell
 ISE by querying the $ExecutionContext automatic variable.
 .Example
 Test-IsISEHost
 Prints out True if runing inside the ISE, False if run in console
 .Example
 if(Test-IsISEHost) { "Using the ISE" }
 Prints out Using the ISE when run inside the ISE, otherwise nothing
 .Inputs
 None
 .Outputs
 [Boolean]
 .Notes
 Name: Test-ISEHost
 Book: Windows PowerShell Best Practices, Microsoft Press, 2009
 Author: Ed Wilson
 Version: 1.0
 Date: 4/5/2009
 .Link
 about_Automatic_variables
 Http://www.ScriptingGuys.Com
 #>
 $ExecutionContext.Host.name -match "ISE Host$"
} #end Test-IsIseHost

Function Set-Circle
{
 Param(
  [int]$script:xCenter = 20,
  [int]$script:yCenter = 10,
  [int]$script:radius = 5
 )
 Clear-Host
 $r2 = $radius * $radius
 for($x = -$radius; $x -le $radius ; $x++)
  {
   $y = ([int][math]::sqrt($r2 - $x*$x) + 0.5)
   Set-ConsolePosition -x ($xCenter + $x) -y ($yCenter + $y)
   Write-Host -ForegroundColor Yellow -NoNewline "@"
   Set-ConsolePosition -x ($xCenter + $x) -y ($yCenter - $y)
   Write-Host -ForegroundColor Yellow -NoNewline "@"
  } #end for $x
} #end function Set-Circle

function global:set-ConsolePosition ([int]$x,[int]$y) {
# Get current cursor position and store away
$position=$host.ui.rawui.cursorposition
# Store new X and Y Co-ordinates away
$position.x=$x
$position.y=$y
# Place modified location back to $HOST
$host.ui.rawui.cursorposition=$position
} # end function set-consolePosition

Function Set-Fence
{
 for($a = 1; $a -le 14; $a++)
 {
  if($a -eq 14)
   { Write-host "_/\_" -nonewline }
  else
   { Write-host "_/\" -nonewline }
  }
 ""
for($i = 1 ; $i -le 5 ; $i ++)
 {
   for($j = 1 ; $j -le 15 ; $j++)
    { write-host "|  " -nonewline }
    ""
 }
} #End function Set-Fence

Function Set-Cat
{
$cat=@"
 /\___/\
 )     (
=\     /=
  }==={
 /     \
 |     |
/       \
\       /
 \__  _/
    (
     )
    *
"@ Write-host -ForegroundColor Green $cat -noNewLine
} #end function Set-Cat


# *** Entry point to Script ***

if(Test-isIseHost) {"this script does not run in the ISE" ; exit}
$Host.UI.RawUI.WindowTitle = "Scripting Guys say hi..."
Set-Circle -xCenter 20 -yCenter 10 -radius 5
Set-ConsolePosition -x 0 -y ($yCenter + $Radius +19)
Set-Fence
Set-ConsolePosition -x 0 -y ($yCenter + $Radius +10)
Set-Cat
Set-ConsolePosition -x 0 -y ($yCenter + $Radius +25)

 

This script will not run correctly in the Windows PowerShell ISE. Therefore, I use the Test-isIseHost function to check the host that is executing the script. If the script is run inside the Windows PowerShell ISE, the script will exit. Most of the function is taken up with comment-based help but the essential line of code is seen here.

$ExecutionContext.Host.name -match "ISE Host$"

 

The script begins by creating the Set-Circle function. This function accepts three input parameters that determine where the circle will be drawn and the size of the circle to draw. The Set-Circle function is seen here.

Function Set-Circle
{
 Param(
  [int]$script:xCenter = 20,
  [int]$script:yCenter = 10,
  [int]$script:radius = 5
 )
 Clear-Host
 $r2 = $radius * $radius
 for($x = -$radius; $x -le $radius ; $x++)
  {
   $y = ([int][math]::sqrt($r2 - $x*$x) + 0.5)
   Set-ConsolePosition -x ($xCenter + $x) -y ($yCenter + $y)
   Write-Host -ForegroundColor Yellow -NoNewline "@"
   Set-ConsolePosition -x ($xCenter + $x) -y ($yCenter - $y)
   Write-Host -ForegroundColor Yellow -NoNewline "@"
  } #end for $x
} #end function Set-Circle

 

The Set-Circle function calls the Set-ConsolePosition function to set the insertion point in the Windows PowerShell console. Then it uses the Write-Host Windows PowerShell cmdlet to write the at sign character (@) to the Windows PowerShell console. The Set-ConsolePosition function was written by Microsoft MVP Sean Kearney. This function is discussed in the "Draw Boxes and Lines in the Windows PowerShell Console Host" Hey Scripting Guy! blog. It was also used in the "Modify the PowerShell Console Title and Display a Rabbit" Weekend Scripter post that I wrote for the Scripting Wife's birthday. The Set-ConsolePosition function is seen here.

function global:Set-ConsolePosition ([int]$x,[int]$y) {
# Get current cursor position and store away
$position=$host.ui.rawui.cursorposition
# Store new X and Y Co-ordinates away
$position.x=$x
$position.y=$y
# Place modified location back to $HOST
$host.ui.rawui.cursorposition=$position
} # end function set-consolePosition

 

The Set-Fence function is used to draw the fence to the Windows PowerShell console. Because there is lots of repetition in building a fence (whether in real life (IRL) or virtually, it is a natural fit for a for loop. I decided to use the if statement to detect when I am coming to the end of the fence so that I could add the last "board" in the last position. The Set-Fence function is seen here.

Function Set-Fence
{
 for($a = 1; $a -le 14; $a++)
 {
  if($a -eq 14)
   { Write-host "_/\_" -nonewline }
  else
   { Write-host "_/\" -nonewline }
  }
 ""
for($i = 1 ; $i -le 5 ; $i ++)
 {
   for($j = 1 ; $j -le 15 ; $j++)
    { write-host "|  " -nonewline }
    ""
 }
} #End function Set-Fence

 

The Set-Cat function uses a here-string to define a cat that is actually drawn to the Windows PowerShell console through the Write-Host Windows PowerShell cmdlet. This function is shown here.

Function Set-Cat
{
$cat=@"
 /\___/\
 )     (
=\     /=
  }==={
 /     \
 |     |
/       \
\       /
 \__  _/
    (
     )
    *
"@
Write-host -ForegroundColor Green $cat -noNewLine
} #end function Set-Cat

 

The entry point to the script puts everything together. I use the window title property from the InternalHostRawUserInterface class to change the default Windows PowerShell console Window title. The InternalHostRawUserInterface class is located in the System.Management.Automation.Internal.Host .NET Framework namespace, and is documented in the Windows PowerShell Owner's Manual. The entry point to the script is seen here.

# *** Entry point to Script ***

$Host.UI.RawUI.WindowTitle = "Scripting Guys say hi..."
Set-Circle -xCenter 20 -yCenter 10 -radius 5
Set-ConsolePosition -x 0 -y ($yCenter + $Radius +19)
Set-Fence
Set-ConsolePosition -x 0 -y ($yCenter + $Radius +10)
Set-Cat
Set-ConsolePosition -x 0 -y ($yCenter + $Radius +25)

 

When the script runs, the output seen in the following figure appears.

  

 

I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at scripter@microsoft.com or post them on the Official Scripting Guys Forum.. See you tomorrow. Until then, peace.

 

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment