Games in PowerShell

This is an update to a previous blog which can be found here. I am now considering that one out of date and will leave a link to this one as, well, it’s better.

you can find the full code I used at the bottom of this blog.

I wanted to change my games and add some more functionality as I wanted everything to be in one place, in one file so that execution policies weren’t as big of an issue and also so that, if someone used my code, they wouldn’t have to change file locations within the scripts which can be a real pain.

Now, don’t get me wrong, this code is not perfect. For example, I am having difficulty verifying that the input data for the 1 to 100 guess game is actually a number, currently if anything but a number is entered it will output an error, but at least it carries on and doesn’t “blow up.”

The script can be broken up into 3 distinctive parts: the menu; the games and a function to change the PowerShell windows to a more convenient size. (Now in “Your Boss Probably Won’t See You Pissing About Size”).

Anyway, heres the code in full:

#Window size change
funtion change-gamewindowsize{

 $pshost = Get-Host
 $pswindow = $pshost.UI.RawUI
 $newsize = $pswindow.BufferSize
 $newsize.width = 150
 $pswindow.buffersize = $newsize
 $newsize = $pswindow.windowsize
 $newsize.width = 51
 $newsize.Height = 10
 $pswindow.windowsize = $newsize
}
change-gamewindowsize

#INTRO (Start Menu)
function menu2{

 function Show-Menu{
  param (
  [string]$Title = 'My Menu'
  )
  Clear-Host
  Write-Host "================ $Title ================"

  Write-Host "1: Press '1' to play 1-10 with 1 guess"
  Write-Host "2: Press '2' for 1-100 with unlimited guesses"
  Write-Host "Q: Press 'Q' to quit."
 }

 Show-Menu -Title 'Select an option'
 $selection = read-host "please make a selection"

 if ($selection -eq "1"){
  write-host "You chose option one" (single-guess)
 }elseif ($selection -eq "2"){
  Write-Host "you chose option two" (1to100guessgame)
 }elseif ($selection -eq "q"){
  clear
 Do {$areyousuremessage = Read-Host "Are you sure you want to quit? Y or N?"} while (("y","n") -notcontains $areyousuremessage)
 switch ($areyousuremessage){
  "y" {exit}
  "n" {menu2}
 }

 }elseif ($selection -ne "1" -or "2" -or "q"){
  (menu2)
 }
}

#Single guess game
function single-guess{

 clear
 Write-Host "You only have one guess!"
 Start-Sleep -Seconds 1
 Write-Host "Are you ready?"
 start-sleep -Seconds 1

 $random =  Get-Random -Minimum 1 -Maximum 11

 do {
  try {
  $numOk = $true
  [int]$input1 = Read-host "Make a guess between 1 and 10"
  }catch {$numOK = $false}
 }until (($input1 -ge 1 -and $input1 -lt 11) -and $numOK)

 if ($input1 -eq $random){
  Write-Host "You got it right!"
 }elseif ($input1 -ne $random){
  Write-Host "You got it wrong! the number was $random"

 Start-Sleep -Seconds 2

 do {$playagain1 = Read-Host "Do you want to play again? Y or N"} while (("y","n") -notcontains $playagain1)

 if ($playagain1 -eq "y"){
  single-guess
 }elseif ($playagain1 -eq "n"){
  (menu2)
 }

 }
}

#1-100 Guess game
function 1to100guessgame{

 clear

 [int]$random100 = Get-Random -Minimum 1 -Maximum 101

 Write-Host "Try and guess my number between 1 and 100"

 while ($input100 -ne $random100){
  Write-Host "enter your guess below"
  $input100 = [int] (Read-Host)

  $option1 = if ($input100 -gt $random100) {Write-Host "$input100 was too high"}
  $option2 = if ($input100 -lt $random100) {Write-Host "$input100 was too low"}
  $option3 = if ($input100 -gt [int](100) -or $input -lt [int](0)) {Write-Host 'between 1 and 100!'}

 } Write-Host "Correct! the number was $input100"

 do {$playagain1 = Read-Host "Do you want to play again? Y or N"} while (("y","n") -notcontains $playagain1)

 if ($playagain1 -eq "y"){
  1to100guessgame
 }elseif ($playagain1 -eq "n"){
  (menu2)
 }
}

menu2

Obviously, the code can be collapsed at each different function. And to add a new game you only need to create a new entry in the menu listing and then add the “Do you want to play again” bit at the end of it. Basically childsplay.

Have fun!

Number Guessing Games in PowerShell

CLICK HERE TO SEE THESE GAMES AND A MENU IN A SINGLE FILE.

This guide will show you how to make a two types of number guessing games in the coding language of PowerShell.

——————–1-10 With A Single Guess———————

Below is my code for a 1 to 10 guessing game in which the player has a single try to guess the number correctly:

function single-guess{

 clear
 Write-Host "You only have one guess!"
 Start-Sleep -Seconds 1
 Write-Host "Are you ready?"
 start-sleep -Seconds 1

 $random1to10 =  Get-Random -Minimum 1 -Maximum 11

 do {
  try {
   $numOk = $true
   [int]$input1 = Read-host "Make a guess between 1 and 10"
   }catch {$numOK = $false}
 }until (($input1 -ge 1 -and $input1 -lt 11) -and $numOK)

 if ($input1 -eq $random1to10){
  Write-Host "You got it right!"
 }elseif ($input1 -ne $random1to10){
  Write-Host "You got it wrong! the number was $random1to10"

 Start-Sleep -Seconds 2
 }
}

From this you can see that I start with a little intro of “Are you ready?” and other various starting lines. I then create a random number between 1 and 11 (Actually between 1 and 10 as the -maximum in this case signifies the highest amount the number cannot be), and then put that into  a variable. I then ask the user for a number (guess) between 1 and 10 and then use an if statement to test whether the guess was the same as the randomly generated number.

Now that you have the basic 1 to 10 game, we will move onto a 1 to 100 guess game with unlimited guesses.

——————1-100 With Unlimited Guesses——————

This code is a bit different since the user can have unlimited guesses. You can see how I made this possible in the code below:

function 1to100guessgame{

 clear

 [int]$random100 = Get-Random -Minimum 1 -Maximum 101

 Write-Host "Try and guess my number between 1 and 100"

 while ($input100 -ne $random100){
  Write-Host "enter your guess below"
  $input100 = [int] (Read-Host)

  $option1 = if ($input100 -gt $random100) {Write-Host "$input100 was too high"}
  $option2 = if ($input100 -lt $random100) {Write-Host "$input100 was too low"}
  $option3 = if ($input100 -gt [int](100) -or $input -lt [int](0)) {Write-Host 'between 1 and 100!'}

 } Write-Host "Correct! the number was $input100"
}

In this code I still created a random number and put it into a variable. But I used a “while” statement instead of an “if” statement, meaning that it loops until the user has guessed the correct number. I still haven’t figured out how to make sure that the user inputted date is an actual number, which if it’s not then it will output an error.

The 1 to 100 guessing game also informs the user whether the number they entered is too high or too low, this helps the user guess the number quicker.

——————————–CONCLUSION——————————–

These games a fun and all but they aren’t very well accessible or re-run-able (if that’s even a word). So I think I will create a menu for these and any future games I make so that they can all be played in one place and in one file. Till then!

Remember! If you want to be able to run scripts then you need to change you execution policy. You can see how to do that here!

Adding Signatures In Mimecast

Bit different from, the now usual, Powershell guides. Thought I’d do something different. This guide will show you how to add a custom signature to a user, multiple users’ or even globally.

Lets start off. You’ll want to log into your Mimecast administrative console, go to Service-Gateway-Policies. In here you should see “Stationary”. We want to create a new definition, so click on the “Definition” button on the “Stationary” listing.

Here you can click the “New Item” button. For the Description, obviously, enter a brief description of the new definition. The “Unique Identification Text” is used to scan an email that the definition is applied to to determine if the signature has already been added, so you want to add something that is in the signature and something that is unique to this signature. For the short code, enter a unique name. Below is an example of mine:

1

Now we want to edit the HTML so that there actually is a signature to put onto the emails. Click on the “Edit HTML” button and enter your signature. This is the code I added to mine:

<html>
 <head>
 </head>
  <body>
    <mc type="body">

    <font size="2" color="gray">
    This is a test email signature for marketing
    </font>

    <img src="IMAGE LINK" alt="ALTERNATIVE IMAGE NAME" style="width:214px;height:24px:" />

 </body>
</html>

So in my signature I have the message “This is a test email signature for marketing” and also a company logo.

Now we have that, we need to add it to an actual policy, otherwise it simply won’t be used by anything. Navigate back after saving your definition to the “Policies” page and click on the “Stationary” row. You now want to click “New Policy” which should open up a new policy creation window.

For the “Policy Narrative” enter a name for the policy, for the “Select Stationary”, select “lookup”, find your newly created definition and click “Select”. Since I created mine as a test and my Mimecast access is on my business email address, I configured an individual send and to email address for the policy to apply to. On this page you can also select when the policy will be active or even a range of source IP addresses.

Below are the values that I entered. The emails are removed for obvious reasons:

2

Finally, below is an example of an email with the newly added signature:

3

You should now have a custom signature that applies to every user defined in the policy instead of individual users.

File & Folder Creation with File Sorting in Powershell

Long post today. Definitely my most complex and longest script. Basically what this does it is looks at two separate CSV files, one has a list of locations and the other has a list of users/ people with a location assigned to them as well as some other attributes. WARNING! this script is variables center!

First of all, lets import our locations and create a folder with that location name. This is the code I used for this:

$get_Location_csv = Import-Csv -path 'C:\#PATH TO LOCATIONS CSV FILE'
[string]$root_dir = 'C:\#PATH TO ROOT FOLDER'
try{
 foreach ($location_data in $get_Location_csv){
  $location = $location_data.location #obtain location info
  if(Test-Path -Path $root_dir$location){
   Write-Host "Path already exists!"
  }else{
   New-Item -path $root_dir -Name "$location" -ItemType directory -ErrorAction SilentlyContinue
  }
 }

So from this you can see that we import the folder with the CSV values, check if where the folder will be created already exists, if so then output text, if not then create the folder with the location name. In case you were wondering, here is the value from my CSV file for the locations:

1 location CSV entries

Now that the files have been created, we want to import the other CSV file which contains a list of the users we need sorting and where they need sorting to. Below is the code I used to get the values I wanted, create the file, name it, put data in it and then put it into the relevant folder based on the users location.

$get_user_data = Import-Csv -Path "$root_dir\#USER INFO CSV"

foreach ($i in $get_user_data){
 $first = $i.first
 $last = $i.last
 $username = $i.username
 $location = $i.location
 $datetime = [datetime] (Get-Date)
 $district = $i.district
 foreach($l in $location){
  New-Item -Path "$root_dir$location" -Value "$first $last $location District = $district $datetime" -Name "$username .txt" -ErrorAction Stop
 }
}

To end the code off so that it worked more cleanly in the case of an error I added the following:

}catch{
 $_.exception.message
 Write-Warning 'location:'$i 'was not created successfull!'
}

This catches any errors that might occur during the scripts operation

Again, in case your wondering what is actually in the users CSV file, you can see that in the below screenshot:

Users CSV file

 

This is the output of the script

Here you can see the folders the script created:Folders createdYou can see that the script created all of the locations in the location CSV file. (Leeds, Newcastle, Rotherham, Sheffield, York)

Here you can see the files that are in one of the folders (I chose Leeds):

Users created in leedsHere is what is in each of the files:

User information

From these screenshots you can see that the script has successfully created and sorted the files by the location defined to each user in the users CSV file. You could probably make this work from just the one CSV file, but I went for the long way round 🙂

Here is the entire script!

$get_Location_csv = Import-Csv -path 'C:\#PATH TO LOCATIONS CSV FILE'
[string]$root_dir = 'C:\#PATH TO ROOT DIRECTORY'
try{
 foreach ($location_data in $get_Location_csv){
  $location = $location_data.location
  if(Test-Path -Path $root_dir$location){
   Write-Host "Path already exists!"
  }else{
   New-Item -path $root_dir -Name "$location" -ItemType directory -ErrorAction SilentlyContinue
  }
 }

$get_user_data = Import-Csv -Path "$root_dir\Users.csv"

foreach ($i in $get_user_data){
 $first = $i.first
 $last = $i.last
 $username = $i.username
 $location = $i.location
 $datetime = [datetime] (Get-Date)
 $district = $i.district
 foreach($l in $location){
  New-Item -Path "$root_dir$location" -Value "$first $last $location District = $district $datetime" -Name "$username .txt" -ErrorAction Stop
 }
}
}catch{
 $_.exception.message
 Write-Warning 'location:'$i 'was not created successfull!'
}

Drive Name Checker Against Variable

Before you can use scripts, see my post on how to allow them to be run here

This script gets the name of a drive specified by the drive letter and then compares this to a variable. In my script I compared the drive to the day of the week and the actual name of the drive.

First we need to get the name of the drive and put it into a variable. This is the code I used:

$drive = Get-Wmiobject -Class win32_volume -Filter "Driveletter = 'D:'"

Now we need a something to compare the drive name to. Here you can see that I have used both the day of the week and the actual name of the drive. I did this because you might have daily back-ups and want to make sure that the right drive is inserted for that day. Here’s the code I used:

$compareto = ( "Back-Up Drive" )

or you could compare the drive name to the day of the week:

$compareto = ( (Get-Date).DayOfWeek )

Here is the actual function that compares the drive name to the variable “$compareto” that we just created:

function usb-check {

 if ( (($drive).Label -eq $compareto) ){

  Write-Host "The drive is the same as the variable"

 }elseif ( (($drive).Label -eq $compareto) ){

  Write-host "The drive is NOT the same as specified"

 } 
}

Here is the full code for you to use:

$drive = Get-WmiObject -Class win32_volume -Filter "DriveLetter = 'D:'"
$compareto = ( "Back-Up Drive")
## ( (Get-Date).DayOfWeek )
##

function usb-check {
 if ( (($drive).Label -eq $compareto) ){
  Write-Host "The drive is the same as specified"
 }elseif ( (($drive).Label -ne $compareto) ){
  Write-Host "The drive is not the same as specified"
 } 
}

usb-check

pause

You can see that I have two variables, one commented out and another in use. This is just to give me and you more options to switch between quickly. If your wondering below are the two outputs from the function:

1

2

Hope you enjoyed!

 

Changing Script Execution Policies with Powershell

First, load up a Powershell prompt in Administrator mode.

Using the command:

Get-ExecutionPolicy -List

will bring up all of the execution policies for the different scopes. This can be seen in the screenshot below.

1

Now that we have our existing execution policies, we want to change them so that scripts can be run on your machine. The two we’re interested in is the “CurrentUser” and the “LocalMachine” scopes.

Given this, we want to change the execution policy for these two to be “RemoteSigned”. This way only the scripts that you authorize will be run, instead of the “Unrestricted” option with would allow Powershell to run ANY script. Obviously this could be a large security risk. With RemoteSigned, it also means that any downloaded scripts will need to be trusted in order to work.

Using the command:

Set-ExecutionPolicy RemoteSigned

When you are presented with the following screen, you want to select the “Yes to All” option or type “A”

2

Finally, we can run the command:

Get-ExecutionPolicy -List

Again which will show that the execution policy has now been changed.

3

You should now be able to run Powershell scripts. Please note that you may need to load then in Powershell ISE and run them which should ask you to make the script trusted or not.

Making a Paint Calculator in Powershell

First of all, open up a new Powershell ISE window. You’ll also want to make sure that your script execution policy allows for scripts to be run. To do this you can follow this guide.

Now that that’s out of the way, lets start creating our script.

To start off, we want to collect some of basic values. These values will be put into a variable. In the below screenshot you can see that I have collected some basic information using the “Read-Host” option.

1

Now that we have these I’m going to get the total area of the wall and put it into the variable “$wall”. I now divide the wall area by the spread of the paint and make this round up to the nearest integer.

2

Now I get the price of a tin of paint and times it by the rounded up variable just discussed.

3

Now we get onto the actual function. We start off by taking the rounded up amount of tins and saying “if it is less than one,” then simply output the original price the user inputted as only one tin of paint is needed. Else, we say “write the amount of tins needed and the total price”

4

Here is the full script with descriptors:

function paint {

 #Get and then times height and length. Then get the spread of the tin of paint. For example 80m.
 [int]$length = Read-Host 'length of walls in meters?'
 [int]$height = Read-Host 'height of walls in meters?'
 [int]$wall = $height * $length
 [int]$spread = Read-Host 'Coverage of a single tin of paint in meters (not meters squared)?'

 #now we take the total area and divide by the coverage of a tin of paint
 [int]$add = ($wall / $spread)

 #now we take this and round it up to the nearest integer (this gets the amount of tins needed)
 [int]$div = [math]::Ceiling($add)

 #now we get the price of a tin of paint
 [int]$price = Read-Host -Prompt 'how much does a tin of paint cost?'

 #Now we times the inputted price by the rounded up amount of tins needed
 [int]$tprice = $price * $div

 #now we do the function
 #if the amount of tins is less than 1, then output original inputted price
 #if larger than one, ouput the amount of tins needed and total price.
 if ( ($div -le [int]1) ) {
  Write-Host "Less than one tin is needed. This will only cost £$price"
 }else {
  Write-Host "$div tins of paint are needed. This will cost £$tprice"
 }
} 
paint
pause

I added the “pause” at the end since I didn’t want the Powershell box to disappear as soon as all the variables were collected.

Hope you enjoyed and found this useful, if not interesting.

 

Renaming NICs with Netsh

First, you want to open a command prompt in Administrator mode.Open CMD

Secondly, open up a netsh prompt by typing “netsh” into the command prompt and pressing enter.Open Netsh

Thirdly, we want to list the interfaces that are currently available on the computer. Then find the one that you want to change the name for. You can list the interfaces by typing “interface show interface”.List Interfaces

Now we have found the interface that we want to change the name for, LET’S CHANGE THE NAME ALREADY! You’ll want to type:

interface set interface name="connectionnamehere" newname="newname"

Below in the screenshot are the values I added. Obviously making the connection name more Recognisable.command entered

Finally, when listing the interfaces again,  you can see that the interface’s name has changed.

result

You may have noticed that the command prompts permission level changed to Administrator mode after the first screenshot… I completely forgot that I needed to be in administrator mode to perform a rename on a NIC. Hope this was useful to you!