{"id":2057,"date":"2015-07-01T00:00:00","date_gmt":"2015-07-01T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/powershell-day-to-day-admin-tasks-monitoring-performance\/"},"modified":"2021-04-20T10:13:58","modified_gmt":"2021-04-20T10:13:58","slug":"powershell-day-to-day-admin-tasks-monitoring-performance","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/powershell-day-to-day-admin-tasks-monitoring-performance\/","title":{"rendered":"PowerShell Day-to-Day Admin Tasks: Monitoring Performance"},"content":{"rendered":"<h4>The series so far:<\/h4>\n<ol>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/automating-day-to-day-powershell-admin-tasks---jobs-and-workflow\/\">Automating Day-to-Day PowerShell Admin Tasks \u2013 Part 1: Jobs and Workflow<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/powershell-day-to-day-admin-tasks-wmi,-cim-and-pswa\/\">PowerShell Day-to-Day Admin Tasks \u2013 Part 2: WMI, CIM and PSWA<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/powershell-day-to-day-admin-tasks-monitoring-performance\/\">PowerShell Day-to-Day Admin Tasks \u2013 Part 3: Monitoring Performance<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/powershell-day-to-day-sysadmin-tasks-securing-scripts\/\">PowerShell Day-to-Day Admin Tasks \u2013 Part 4: Securing Scripts<\/a><\/li>\n<li>PowerShell Day-to-Day Admin Tasks \u2013 Part 5: Events and Monitoring<\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sysadmin\/powershell\/powershell-day-to-day-admin-tasks-part-6-real-time-it-dashboard\/\">PowerShell Day-to-Day Admin Tasks - Part 6: Real Time IT Dashboard<\/a><\/li>\n<\/ol>\n\n<p class=\"start\">Whether you are a systems administrator or an administrator of either database or networks, it is likely that you have a daily struggle with the task of gathering and analysing performance counters in order to monitor performance of the devices in your care. If the systems are operational and respond to their workload quickly, then this indicates that all is likely to be well. But how do you make sure routinely? Can you easily spot signs of potential trouble?<\/p>\n<p>I&#8217;ve already demonstrated the PowerShell methods of accessing and interacting with your devices. So you&#8217;re ready to understand the many opportunities that the various PowerShell commands provide to make your life easier and less monotonous. This article will describe how to collect, export, display and analyse data from performance counters.<\/p>\n<p>As this article is relatively important for a SysAdmin, I will provide several basic examples just to illustrate how data about performance counters is gathered and analysed. Then, at the end, we will look at more practical examples.<\/p>\n<h2>Gathering data from performance counters<\/h2>\n<p>It is possible to gather data performance that will help us with the diagnosis of certain problems. Indeed, we can access many different types of data on the device that we&#8217;re monitoring: data such as Processor, Memory or Disk amongst others. In order to do that, the command <strong>Get-Counter<\/strong> was introduced with Windows 8 and Windows Sever 2012. Let&#8217;s start by obtaining available groups on our local device:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">  PS &gt; Get-Counter -ListSet * | Select-Object -ExpandProperty CounterSetName <\/pre>\n<p>This command gives us a great deal of information in the results, so I will only display the names of the groups.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure0-ac5c570b-bcd8-403e-ba03-44e4c5e4bfad.png\" alt=\"2249-figure0-ac5c570b-bcd8-403e-ba03-44e\" \/><\/p>\n<p class=\"caption\">Figure1 &#8211; List of groups available<\/p>\n<p>As well as the core groups, or sets, of counters, certain additional groups may be available depending on the machine you execute this command on. Here, the device has the &#8220;Hyper-V&#8221; role available so there are corresponding groups of counters. If we want to drill down into the counters available for Hyper-V, we can then display several groups starting with &#8220;Hyper-V&#8221;. The complete list of these groups on my device can be obtained with the following command:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">    PS &gt; Get-Counter -ListSet *Hyper-V* | Select-Object CounterSetName, CounterSetType, Description, Paths | Out-GridView -Title \"Hyper-V counters\" \r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure6-1922d3ca-f744-476a-858f-b633f6f451b7.png\" alt=\"2249-figure6-1922d3ca-f744-476a-858f-b63\" \/><\/p>\n<p class=\"caption\">Figure2 &#8211; List of groups beginning with &#8220;Hyper-V&#8221;<\/p>\n<p>Here, I&#8217;ve used the <strong>Out-<\/strong><strong>GridView<\/strong> Cmdlet to represent this data in a more readable form.<\/p>\n<p>As a matter of interest, you can find out the total number of available groups at your disposal with the following commands:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">  PS &gt; $TotalCounter = Get-Counter -ListSet *\r\n    PS &gt; $TotalCounter | Measure-Object | select Count\r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure2-fc85aaa9-1b2a-47d8-a778-e6a0571a2fd7.png\" alt=\"2249-figure2-fc85aaa9-1b2a-47d8-a778-e6a\" \/><\/p>\n<p class=\"caption\">Figure3 &#8211; Number of available groups<\/p>\n<h2>Accessing the counter data<\/h2>\n<p>The <strong>&#8211;<\/strong><strong>counter<\/strong> parameter associated with the <strong>Get-Counter<\/strong> command allows us to specify one or more counters to analyze. In a first instance, I&#8217;ll retrieve the available memory on my Hypervisor:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> PS &gt; get-counter -counter \"\\memory\\available mbytes\"\r\n<\/pre>\n<div class=\"note\">\n<p class=\"note\">Note:When you obtain the result, the data is given in a pre-formatted &#8220;cooked value&#8221;. This refers to the formula for calculating performance data. A performance counter can be &#8216;Raw&#8217;, &#8216;Second&#8217; and &#8216;cooked&#8217;. An expression containing the first two gives the &#8220;<a href=\"http:\/\/blogs.technet.com\/b\/nexthop\/archive\/2011\/06\/02\/gpsperfcounters.aspx\">cooked values<\/a>&#8220;. These latter ones are a representation of the values understandable by humans.<\/p>\n<\/div>\n<p>Now, I want to verify that the virtual machine displayed on my Hypervisor has enough memory. (This is not to train you on the learning of Hyper-V, for this, I merely suggest this excellent article on the concept of <a href=\"http:\/\/blogs.technet.com\/b\/chrisavis\/archive\/2013\/03\/06\/monitoring-dynamic-memory.aspx\">Dynamic Memory<\/a>) For this, I check the result of the &#8220;Average Pressure&#8221; counter. If the latter is below 100, then the virtual machine has sufficient memory:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">   PS &gt; (Get-Counter '\\Hyper-V Dynamic Memory VM(*)\\Average Pressure').CounterSamples[0].CookedValue \r\n<\/pre>\n<p>The sign * means that all processes of the overall virtual machines. But I can point out a particular process:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">    PS &gt; (Get-Counter '\\Hyper-V Dynamic Memory VM(WindowsServer2016)\\Average Pressure').CounterSamples[0].<\/pre>\n<p>This is fine but in this example, I already knew the names of the counters I needed. Occasionally, however, I will need to find out the available counters in a new group. In this example, I have a particular interest in monitoring the performance of Hyper-V. Therefore, I retrieve in a first instance the overall paths of this group of performance counters into a <strong>$<\/strong><strong>HyperVInformations<\/strong> variable. Then I display the counters:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">    PS &gt; $HyperVInformations = (get-counter -ListSet \"Hyper-V Hypervisor\").paths\r\n    PS &gt; Get-Counter -Counter $HyperVInformations\r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure17-31ac5598-10fb-4234-a9ed-17878dc88642.png\" alt=\"2249-figure17-31ac5598-10fb-4234-a9ed-17\" \/><\/p>\n<p class=\"caption\">Figure4 &#8211; List of counters<\/p>\n<p>If I wish to display only one counter as I did in previous examples, then I just need to indicate it in the <strong>Get-Counter<\/strong> cmdlet:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> PS &gt; (Get-Counter -ListSet \"Hyper-V Hypervisor\").paths\r\n    PS &gt; Get-Counter -Counter \"\\Hyper-V Hypervisor\\Virtual Processors\"\r\n<\/pre>\n<h2>Obtaining several data sets<\/h2>\n<p>By default, only a single set of data is retrieved. However, we are likely to be interested in seeing the progressive values of a counter over a longer period of time. The first idea that comes to mind is to manually run the same command at regular intervals. Is this a solution? No, I must automate this action. That&#8217;s perfect, because PowerShell has foreseen this with the parameter <strong>&#8211;<\/strong><strong>MaxSamples<\/strong>. It allows us to specify the number of sets of data to retrieve. I can also use the parameter <strong>-Continuous<\/strong> to gather results <em>ad infinitum<\/em>, using CTRL + C to stop the retrieving process.<\/p>\n<p>This command allows us to verify the memory of our host for a 10 second interval (10 sets * 1 second), with one reading every second:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">  PS &gt; Get-Counter -Counter \"\\memory\\available mbytes\" -MaxSamples 10 -SampleInterval 1 \r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure7-ef23004f-2076-4398-861b-80c479eb5821.png\" alt=\"2249-figure7-ef23004f-2076-4398-861b-80c\" \/><\/p>\n<p class=\"caption\">Figure5 &#8211; Display of memory on the data of 10 sets<\/p>\n<p>It is, of course, possible to specify a sampling time-interval (in seconds) to this command, as by default, the values are retrieved every second. So as to have a preview of the memory usage, we will specify 10 sets of data taken one every minute over ten minutes:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">  PS &gt; Get-Counter -Counter \"\\memory\\available mbytes\" -MaxSamples 10 -SampleInterval 60 \r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure8-ada60eb2-9355-43bf-a0cd-bbe5243ba4a2.png\" alt=\"2249-figure8-ada60eb2-9355-43bf-a0cd-bbe\" \/><\/p>\n<p class=\"caption\">Figure6 &#8211; Time interval every minute<\/p>\n<p>You can indicate several counters within the same command by passing them as an array:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">  PS &gt; $CtrsList = \"\\Memory\\Page Faults\/sec\",\"\\Memory\\% Committed Bytes In Use\",\"\\Memory\\Available MBytes\"\r\n    PS &gt; Get-Counter -counter $CtrsList | Select-Object -ExpandProperty CounterSamples\r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure9-242a52f3-eba9-4672-b7e1-dbab39638b65.png\" alt=\"2249-figure9-242a52f3-eba9-4672-b7e1-dba\" \/><\/p>\n<p class=\"caption\">Figure7 &#8211; Multiple counters<\/p>\n<h2>Remote counter access<\/h2>\n<p>We can interrogate remote devices to obtain their performance counter data. For this, the <strong>&#8211;<\/strong><strong>ComputerName<\/strong> parameter is used. As well as specifying a single computer, we can use it to interrogate a number of devices to check that the device behaves correctly. We can pass the cmdlet a list of computers as an array.<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> PS &gt; $Counters = '\\Memory\\% Committed Bytes in Use',\r\n    \u00a0\u00a0 '\\Memory\\Available MBytes',\r\n    \u00a0\u00a0 '\\PhysicalDisk(_Total)\\Disk Write\/sec'\r\n    PS &gt; $Computers = \"ADM01\",\"ADM11\"\r\n    PS &gt; Get-Counter -counter $Counters -ComputerName $Computers  \r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure10-b0f733cd-9f2c-4bce-b53f-d2ac9ec4943c.png\" alt=\"2249-figure10-b0f733cd-9f2c-4bce-b53f-d2\" \/><\/p>\n<p class=\"caption\">Figure8 &#8211; Remote data access<\/p>\n<p>You may also use a text folder that contains a list of servers to be analyzed: for this, you need to indicate it the following to the parameter <strong>&#8211;<\/strong><strong>computername<\/strong>:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">    PS &gt; Get-Counter -computername (get-content servers.txt) \"\\Memory\\Available Mbytes\"  <\/pre>\n<div class=\"note\">\n<p class=\"note\">Note:The main restriction is that Get-Counter has no <strong>&#8211;<\/strong><strong>Credentials<\/strong> parameter. The\u00a0local account that you use to run PowerShell must be in the &#8216;Performance Monitor Users&#8217; group on every remote server. If this proves to be a problem, you must use the <strong>Invoke-Command<\/strong> in the following way:<\/p>\n<\/div>\n<pre class=\"lang:ps theme:powershell-ise\">    PS &gt; Invoke-Command -ComputerName ADM01,ADM11 -ScriptBlock { Get-Counter -Counter \"xxxxxxxxxxx\" } -credential DOMAIN\\USER\u00a0 \r\n<\/pre>\n<h2>The counters and jobs<\/h2>\n<p>You will have gathered that, to obtain data performance over a time period, you will need that time period for execution. Furthermore, it is likely that this data must be gathered over set periods of time, Such as outside office hours. Therefore, I recommend to use PowerShell jobs as we have already seen in the first part of these series.<\/p>\n<p>Herewith a very simple example:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> PS &gt; Start-Job -ScriptBlock {Get-Counter -Counter \"\\LogicalDisk(_Total)\\% Free Space\" -MaxSamples 1000} \r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure13-64567026-2756-47f5-af4f-16004246002d.png\" alt=\"2249-figure13-64567026-2756-47f5-af4f-16\" \/><\/p>\n<p class=\"caption\">Figure9 &#8211; Jobs and counters<\/p>\n<p>Then I only need to launch a <strong>Receive-Job<\/strong> to obtain the result of my command.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure14-e2b7d933-a70c-46df-b7dd-61288496e0e7.png\" alt=\"2249-figure14-e2b7d933-a70c-46df-b7dd-61\" \/><\/p>\n<p class=\"caption\">Figure10 &#8211; Receive-Job<\/p>\n<p>So finally, let&#8217;s imagine that several processes are being performed on my server during the night and I wish to inspect the way that disk space has changed overnight when I need the data the following morning. I plan the job so that it begins at 1 am on the &#8220;Free Space&#8221; counter for all the disks:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">    $CheckFreeSpace = {Get-Counter -Counter \"\\LogicalDisk(_Total)\\% Free Space\" -MaxSamples 360 -SampleInterval 60 | Export-Counter -Path C:\\CheckFreeSpace.csv -FileFormat CSV}\r\n    \r\n    $MyTrigger = New-JobTrigger -Daily -At 1am\r\n    \r\n    Register-ScheduledJob -Name \"Check Free Space\" -Trigger $MyTrigger -ScriptBlock $CheckFreeSpace\r\n<\/pre>\n<p>You just have to run <strong>Get-<\/strong><strong>ScheduledJob<\/strong> to get the status of this job. Then, the csv file will be created and you can inspect data into Microsoft Excel when it is done. I will explain later how to export results with <strong>Export-Counter<\/strong>.<\/p>\n<h2>Counters and Microsoft products<\/h2>\n<p>We can easily get performance counters from the more common Microsoft products.<\/p>\n<h3>Microsoft Exchange.<\/h3>\n<p>I can get the number of users connected on the Web Access with the following command:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">   PS &gt; Get-Counter \"\\MSExchange OWA\\Current Unique Users\" -ComputerName CAS-Server \r\n<\/pre>\n<p>I can also obtain the number of clients actually connected on my CAS server:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">  PS &gt; Get-Counter \"\\MSExchange RpcClientAccess\\User Count\" -ComputerName CAS-Server<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure11-8a707d27-9c3d-4d80-848c-1636f6215af4.png\" alt=\"2249-figure11-8a707d27-9c3d-4d80-848c-16\" \/><\/p>\n<p class=\"caption\">Figure11 &#8211; Exchange 2010 and counters<\/p>\n<p>And finally the number of operations per second:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> PS &gt; Get-Counter '\\MSExchange RpcClientAccess\\RPC Operations\/sec'  <\/pre>\n<h3>System Center Operations Manager.<\/h3>\n<p>Here I wish to know the number of workflows running on my SCOM server:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">   PS &gt; Get-Counter -ComputerName RMS-Server -Counter \"\\Health Service\\Workflow Count\" -SampleInterval 1 -MaxSamples 1 \r\n<\/pre>\n<div class=\"note\">\n<p class=\"note\">Note:A workflow, in this context, means a process being executed and launched by the SCOM agent.<\/p>\n<\/div>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure16-2b49598d-453c-4127-83a4-5fb71cd8e850.png\" alt=\"2249-figure16-2b49598d-453c-4127-83a4-5f\" \/><\/p>\n<p class=\"caption\">Figure12 &#8211; SCOM 2012 R2 and counters<\/p>\n<h2>Exporting data<\/h2>\n<p>At this point in the article, you have all you need to obtain the performance of your devices. To end this article on the counters, there is one more important thing to learn: the display of results in graphic forms. This will ease the reading and analysis. The command <strong>Export-Counter<\/strong> allows to create a file with the extension <strong>.BLG<\/strong> that may be read with the Windows Performance Monitor tool.<\/p>\n<p>Let&#8217;s take the following example:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> $CtrList = @(\r\n    \u00a0\u00a0\u00a0 \"\\System\\Processor Queue Length\",\r\n    \u00a0\u00a0\u00a0 \"\\Memory\\Pages\/sec\",\r\n    \u00a0\u00a0\u00a0 \"\\Memory\\Available MBytes\",\r\n    \u00a0\u00a0\u00a0 \"\\Processor(*)\\% Processor Time\",\r\n    \u00a0\u00a0\u00a0 \"\\Network Interface(*)\\Bytes Received\/sec\",\r\n    \u00a0\u00a0\u00a0 \"\\Network Interface(*)\\Bytes Sent\/sec\",\r\n    \u00a0\u00a0\u00a0 \"\\LogicalDisk(C:)\\% Free Space\",\r\n    \u00a0\u00a0\u00a0 \"\\LogicalDisk(*)\\Avg. Disk Queue Length\"\r\n    \u00a0\u00a0\u00a0 )\r\n    Get-Counter -Counter $CtrList -SampleInterval 5 -MaxSamples 5 | Export-Counter -Path C:\\PerfExample.blg -FileFormat BLG -Force\r\n<\/pre>\n<div class=\"note\">\n<p class=\"note\">Note:The argument <strong>&#8211;<\/strong><strong>Force <\/strong>allows to force the overwriting of the file if it already exists.<\/p>\n<\/div>\n<p>A file is thereby created with counters contained in <strong>$<\/strong><strong>CtrList<\/strong>. This data may also be registered in CSV or TSV formats. You may then select or deselect counters to facilitate the reading of the graphics.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure12-9d736a04-74a0-4f9a-a9be-8e08a0b27fc7.png\" alt=\"2249-figure12-9d736a04-74a0-4f9a-a9be-8e\" \/><\/p>\n<p class=\"caption\">Figure13 &#8211; Performance Monitor<\/p>\n<h2>To go further<\/h2>\n<p>You may wish to create your own counters for very specific needs. There are a wide range of counters already provided for all sorts of requirements but the facility to add your own opens up all sorts of possibilities. You can use custom counters to instrument server-based processes such as ETL or even monitor the performance metrics of applications such as website transactions. You can really amuse yourself with this facility as it is very powerful, but you&#8217;ll need a good understanding of the mechanism.<\/p>\n<p>Here is a simple example that you can build on.<\/p>\n<p>In a first instance, I must define a few variables:<\/p>\n<ul>\n<li>The name of the category,<\/li>\n<li>an associated description &#8220;help&#8221;<\/li>\n<li>the type of category (simple instance or multiple instances).<\/li>\n<\/ul>\n<p>Then I define two objects: one object of data collection that will contain one or several data objects.<\/p>\n<p>Here is the creation of the category of counter: &#8220;My-Custom-Category&#8221;<\/p>\n<pre class=\"lang:ps theme:powershell-ise\"> MyDataCollection = New-Object System.Diagnostics.CounterCreationDataCollection\r\n    $MyFirstData = New-Object System.Diagnostics.CounterCreationData\r\n    \r\n    $CatName = \"My-Custom-Category\"\r\n    $CatHelp = \"A Custom Performance object\"\r\n    $CatType = [System.Diagnostics.PerformanceCounterCategoryType]:MultiInstance \r\n<\/pre>\n<p>That&#8217;s fine but the category is for the moment empty. It would be interesting to create counters in it. To do that I must create one or more <strong>PerformanceCounter<\/strong> objects that can take several arguments within its parameters. In my example, I indicate:<\/p>\n<ul>\n<li>the name of the category in which it will be created<\/li>\n<li>its type (See the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.diagnostics.performancecountertype(v=vs.110).aspx\">possible types<\/a>)<\/li>\n<li>a description<\/li>\n<li>and if I can modify it or not (True\/False)<\/li>\n<\/ul>\n<p>And finally, I give it a value with <strong>RawValue<\/strong>:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">    $MyFirstData.CounterName = \"My-Custom-CounterName\"\r\n    $MyFirstData.CounterType = \"NumberOfItems32\"\r\n    $MyFirstData.CounterHelp = \"My first custom counter\"\r\n    $MyDataCollection.Add($MyFirstData)\r\n    \r\n    [System.Diagnostics.PerformanceCounterCategory]::Create($CatName, $CatHelp, $CatType, $MyDataCollection) \r\n    \r\n    $Counter1 = New-Object System.Diagnostics.PerformanceCounter($CatName, \"My-Custom-CounterName\", \"My-Custom-Instance\", $false)\r\n    $Counter1.RawValue = 1024\r\n<\/pre>\n<p>See the complete example and comments for a more detailed understanding:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">   # We need two objects\r\n    $MyDataCollection = New-Object System.Diagnostics.CounterCreationDataCollection\r\n    $MyFirstData = New-Object System.Diagnostics.CounterCreationData\r\n    \r\n    # Variables for Counter Creation Data linked to $MyDataCollection\r\n    $MyFirstData.CounterName = \"My-Custom-CounterName\"\r\n    $MyFirstData.CounterType = \"NumberOfItems32\"\r\n    $MyFirstData.CounterHelp = \"My first custom counter\"\r\n    $MyDataCollection.Add($MyFirstData)\r\n    \r\n    # Variables for Performance Counter Category\r\n    $CatName = \"My-Custom-Category\"\r\n    $CatHelp = \"A Custom Performance object\"\r\n    $CatType = [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance\r\n    \r\n    # Create performance counter category linked to $MyDataCollection\r\n    [System.Diagnostics.PerformanceCounterCategory]::Create($CatName, $CatHelp, $CatType, $MyDataCollection)\r\n    \r\n    # Create my first counter with a counter name + instance name and if it's read-only or not?\r\n    $Counter1 = New-Object System.Diagnostics.PerformanceCounter($CatName, \"My-Custom-CounterName\", \"My-Custom-Instance\", $false)\r\n    # Set a value\r\n    $Counter1.RawValue = 1024\r\n    \r\n    # Check if \"My-Custom-Category\" exist ?\r\n    (get-counter -listset \"My-Custom-Category\").paths\r\n    \r\n    # Now check the CookedValue \r\n    Get-Counter -Counter \"\\My-Custom-Category(*)\\My-Custom-CounterName\" | Select-Object -ExpandProperty CounterSamples\r\n    \r\n    \r\n    \r\n    # And just check all the properties\r\n    $counter1 \r\n<\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2249-figure19-e5dfa011-21ff-44b0-a503-bfd83a422752.png\" alt=\"2249-figure19-e5dfa011-21ff-44b0-a503-bf\" \/><\/p>\n<p class=\"caption\">Figure14 &#8211; Full example of a created custom counter<\/p>\n<p>Once your tests completed, you can delete the categories:<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">   [System.Diagnostics.PerformanceCounterCategory]::Delete(\"$CatName\")<\/pre>\n<div class=\"note\">\n<p class=\"note\">Note:You must close your PowerShell console so that the category will not be displayed.<\/p>\n<\/div>\n<h2>Conclusion<\/h2>\n<p>Performance counters are the basic way of handling a vast range of measurements that you need in order to ensure that your servers are trouble-free. With the basic principles I&#8217;ve illustrated, you should be able to gather performance data for such performance categories as Disk, Processor, Memory, Hyper-V, SQL Server, Exchange and so on, for all your servers and devices. With custom counters, you will even be able to monitor the business processes within applications.<\/p>\n<p>I suggest that you create different scripts for each category of counter. Then it will be simple to plan and execute them on demand on the list of devices you provide. I personally organize my counter-value-retrieving data scripts in this manner.<\/p>\n<p>In the absence of a third-party monitoring tool that answers all your requirements, I find that performance counters are a very good approach to analyze the behavior of the devices. By using the <strong>Export-Counter<\/strong> command, I can execute a true analysis and also send comprehensible results to non-technical people.<\/p>\n<p>The most difficult task, in my opinion, is to find out which counters are most relevant to your needs and thereby reduce reporting to the bare minimum. It is far too easy to obtain too much data on the devices and thereby increase the implementation time of your scripts. You can be sure that the time you spend in refining your performance-counter metrics will be gained tenfold when the time comes for you to analyze a critical situation on one of your servers, or spot an issue before it becomes a big problem. PowerShell is here to help you attend to detail with the minimum of effort..<\/p>\n","protected":false},"excerpt":{"rendered":"<p>By reading performance counters from services such as SQL Server or Exchange, you can get a wealth of performance information. By automating the process of gathering and storing appropriate counters, you can routinely check a range of devices quickly using visual tools such as PerfMon. By then creating your own counters, you can add counter-based metrics to anything that can be measured programmatically, such as  services, applications, processes such as ETL, or deployments. &hellip;<\/p>\n","protected":false},"author":158223,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[35],"tags":[4242,4824,4869,4364,4635,4150,4151,4871],"coauthors":[6804],"class_list":["post-2057","post","type-post","status-publish","format-standard","hentry","category-powershell","tag-basics","tag-etl","tag-exchange","tag-monitoring","tag-powershell","tag-sql","tag-sql-server","tag-sysadmin"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/158223"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=2057"}],"version-history":[{"count":8,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2057\/revisions"}],"predecessor-version":[{"id":90619,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2057\/revisions\/90619"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=2057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=2057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=2057"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=2057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}