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) ×