Introduction
This script can be used for exporting specified performance counter values from multiple remote target servers to CSV file. The challenge is to gather the specific counter information and append it to CSV file with Powershell2.0.
Performance counters
The script will pull the below mentioned counter values
- Processor (_total)\% processor time
- system\processor queue length
- Memory\Available MBytes
- Memory\% committed bytes in use
- PhysicalDisk (*)\Current Disk Queue Length
- PhysicalDisk (*)\Avg. Disk sec/Transfer
- PhysicalDisk (*)\% Disk Time
- PhysicalDisk (*)\Disk Read Bytes/sec
- PhysicalDisk (*)\Disk Write Bytes/sec
- Network Interface (*)\Bytes Total/sec
Scenarios
IT Administrators may want to analyze the performance the servers with the help of perfmon counters information’s.
Prerequisites
- The source machine should have PowerShell 2.0 installed
Download the code:- http://gallery.technet.microsoft.com/PowerShell-Perfmon-0f013da8
Script
You can use this script in following ways:
1. Download the script.
2. Open the script file with Notepad or any other script editors (preferably Windows PowerShell ISE)
3. Change the Input file path and Output file if required other than the default location as shown in below screenshot.
4. Counters can be selected based on your requirement by changing the below code
5. Save the file then run the script via PowerShell in “Run as administrator” mode.
You can run this script manually or by scheduler task
How to create a scheduler task:
1. Open “Task Scheduler” (Goto START—RUN —Type Tasks and hit enter)
2. Click “Create task”
3. Pick a name, and choose “Run whether user is logged on or not”
Choose “Triggers” Tab, Click “New”
5. Specify option you like, and then click “OK” to create a trigger
Choose “Actions” tab, Click “New”
7. Copy following command to “Program/script” textbox, click C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
8. Enter the path of the saved script file in “Add arguments (optionally)” textbox
As per the screenshot I saved the file under C:\Perform_script.ps1 hence I updated the add arguments text box as
C:\Perform_script.ps1; exit”
Code:
<# # Script: Get-CounterStats # Author: Prashanth and Praveen # Comments: This script will collect the specific counters value from the multiple target machines/servers which will be used to analayze the performance of target servers. #> #Define Input and output filepath $servers=get-content "C:\servers.txt" $outfile="C:\perfmon.csv" ################################################################################################################ ################################################################################################################ #Actual script starts here function Global:Convert-HString { [CmdletBinding()] Param ( [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [String]$HString )#End Param Begin { Write-Verbose "Converting Here-String to Array" }#Begin Process { $HString -split "`n" | ForEach-Object { $ComputerName = $_.trim() if ($ComputerName -notmatch "#") { $ComputerName } } }#Process End { # Nothing to do here. }#End }#Convert-HString #Function to have the customized output in CSV format function Export-CsvFile { [CmdletBinding(DefaultParameterSetName='Delimiter', SupportsShouldProcess=$true, ConfirmImpact='Medium')] param( [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [System.Management.Automation.PSObject] ${InputObject}, [Parameter(Mandatory=$true, Position=0)] [Alias('PSPath')] [System.String] ${Path}, #region -Append [Switch] ${Append}, #endregion [Switch] ${Force}, [Switch] ${NoClobber}, [ValidateSet('Unicode','UTF7','UTF8','ASCII','UTF32','BigEndianUnicode','Default','OEM')] [System.String] ${Encoding}, [Parameter(ParameterSetName='Delimiter', Position=1)] [ValidateNotNull()] [System.Char] ${Delimiter}, [Parameter(ParameterSetName='UseCulture')] [Switch] ${UseCulture}, [Alias('NTI')] [Switch] ${NoTypeInformation}) begin { # This variable will tell us whether we actually need to append # to existing file $AppendMode = $false try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Export-Csv', [System.Management.Automation.CommandTypes]::Cmdlet) #String variable to become the target command line $scriptCmdPipeline = '' # Add new parameter handling #region Dmitry: Process and remove the Append parameter if it is present if ($Append) { $PSBoundParameters.Remove('Append') | Out-Null if ($Path) { if (Test-Path $Path) { # Need to construct new command line $AppendMode = $true if ($Encoding.Length -eq 0) { # ASCII is default encoding for Export-CSV $Encoding = 'ASCII' } # For Append we use ConvertTo-CSV instead of Export $scriptCmdPipeline += 'ConvertTo-Csv -NoTypeInformation ' # Inherit other CSV convertion parameters if ( $UseCulture ) { $scriptCmdPipeline += ' -UseCulture ' } if ( $Delimiter ) { $scriptCmdPipeline += " -Delimiter '$Delimiter' " } # Skip the first line (the one with the property names) $scriptCmdPipeline += ' | Foreach-Object {$start=$true}' $scriptCmdPipeline += '{if ($start) {$start=$false} else {$_}} ' # Add file output $scriptCmdPipeline += " | Out-File -FilePath '$Path' -Encoding '$Encoding' -Append " if ($Force) { $scriptCmdPipeline += ' -Force' } if ($NoClobber) { $scriptCmdPipeline += ' -NoClobber' } } } } $scriptCmd = {& $wrappedCmd @PSBoundParameters } if ( $AppendMode ) { # redefine command line $scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock( $scriptCmdPipeline ) } else { # execute Export-CSV as we got it because # either -Append is missing or file does not exist $scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock( [string]$scriptCmd ) } # standard pipeline initialization $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } } #Performance counters declaration function Get-CounterStats { param ( [String]$ComputerName = $ENV:ComputerName ) $Object =@() $Counter = @" Processor(_total)\% processor time system\processor queue length Memory\Available MBytes Memory\% committed bytes in use PhysicalDisk(*)\Current Disk Queue Length PhysicalDisk(*)\Avg. Disk sec/Transfer PhysicalDisk(*)\% Disk Time PhysicalDisk(*)\Disk Read Bytes/sec PhysicalDisk(*)\Disk Write Bytes/sec Network Interface(*)\Bytes Total/sec "@ (Get-Counter -ComputerName $ComputerName -Counter (Convert-HString -HString $Counter)).counterSamples | ForEach-Object { $path = $_.path New-Object PSObject -Property @{ computerName=$ComputerName; Counter = ($path -split "\\")[-2,-1] -join "-" ; Item = $_.InstanceName ; Value = [Math]::Round($_.CookedValue,2) datetime=(Get-Date -format "yyyy-MM-d hh:mm:ss") } } } #Collecting counter information for target servers foreach($server in $Servers) { $d=Get-CounterStats -ComputerName $server |Select-Object computerName,Counter,Item,Value,datetime $d |Export-CsvFile $outfile -Append -NoTypeInformation } #End of Script
Output:-