All posts by Thiyagu

How to Un-ZIP compressed files using PowerShell Expand-Archive cmdlet

In the previous post, we have discussed how to zip the folder/files, so here we going to discuss how to unzip files and folders archives. The process is even easier than compressing them; all you need is the source file and a destination for the data ready to unzip.

Syntax : Expand-Archive -LiteralPath <PathToZipFile> -DestinationPath <PathToDestination>

In the above command, replacing <PathToZipFile> and <PathToDestination> with the path to the files you want to Un-compress and the name and folder you want it to go to, respectively

Example :

Expand-Archive -LiteralPath C:\dotnet-helpers\Source\ExtractMe.zip -DestinationPath C:\dotnet-helpers\Destination\

The destination folder specified to extract the files into will populate with the contents of the archive. If the folder didn’t exist before unzipping, PowerShell will create the folder and place the contents into it before unzipping.

If the destination folder already exists in the destination, PowerShell will return an error when it tries to unzip the files. However, you can use -Force PowerShell to overwrite the data with the new ones using the -Force parameter.

OUTPUT

Use-PowerShell-to-Un-ZIP-compressed-files_thiyagu_dotnet-helpers.

How to Remove Empty Folders/Directories recursively with PowerShell

As part of System Admin, you will have control of more servers and there may be hundreds of empty folders as junk files which may take up your hard disk. While the junk files occupy disk and it became more Junk in the servers so it became critical to maintaining the important files.

The empty folders don’t take up disk space, but to organize your data better, you may want to trim them every once in a while. If you feel to manually delete empty folders then it will need to routine and time consuming manual work. So we below PowerShell script will help you t to query and delete all empty folders and subfolders.

The following PowerShell command-line deletes empty folders, located under the specified base folder recursively.

STEP #1: Get the recursive child items

First, we need to get the child items from the source path ie., C:\dotnet-helpers\TEMP Folder

//gci alias of Get-ChildItem
gci “C:\dotnet-helpers\TEMP Folder” -r

STEP #2: Fetch all the empty folders

To filter the folders/directories available in the current context, the following property can use $_.psiscontainer. It will return a boolean, indicating whether the current object is a directory or not.

PSIsContainer retrieves an array of strongly typed FileSystemInfo objects representing files and subdirectories of the current directory. The count is not 0, it doesn’t exist at all meaning that the directory is empty or holds other empty folders

(gci “C:\dotnet-helpers\TEMP Folder” -r | ? {$_.PSIsContainer -eq $True}) | ?{$_.GetFileSystemInfos().Count -eq 0}

OUTPUT

STEP #3: Remove the collection of Empty folders.

Finally, use the remove-item cmdlet to remove all the empty folder/directories 

(gci “C:\dotnet-helpers\TEMP Folder” -r | ? {$_.PSIsContainer -eq $True}) | ?{$_.GetFileSystemInfos().Count -eq 0} | remove-item

How to get Sitecore Admin users for the domain using Sitecore PowerShell Extensions

The revisiting of Admin access is an important activity for the support team as most of the time we may provide temporary access for a certain time and forgot to roll back.

In this post, we will explore a great way of extracting Admin user data . This is the simplest way to extract using the Sitecore Powershell ISE.

Sample 1: Get All User mapped with specific domain

##################################################
#Project: Get a list of all users for Domain
#Developer: Thiyagu S (dotnet-helpers.com)
#Tools : PowerShell 5.1.15063.1155 & SiteCore 8.1
#E-Mail: mail2thiyaguji@gmail.com 
##################################################
#Getting User list by filtering with domain "dotnet-helpers"
$allSitecoreUsers = Get-User -Filter “dotnet-helpers\*”
$allSitecoreUsers | ForEach-Object  {
Write-Host $_.Name
}

Sample 2: Get All Admin Users mapped with specific domain

#####################################################################################################
#Project: How to get Sitecore Admin users for the domain using Sitecore PowerShell Extensions.
#Developer: Thiyagu S (dotnet-helpers.com)
#Tools : PowerShell 5.1.15063.1155 & SiteCore 8.1
#E-Mail: mail2thiyaguji@gmail.com 
#####################################################################################################
 
$adminSitecoreUsers = Get-User -Filter “dotnet-helpers\*”
$adminSitecoreUsers | Where{$_.IsAdministrator -eq $true } | ForEach-Object  {
Write-Host $_.Name
}

Output

Creating Multiple Tables in single HTML Report using Powershell

Actually System Admins do a lot stuff with Powershell Scripts. Often in Powershell you get lists where data is collected in table format. All Tech/non Tech peoples loves a nice HTML report for reviewing. Creating these type of reports in PowerShell is very easy and simple with Powershell . These type of nice HTML reports can be generate with the help ConvertTo-HTML cmdlet.  Converts Microsoft .NET Framework objects into HTML that can be displayed in a Web browser. The Powershell based Reports are easy to create  and you also can create a unique .css file to make the design for all reports identically to impress with reports.

In my previous article i had posted the article which helps to create single HTLML report. Here i going to deep drive about how to populate multiple reports in single HTML format.

Create CSS File

Here i had wrote the required CSS code for the report and placed the below code in notepad and saved with the name C:\dotnet-helpers\Logreport.css. If required you can create two separate .css file and design your reports based on your requirements. 

body {
  font-family: Monospace;
  font-size: 10pt;
}
table,td, th {
  border: 1px solid black;
}
th {
  color: #00008B;
  background-color: white;
  font-size: 12pt;
}
table {
  margin-left: 30px;
}
h2 {
  font-family: Tahoma;
  color: #6D7B8D;
}
h1 {
  color: #DC143C;
}
h5 {
  color: #c7bc07;
  font-size: 10pt;
}

In the below script, I had creating two separate variable to assign the Application and System Event logs ( $applicationLog ,$systemLog). Here you can get detail post about the Event log, so refer if required more details on it.

Then you can refer the stylesheet from an external CSS file with help of -CssUri parameter (-CssUri ‘C:\dotnet-helpers_com\Logreport.css’) and generate the HTML report in the destination location. The CSS  file will applied to the HTML element during the execution and generate the report.

#######################################################################
#Project : Creating Powershell Mulitple Reports in HTML with CSS Format
#Developer : Thiyagu S (dotnet-helpers.com)
#Tools : PowerShell 5.1.15063.1155 
#E-Mail : mail2thiyaguji@gmail.com 
######################################################################
 
$applicationLog = Get-EventLog -LogName Application -Newest 5| Select-Object -Property Source, EventID, InstanceId  
convertto-html -Title "Daily Log Report"-PreContent"<H1>Daily Event Applicaton Log Report</H1>" -PostContent "<H5><i>Copy right @ dotnet-helpers.com</i></H5>" -CSSUri "C:\dotnet-helpers_com\Logreport.css"
 
$systemLog = Get-EventLog -LogName System -Newest 5 | Select-Object -Property Source, EventID, InstanceId| 
convertto-html -Title "Daily Log Report" -PreContent "<H1>Daily Event Server Log Report</H1>" -PostContent "<H5><i>Copy right @ dotnet-helpers.com</i></H5>" -CSSUri "C:\Thiyagu Disk\Logreport.css"
 
 
ConvertTo-HTML -body "$applicationLog $systemLog"  | Set-Content "C:\dotnet-helpers_com\EventLogReport.html"

OUTPUT

How to remove duplicate rows in a CSV using Powershell

We are maintaining the user database in our environment, every week automatically the excel will be placed in the the specific folder. Post this, the automatic script will start run and upload the user information in the database by reading the excel file. In our current scenario, the excel will have duplicate entries which will create more than one entry for in the user in the database. The problem is that every once in a while, duplicates end up in the CSV file

To over come this scenario we thought to create script to remove the duplicate detail (which similar in any other rows in excel). This can be achieve by using the Sort-Object and the Import-CSV cmdlet to remove duplicates from a CSV file.

After the contents of the CSV file sorted using Sort-Object, you can use the unique switch to return only unique rows from the file.

Example

#######################################################################
#Project : How to remove duplicate rows in a CSV using Powershell
#Developer : Thiyagu S (dotnet-helpers.com)
#Tools : PowerShell 5.1.15063.1155 
#E-Mail : mail2thiyaguji@gmail.com 
######################################################################
#Getting the Path of CSV file
$inputCSVPath = 'C:\BLOG_2020\DEMO\UserDetails.csv'
#The Import-Csv cmdlet creates table-like custom objects from the items in CSV files
$inputCsv = Import-Csv $inputCSVPath | Sort-Object * -Unique
#The Export-CSV cmdlet creates a CSV file of the objects that you submit. 
#Each object is a row that includes a comma-separated list of the object's property values.
$inputCsv | Export-Csv "C:\\BLOG_2020\DEMO\UserDetails_Final.csv"  -NoTypeInformation

Input CSV:

Output CSV:

Unlocking all locked items in Sitecore using Sitecore PowerShell Extensions (SPE)

In my Sitecore environment, there are 100+ non-admin users are working and we have been asked many times if it is possible for non admin users in Sitecore to be able to unlock items that have been locked by others Users. But in open, we dont have option for non-admin users to Un-Lock the others locked items, in this case they need to contact the specific person or admin users for Un-Locking items.

But this is a feature that many user want to perform Un-locking without others support, So based on requirement we thought to write custom command to unlock the items with help of Sitecore Powershell extension.

In this article, we going to see how to create custom Powershell script for Un-Locking the parent and child items for all the language versions.

STEP 1:

First you need to Get Source , child path items and assigned to the variables ($rootItem, $ChildItems ). After below script execution, the variable $items will contain the parent and its child items collection.

$sourcePath = “/sitecore/content/Sites/White/home/components”
$rootItem = Get-Item -Path $sourcePath
$ChildItems = Get-ChildItem -Path $sourcePath -Recurse
$items = $ChildItems + $rootItem

STEP 2:

Next you need to start looping the items ($items) one by one to check for all the languages.

foreach ($item in $items)
{
foreach ($version in $item.Versions.GetVersions($true))
{
Your unlocking login here….
}
}

STEP 3:

The main logic is to check each item with each language version to verify whether its locked or not. If its locked then below condition will allow to Un-Lock the specific item on specific language version.

if($version.Locking.IsLocked())
{
$version.Editing.BeginEdit();
$version.Locking.Unlock();
$version.Editing.EndEdit();
Write-Host “Item Un-locked” $item.ID “for Language” $version.Language;
}

Full code

###########################################################################################
#Project : Unlocking all locked items in Sitecore using Sitecore PowerShell Extensions (SPE)
#Developer : Thiyagu S (dotnet-helpers.com)
#Tested Tool : Sitecore 8.1 
#E-Mail : mail2thiyaguji@gmail.com 
###########################################################################################
$sourcePath = "/sitecore/content/Sites/White/home/components"
function UnlockSiteCoreItems
{
    $rootItem = Get-Item -Path $sourcePath
    $ChildItemsToUnlock = Get-ChildItem -Path $sourcePath -Recurse
    $items = $ChildItemsToUnlock + $rootItem
    
    foreach ($item in $items)
    {
        foreach ($version in $item.Versions.GetVersions($true))
        {
            if($version.Locking.IsLocked())
            {
                $version.Editing.BeginEdit();
                $version.Locking.Unlock();
                $version.Editing.EndEdit();
                Write-Host "Item Un-locked" $item.ID "for Language" $version.Language;
            }
        }
    }
}
$unlockedItemsDetails = UnlockSiteCoreItems

OUTPUT:

How to create Basic Chart by reading excel using PowerShell

As system admins, we are used to digging through heaps of searching, selecting, sorting, filtering, until we got what we were looking for. My point is, while you might appreciate nicely presented, If we are providing the technical details in paragraph format will usually get bored and things they don’t understand, this what we will do at most of the time. Most of the management peoples like simple and colorful representation like charts. Basically it will be easily understandable without reading long texts.

Below code is pretty basic and there are couple of things which is taken by default like Chart Type (which is Bar chart), Data range used for chart (Since single data set is present), position of the chart etc. Before executing the script, we need the data in a tabular format which is to be used to create a chart in the Excel. Let you create the excel sheet similar like below before we moving to the scripting part.

First let you Open the excel and add a chart details in the sheet as shown below. If required Set the Title and the Save the excel. Finally close the excel.

Full Code :

#######################################################################
#Project : How to create Basic Chart by reading excel using PowerShell
#Developer : Thiyagu S (dotnet-helpers.com)
#Tools : PowerShell 5.1.15063.1155 
#E-Mail : mail2thiyaguji@gmail.com 
######################################################################
# Creating excel com object
$xlChart=[Microsoft.Office.Interop.Excel.XLChartType]
#You can use New-Object to work with Component Object Model (COM) components.
#To create a COM object, you need to specify the ComObject parameter with the Programmatic Identifier of the COM class that you want to use
$excelObj = New-object -ComObject Excel.Application 
#Assign the the file path of the Excel
$fileName = 'C:\dotnet-helpers\TutorialDetails.xlsx'
#Open Excel
$workbook = $excelObj.Workbooks.Open($fileName)
#Open the first sheet of the excel 
$worksheetChart = $workbook.WorkSheets.item(1) 
#Makes the current sheet the active sheet.
$worksheetChart.activate() 
# Adding the Chart
$basicchart = $worksheetChart.Shapes.AddChart().Chart
# Set it true if you want to have chart Title
$basicchart.HasTitle = $true
# Assigning the Title for the chart
$basicchart.ChartTitle.Text = "Tutorial Views Report"
# Save the sheet
$workbook.Save()  
# Closing the work book and ComObject
$workbook.close() 
$excelObj.Quit()
# Releasting the excel com object
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelObj)

OUTPUT

How to use splatting in Powershell – Part I

Splatting is a method of passing a collection of parameter values to a command as unit. PowerShell associates each value in the collection with a command parameter. Splatted parameter values are stored in named splatting variables, which look like standard variables, but begin with an At symbol (@) instead of a dollar sign ($). The At symbol tells PowerShell that you are passing a collection of values, instead of a single value.

Splatting is the ability to use a dictionary or a list to supply parameters to a command. Proxy commands are wrappers of existing commands in Windows PowerShell, and to make this possible.Instead of having to stretch your parameter assignments out horizontally, Splatting gives us a clean, concise, readable format that extends vertically in which to assign values to our parameters.

PROS of Splatting:

  • Splatting makes your commands shorter and easier to read.
  • You can re-use the splatting values in different command calls and use splatting to pass parameter values from the $PSBoundParameters automatic variable to other scripts and functions.

SYNTAX

<CommandName> <optional parameters> @<HashTable> <optional parameters>
<CommandName> <optional parameters> @<Array> <optional parameters>

Example 1: Splatting with Array

In this examples compare two Copy-Item commands that copy the txt file to the txt file in the same directory. For better understanding,
first let we see the example uses the traditional format which we usually use all the time.

Copy-Item -Path ‘C:\blog\source.txt’ ‘C:\blog\desination.txt’

In next let we create simple example and will use array splatting.
The first command creates an array of the parameter values and stores it in the $splattingArray variable.The values are in position order in the array.
The second command uses the @splattingArray variable in a command in splatting and you can notice that the $ symbol replaces the dollar sign (@splattingArray) in the command.

$splattingArray = “C:\blog\source.txt”, C:\blog\desination.txt”
Copy-Item -Path @splattingArray

Example 2: Splatting with Hash table

In this example we uses hash table splatting. The first command creates a hash table with key-value pairs and stores it in the $splattingHash variable.
The second command uses the $splattingHash variable in a command with splatting. and you can notice that the $ symbol replaces the dollar sign ($splattingHash) in the command.

$splattingHash = @{
  Path = "C:\blog\source.txt"
  Destination = "C:\blog\desination.txt"
}
Copy-Item @splattingHash

 

#Define the hash table            
$splattingGWMIParams = @{            
    Class = "Win32_OperatingSystem"            
    Credential = $Cred            
    ComputerName = 'localhost'            
}            
            
#Splat the hash table           
Get-WmiObject @splattingGWMIParams

 

What do you think?

I hope you have an idea of  How to use splatting in Powershell Scriptingl. I would like to have feedback from my posts readers. Your valuable feedback, question, or comments about this article are always welcome.

Creating Chart Reports using Powershell Chart controls

As system admins, we are used to digging through heaps of searching, selecting, sorting, filtering, until we got what we were looking for. My point is, while you might appreciate nicely presented, If we are providing the technical details in paragraph format will usually get bored and things they don’t understand, this what we will do most of the time. Most of the management peoples like simple and colorful representations like charts. Basically, it will be easily understandable without reading long texts.

Microsoft Chart Controls (MCCs) is a great tool to show up reports and you can create a wide range of different chart types, with a custom design. You can display your chart in a GUI (e.g. Windows Forms) or save it as a graphics file to include it in an HTML report or email. A standard chart created with MCCs basically consists of three elements that are Chart object, a ChartArea object, and one or more data Series.

From MSDN, Two important properties of the Chart class are the Series and ChartAreas properties, both of which are collection properties. The Series collection property stores Series objects, which are used to store data that is to be displayed, along with attributes of that data. The ChartAreas collection property stores ChartArea objects, which are primarily used to draw one or more charts using one set of axes.

How to create a simple Memory Usage Chart and save it in your local drive: In this post, we will create a chart that shows your pc’s top 5 processes by memory usage and save it as a *.png-file.

STEP #1

Let you loading the necessary assembly and determine the path whether the PNG need to save.

[void][Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms.DataVisualization”)
$chartSavePath = ‘C:\MonitorCPUusage’

STEP #2

In this example we won’t display this one in a GUI so you only need to set a few properties like black color and size. Here we going to create instance of the .NET-object we’ve just created and named “$chartobject” and set the Width, Height, back color. The System.Windows.Forms.DataVisualization.Charting namespace contains methods and properties for the Chart Windows forms control.

# Creating chart object
$chartobject = New-object System.Windows.Forms.DataVisualization.Charting.Chart
$chartobject.Width = 800
$chartobject.Height =800
$chartobject.BackColor = [System.Drawing.Color]::orange

STEP #3

Next, you need to add a title to the chart. A Chart object can have multiple titles (e.g. a title and a subtitle, or a title for each ChartArea attached to this Chart object), so we create it by adding it with title collection.

# Set Chart title
[void]$chartobject.Titles.Add(“dotnet-helpers chart-Memory Usage”)
$chartobject.Titles[0].Font = “Arial,13pt”
$chartobject.Titles[0].Alignment = “topLeft”

STEP #4

As mentioned before, a Chart object can have multiple ChartArea objects. Per default, they will automatically share the available space of the Chart object (determined by the Chart object’s height and width properties). But you can also customize the location and size of each ChartArea by setting the “$ChartArea.Position.Auto” – property to $false and set size and position yourself

# create a chartarea to draw on and add to chart
$chartareaobject = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$chartareaobject.Name = “ChartArea1”
$chartareaobject.AxisY.Title = “dotnet-helpers chart – Memory(MB)”
$chartareaobject.AxisX.Title = “dotnet-helpers chart – Process Name”
$chartareaobject.AxisY.Interval = 100
$chartareaobject.AxisX.Interval = 1
$chartobject.ChartAreas.Add($chartareaobject)

STEP #5

Typically, if you want to add a legend along with a chart,I will avoid having anything on the actual chart itself and leave the description for each piece to be in the legend. Because we’ll have two data Series in the same ChartArea and it’s probably a good idea to be represent in the legend way.

# Creating legend for the chart
$chartlegend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
$legend.name = “Legend1”
$chartobject.Legends.Add($legend)

STEP #6

Here we getting the using process details by get-process cmdlet, sort by private memory size and take the top five entries of the list.

# Getting the top 5 CPU utilzation process details
$topCPUUtilization = Get-Process | sort PrivateMemorySize -Descending | Select-Object -First 5

STEP #7

Finally, we need to set the data series to chart object. We create it by setting a name for the Series and adding it directly to the chart’s Series collection. For this example, i had set the chart type to column. When choosing the type, there is one important thing to consider: You know already that a ChartArea can have multiple Series.

# Set Series to CharObject
[void]$chartobject.Series.Add(“VirtualMemory”)
$chartobject.Series[“VirtualMemory”].ChartType = “Column”
$chartobject.Series[“VirtualMemory”].BorderWidth = 3
$chartobject.Series[“VirtualMemory”].IsVisibleInLegend = $true
$chartobject.Series[“VirtualMemory”].chartarea = “ChartArea1”
$chartobject.Series[“VirtualMemory”].Legend = “Legend1”
$chartobject.Series[“VirtualMemory”].color = “#62B5CC”
$topCPUUtilization | ForEach-Object {$chartobject.Series[“VirtualMemory”].Points.addxy( $_.Name , ($_.VirtualMemorySize / 1000000)) }

# Set Series to CharObject
[void]$chartobject.Series.Add(“PrivateMemory”)
$chartobject.Series[“PrivateMemory”].ChartType = “Column”
$chartobject.Series[“PrivateMemory”].IsVisibleInLegend = $true
$chartobject.Series[“PrivateMemory”].BorderWidth = 3
$chartobject.Series[“PrivateMemory”].chartarea = “ChartArea1”
$chartobject.Series[“PrivateMemory”].Legend = “Legend1”
$chartobject.Series[“PrivateMemory”].color = “#E3B64C”
$topCPUUtilization | ForEach-Object {$chartobject.Series[“PrivateMemory”].Points.addxy( $_.Name , ($_.PrivateMemorySize / 1000000)) }

STEP #8

At last, you want to save chart as a image file using the .saveImage() method of the Chart object.

# save chart with the Time frame
$chartobject.SaveImage(“$chartSavePath\CPUusage_$(get-date -format `”yyyyMMdd_hhmmsstt`”).png”,”png”)

Full Code

[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
$chartSavePath = 'C:\MonitorCPUusage'
 
# Creating chart object
# The System.Windows.Forms.DataVisualization.Charting namespace contains methods and properties for the Chart Windows forms control.
   $chartobject = New-object System.Windows.Forms.DataVisualization.Charting.Chart
   $chartobject.Width = 800
   $chartobject.Height =800
   $chartobject.BackColor = [System.Drawing.Color]::orange
 
# Set Chart title 
   [void]$chartobject.Titles.Add("dotnet-helpers chart-Memory Usage")
   $chartobject.Titles[0].Font = "Arial,13pt"
   $chartobject.Titles[0].Alignment = "topLeft"
 
# create a chartarea to draw on and add to chart
   $chartareaobject = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
   $chartareaobject.Name = "ChartArea1"
   $chartareaobject.AxisY.Title = "dotnet-helpers chart - Memory"
   $chartareaobject.AxisX.Title = "dotnet-helpers chart - ProcessName"
   $chartareaobject.AxisY.Interval = 100
   $chartareaobject.AxisX.Interval = 1
   $chartobject.ChartAreas.Add($chartareaobject)
 
# Creating legend for the chart
   $chartlegend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
   $legend.name = "Legend1"
   $chartobject.Legends.Add($legend)
 
# Get the top 5 process using in our system
   $topCPUUtilization = Get-Process | sort PrivateMemorySize -Descending  | Select-Object -First 5
 
# data series
   [void]$chartobject.Series.Add("VirtualMemory")
   $chartobject.Series["VirtualMemory"].ChartType = "Column"
   $chartobject.Series["VirtualMemory"].BorderWidth  = 3
   $chartobject.Series["VirtualMemory"].IsVisibleInLegend = $true
   $chartobject.Series["VirtualMemory"].chartarea = "ChartArea1"
   $chartobject.Series["VirtualMemory"].Legend = "Legend1"
   $chartobject.Series["VirtualMemory"].color = "#00bfff"
   $topCPUUtilization | ForEach-Object {$chartobject.Series["VirtualMemory"].Points.addxy( $_.Name , ($_.VirtualMemorySize / 1000000)) }
 
# data series
   [void]$chartobject.Series.Add("PrivateMemory")
   $chartobject.Series["PrivateMemory"].ChartType = "Column"
   $chartobject.Series["PrivateMemory"].IsVisibleInLegend = $true
   $chartobject.Series["PrivateMemory"].BorderWidth  = 3
   $chartobject.Series["PrivateMemory"].chartarea = "ChartArea1"
   $chartobject.Series["PrivateMemory"].Legend = "Legend1"
   $chartobject.Series["PrivateMemory"].color = "#bf00ff"
   $topCPUUtilization | ForEach-Object {$chartobject.Series["PrivateMemory"].Points.addxy( $_.Name , ($_.PrivateMemorySize / 1000000)) }
 
# save chart with the Time frame for identifying the usage at the specific time
   $chartobject.SaveImage("$chartSavePath\CPUusage_$(get-date -format `"yyyyMMdd_hhmmsstt`").png","png")

 

OUTPUT: