Sitecore : Helpful PowerShell Scripts
Explore valuable scripts in Sitecore using SPE
As we all know Sitecore PowerShell Extensions (SPE) module serves as a powerful Sitecore development tool, greatly enhancing your productivity and reducing the time required to deliver a Sitecore solution created by Adam Najmanowicz and Michael West.
It includes out-of-the-box reports that offer a wide range of auditing capabilities for your Sitecore solution. However in certain situations, we may find it necessary to develop custom scripts to meet specific client requirements.
Get Prabhu Ranganathan’s stories in your inbox
Join Medium for free to get updates from this writer.
Here are some custom scripts I’ve developed to meet specific client requirements. They might prove useful to others facing similar needs.
Pages Last Updated
SPE script for generating a report of Sitecore items that were last updated on or after a specified date,
- The script finds child templates that inherit from a specified standard template.
- It collects items that are descendants of the chosen root and meet the specified criteria.
- Depending on the selected period (before or after), it displays items last updated before or after the specified date.
# Set the default database
$database = "master"
$root = Get-Item -Path (@{$true = "$($database):\content\home"; $false = "$($database):\content" }[(Test-Path -Path "$($database):\content\home")])
# Get the base template for filtering items
$baseTemplate = Get-Item master:\"sitecore\templates\User Defined\Web2014\Container\Pages"
$periodOptions = [ordered]@{Before = 1; After = 2; }
$maxDaysOptions = [ordered]@{"-- Skip --" = [int]::MaxValue; 30 = 30; 90 = 90; 120 = 120; 365 = 365; }
# Define settings for the user prompt
$settings = @{
Title = "Report Filter"
OkButtonName = "Proceed"
CancelButtonName = "Abort"
Description = "Filter the results for Components updated on or after the specified date"
Parameters = @(
@{
Name = "root";
Title = "Choose the report root";
Tooltip = "Only items from this root will be returned.";
},
@{
Name = "selectedDate"
Value = [System.DateTime]::Now
Title = "Date"
Tooltip = "Filter the results for items updated on or before/after the specified date"
Editor = "date time"
},
@{
Name = "selectedPeriod"
Title = "Period"
Value = 1
Options = $periodOptions
Tooltip = "Pick whether the items should have been last updated before or after the specified date"
Editor = "radio"
},
@{
Name = "selectedMaxDays"
Title = "Max Days"
Value = [int]::MaxValue
Options = $maxDaysOptions
Tooltip = "Pick the maximum number of days to include starting with the specified date"
Editor = "combo"
}
)
Icon = [regex]::Replace($PSScript.Appearance.Icon, "Office", "OfficeWhite", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
ShowHint = $true
}
$result = Read-Variable @settings
if ($result -ne "ok") {
Exit
}
# Function to get the last updated item
function Get-LastUpdated($item) {
Write-Host $item.Paths.FullPath
Write-Log $item.Paths.FullPath
$allitems = Get-ItemReference -Path "$($database):$($item.Paths.FullPath)" | Where-Object { $_.Name -ne 'Header' -and $_.Name -ne 'HeaderView' -and $_.Name -ne 'Top-Component' -and $_.Name -ne 'Footer' -and $_.Name -ne 'FooterView' -and $_.Name -ne 'Search Box' -and $_.Name -ne 'Global Navigation' -and $_.Name -ne 'Global-Nav' -and $_.Name -ne 'Folder' -and $_.TemplateName -ne 'Device' -and $_.TemplateName -ne 'Workflow' -and $_.TemplateName -ne 'Layout' -and $_.TemplateName -ne 'Branch' -and $_.TemplateName -ne 'Meta Tag' -and $_.TemplateName -ne 'List Configuration' -and $_.TemplateName -ne 'State' } | Sort-Object __Updated -descending
Write-Log "allitems count=$($allitems.Count)"
if ($allitems.Count -ne 0) {
foreach ($associateditem in $allitems) {
if ($associateditem.HasChildren) {
$descendants = Get-ChildItem -Path "$($database):$($associateditem.Paths.FullPath)" -Recurse -WithParent | Where-Object { $_.Paths.FullPath.StartsWith('/sitecore/content/') } | Sort-Object __Updated -descending | Select -First 1
}
if ($descendants -ne $null) {
if ($lastUpdated -ne $null -and ($lastUpdated -lt $descendants.Fields[[Sitecore.FieldIDs]::Updated].Value) -or ($lastUpdated -lt $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value)) {
Write-Host $descendants.Paths.FullPath +":"+ $descendants.Fields[[Sitecore.FieldIDs]::Updated].Value
Write-Host $associateditem.Paths.FullPath +":"+ $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value
Write-Log $descendants.Paths.FullPath +"1:"+ $descendants.Fields[[Sitecore.FieldIDs]::Updated].Value
Write-Log $associateditem.Paths.FullPath +":"+ $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value
if ($descendants.Fields[[Sitecore.FieldIDs]::Updated].Value -gt $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value) {
$lastUpdated = $descendants.Fields[[Sitecore.FieldIDs]::Updated].Value
}
else {
$lastUpdated = $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value
}
}
}
else {
if ($lastUpdated -ne $null -and ($lastUpdated -lt $item.Fields[[Sitecore.FieldIDs]::Updated].Value) -or ($lastUpdated -lt $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value)) {
Write-Host $item.Paths.FullPath +":"+ $item.Fields[[Sitecore.FieldIDs]::Updated].Value
Write-Host $associateditem.Paths.FullPath +":"+ $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value
Write-Log $item.Paths.FullPath +"2:"+ $item.Fields[[Sitecore.FieldIDs]::Updated].Value
Write-Log $associateditem.Paths.FullPath +":"+ $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value
if ($item.Fields[[Sitecore.FieldIDs]::Updated].Value -gt $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value) {
$lastUpdated = $item.Fields[[Sitecore.FieldIDs]::Updated].Value
}
else {
$lastUpdated = $associateditem.Fields[[Sitecore.FieldIDs]::Updated].Value
}
}
}
}
return [Sitecore.DateUtil]::IsoDateToDateTime($lastUpdated)
}
else {
return [Sitecore.DateUtil]::IsoDateToDateTime($item.Fields[[Sitecore.FieldIDs]::Updated].Value)
}
}
filter Where-LastUpdated {
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[Sitecore.Data.Items.Item]$Item,
[datetime]$Date = ([datetime]::Today),
[switch]$IsBefore,
[int]$MaxDays
)
$convertedDate = [Sitecore.DateUtil]::IsoDateToDateTime($item.Fields[[Sitecore.FieldIDs]::Updated].Value)
$isWithinDate = $false
if ($IsBefore.IsPresent) {
if ($convertedDate -le $Date) {
$isWithinDate = $true
}
}
else {
if ($convertedDate -ge $Date) {
$isWithinDate = $true
}
}
if ($isWithinDate) {
if ($MaxDays -lt [int]::MaxValue) {
if ([math]::Abs(($convertedDate - $Date).Days) -le $MaxDays) {
$item
}
}
else {
$item
}
}
}
#base template guid
$stdTemplate = "{AB86861A-6030-46C5-B394-E8F99E8B87DB}"
$childTemplates = $baseTemplate.Axes.GetDescendants() | Where-Object { [Sitecore.Data.Managers.TemplateManager]::GetTemplate($_).InheritsFrom($stdTemplate) }
Write-Host $root.Paths.FullPath
# Iterate through child templates and filter items
foreach ($childTemplate in $childTemplates) {
$items += @($childTemplate | Get-ItemReferrer | Where-Object { $_.ItemPath.StartsWith($root.Paths.FullPath) } | Where-LastUpdated -Date $selectedDate -IsBefore:($selectedPeriod -eq 1) -MaxDays $selectedMaxDays | Initialize-Item)
}
$message = "before"
if ($selectedPeriod -ne 1) {
$message = "after"
}
if ($items.Count -eq 0) {
Show-Alert "There are no items updated on or after the specified date"
}
else {
$props = @{
Title = "Items Last Updated Report"
InfoTitle = "Items last updated $($message) date $($selectedDate)"
InfoDescription = "Lists all items last updated $($message) the date selected."
PageSize = 25
}
$items |
Show-ListView @props -Property @{Label = "Name"; Expression = { $_.DisplayName } },
@{Label = "Actual Last Updated"; Expression = { $_.__Updated } },
@{Label = "Last Published"; Expression = { $_."__Last Published" } },
@{Label = "Related Item Last Updated"; Expression = { Get-LastUpdated($_) } },
@{Label = "Updated by"; Expression = { $_."__Updated by" } },
@{Label = "Created"; Expression = { $_.__Created } },
@{Label = "Created by"; Expression = { $_."__Created by" } },
@{Label = "Template Name"; Expression = { $_.TemplateName } },
@{Label = "Path"; Expression = { $_.ItemPath } }
}
Close-WindowGet All Users Activity
SPE script to retrieve user information from the ASP.NET Membership database and display it in a tabular format with the below properties,
- User: User’s username.
- Is Online: Indicates whether the user is currently online.
- Creation Date: The date when the user account was created.
- Last Login Date: The date of the user’s last login.
- Last Activity Date: The date of the user’s last activity
# Retrieve user information from the ASP.NET Membership database
$users = [System.Web.Security.Membership]::GetAllUsers()
# Define a list of properties to display
$properties = @(
@{ Label = "User"; Expression = { $_.UserName } },
@{ Label = "Is Online"; Expression = { $_.IsOnline } },
@{ Label = "Creation Date"; Expression = { $_.CreationDate } },
@{ Label = "Last Login Date"; Expression = { $_.LastLoginDate } },
@{ Label = "Last Activity Date"; Expression = { $_.LastActivityDate } }
)
# Display user information in a tabular format
$users | Show-ListView -Property $properties -Title "User Information" -PageSize 25Find and Delete Unused MediaItems
SPE script to to identify and delete unused media items within a Sitecore database. This script can be useful for cleaning up a Sitecore media library by identifying and removing media items that are not used within the content of your Sitecore instance.
# Specify the database
$databaseName = "master"
# Get the Sitecore database
$database = Get-Database -Name $databaseName
# Define a list to store unused media items
$unusedMediaItems = @()
# Get all media library items
$mediaLibraryPath = "/sitecore/media library"
$mediaLibrary = Get-Item -Path "$($database.Name):$mediaLibraryPath"
# Iterate through media library items
$mediaLibrary.Axes.GetDescendants() | ForEach-Object {
$mediaItem = $_
# Check if the media item is referenced by any content item
$referenced = Get-ItemReferrer -Item $mediaItem | Where-Object { $_.Paths.FullPath -notlike "$($mediaLibrary.Paths.FullPath)/*" }
if ($referenced -eq $null) {
$unusedMediaItems += $mediaItem
}
}
# Display the list of unused media items
$unusedMediaItems | Format-Table -Property @{Label = "Media Item"; Expression = { $_.Paths.FullPath } }
Write-Host "List of unused media items:"
$unusedMediaItems.Count
# Delete unused media items (uncomment the following code to delete them)
# foreach ($unusedItem in $unusedMediaItems) {
# Remove-Item -Path $unusedItem.Paths.FullPath
# }
# Write-Host "Deleted $unusedMediaItems.Count unused media items."Note: Be cautious when enabling the deletion code, as it will permanently remove the identified unused media items. It is advisable to thoroughly test the script.
Lock a User
This SPE script helps to temporarily or permanently disable a user’s access to the Sitecore CMS. If the specified user doesn’t exist in the Membership database, the script displays a message indicating that the user was not found.
# Specify the username of the user you want to lock
$usernameToLock = "UsernameToLock"
# Lock the user
$user = [System.Web.Security.Membership]::GetUser($usernameToLock)
if ($user -ne $null) {
$user.UnlockUser()
$user.IsApproved = $false
[System.Web.Security.Membership]::UpdateUser($user)
Write-Host "User '$usernameToLock' has been locked."
}
else {
Write-Host "User '$usernameToLock' not found."
}Unlock a User
This SPE script helps to enable a user’s access to the Sitecore CMS.
# Specify the username of the user you want to unlock
$usernameToUnlock = "UsernameToUnlock"
# Unlock the user
$user = [System.Web.Security.Membership]::GetUser($usernameToUnlock)
if ($user -ne $null) {
$user.UnlockUser()
$user.IsApproved = $true
[System.Web.Security.Membership]::UpdateUser($user)
Write-Host "User '$usernameToUnlock' has been unlocked."
}
else {
Write-Host "User '$usernameToUnlock' not found."
}Lock and Unlock specific Domain users
This SPE script makes life easier by taking care of user account management during a content freeze on deployments or some other situation. It ensures that non-admin users can’t make changes during a content freeze and re-enables them afterward.
# Specify the Sitecore domain
$domainName = "extranet"
# Get all users in the specified domain
$users = Get-User -Domain $domainName
# Specify the username of the admin user
$adminUsername = "admin"
# Check if a content freeze is active
$contentFreezeActive = $false
if ($contentFreezeActive) {
# Content freeze is active, lock non-admin users
foreach ($user in $users) {
if ($user.UserName -ne $adminUsername) {
$user | Lock-UserAccount
Write-Host "User locked: $($user.UserName)"
}
}
Write-Host "Non-admin users have been locked during the content freeze."
}
else {
# Content freeze is over, unlock previously locked non-admin users
foreach ($user in $users) {
if ($user.UserName -ne $adminUsername) {
$user | Unlock-UserAccount
Write-Host "User unlocked: $($user.UserName)"
}
}
Write-Host "Previously locked non-admin users have been unlocked after the content freeze."
}Unlock the Locked Items
This SPE script written to help when you are dealing with a situation where multiple items in the Sitecore database are locked, and you need to unlock them in a batch.
# Specify the database
$databaseName = "master"
# Get the Sitecore database
$database = Get-Database -Name $databaseName
# Get all locked items in the database
$lockedItems = Get-Item -Path "$($database.Name):/sitecore" -Language * -Version * | Where-Object { $_.Locking.IsLocked() }
# Unlock each locked item
foreach ($item in $lockedItems) {
if ($item.Locking.HasLock()) {
$item.Editing.EndEdit()
Write-Host "Unlocked: $($item.Paths.FullPath)"
}
}
Write-Host "All locked items have been unlocked."Unpublished Items
This SPE script helps to provide the list of items that have never been published or have been unpublished in the web database.
# Specify the database
$databaseName = "master"
# Get the Sitecore database
$database = Get-Database -Name $databaseName
# Get all items that are not published
$unpublishedItems = Get-Item -Path "$($database.Name):/sitecore/content/Home" -Language * -Version * | Where-Object { $_.Publishing.NeverPublish }
# Display the list of unpublished items
$unpublishedItems | Format-Table -Property @{Label = "Item Path"; Expression = { $_.Paths.FullPath } }
Write-Host "List of unpublished items:"
$unpublishedItems.CountYou can find all my scripts in my GitHub repository,
I believe these scripts can be valuable for someone facing similar needs. However, before applying these scripts in any environment, it’s crucial to keep in mind that a thorough review is essential.
Happy learning!! Happy Sharing!!







