Back to top

FREE eBook: The Most USEFUL PowerShell CmdLets and more…

Grab a copy!

PowerShell Function Begin Process End Blocks Explained With Examples

Begin Process End blocks are part of PowerShell Advanced Functions and they are methods of input processing. Although these three blocks are completely optional they give us the possibility of controlling the function’s workflow.

Begin Process End are three separate scripting blocks within a function:

  • BEGIN – executes first and only once. It is useful for preprocessing (setting up and initializing the processing). However, completely optional.
  • PROCESS – executes second and as many times as many objects are sent to the function through PowerShell pipeline (record-by-record processing). It is optional.
  • END – executes last and only once. It is useful for postprocessing (freeing up the resources). However, completely optional.

Begin Process End Blocks – Demo Example

I have prepared a nice demo example to show you Begin, Process, and End script blocks in action.

 Function Run-BeginProcessEndBlocks
 {
 [CmdletBinding()]
 Param
     (
     [Parameter( Mandatory=$true,
                 ValueFromPipeline=$true,
                 HelpMessage="Message text.")]
     [string[]]$message,
     [Parameter( Mandatory=$true,
                 HelpMessage="Call Type.")]
     [string]$CallType
     )
 Begin
 {
    Write-Host "=======================================================" -ForegroundColor White
    Write-Host $CallType -BackgroundColor Yellow -ForegroundColor Blue
    Write-Host "BEGIN" -BackgroundColor Green -ForegroundColor Black

     }
 Process
 {
    Write-Host "PROCESS" -BackgroundColor White -ForegroundColor Black
    Write-Host $message -ForegroundColor Yellow
 
     }
 End
 {
    Write-Host "END" -BackgroundColor Red
     }
 }
     #region Execution examples
     Run-BeginProcessEndBlocks -message "HELLO" -CallType "Single Value"
     Run-BeginProcessEndBlocks -message "Welcome", "to", "IMPROVESCRIPTING.COM", "with", "Dejan" -CallType "String Array"
     "Welcome", "to", "IMPROVESCRIPTING.COM", "with", "Dejan" | Run-BeginProcessEndBlocks -CallType "Pipeline String Array"
     "HELLO"  | Run-BeginProcessEndBlocks -CallType "Pipeline Single Value"
     #endregion

Here is the result of running the script that we will discuss in a moment:

Results of running Run-BeginProcessEndBlocks function

Let me quickly explain the code in Run-BeginProcessEndBlocks function. This function has the following parts:

  • CmdletBinding Attribute
  • Input Parameters
  • Begin block
  • Process block
  • End block
  • Execution examples region

CmdletBinding Attribute makes this function to become a PowerShell Advanced Function that means we can use common parameters (  Debug  (db),   ErrorAction  (ea),  ErrorVariable (ev),  Verbose (vb), etc)  and control the function workflow with Begin, Process, End blocks.

INFO: If you want to know more about CmdletBinding Attribute please read How To Use CmdletBinding Attribute where I have explained this attribute more detailed.

Input Parameters are two of them: message and CallType. The message input parameter accepts an array of strings pipelined by value and this parameter is mandatory. The CallType input parameter is a string data type and it is also mandatory. Later parameter gives us in the result information on which type of call to the function we have implemented and that is important for the topic explanation.

INFO: I have written a post dedicated to PowerShell Parameters with many awesome examples so I highly encourage you to read How To Create Parameters In PowerShell

INFO: The most important concept in PowerShell to understand by far is Pipelining so if you want to know more about it, please read How PowerShell Pipeline Works

Begin block gives us feedback in result about call type to the function and labels execution of this block of code with BEGIN word.

Process block gives us first, label when this block of code has been executed with word PROCESS and second gives us the value of the message input parameter.

End block gives us feedback in the result when this block of code has been executed with the label word END.

Execution examples region has different calls to the function which are very important for the explanation of the post’s topic in the subheading that follows.

INFO: In order to write this demo example fast I have used PowerShell ISE Add-on function New-Function which I have explained in the post How To Write Advanced Functions Or CmdLets With PowerShell (Fast)

How Do Input Processing Methods (Begin, Process, End) Work?

Since we now know our demo example we can jump into the execution of the code and that will help us understand the Begin, Process, End script blocks. I would like you to pay attention to when and how many times each of the blocks have been executed dependent on the function call type.

The first call to Run-BeginProcessEndBlocks function

Call Type: Call to message parameter of function Run-BeginProcessEndBlock with a single string value.

Run-BeginProcessEndBlocks -message "HELLO" -CallType "Single Value"
Result of the call to Run-BeginProcessEndBlocks function

Explanation: Begin block has been executed first and only once, Process block follows next in execution and it is run only once showing us the value of message parameter, finally last but not least End block has been executed only once.

The second call to Run-BeginProcessEndBlocks function

Call Type: Call to message parameter of function Run-BeginProcessEndBlock with numerous string values.

Run-BeginProcessEndBlocks -message "Welcome", "to", "IMPROVESCRIPTING.COM", "with", "Dejan" -CallType "String Array"
Result of the call to Run-BeginProcessEndBlocks function

Explanation: Begin block has been executed first and only once, Process block follows next in execution and it is run only once showing us the value of message parameter, finally last but not least End block has been executed only once.

IMPORTANT: Please notice that although we have sent numerous string values into the message parameter PROCESS block has been executed only once since this type of call to Run-BeginProcessEndBlocks allows PowerShell to process the call as one batch.

TIP: If we want to process record-by-record even when we call functions with the parameter of string arrays then we should implement foreach loop like in the example below.

PROCESS
{
    foreach ($item in $message)
    {

    }
}

The third call to Run-BeginProcessEndBlocks function

Call Type: Pipeline call to Run-BeginProcessEndBlocks function with numerous string values.

"Welcome", "to", "IMPROVESCRIPTING.COM", "with", "Dejan" | Run-BeginProcessEndBlocks -CallType "Pipeline String Array"
Result of the call to Run-BeginProcessEndBlocks function

Explanation: Begin block has been executed first and only once, Process block follows next in execution and it is run as many times as there are string values send through the pipeline into the function, finally last but not least End block has been executed only once.

IMPORTANT: When we send objects through the PowerShell Pipeline to the function we should notice that the process block will execute for each object once (record-by-record processing). PowerShell cannot process this call in one batch like in the previous call to the function.

The fourth call to Run-BeginProcessEndBlocks function

Call Type: Pipeline call to Run-BeginProcessEndBlocks function with a single string value.

"HELLO"  | Run-BeginProcessEndBlocks -CallType "Pipeline Single Value"
Result of the call to Run-BeginProcessEndBlocks function

Explanation: Begin block has been executed first and only once, Process block follows next in execution and it is run only once showing us the value of message parameter, finally last but not least End block has been executed only once.


NOTE: If you want to see how the actual execution of the function works then make a breakpoint and switch in debugging mode. To know more about PowerShell Debugging read: How To Debug PowerShell Scripts

Begin, Process, End Block – Summary

Here are the main takeaways from this topic.

BEGIN

Here are the main features of the BEGIN block:

  • one-time input preprocessing method.
  • run first
  • optional
  • used to initialize and setup processing

The syntax for BEGIN block script:

Begin
{

}

PROCESS

Here are the main features of the PROCESS block:

  • record-by-record input processing method.
  • run second
  • optional
  • main functionality where the work is done

The syntax for PROCESS block script:

Process
{

}

END

Here are the main features of the END block:

  • one-time input postprocessing method.
  • run last
  • optional
  • used to release the resources after processing

The syntax for END block script:

End
{

}

Useful PowerShell Begin, Process, End Articles

Here are some useful articles and resources:

Real-World Examples

Here are a few examples of PowerShell Functions that are part of the Efficiency Booster PowerShell Project. This project is a library of my own CmdLets that help us IT personal in our everyday IT tasks.

If you want example functions to work as expected please download the source code from here.

Example 1 – Write-ErrorLog Function

This function writes errors that occur in our functions into an external Error Log text file and it is very useful for error handling and improving the quality of the code that has been written in the functions.

BEGIN block is used to check if the error log folder and file exist and if not to create them. It is very important to check if the external file exists before writing into it.

PROCESS block contains the main functionality to write error properties into an external error log text file.

END block was not used.

NOTE: If you want to know more about this function and PowerShell Error Handling please read the article: How To Log PowerShell Errors And Much More

Example of error logged in an external text file

Here is the code of Write-ErrorLog Function:

Function Write-ErrorLog {
[CmdletBinding()]
param (

    [Parameter(Mandatory=$false,
                HelpMessage="Error from computer.")] 
    [string]$hostname,

    [Parameter(Mandatory=$false,
                HelpMessage="Environment that failed. (Test, Production, Course, Acceptance...)")] 
    [string]$env,

    [Parameter(Mandatory=$false,
                HelpMessage="Type of server that failed. (Application, Web, Integration...)")] 
    [string]$logicalname,
    
    [Parameter(Mandatory=$false,
                HelpMessage="Error message.")] 
    [string]$errormsg,
    
    [Parameter( Mandatory=$false,
                HelpMessage="Exception.")]
    [string]$exception,
    
    [Parameter(Mandatory=$false, 
                HelpMessage="Name of the script that is failing.")]
    [string]$scriptname,
     
    [Parameter(Mandatory=$false,
                HelpMessage="Script fails at line number.")]
    [string]$failinglinenumber,

    [Parameter(Mandatory=$false,
                HelpMessage="Failing line looks like.")]
    [string]$failingline,
    
    [Parameter(Mandatory=$false,
                HelpMessage="Powershell command path.")]
    [string]$pscommandpath,    

    [Parameter(Mandatory=$false,
                HelpMessage="Position message.")]
    [string]$positionmsg, 

    [Parameter(Mandatory=$false,
                HelpMessage="Stack trace.")]
    [string]$stacktrace
)
BEGIN { 
        
        $errorlogfile = "$home\Documents\PSlogs\Error_Log.txt"
        $errorlogfolder = "$home\Documents\PSlogs"
        
        if  ( !( Test-Path -Path $errorlogfolder -PathType "Container" ) ) {
            
            Write-Verbose "Create error log folder in: $errorlogfolder"
            New-Item -Path $errorlogfolder -ItemType "Container" -ErrorAction Stop
        
            if ( !( Test-Path -Path $errorlogfile -PathType "Leaf" ) ) {
                Write-Verbose "Create error log file in folder $errorlogfolder with name Error_Log.txt"
                New-Item -Path $errorlogfile -ItemType "File" -ErrorAction Stop
            }
        }
}
PROCESS {  

            Write-Verbose "Start writing to Error log file. $errorlogfile"
            $timestamp = Get-Date 
            #IMPORTANT: Read just first value from collection not the whole collection.
            "   " | Out-File $errorlogfile -Append
            "************************************************************************************************************" | Out-File $errorlogfile -Append
            "Error happend at time: $timestamp on a computer: $hostname - $env - $logicalname" | Out-File $errorlogfile -Append
            "Error message: $errormsg" | Out-File $errorlogfile -Append
            "Error exception: $exception" | Out-File $errorlogfile -Append
            "Failing script: $scriptname" | Out-File $errorlogfile -Append
            "Failing at line number: $failinglinenumber" | Out-File $errorlogfile -Append
            "Failing at line: $failingline" | Out-File $errorlogfile -Append
            "Powershell command path: $pscommandpath" | Out-File $errorlogfile -Append
            "Position message: $positionmsg" | Out-File $errorlogfile -Append
            "Stack trace: $stacktrace" | Out-File $errorlogfile -Append
            "------------------------------------------------------------------------------------------------------------" | Out-File $errorlogfile -Append                   
            
            Write-Verbose "Finish writing to Error log file. $errorlogfile"
}        
END { 

}
}
#region Execution examples
#Write-ErrorLog -hostname "Server1" -env "PROD" -logicalname "APP1" -errormsg "Error Message" -exception "HResult 0789343" -scriptname "Test.ps1" -failinglinenumber "25" -failingline "Get-Service" -pscommandpath "Command pathc." -positionmsg "Position message" -stacktrace "Stack trace" -Verbose
#endregion

Example 2 – Save-ToExcel Function

This function creates an Excel Sheet as a report of the result from the functions sent down the PowerShell pipeline.

BEGIN block is used to create an empty array and test whether a folder where we will save Excell Sheet exists and if not to create the one.

PROCESS block is only used to fill the array of objects with objects sent down the PowerShell Pipeline into the function.

END block has the main functionality to format the Excell sheet, “past in” the array of objects and finally save the Excel Sheet file.

NOTE: It is important to note that this function main processing is not in PROCESS block but rather in the END block

Example Excell Sheet of Save-ToExcel CmdLet

Here is the source code of Save-ToExcel function:

Function Save-ToExcel {
[CmdletBinding()]
param (
    [Parameter(Mandatory=$true,
                ValueFromPipeline=$true, 
                HelpMessage="Input rows to be saved as Excel file.")] 
    [PSobject[]]$InputObject,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Excel file name.")]
    [string]$ExcelFileName,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Excel workbook title.")]
    [string]$title,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Excel workbook author.")]
    [string]$author,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Excel worksheet name.")]
    [string]$WorkSheetName,
    
    [Parameter(HelpMessage="Write to error log file or not.")]
    [switch]$errorlog,
    
    [Parameter( HelpMessage="Send email.")]
    [switch]$sendemail,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Client for example OK = O client, BK = B client")]
    [string]$client,
     
    [Parameter(Mandatory=$true,
                HelpMessage="Solution, for example FIN = Financial solution, HR = Humane Resource solution")]
    [string]$solution
    
    
)
BEGIN { 
    
    #Creat an empty array
    $objects = @()

    $reportsfolder = "$home\Documents\PSreports"
        
        if  ( !( Test-Path -Path $reportsfolder -PathType "Container" ) ) {
            
            Write-Verbose "Create reports folder in: $reportsfolder"
            New-Item -Path $reportsfolder -ItemType "Container" -ErrorAction Stop
        }
        
}
PROCESS { 

    $objects += $InputObject
    
}
END { 

    $date = Get-Date -UFormat "%Y-%m-%d_%H-%M-%S"

    $excelFile = "$home\Documents\PSreports\$ExcelFileName" + "-" + "$client" + "-" + "$solution" + "-" + $date + ".xlsx"

    try {
        
        #Write Excel file only if there are some Input objects!!!!!
        if ( $objects ) {

            [System.Threading.Thread]::CurrentThread.CurrentCulture = "en-US"

            #Temporary .csv file with GUID name has been created first.
            $temporaryCsvFile = ($env:temp + "\" + ([System.Guid]::NewGuid()).ToString() + ".csv") 
            #Delimiter ";" helps that result is parsed correctly. Comma delimiter parses incorrectly.
            $objects | Export-Csv -ErrorAction Stop -path $temporaryCsvFile -noTypeInformation -Delimiter ";"
            Write-Verbose "Temporary csv file saved: $temporaryCsvFile"
        
            $excelObject = New-Object -ComObject Excel.Application -ErrorAction Stop
            Write-Verbose "Excel sheet created."
            $excelObject.Visible = $false    

            $workbookObject = $excelObject.Workbooks.Open($temporaryCsvFile)  
            $workbookObject.Title = ("$title " + (Get-Date -Format D)) 
            $workbookObject.Author = "$author"
        
            $worksheetObject = $workbookObject.Worksheets.Item(1) 
        
            #Method TextToColumns is important to convert .csv file data into right columns in Excel file.
            $colA=$worksheetObject.range("A1").EntireColumn
            $colrange=$worksheetObject.range("A1")
            $xlDelimited = 1
            $xlTextQualifier = 1
            $colA.TextToColumns($colrange,$xlDelimited,$xlTextQualifier,$false,$false,$false,$true)
     
            $worksheetObject.UsedRange.Columns.Autofit() | Out-Null
            $worksheetObject.Name = "$WorkSheetName"
        
            #Style of table in Excel worksheet.
            $xlSrcRange = 1
            $XlYes = 1
            #Syntax - expression.Add(SourceType, Source, LinkSource, HasHeaders, Destination)
            $listObject = $worksheetObject.ListObjects.Add($xlSrcRange, $worksheetObject.UsedRange, $null, $XlYes, $null) 
            $listObject.Name = "User Table"
            $listObject.TableStyle = "TableStyleMedium4" # Style Cheat Sheet in French/English: http://msdn.microsoft.com/fr-fr/library/documentformat.openxml.spreadsheet.tablestyle.aspx   

            $workbookObject.SaveAs($excelFile,51) # http://msdn.microsoft.com/en-us/library/bb241279.aspx 
            $workbookObject.Saved = $true
            $workbookObject.Close() 
            [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbookObject) | Out-Null  

            $excelObject.Quit() 
            [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelObject) | Out-Null
            [System.GC]::Collect() 
            [System.GC]::WaitForPendingFinalizers()    
            Write-Verbose "Excel application process deleted from the system."
        
            if(Test-Path -path $temporaryCsvFile) { 
                Remove-Item -path $temporaryCsvFile -ErrorAction Stop
                Write-Verbose "Temporary csv file deleted: $temporaryCsvFile" 
            }
        
            if ( $sendemail ) {
        
                $errorlogfile = "$home\Documents\PSlogs\Error_Log.txt"
                $attachments = "$errorlogfile","$excelFile"
            
                Write-Verbose "Sending email."
                Send-Email -Attachments $attachments -Priority "Normal" -errorlog -client $client -solution $solution
                Write-Verbose "Email sendt."
             }
        
        }
    } catch {
        Write-Warning "SaveToExcel function failed"
        Write-Warning "Error message: $_"

        if ( $errorlog ) {

            $errormsg = $_.ToString()
            $exception = $_.Exception
            $stacktrace = $_.ScriptStackTrace
            $failingline = $_.InvocationInfo.Line
            $positionmsg = $_.InvocationInfo.PositionMessage
            $pscommandpath = $_.InvocationInfo.PSCommandPath
            $failinglinenumber = $_.InvocationInfo.ScriptLineNumber
            $scriptname = $_.InvocationInfo.ScriptName

            Write-Verbose "Start writing to Error log."
            Write-ErrorLog -hostname "SaveToExcel has failed" -errormsg $errormsg -exception $exception -scriptname $scriptname -failinglinenumber $failinglinenumber -failingline $failingline -pscommandpath $pscommandpath -positionmsg $pscommandpath -stacktrace $stacktrace
            Write-Verbose "Finish writing to Error log."
        } 
    } 
}


}
#region Execution examples
#Get-OSInfo -computers "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -ExcelFileName "OS_Info" -title "OS Info for servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "OS Info" -client "OK" -solution "FIN" -errorlog -Verbose

#Get-Printer -computers "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -ExcelFileName "Printers_With_Error" -title "Printers with errors on servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "Printers with errors" -client "OK" -solution "FIN" 

#Get-Printer -computers "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -ExcelFileName "Printers_With_Error" -title "Printers with errors on servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "Printers with errors" -sendemail -client "OK" -solution "FIN" 

#Get-DiskFreeSpace -computers "OKFINservers.txt" -client "OK" -solution "FIN" -Verbose -errorlog | Save-ToExcel -ExcelFileName "Free_disk_space" -title "Free disk space on servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "Free disk space" -sendemail -client "OK" -solution "FIN" 

#Get-ErrorFromEventLog -computers "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -days 3 -Verbose | Save-ToExcel -ExcelFileName "Get-ErrorsInEventLogs" -title "Get errors from Event Logs on servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "Errors from Event Logs" -sendemail -client "OK" -solution "FIN" 

#Get-ErrorFromEventLog -computers "OKFINkursservers.txt" -errorlog -client "OK" -solution "FIN" -days 3 -Verbose | Save-ToExcel -ExcelFileName "Get-ErrorsInEventLogs" -title "Get errors from Event Logs on servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "Errors from Event Logs" -client "OK" -solution "FIN" 

#Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -ExcelFileName "Get-CPUinfo" -title "Get CPU info of servers in Financial solution for " -author "DJ PowerScirpt" -WorkSheetName "CPU Info" -client "OK" -solution "FIN" 
#endregion

Example 3 – Get-CPUInfo Function

This function as result returns CPU properties for a list of servers and it is a typical representative of how most of the functions in the Efficiency Booster PowerShell Project have been written.

BEGIN block depending on the PowerShell Parameter Set used will check if an external file with the list of servers exists and read the content of it.

IMPORTANT: If you want to know more about PowerShell ParameterSets and how to create and use them please read How To Use Parameter Sets In PowerShell Functions

PROCESS block contains the main functionality of Get-CPUInfo Function

END block is not used.

Here is the source code of Get-CPUInfo function:

Function Get-CPUInfo {
[CmdletBinding(DefaultParametersetName="ServerNames")]
param (
    [Parameter( ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true,
                ParameterSetName="ServerNames",
                HelpMessage="List of computer names separated by commas.")]
    [Alias('hosts')] 
    [string[]]$computers = 'localhost',
    
    [Parameter( ParameterSetName="FileName",
                HelpMessage="Name of txt file with list of servers. Txt file should be in 01servers folder.")] 
    [string]$filename,
    
    [Parameter( Mandatory=$false,
                HelpMessage="Write to error log file or not.")]
    [switch]$errorlog,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Client for example OK = O client, BK = B client")]
    [string]$client,
     
    [Parameter(Mandatory=$true,
                HelpMessage="Solution, for example FIN = Financial, HR = Human Resource")]
    [string]$solution     
)

BEGIN {

    if ( $PsCmdlet.ParameterSetName -eq "FileName") {

        if ( Test-Path -Path "$home\Documents\WindowsPowerShell\Modules\01servers\$filename" -PathType Leaf ) {
            Write-Verbose "Read content from file: $filename"
            $computers = Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\$filename" )        
        } else {
            Write-Warning "This file path does NOT exist: $home\Documents\WindowsPowerShell\Modules\01servers\$filename"
            Write-Warning "Create file $filename in folder $home\Documents\WindowsPowerShell\Modules\01servers with list of server names."
            break;
        }
       
    }

}
PROCESS { 

    foreach ($computer in $computers ) {
        
        if ( $computer -eq 'localhost' ) {
            $computer = $env:COMPUTERNAME
            Write-Verbose "Replace localhost with real name of the server."
        }
        
        $computerinfo = Get-ComputerInfo -computername $computer -client $client -solution $solution
        $hostname = $computerinfo.hostname
        $env = $computerinfo.environment
        $logicalname = $computerinfo.logicalname
        $ip = $computerinfo.ipaddress
        
        try {
            Write-Verbose "Start processing: $computer - $env - $logicalname"
            Write-Verbose "Start Win32_Processor processing..."
            $CPUInfos = $null

            $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Processor';
                         'ErrorAction'='Stop'}

            $CPUInfos = Get-CimInstance @params | 
                            Select-Object   @{label="ServerName"; Expression={$_.SystemName}}, 
                                            @{label="CPU"; Expression={$_.Name}}, 
                                            @{label="CPUid"; Expression={$_.DeviceID}}, 
                                            NumberOfCores, 
                                            AddressWidth
            
            Write-Verbose "Finish Win32_Processor processing..."        
            
            foreach ($CPUInfo in $CPUInfos) {
                Write-Verbose "Start processing CPU: $CPUInfo"

                $properties = @{ 'Environment'=$env;
                                 'Logical name'=$logicalname;
                                 'Server name'=$CPUInfo.ServerName;
            	                 'CPU'=$CPUInfo.CPU;
            	                 'CPU ID'=$CPUInfo.CPUid;
            	                 'Number of CPU cores'=$CPUInfo.NumberOfCores; 
                                 '64 or 32 bits'=$CPUInfo.AddressWidth;
                                 'IP'=$ip;
                                 'Collected'=(Get-Date -UFormat %Y.%m.%d' '%H:%M:%S)}

                $obj = New-Object -TypeName PSObject -Property $properties
                $obj.PSObject.TypeNames.Insert(0,'Report.CPUInfo')

                Write-Output $obj
                Write-Verbose "Finish processing CPU: $CPUInfo"
            }
            
            Write-Verbose "Finish processing: $computer - $env - $logicalname"
                        
        } catch {
            Write-Warning "Computer failed: $computer - $env - $logicalname CPU failed: $CPUInfos"
            Write-Warning "Error message: $_"

            if ( $errorlog ) {

                $errormsg = $_.ToString()
                $exception = $_.Exception
                $stacktrace = $_.ScriptStackTrace
                $failingline = $_.InvocationInfo.Line
                $positionmsg = $_.InvocationInfo.PositionMessage
                $pscommandpath = $_.InvocationInfo.PSCommandPath
                $failinglinenumber = $_.InvocationInfo.ScriptLineNumber
                $scriptname = $_.InvocationInfo.ScriptName

               
                $ErrorArguments = @{
                    'hostname' = $computer;
                    'env' = $env;
                    'logicalname' = $logicalname;
                    'errormsg' = $errormsg;
                    'exception' = $exception;
                    'stacktrace'= $stacktrace;
                    'failingline' = $failingline;
                    'positionmsg' = $positionmsg;
                    'pscommandpath' = $pscommandpath;
                    'failinglinenumber' = $failinglinenumber;
                    'scriptname' = $scriptname
                }
               
                ##Splatting as array
                ##$ErrorArguments = 'Test', 'PROD', 'APP'

                Write-Verbose "Start writing to Error log."
                Write-ErrorLog @ErrorArguments
                #Write-ErrorLog -hostname $computer -env $env -logicalname $logicalname -errormsg $errormsg -exception $exception -scriptname $scriptname -failinglinenumber $failinglinenumber -failingline $failingline -pscommandpath $pscommandpath -positionmsg $pscommandpath -stacktrace $stacktrace
                Write-Verbose "Finish writing to Error log."
            }
        }
                        
    }
     
}
END { 
}
}
#region Execution examples
#Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical Name', 'Server Name', 'CPU', 'CPU ID', 'Number of CPU cores', '64 or 32 bits', 'IP', 'Collected'   | Out-GridView

<#
#Test ParameterSet = ServerName
Get-CPUInfo -client "OK" -solution "FIN"
Get-CPUInfo -client "OK" -solution "FIN" -errorlog
Get-CPUInfo -client "OK" -solution "FIN" -errorlog -Verbose
Get-CPUInfo -computers 'APP100001' -client "OK" -solution "FIN" -errorlog
Get-CPUInfo -computers 'APP100001', 'APP100002' -client "OK" -solution "FIN" -errorlog -Verbose
Get-CPUInfo -hosts 'APP100001' -client "OK" -solution "FIN" -errorlog
Get-CPUInfo -computers (Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\OKFINservers.txt" )) -client "OK" -solution "FIN" -errorlog -Verbose

#Pipeline examples
'APP100001' | Get-CPUInfo -client "OK" -solution "FIN" -errorlog
'APP100001', 'APP100002' | Get-CPUInfo -client "OK" -solution "FIN" -errorlog -Verbose
'APP100001', 'APP100002' | Select-Object @{label="computers";expression={$_}} | Get-CPUInfo -client "OK" -solution "FIN" -errorlog
Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\OKFINservers.txt" ) | Get-CPUInfo -client "OK" -solution "FIN" -errorlog -Verbose
'ERROR' | Get-CPUInfo -client "OK" -solution "FIN" -errorlog

#Test CmdLet help
Help Get-CPUInfo -Full

#SaveToExcel
Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -errorlog -ExcelFileName "Get-CPUinfo" -title "Get CPU info of servers in Financial solution for " -author "DJ PowerScript" -WorkSheetName "CPU Info" -client "OK" -solution "FIN" 
#SaveToExcel and send email
Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -sendemail -errorlog -ExcelFileName "Get-CPUinfo" -title "Get CPU info of servers in Financial solution for " -author "DJ PowerScript" -WorkSheetName "CPU Info" -client "OK" -solution "FIN" 

#Benchmark
#Time = 52; Total Items = 46
Measure-BenchmarksCmdLet { Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose }
#Time = 52 sec; Total Items = 46
Measure-BenchmarksCmdLet { Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" }

#Baseline create
Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-Baseline -errorlog -BaselineFileName "Get-CPUInfo" -client "OK" -solution "FIN" -Verbose
#Baseline archive and create new
Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-Baseline -archive -errorlog -BaselineFileName "Get-CPUInfo"  -client "OK" -solution "FIN" -Verbose

#Test ParameterSet = FileName
Get-CPUInfo -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose
Get-CPUInfo -filename "OKFINcourseserverss.txt" -errorlog -client "OK" -solution "FIN" -Verbose
#>
#endregion

About Dejan Mladenović

Post Author Dejan MladenovicHey Everyone! I hope that this article you read today has taken you from a place of frustration to a place of joy coding! Please let me know of anything you need for Windows PowerShell in the comments below that can help you achieve your goals!
I have 18+ years of experience in IT and you can check my Microsoft credentials. Transcript ID: 750479 and Access Code: DejanMladenovic
Credentials
About Me...

My Posts | Website

Dejan Mladenović

Hey Everyone! I hope that this article you read today has taken you from a place of frustration to a place of joy coding! Please let me know of anything you need for Windows PowerShell in the comments below that can help you achieve your goals! I have 18+ years of experience in IT and you can check my Microsoft credentials. Transcript ID: 750479 and Access Code: DejanMladenovic
Credentials About Me...

Recent Posts

PowerShell Function Begin Process End Blocks Explained With Examples Pinterest