An Example ScriptModule and Advanced Function

And here it is...

function Restart-Host {
        [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='High')]
        param (
                [Parameter(Mandatory=$True,
                           ValueFromPipeline=$True,
                                   ValueFromPipelineByPropertyName=$True)]
            [Alias('host')]
                [ValidateLength(3,30)]
                [string[]]$computername,
               
                [string]$logname = 'errors.txt'
        )
        begin {
        write-verbose "Deleting $logname"
                del $logname -ErrorAction SilentlyContinue
        }
        process {
                write-verbose "Beginning process loop"
       
        # The $computername parameter will contain 1+ names, so
        # we want to work with just one at a time. A ForEach loop[
        # permits us to do that.
        foreach ($computer in $computername) {
       
            # If a Stop error occurs in a Try block, the following
            # catch block will execute.
            try {
           
                # we'll use $continue to track whether or not this fails
                $continue = $true
                Write-Verbose "Trying $computer"
                $os = Get-WmiObject -class Win32_operatingsystem -computer $computer -erroraction stop
            } catch {
                # set $continue to false, so we know not to try anything else
                # with this failed computer. Also log the computer name.
                Write-Verbose "$computer failed; logging"
                $computer | out-file $logname -append
                $continue = $false
            }
           
            # only do this if the WMI call succeeded.
            if ($continue) {
                Write-Verbose "Connection to $computer successful"
               
                # this generates the confirm/whatif prompt/output
                # and will return False if we're not supposed to
                # actually execute
                if ($pscmdlet.ShouldProcess($computer)) {
                    write-verbose "Executing reboot on $computer"
                    $os.reboot()
                }
            }
        }
        }
}
function Get-ComputerInfo {
        <#
        .SYNOPSIS
        Gets OS version information
        .DESCRIPTION
        See synopsis.
        .EXAMPLE
        Get-OSVersion -computername server-r2
        .EXAMPLE
        'localhost','server-r2' | Get-OSVersion
        .EXAMPLE
        Import-Module ActiveDirectory
        Get-ADComputer -filter * | Select @{n='computername',e={$_.name}} | Get-OSVersion
        .EXAMPLE
        Get-OSVersion -computername (Get-Content names.txt)
        .PARAMETER computername
        The computer name to query. Just one.
        .PARAMETER logname
        The name of a file to write failed computer names to. Defaults to errors.txt.
        #>
        [CmdletBinding()]
        param (
        # see about_functions_advanced_parameter for this stuff
                [Parameter(Mandatory=$True,
                           ValueFromPipeline=$True,
                                   ValueFromPipelineByPropertyName=$True,
                   HelpMessage='What computer name would you like to target?')]
            [Alias('host')]
                [ValidateLength(3,30)]
                [string[]]$computername,
               
                [string]$logname = 'errors.txt'
        )
   
    # this block executes once when the function is first called
        begin {
        write-verbose "Deleting $logname"
                del $logname -ErrorAction SilentlyContinue
        }
   
    # this block will execute once if nothing was piped in
    # if something was piped in, this will execute once for
    # each thing that was piped in
        process {
       
        # we don't need to explicitly code a -verbose parameter.
        # PowerShell will handle it automagically.
                write-verbose "Beginning process loop"
       
        # $computername may contain 1+ items, so we'll use a foreach loop
        # that allows us to just work with one computer at a time.
        # that way if one computer fails, we can still continue trying
        # the other ones
        foreach ($computer in $computername) {
       
            # in a try block, errors that occur with -ErrorAction Stop will be
            # captured instead of making the whole script explode. The following
            # catch block will allow us to deal with the error.
            try {
           
                # setting $continue to True allows us to track whether
                # or not this WMI call succeeds
                Write-Verbose "Trying $computer"
                $continue = $true
                $os = Get-WmiObject -class Win32_operatingsystem -computer $computer -erroraction stop
            } catch {
           
                # the WMI call failed, so we set $continue to false. That
                # will let us skip the rest of the script for the current
                # computer.
                Write-Verbose "$computer failed."
                $computer | out-file $logname -append
                $continue = $false
            }
           
            # only do this is $continue is still true.
            if ($continue) {
                write-verbose "$computer succeeded; trying next WMI calls"
                write-verbose "BIOS"
                $bios = get-wmiobject -class win32_Bios -computer $computer
               
                # we only need to query one processor
                write-verbose "Processor"
                $proc = get-wmiobject -class win32_processor -computer $computer |
                    select-object -first 1
               
                # we have WMI information in $os, $bios, and $proc.
                # so let's create a hashtable with all the info we
                # want to have in our final output
                Write-Verbose "Creating output for $computer"
                $info = @{
                    'ComputerName'=$computer;
                    'OSVersion' = $os.caption;
                    'OSBuild' = $os.buildnumber;
                    'SPVersion' = $os.servicepackmajorversion;
                    'BIOSSerial' = $bios.serialnumber;
                    'OSArchitecture' = $os.osarchitecture;
                    'ProcArchitecture' = $proc.addresswidth
                }
               
                # create the output object with the above info
                $obj = New-Object -TypeName PSObject -Property $info
               
                # output the object to the pipeline
                write-output $obj
            }
        }
        }
}

# create an alias
New-Alias gif Get-ComputerInfo

# make sure our two functions and the alias get
# exposed when someone imports this module
Export-ModuleMember -function Get-ComputerInfo
Export-ModuleMember -function Restart-Host
Export-ModuleMember -Alias gif

This is intended to be saved in \Documents\WindowsPowerShell\Modules\Tools\Tools.psm1 on your computer. Load using Import-Module Tools.

Discuss this Blog Entry 1

on Jun 23, 2011
Don, you know that I have been a fan of your work literally for years. How does this fit with http://www.windowsitpro.com/blog/powershell-with-a-purpose-blog-36/windows-powershell/powershell-part-6-139490? I kid...I kid. Seriously, thanks for the great tools and all the work that you do for the community.

Please or Register to post comments.

What's PowerShell with a Purpose Blog?

Don Jones demystifies Windows PowerShell.

Blog Archive

Sponsored Introduction Continue on to (or wait seconds) ×