MWJ Computing A life lived through digital exploration.

2Aug/100

Documenting PowerShell Scripts – Part 1

A “best practice” I follow is I document everything I do in a script. There are times I need to go back to a script years later and need to know exactly what it does. This is the first post in a series on how I document my scripts. Hopefully this helps you.

The first topic we are going to cover is something called “Advanced Functions”. This topic has been covered many times before by other people. I wanted to put my spin on this.

When you use Advanced Functions you add the following line to the first line of your function or script.

[CmdletBinding()]

This line, when used in Windows PowerShell 2.0 scripts or functions, gives you the following cmdlets among other things.

  • Write-Verbose
  • Write-Debug

How does this help me document you ask?

I use Write-Verbose for everything I am doing in a script and function. From assigning variables, changing values, switching in and out of functions, I document EVERYTHING. You can put anything you want in Write-Verbose.

One cool trick I do is the following where it gives you the name of the script you are running when you run it.

Write-Verbose -Message "Running Script: $MyInvocation.MyCommand"

I also add things to my scripts and functions so that when other people run the script, they can see who wrote it and other information.

Write-Verbose -Message "Running Script: $MyInvocation.MyCommand"
Write-Verbose -Message "Author: Matt Johnson - email@address"
Write-Verbose -Message "Script Version: 1.0"
Write-Verbose -Message "Join the SE Michigan PowerShell Script Club"
Write-Verbose -Message "http://www.michiganpowershell.com"

Now when you run your script or function –verbose you get the added information you placed in your script. The possibilities are endless.

I also use Write-Debug but not as frequently. I use those lines to go into further detail on what I am doing. Something that people running my scripts may not want to see if they want more info.

I encourage you to add the [CmdletBinding()] statement to your PowerShell 2.0 scripts and functions and play around with those two statements.

Up Next: Inline Help

24May/100

2010 Scripting Games Wrap Up

Well the expert answers are now being published over on the Hey Scripting Guys blog. So I figured I would write up a little on my experience during the games, how little they may be.

I sent in only 3 scripts as life got in the way. Too much school and working. Oh well. I did however complete 95% of each script but wasn’t happy with the code so I didn’t submit them. I know I should have submitted them anyways, but oh well. This however doesn’t mean I am done working on them. I plan on posting my solutions on my blog as I get time to finish them. (Probably sometime in June.)

The good thing is that I did learn some things and remember a few others. After all, isn’t that the whole reason for the Scripting Games anyways?

  1. The first thing I remembered is how cool Tee-Object is. For those of you who don’t know Tee-Object sends what you pass it to both the screen and a file. I am assuming this is based of the tee command in Unix. No matter where it is from, I am going to try to remember to add this to my bag of tricks. See my example below. I am running Get-Process and selecting the first 10. I am then passing that to Tee-Object and saving it to a file and viewing the content at the same time. Very Cool!
    tee-object-51910
  2. I learned I was making things to hard for myself. Before the Scripting Games I would use a parameter named DEBUG and an if statement to write extra information to the screen when running a script. Good news! PowerShell v2.0 has a statement you can add to your scripts to force your scripts to recognize the debug parameter. Once you add that you can use the Write-Debug cmdlet. This makes life so much easier.
  3. I remembered that there are tons of different resources. Use them. I can’t stress that enough. Without those resources everything gets exponentially more difficult.

There are also some thank you’s that need to go out.

  1. The Scripting Guys. I can’t even imagine how much work goes into producing an event like this. Thank you for doing this for the community.
  2. Joel Bennett (Jaykul) for hosting PoshCode and the repository for posting our scripts.
  3. The sponsors of the Scripting Games.

Lastly, I want to thank Ed personally for allowing me to write a solution for Advanced Event 4. I can say that has been the highlight of my scripting career.

Filed under: PowerShell No Comments
26Apr/100

2010 Scripting Games Are Here!

The 2010 Scripting Games began this morning! You should head over to the Official 2010 Scripting Games Page and get started!

Happy Scripting!

Filed under: PowerShell No Comments
19Apr/104

Function to check for valid IP

Just thought I would share this. I needed to check to see if an IP was valid when going through an excel document. So I wrote a quick function to test to see if it is a valid IP address.

You can download this function here.

Quick and Simple! Enjoy!

function Test-IsValidIP{
    param (
        [string]$ipAddress
    )

    #Regex Query
    $regexQuery = "^([1-9]|[1-9][0-9]|1[0-9][0-9]`
        |2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]`
        |1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$"

    if ($ipAddress -match $regexQuery){
        return($true)
    } else {
        return($false)
    }
}
Filed under: PowerShell 4 Comments
15Apr/100

Are you competing in the Scripting Games? I am!

I am and let me explain why. The Scripting Games that are put on by the Microsoft Scripting Guys is a great opportunity to learn, advance or prove you know your stuff when it comes to scripting. I participated the last few times that the games were ran and I loved it. Every minute of it.

The scripting games start on April 26th and go to May 7th. I know I am encouraging everyone in the SE Michigan PowerShell Script club to participate and hopefully you do to!

There are 10 events in both an beginner and advanced categories. This year there are two languages that the scripts can be written in. Those are PowerShell and VBScript. (I heard that this is the last year for VBScript. Boohoo! VBScript will always have a place in my heart but change is good. And besides PowerShell is awesome!) These events encompass tasks that can help you with your day to day job. Looking at the 2010 Scripting Games Study guide gives us a hint at what the events might entail. From working with text files and folders to using WMI information I am sure that everyone will find this to be fun and challenging.

When you are done writing your script, you can post it up along with everyone else's submission on the special Scripting Games section of the PoshCode.org website. That site is at http://2010sg.poshcode.org. Very cool of PoshCode to do this if I do say so.

At the end of each event scripting experts will provide commentary on how they tackled the script and their solution. This is a great opportunity to learn from some of the best in the scripting community. You should note however that there are almost always many ways to solve a problem, but what some of the experts do is amazing in how well their scripts are written.

So with all that being said, I urge you to compete. Oh I forgot to mention there will be prizes? According to the FAQ they will be having 11 drawings, which amounts to one drawing per day and a grand prize. All you have to do to be eligible is to submit a script for the event! Now how easy is that? And who doesn’t love prizes? I know I do.

What do you do next? Well there are a few things you can do to get prepared.

  1. Register to compete! You can do this by going to http://2010sg.poshcode.org. Make sure you do this so you can hit the round running on April 26th, 2010.
  2. Read the Frequently Asked Questions. You can find them at http://bit.ly/2010sgdetails
  3. Use the study guide the Scripting Guys so graciously provided at http://bitl.ly/2010sgstudyguide.
  4. Read the Scripting Guys Blog and follow along as the Scripting Wife learns PowerShell! Their blog is at http://blogs.technet.com/heyscriptingguy/default.aspx
  5. If you have your own website or blog, put the 2010 Scripting Games badge on your site so that everyone knows you are competing and you can help bring in more people! You can get that at http://bit.ly/2010sggrabbadge.
  6. If you use twitter or Facebook, make sure you add the Twibbon for your profile picture! You can get the twibbon at http://twibbon.com/join/2010-scripting-games.

I hope to see you on the “Scripting Field”.

Happy Scripting!

Filed under: PowerShell No Comments
13Apr/102

Validate time with a format of hh:mm:ss using RegEx

Here are two quick ways to validate an entered date. Both examples work with PowerShell 2.0 but only the first one works with PowerShell 1.0.

The following is a RegEx string to validate input in the format of hh:mm:ss.

[01][0-9]:[0-6][0-9]:[0-6][0-9]

We can use a simple if statement to validate the time as seen below

$time = "22:33:22"

if ($time -match "[01][0-9]:[0-6][0-9]:[0-6][0-9]"){
    Write-Host $true
} else{
    Write-Host $false
}

Pat Richard pointed out that we can do this with a few less lines of code, so you can choose what way you want to do this. He used the –match switch against the variable itself. Here is what he suggested:

$time = "22:33:22"
$time -match "[01][0-9]:[0-6][0-9]:[0-6][0-9]"

With PowerShell 2.0, we can validate it when it is entered as a parameter by adding the following lines into your param() statement replacing the variable $userTime with the name of your variable.

[ValidatePattern("[01][0-9]:[0-6][0-9]:[0-6][0-9]")]
[string]$userTime

The following function validates time in the format of hh:mm:ss. It can also be downloaded here.

function Test-IsValidTime {
    <#
    .SYNOPSIS
        Checks to see if value entered is in valid format.

    .DESCRIPTION
        This function tests to see if the date entered in hh:mm:ss format is a valid time.

    .PARAMETER  time
        Time entered in format of hh:mm:ss.

    .EXAMPLE
        PS C:\> Test-IsValidTime -time '12:34:56'

    .INPUTS
        System.String

    .OUTPUTS
        System.Boolean

    .NOTES
        This function was written by Matt Johnson of the SE Michigan PowerShell Script Club.

    .LINK
        http://www.mwjcomputing.com/blog/

    .LINK
        http://www.michiganpowershell.com/

    #>

    param (
    [string]$time
    )

    if ($time -match "[01][0-9]:[0-6][0-9]:[0-6][0-9]"){
        return $true
    } else{
        return $false
    }

} #End Function Test-IsValidTime

 

Happy Scripting!

Filed under: PowerShell 2 Comments
13Apr/100

Script to modify window for PowerShell demo

When I do PowerShell demos, I want my screen to have some default characteristics. The script below is the one I started using when I do a PowerShell demo for co-workers, friends or the SE Michigan PowerShell Script Club. Feel free to tailor it to your liking!

You can download this script here.

Happy Scripting!

######################################################
# Script Name: set-powershelldemo.ps1
# Written By: Matt Johnson - powershell@mwjcomputing.com
# Revision Date: 4/12/2010
# Version: 2.0
# Version History:
#  - 1.0: Inital Script
#  - 2.0: Added host info switch and display
# Description: This script sets the window for the demo.
# Command Line: ./set-powershelldemo.ps1
# Example 1: ./set-powershelldemo.ps1
# Example 2: ./set-powershelldemo.ps1 -displayHost
######################################################
param(
    [switch]$displayHost
)

# Get UserInterface Object
$userInterface = (Get-Host).UI.RawUI

# Set Window Title
$userInterface.WindowTitle = "MWJ Computing PowerShell Demo"

# Set Window Size
$windowSize = $userInterface.WindowSize
$windowSize.Width = 120
$windowSize.Height = 50
$userInterface.WindowSize = $windowSize

# Check for admin script
$wid=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$prp=new-object System.Security.Principal.WindowsPrincipal($wid)
$adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator
$IsAdmin=$prp.IsInRole($adm)

# Check to see if admin, if is change background to red.
if ($IsAdmin){
    (get-host).UI.RawUI.Backgroundcolor="DarkRed"
}

# Set Location to c:\fso
Set-Location -path 'C:\fso'

# Clear Screen
Clear

# Display Welcome Message
Write-Host -object "Welcome to the MWJ Computing PowerShell Demo."`
    -foregroundcolor Yellow
Write-Host -object `
    "For more information, please visit http://www.mwjcomputing.com/blog/." `
    -foregroundcolor Yellow
Write-Host -object "Happy Scripting!" -foregroundcolor Yellow

# Check for DiplayHost switch.
if ($displayHost){
    Write-Host -object ""
    Write-Host -object "UserName: $env:USERNAME" `
        -foregroundcolor Yellow
    Write-Host -object "HostName: $env:COMPUTERNAME" 1
        -foregroundcolor Yellow
    Write-Host -object "DomainName: $env:USERDNSDOMAIN" 1
        -foregroundcolor Yellow
    Write-Host -object "Date: $(Get-Date)" -foregroundcolor Yellow
    Write-Host -object "Execution Policy: $(Get-ExecutionPolicy)" `
        -foregroundcolor Yellow
}
 
Filed under: PowerShell No Comments
12Apr/100

Need a certain PowerShell SnapIn? Make it required!

I started doing this on all my scripts that require something like the Quest Active Directory SnapIns. It is quick and simple and when the script runs it checks for it and displays a message indicating you are missing a requirement. Pretty cool if you ask me.

To require a SnapIn add the following line in the beginning of your script but replace it with the name of the SnapIn:

#Requires -pssnapin name_of_snapin

As an example, lets say you want to require Quest’s Active Directory SnapIn. You would add the following line in the beginning of your script

#Requires -pssnapin Quest.ActiveRoles.ADManagement

If you don’t have the snapin loaded, you will get an error like the one below.

snapin-requires

This is a nice feature and hopefully you all start using it!

Happy Scripting!

Filed under: PowerShell No Comments
25Mar/100

PowerShell Script – Get-DiskOffset.ps1

######################################################
# Script Name: get-diskoffset.ps1
# Written By: Matt Johnson - powershell [at] mwjcomputing.com
# Revision Date: 3/25/2010
# Version: 1.0
# Version History:
#  - 1.0: Initial Script
# Description: This script displays the disk offset info.
# Command Line: ./get-serverspace.ps1
# Example: ./get-diskoffset.ps1 MAGNET
# Example: ./get-diskoffset.ps1
# Notes:
# - Based on script located at http://braunblog.com/?p=32
######################################################

param (
    [string]$computerName = "localhost"
)

# Formatting Options
$OffsetKB = @{label=Offset(KB);Expression= `
    {$_.StartingOffset/1024 -as [int]}}
$SizeMB = @{label=Size(MB);Expression={$_.Size/1MB -as [int]}} 

# WMI Query
$wmiObj = Get-WmiObject -ComputerName $computerName -Class `
    "Win32_DiskPartition" -ErrorAction SilentlyContinue

# Check for Results
if(-not $wmiObj)
{
    # Display Error
    "Can't connect to $computerName"
} else {
    # Display Results
    $wmiObj | ft SystemName, Name, DiskIndex, $SizeMB, $OffsetKB  -AutoSize
}
Filed under: PowerShell No Comments
19Mar/100

PowerShell Script – Get-ServiceUser.ps1

This script gets the services that are running under the specified user.

You can download the script here.

######################################################
# Script Name: Get-ServiceUser.ps1
# Written By: Matt Johnson - powershell [at] mwjcomputing.com
# Revision Date: 3/17/2010
# Version: 3.0
# Version History:
#  - 1.0: Initial Script
#  - 2.0: Enables use of | Out-File
#  - 3.0: Added ability to specify only one machine.
# Description: This script gets a list of services that
#                are running as a particular user from
#                a text file.
# Command Line: ./Get-ServiceUser.ps1
# Example: ./Get-ServiceUser.ps1 -userAccount 'LocalSystem'
#              -filePath "\\fileserver\data\servers.txt"
#          This checks for the user LocalSystem account
#              against names in the servers.txt file.
# Example: ./Get-ServiceUser.ps1 -userAccount 'MWJ\service'
#              -pcName "MAGNET"
#          This checks for the user MWJ\service against
#              the server MAGNET.
# Example: ./Get-ServiceUser.ps1
#          This uses the default options of LocalSystem
#              against c:\fso\data\servers.txt.
######################################################
param (
[string]$userAccount = "LocalSystem",
[string]$filePath = "c:\fso\data\servers.txt",
[string]$pcName
)

# Check to see if $pcName is populated.
if (-not $pcName) {
    # Get content of text file.
    $servers = Get-Content -path $filePath
} else
{
    # Set list of servers to name of entered PC.
    $servers = $pcName
}

# Loop through each line of the text file.
foreach ($server in $servers)
{
    " "
    "Services running as $userAccount on $server"
    "-------------------------------------------"
    # Get Win32_Service WMI Class
    $services = Get-WmiObject -class Win32_Service `
    -ErrorAction SilentlyContinue -computerName $server
    # Check to see if anthing is returned.
    if (-not $services)
    {
        # Write error message
        "Cannot connect to $computer"
    } else
    {
        # Loop through each service and display the name.
        foreach ($service in $services)
        {
            $service | where {$_.StartName -like $userAccount} `
            | Select DisplayName
        }
    }
}
Filed under: PowerShell No Comments