Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Since every environment is different, all code should not be run in a production environment without your team or organization thoroughly testing first. We recommend the use of a test lab environment often referred to as a development/staging instance of Sitecore.
The disclaimer is provided because someone somewhere will inevitably not follow this recommendation and if they do hose their Sitecore environment, they have no one to blame but themselves.
All data and information provided in this book are for informational purposes only. Adam Najmanowicz, Michael West, and the SPE Team make no representations as to accuracy, completeness, currentness, suitability, or validity of any information in this book and will not be liable for any errors, omissions, or delays in this information or any losses, injuries, or damages arising from its display or use. All information found in this book is provided "as is" with no express or implied warranties.
SPE includes several built-in interfaces for managing and executing scripts, as well as provides tools for modifying content.
Here we'll discuss the Console, ISE, and other dialogs made available through SPE.
Thank you for taking the time to check out the latest and greatest changes for SPE. Send a tweet sharing how much you love the module on Twitter.
The following links provide a way to report issues and get the latest release.
See the for a compatibility matrix.
The (SPE) module is a Sitecore development accelerator that can drastically increase your productivity and curtail the amount of time it takes to deliver a Sitecore solution.
The module provides a command line (CLI) and a scripting environment (ISE) for automating tasks. SPE works with the Sitecore process, capable of making native calls to the Sitecore API and manipulating files. Running commands and writing scripts follow the standard and well-known Windows PowerShell syntax. Windows PowerShell is a common tool used in IT for desktop and server management, so we decided to stick with that as a framework to build upon.
Sitecore PowerShell Extensions provides an organization structure composed of modules, libraries, and scripts. Modules make up the highest level and can be grouped together by module folders.
Some benefits to using modules:
The contained within each module can be enabled or disabled globally. For this to take full affect the integration should be rebuilt in the ISE.
Organization of custom scripts is a cinch.
The Functions integration allows for scripts to be discoverable through autocomplete while authoring scripts. Functions can be "disabled" by disabling the containing module.
Begin by adding a script library called "Functions" to a module. This can be created by the new module wizard.
Add a script to the "Functions" script library with a name that represents the purpose.
Use the command Import-Function
Custom ribbon commands for use in the ISE.
The Workflows integration allows for scripts to run like workflow commands. Rules can be used to control visiblity and enablement. The script is only executed when the command is triggered.
Begin by adding a new item to a workflow command of template type /Modules/PowerShell Console/PowerShell Script Workflow Action. We've added an insert option to help with this.
Edit the Type string field to your custom type or to the built in type Spe.Integrations.Workflows.ScriptAction, Spe.




$Host.UI.RawUI.BackgroundColor = ($bckgrnd = 'DarkRed')
$Host.UI.RawUI.ForegroundColor = 'Cyan'
$Host.PrivateData.WarningForegroundColor = 'Magenta'
$Host.PrivateData.WarningBackgroundColor = "Green"
$Host.PrivateData.VerboseForegroundColor = 'Green'
$Host.PrivateData.VerboseBackgroundColor = "Red"
Write-Host " Write-Host "
Write-Verbose " Write-Verbose " -Verbose
Write-Warning " Write-Warning "
Show-Result -Text -Width 500 -Height 300
The following examples are best kept on SSE since it provides more context about the problem being solved.
Question Find all items based on a template found anywhere in the inheritance chain.
# Sample Item
$sourceTemplate = Get-Item -Path "master:\{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
# Sample Content
$targetTemplate = Get-Item -Path "master:\{93A8866B-972F-4FBF-8FD9-D6004B18C0AF}"
# Use Get-ItemReferrer to find all items referencing the template, rather than scanning the content tree.
$sourceTemplate | Get-ItemReferrer |
Where-Object { $PSItem.TemplateId -eq $sourceTemplate.ID -and $PSItem.Paths.IsContentItem } |
ForEach-Object {
Set-ItemTemplate -Item $PSItem -TemplateItem $targetTemplate
}Edit the Script body with the appropriate script. I like to save my workflow scripts in a library called Workflows.
Configure the Enable rules on the workflow action item to specify when to execute. Leave the rule alone if you wish for it to execute any time the command is activated.
Edit the script in your Workflows library to perform the appropriate actions. The script can run in the background and show dialogs.
Change the icon of the workflow action item to match the script purpose.
Celebrate your success with the team!
Example: The following requests input from the user then writes to the workflow history.
See how Adam integrated workflow actions if you are really curious to know more.
$item = $SitecoreContextItem
$comment = Show-Input -Prompt "Enter a comment:"
if($comment) {
New-ItemWorkflowEvent -Item $item -Text $comment
}
Close-WindowThe book provides documentation about how to use the module based on the latest released version. While some of the screenshots and materials may be slightly out-of-date, you will inevitably find details referring to something that doesn't exist on your installed version. Feel free to submit a pull request for corrections here.
Support for Sitecore 7 has discontinued with SPE 5.0. Check the appendix for version compatibility.
The following are some helpful modules distributed with SPE.
Core
Platform
PowerShell Background Session Manager
Recreate site from sitemap
X-UnitTests - examples at how to use to test your scripts
Extensions
- reports based on the Sitecore Rules Engine.
- similar to the Luke tool
Maintenance
Index On Demand
Media Library Maintenance
System Maintenance
Reporting
- variety of reports to help audit the Sitecore solution.
Samples
Automatically show quick info section
Enforce user password expiration
Example Event Handlers
Tools
Authoring Instrumentation
Copy Renderings
Data Management
Training
There is nothing you can not do with PowerShell Console, because you're inside the Sitecore application. You can call the Sitecore API. - Alistair Deneys - Sitecore Symposium 2012
Recommended by John West to use as a tool for maximizing Sitecore developer productivity.
Get a job done with a one liner! Just provisioned a new language for the whole content tree with a one-liner. Whaaaat? Have to include it as a default install for all sandboxes now. - Alex Shyba's comment on Marketplace
Thank you for the GitBook. Invaluable Reference. - Nick Wesselman's tweet
The Sitecore powershell tools are absurdly good and helpful. I know they make a lot of people nervous, but they are incredibly well managed. Everybody should learn to sling some shell in Sitecore, you'll never look back. - Christopher Campbell tweet
I literally couldn't work without SPE - I can't remember the last implementation I did that didn't have it installed lol @michaellwest & @adamnaj better not ever retire it 😄 - Richard Seal
See the Troubleshooting section for some common fixes.
Questions, comments, and feature requests should be submitted on GitHub. You may also check out the SPE Slack channel for more interactive support. Not on Slack yet? Contact us on Twitter and we'll send you an invite.
Disclaimer: With great power comes great responsibility – this tool can do a lot of good but also bring harm to a lot of content in a very short time – backup your system before running a script that modifies your content and never run any untested scripts in a production environment! We will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content.

More reasons can be found in Adam's post.
The Platform module is one you should avoid changing.
Getting started with your own module is a short process and something you should do for all of your custom scripts.
Navigate to the Script Library item and Insert -> PowerShell Script Module.
Enter the name for the new module and click OK.
Right click the new module and Scripts -> Create libraries for integration points.
Select the appropriate integration points for your module.
Select the module and enable for use.
Open the ISE, switch to the Settings tab, and rebuild integrations.
Note: It's best practice to create function scripts that follow the Verb-Noun pattern as outlined by Microsoft.
Here's a short video on authoring custom functions.
The path structure needs to follow [MODULE]/Internal/ISE Plugins/[PLUGIN_NAME]. Here we have X-Demo/Internal/ISE Plugins/Analyze Script.
Use the following sample to fill in the script body.
Now you can run the command from the ribbon and see the results in the ISE.
if([string]::IsNullOrWhiteSpace($scriptText)){
Show-Alert "Script is empty - nothing to format."
exit
}
Import-Module -Name PSScriptAnalyzer
Invoke-ScriptAnalyzer -ScriptDefinition $scriptTextScripted Data Sources provide a way to use a PowerShell script to perform complex queries.
Here are some good reasons to use this feature:
Delivering complex functionality based on multiple criteria.
Your field may need to provide different set of items to choose from based on:
user name or role (in simplest case this can be done using right management, but maybe not always possible in a more elaborate scenario)
current day or month?
In a multisite/multimarket scenario you may want to show different items for each site
based on engagement analytics parameters of the page
based on where in the tree an item exist (some of it can be done with use of a “query:”)
anything you might want to build the code data source for…
Something that would be beyond the reach of a regular Sitecore query and potentially something that you would really need to deliver code source for. But maybe you’re not in a position to deploy that on your environment?
Field Data Source provides a great opportunity for a script.
Below are field types you may wish to use a script:
Checklist
Droplist
Grouped Droplink
Grouped Droplist
//TODO
//TODO
PowerShell Scripted Data Sources and
Sitecore Spark on using scripted datasources
The Notification integration reveals to the user a notification above the content. The Sitecore rules engine may be used to control the enabled state; simply configure the Enable rule on the script. The script is executed every time the page loads.
Example: The following adds an information notification to the page for Sitecore 8 and a warning for Sitecore 7.
$title = "Thank you for using SPE!"
$text = "Today is $([datetime]::Now.ToLongDateString())"
$icon = @{$true="Office/32x32/information.png";$false="Applications/16x16/warning.png"}[$SitecoreVersion.Major -gt 7]
$notification = New-Object -TypeName Sitecore.Pipelines.GetPageEditorNotifications.PageEditorNotification -ArgumentList $text, "Info"
$notification.Icon = $icon
$pipelineArgs.Notifications.Add($notification)Note: Examples included in the following modules
License Expiration
The Experience Button integration adds a button to the Page Editor. Rules can be used to control visiblity and enablement. The script is only executed when the button is clicked.
Begin by adding a new script to the Experience Button library. The name of the script will appear in the tooltip.
Edit the script to perform the appropriate actions. The script can run in the background and show dialogs.
Change the icon of the item to match the script purpose.
Configure any Enable
Example: The following adds a command which will display a dialog asking a question, then send an email with the response.
Use the following in your scripts to get access to the arguments passed to the processor.
$pipelineArgs = Get-Variable -Name pipelineArgs -ValueOnlyConfigure any Enable rules to ensure your script only runs when necessary.
Note: Examples included in the following modules
Enforce user password expiration
Note: Examples included in the following modules
Automatically show quick info section
Note: Examples included in the following modules
Unlock user items on logout
There are multiple methods of accessing help documentation in SPE to provide you with information on the commands available to you.
A report is available which will show you all available SPE commands:
When executed, this report provides a paged view of the SPE commands.
To display the available help for a command in the Console, simply use the Get-Help command:
For full documentation, including examples, use the -Full parameter:
Through the Integrated Scripting Environment (ISE), SPE provides a method of acccessing help for available commands. To view the help for a command, simply highlight the command and press Ctrl + Enter.
After doing this, a dialog will appear with the relevant help information:
When writing scripts, you are able to include formatted comments that will be used to provide help text for functions. If formatted correctly, this help text will be available through the methods described above.
Example: A simple function with documentation:
Once the script containing this function has been invoked, the help text will be available:
For further information on comment-based help, refer to the .
Online help is additionaly available for all SPE commands in this documentation, with detailed explanations of commands and their parameters, along with useful examples. These can be found in the .
The Event Handler integration provides a way to execute scripts when defined events are fired.
Steps required to activate this integration include the following:
Enable the Spe.Events.config or apply your own patch with the required events enabled.
Add a new integration point library to your new or existing module.
Add a new script to the appropriate event library.
Configure an Enable Rule if needed.
Profit!
While SPE comes with an example configuration, which is disabled by default, it contains several events that may not meet your requirements.
An event configuration patch may look like the following:
To mimic the event item:added you should create nested script libraries such as Event Handlers -> Item -> Added followed by a script.
Review prerequisites and details on how to get setup with SPE.
Take a quick look at the to see which version of SPE you should be installing that is compatible with your Sitecore environment. Generally SPE has pretty good backwards compatibility but may require a new version to support the latest Sitecore CMS release.
Windows Management Framework 5.1 (PowerShell) is generally available for most Windows environments.
Task Management
Getting Started - includes the Kitchen Sink Demo for Read-Variable.
License Expiration
Random desktop background
Training Modules
Unlock user items on logout
Bulk Data Generator - useful for items and users
Bulk Item Restorer - restore items from recycle bin
Bulk Template Changer - can't think of a better description than this
Data Importer - create or update items from a Csv
Find and Replace - use Content Search to change text
Elevated Unlock - provides options to unlock items using delegated administration
Package Generator - a simple method to package up items
Publishing Status Gutter
Security Management
Logged in Session Manager
Transfer item security




Multilist
Name Lookup Value List
Droplink
Begin by adding a new script library called Data Sources followed by adding a script. You can call it something like Get-GlobalOption.
Add the path to your script in the Source field on the data template. The source should be prefixed with script: followed by the path.
Enjoy the results.





$pipelineArgs.Username
$pipelineArgs.Password
$pipelineArgs.Success
$pipelineArgs.StartUrl$pipelineArgs.Username
$pipelineArgs.StartUrl




PowerShell Execution Policy set to RemoteSigned (probably optional)
Working with Docker is going to be the preferred method of installation.
You can find two flavors of the images:
Ex: docker pull sitecorepowershell/sitecore-powershell-extensions:6.4-1809
Sitecore Built
Ex: docker pull scr.sitecore.com/sxp/modules/sitecore-spe-assets:6.4-1809
With this approach, you essentially add a new layer during your image build to include the files from the asset image. Here are some samples of what you can add to your existing setup. Check out Sitecore's samples for additional guidance.
docker-compose.yml
Dockerfile (mssql-init)
Dockerfile (cm)
The SPE module installs like any other for Sitecore. This approach is appropriate for installations not within a containerized environment.
Download the module from the GitHub releases page and install through the Installation Wizard.
For Sitecore 10.1 and newer along with Identity Server you should enable the provided configuration Spe.IdentityServer.config.
For Sitecore 10.1 and newer you can leverage the IAR packages. There is still the need for dacpac deployments because SPE includes a security user and role.
An additional patch is required for 10.1 to include the location /sitecore modules/items/. See Gist here.
We've tried to make upgrading SPE as seamless as possible. The following should provide you with some basic information on what to expect when upgrading.
You should be able to install directly over the previous installation of 6.0+.
For Sitecore 10.1 and newer along with Identity Server you should enable the provided configuration Spe.IdentityServer.config.
For Sitecore 10.1 and newer you can leverage the IAR packages. There is still the need for dacpac deployments because SPE includes a security user and role.
An additional patch is required for 10.1 to include the location /sitecore modules/items/. See Gist here.
These versions used a different name for the assemblies and configs. You may find it easier to delete all files originally distributed with SPE before installing a newer version. Here are a few steps to consider:
Delete all files in the bin and App_Config/Include directories prefixed with Cognifide.
Delete /sitecore modules/Shell/PowerShell
Delete /sitecore modules/PowerShell
Reference the original SPE package (if available) to identify if any other files were included.
Sitecore items in the content tree will potentially shuffle around into their new location. Be sure to backup your custom scripts first.
See the troubleshooting section here
Example: The following removes an item link followed by removing the item. Originally posted here.
$item = Get-Item -Path "master:\media library\images\koala"
$itemNew = Get-Item -Path "master:\media library\images\penguins"
$links = Get-ItemReferrer -Item $item -ItemLink
foreach($link in $links) {
$linkedItem = Get-Item -Path master:\ -ID $link.SourceItemID
$itemField = $linkedItem.Fields[$link.SourceFieldID]
$field = [Sitecore.Data.Fields.FieldTypeManager]::GetField($itemField)
$linkedItem.Editing.BeginEdit()
$field.Relink($link, $itemNew)
$linkedItem.Editing.EndEdit() | Out-Null
}# The script must return an item. This is useful for populating a Droplink.
Get-ChildItem -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"script:/sitecore/system/Modules/PowerShell/Script Library/X-Demo/Data Sources/Get-GlobalOption$item = Get-Item -Path .
$response = Show-Input -Prompt "What's the message for $($item.Name)?"
if($response) {
$mailSettings = @{
To = @("Michael West < [email protected] >")
From = "Console < [email protected] >"
BodyAsHtml = $true
SmtpServer = "localhost"
}
$subject = "Message sent regarding item $($item.Name) from $($SitecoreAuthority)"
$response += "<br/>$($item.ItemPath)"
Send-MailMessage @mailSettings -Subject $subject -Body $response
}
Close-WindowGet-Help Get-RenderingGet-Help Get-Rendering -Full<#
.SYNOPSIS
A short synopsis of this function.
.DESCRIPTION
A much more detailed description of this function, which outputs a value.
.PARAMETER Value
The value that will be output
.EXAMPLE
PS> Output-Value "My value"
My value
#>
Function Output-String
{
param(
[string]$value
)
Write-Host $value
} Get-Help Output-String<configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<events>
<event name="item:added">
<handler type="Spe.Integrations.Tasks.ScriptedItemEventHandler, Spe" method="OnEvent" />
</event>
</events>
</sitecore>
</configuration>services:
mssql-init:
image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-mssql-init:${VERSION:-latest}
build:
context: ./docker/build/mssql-init
args:
BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-mssql-init:${SITECORE_VERSION}
SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-spe-assets:${SPE_VERSION}
cm:
image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest}
build:
context: ./docker/build/cm
args:
BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION}
SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-spe-assets:${SPE_VERSION}# escape=`
ARG BASE_IMAGE
ARG SPE_IMAGE
FROM ${SPE_IMAGE} as spe
FROM ${BASE_IMAGE}
COPY --from=spe C:\module\db C:\resources\spe# escape=`
ARG BASE_IMAGE
ARG SPE_IMAGE
FROM ${SPE_IMAGE} as spe
FROM ${BASE_IMAGE}
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
WORKDIR /inetpub/wwwroot
COPY --from=spe \module\cm\content .\# Crafted by Dylan
function Remove-ItemLink {
param([Item]$item)
$linkDb = [Sitecore.Globals]::LinkDatabase
$links = Get-ItemReferrer -Item $item -ItemLink
foreach($link in $links) {
$linkedItem = Get-Item -Path master:\ -ID $link.SourceItemID
$itemField = $linkedItem.Fields[$link.SourceFieldID]
$field = [Sitecore.Data.Fields.FieldTypeManager]::GetField($itemField)
$linkedItem.Editing.BeginEdit()
$field.RemoveLink($link)
$linkedItem.Editing.EndEdit()
}
}
# Example usage: delete items along with their references that have passed a certain date defined by a 'date' field
$today = Get-Date
$todayIsoDate = [Sitecore.DateUtil]::ToIsoDate($today)
$query = "/sitecore/system/Modules/Mysite/Service Schedules/*[@date < '$($todayIsoDate)']"
$itemsToDelete = Get-Item -Path master: -Query $query
foreach($item in $itemsToDelete) {
Write-Host "Cleaning up $($itemsToDelete.Paths.Path)"
Remove-ItemLink -Item $item
Remove-Item -Path $item.Paths.Path
}The ConvertFrom-CliXml command imports a CliXml string with data that represents Microsoft .NET Framework objects and creates the objects in PowerShell.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
String containing the Xml with serialized objects.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
System.String
The output type is the type of the objects that the cmdlet emits.
object
Help Author: Adam Najmanowicz, Michael West
ConvertTo-Xml
ConvertFrom-Xml
Export-CliXml
Import-CliXml



The section on working with items provided a variety of examples in retrieving items based on their language. In this section will show how to manage items and their languages.
Example: The following example queries all of the content items and adds a new language version of "en-ca", while overwriting any that exist.
Example: The following example adds a language version from English to US and Polish while leaving the Title field blank. If a version already exists nothing happens.
Example: The following example adds a language version from English to Polish of Template Name Sample Item. If the version exists a new version is created for that language. Finally the results are displayed as a table showing only the Name, Language, and Version.
Example: The following example adds a language version in Polish to the Home item and all its children. If the version exists nothing happens. No fields were harmed in the making of this version.
Example: The following example queries all of the content items and removes the language version of "fr-CA".
Example: The following example creates a new item with language versions only matching the specified languages; all other language version are removed.
Supported parameters:
-Recurse Translates item and its children
-IfExist Accepts one of 3 pretty self explanatory actions: Skip, Append or OverwriteLatest
On top of the ignored fields in the -IgnoredFields the following fields are ignored as configured within the Spe.config file:
The task scheduler is a great way to run scripts in a periodic fashion. You may find the need to automatically archive log files into a compressed file. Perhaps send an email with a generated report based on stale site content.
To help make the setup simple, we've provided a Task Command.
The command shown above is simply a type exposed as a public method in the Spe assembly. There exists an update method which accepts one or more items and executes the associated script.
Beneath Schedules you can create as many tasks as Sitecore will allow. Configure the Command and Items fields like that shown below.
The Items field contains the path to a script in the Script Library.
Below are some of the scripts found out-of-the-box with SPE.
We've added a context menu item to provide you with a shortcut to the Task Scheduler Editor.
Create a new scheduled task:
Run or edit the scheduled task:
The scheduled task is capable of running 1-to-many scripts. Choose all that apply for the selected task. Each script runs within a shared session, making it possible to share results between scripts.
Note: Make use of the Enable Rule to take advantage of the rules engine.
The task schedule has an intuitive dialog for working with and changing the frequency.
Note: Examples included are in the following modules
License Expiration
Media Library Maintenance
System Maintenance
See how Adam added .
The Web API integration point exposes scripts through a url. This can be especially helpful when a script needs to be executed on the server but without knowledge of the script contents.
The url will look something like the following: https://remotesitecore/-/script/v2/master/homeanddescendants?user=sitecore\admin&password=b
Here's the url broken down:
API Version - Specifies which service is being requested.
v2 - This is the service that executes scripts stored in the integration point library.
Database - Specifies which database contains the script.
master - This database requires the credentials to be provided.
Script - Specifies the name of the script contained in the database. The SPE module containing the script needs to be enabled otherwise you'll receive a 404 error.
homeanddescendants - Replace this name with whatever your script is called in the Web API library.
Query String Parameters (deprecated) - Specifies the additional bits of data for use by the web service.
user and password - Authenticates the request and in most cases will be needed. If the script is published to the web database the credentials are not required. You should use the Basic header instead of the query string.
All of the query string parameters added to the variable scriptArguments
Headers:
Use the Basic header to provide authentication information. Here is an example of how to build that for a script.
Note: Examples included in the following modules
Getting Started
The integration point is disabled by default and can be enabled through configuration as described . See Restfulv2. Be sure to enable the SPE script module in the content tree.
Watch Adam present this and much more on Sitecore! Experienced .
Ever wanted to package up items and files without opening the Sitecore Package Designer each time? There are a number of commands available for generating packages.
Example: The following example demonstrates how to generate a package.
$package = New-Package "Package-of-Stuff"
$package.Sources.Clear()
$package.Metadata.Author = "Michael West"
$package.Metadata.Publisher = "Team Awesome"
$package.Metadata.Version = "1.0"
$package.Metadata.Readme = @"
Set of instructions for the user.
"@
# Items using New-ItemSource and New-ExplicitItemSource
$source = Get-Item -Path "master:\templates\Feature\Forms" |
New-ItemSource -Name 'Feature Forms Items' -InstallMode Overwrite
$package.Sources.Add($source)
# Files using New-FileSource and New-ExplicitFileSource
$source = Get-Item -Path "$AppPath\App_Config\Include\Feature\Forms\Company.Feature.Forms.config" |
New-ExplicitFileSource -Name "Feature Forms Files"
$package.Sources.Add($source)
Export-Package -Project $package -Path "$($package.Name)-$($package.Metadata.Version).xml"
Export-Package -Project $package -Path "$($package.Name)-$($package.Metadata.Version).zip" -Zip
Download-File "$SitecorePackageFolder\$($package.Name)-$($package.Metadata.Version).zip"Example: The following adds a Post Step and custom attributes.
Example: The following adds a Post Step included with SPE to delete a file. The SPE Post Step code reads xml data stored in the comment section of the package.
Example: The following adds a Post Step Script included with SPE to change icons. The SPE Post Step code executes a script included with the package as stored in the attributes section.
Exports Microsoft .NET objects froms PowerShell to a CliXml string.
ConvertTo-CliXml [-InputObject] <PSObject>
The ConvertTo-CliXml command exports Microsoft .NET Framework objects from PowerShell to a CliXml string.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Specifies the object to be converted. Enter a variable that contains the objects, or type a command or expression that gets the objects. You can also pipe objects to ConvertTo-CliXml.
The input type is the type of the objects that you can pipe to the cmdlet.
object
The output type is the type of the objects that the cmdlet emits.
System.String
Help Author: Adam Najmanowicz, Michael West
ConvertFrom-Xml
ConvertTo-Xml
We generally see issues occurring due to an incompatible version of Windows PowerShell. Be sure to install Windows PowerShell version 3 or newer.
There is an additional configuration file added to support Identity Server. If you are installing Sitecore 9.1 or later you will want to enable the configuration file Spe.IdentityServer.config.
Some users have reported an where the package installation in Sitecore hangs while installing SPE. One possible fix is to disable the Sitecore Analytics feature; this of course assumes you do not plan on using it for your instance.
Article: Martin Miles encountered the issue and proposed a fix .
Hack: Run this script on Sitecore 8.0.
- Missing Home item (fixed in 3.2)
Be sure the module is enabled and the integrations are rebuilt from within the ISE. The following are some of the integration issues you may experience:
Content Editor Gutter - Entries not listed.
Content Editor Ribbon - Buttons not visible or working.
Control Panel - Entries not listed.
Functions - Import-Function name parameter not populating with functions or can't be found after running the command.
404 error in browser console can be caused by missing SPE files, a custom pipeline, or perhaps a rewrite rule.
"The request failed with an empty response." could be caused when TLS is offloaded to a load balancer and traffic to the endpoint is no longer over HTTPS. Fixed by issue #.
"The underlying connection was closed: An unexpected error occurred on a send." could be caused in Azure PaaS when requests are made using TLS 1.1 or lower. Setting the SecurityProtocol may help. Thanks to Jayesh Sheth for pointing to a resolution.
Comprehensive guide to learning SPE from beginner to advanced.
The world renowned Sitecore PowerShell Extensions module has so much to offer, but sometimes those new to the module may find it difficult to know where to start. This training guide provides you with everything you need to use and be productive with SPE.
Don't worry, you will be able to use it without having to write any code.
This guide provides a progressive roadmap from beginner to advanced SPE user. Follow this path to build your skills systematically:
The Console is a command line interface (CLI) designed for efficiency, providing a streamlined tool for working with Windows PowerShell and Sitecore.
The default security configuration for SPE requires the Console to be in an before allowing the execution of commands. The following figure shows the Console when the User Account Controls (UAC) are disabled. While this is a common configuration for developers, we highly encourage you to ensure UAC is enabled in higher environments.
Below are the shortcuts available in the console.
The SPE Modules support a wide variety of predefined script libraries to help with exposing scripts to the Sitecore interface.
The following list outlines the available libraries for Integration Points that may be added to modules. These may also be generated automatically when creating or updating modules.
The PowerShell Toolbox is quick way to access frequently used scripts.
Navigate to Sitecore -> PowerShell Toolbox and after selecting you should see the configured scripts:
Note: Examples included in the following modules
Authorable Reports
Logged in Session Manager
Examples for managing complex field types such as MultilistField and NameValueListField.
Example: The following demonstrates how to set a field to a known list of Ids. The Id is already converted to a GUID string.
Example: The following replaces an instance of an Id with an alternate Id. The Id is already converted to a GUID string.
Example: The following adds new Ids to an existing list. Makes use of the Sitecore.Text.ListString class.
PS master:\> #Convert original item to xml
PS master:\> $myCliXmlItem = Get-Item -Path master:\content\home | ConvertTo-CliXml
PS master:\> #print the CliXml
PS master:\> $myCliXmlItem
PS master:\> #print the Item converted back from CliXml
PS master:\> $myCliXmlItem | ConvertFrom-CliXmlGet-ChildItem "master:\content" -Recurse |
Add-ItemLanguage -Language "en-us" -TargetLanguage "en-ca" -IfExist OverwriteLatest$languageParameters = @{
Path = "master:\content\home"
Language = "en"
TargetLanguage = @("pl-pl","en-us")
IfExist = "Skip"
IgnoredFields = @("Title")
}
Add-ItemLanguage @languageParameters-TargetLanguage accepts a list of languages that should be created-DoNotCopyFields creates a new version but does not copy field values from original language
-IgnoredFields list of fields that should not be copied over from original item this can contain e.g. __Security if you don't want the new version to have the same restrictions as the original version.
Invoke-ApiScript$package = New-Package "Package-of-Stuff"
$package.Sources.Clear()
$package.Metadata.Author = "Michael West"
$package.Metadata.Publisher = "Team Awesome"
$package.Metadata.Version = "1.0"
$package.Metadata.Readme = @"
Set of instructions for the user.
"@
$package.Metadata.PostStep = "Some.Library.Class,Some.Library"
$package.Metadata.Attributes = "scriptId={9b9a3906-1979-11e7-8c9d-177c30471cec}|width=50|height=200"
Export-Package -Project $package -Path "$($package.Name)-$($package.Metadata.Version).xml"Import-Function -Name New-PackagePostStep
$package = New-Package "Package-of-Stuff"
$package.Sources.Clear()
$package.Metadata.Author = "Michael West"
$package.Metadata.Publisher = "Team Awesome"
$package.Metadata.Version = "1.0"
$package.Metadata.Readme = @"
Set of instructions for the user.
"@
$newPackageFiles = @([PSCustomObject]@{"FileName"="/bin/Company.Feature.Unused.dll"})
$package.Metadata.PostStep = "Spe.Package.Install.PackagePostStep, Spe.Package"
$package.Metadata.Comment = New-PackagePostStep -PackageFiles $newPackageFilesExport-CliXml
Import-CliXml
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Web API - Scripts not existing or can't be found.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Example: The following demonstrates the use of Get-Rendering and Set-Rendering for updating values on templates.
Example: The following demonstrates how to report on pages referencing the specified rendering.
Example: The following demonstrates how to report on which renderings are globally set to "Cacheable".
Example: The following demonstrates how to find renderings with a conditions node set on the item.
Example: The following demonstrates how to disable global caching on all renderings.
Example: The following moves renderings from one placeholder to another. See this article for more details.
Example: The following removes a datasource from a rendering on the FinalLayout.
ID to a set of items in all languages. It verifies that the field Keywords exists.Example: The following example gets all of the items of a MultilistField and append a specific ID, ensuring that it's delimited with the | character.
Example: The following example extracts the items from a 'keywords' field, comma separates the values, and then outputs to a report.
Example: The following example gets all of the name/value pairs of a NameValueListField and appends a new pair.
# Hardcoded list of Ids.
$item.Editing.BeginEdit()
$item["Allowed Controls"] = "{guid1}|{guid2}|{guid3}"
$item.Editing.EndEdit()# Array of Ids.
$array = [System.Collections.ArrayList]@()
$array.Add({guid1}) > $null
$array.Add({guid2}) > $null
$ids = [System.String]::Join("|", $array)
$item.Editing.BeginEdit()
$item["Allowed Controls"] = $ids
$item.Editing.EndEdit()The Get-Archive command returns Sitecore archives in context of the specified database.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Name of the archive to retrieve.
Required?
false
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database for which the archives should be retrieved.
Required?
false
Position?
2
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Database
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Archiving.Archive
Help Author: Adam Najmanowicz, Michael West
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The output type is the type of the objects that the cmdlet emits.
System.String
Help Author: Adam Najmanowicz, Michael West
Ensures the runner process window is closed after the script finishes execution. This is commonly used when the runner should close after a report runs while in the Desktop mode.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Help Author: Adam Najmanowicz, Michael West
Get-ChildItem "master:\content\home" -Language "en" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" } |
Add-ItemLanguage -TargetLanguage "pl-pl" -IfExist Append |
Format-Table Name, Language, Version -AutoSizeAdd-ItemLanguage -Path "master:\content\home" -TargetLanguage "pl-pl" -IfExist Skip -DoNotCopyFields -RecurseGet-ChildItem "master:\content" -Recurse |
Remove-ItemLanguage -Language "fr-CA"$itemPath = "master:\content\home\sample item\Sample Item 3"
New-Item -Path $itemPath -ItemType "Sample/Sample Item" -Language "en-CA"
Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Sample Item 3 False en-CA 1 {C9517583-3AF9-4AFB-B247-BB0A09F55D94} Sample Item<configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<translation>
<ignoredFields>
<field>__Archive date</field>
<field>__Archive Version date</field>
<field>__Lock</field>
<field>__Owner</field>
<field>__Page Level Test Set Definition</field>
<field>__Reminder date</field>
<field>__Reminder recipients</field>
<field>__Reminder text</field>
<!--field>__Security</field-->
</ignoredFields>
</translation>
</sitecore>
</configuration>$username = "admin"
$password = "b"
$pair = "$($username):$($password)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$headers = @{
Authorization = $basicAuthValue
}
Invoke-RestMethod -Headers $headers -Uri "https://spe.dev.local/-/script/v2/master/TrainingWebApi?offset=3&limit=2&fields=(Name,ItemPath,Id)"$package = New-Package "Package-of-Stuff"
$package.Sources.Clear()
$package.Metadata.Author = "Michael West"
$package.Metadata.Publisher = "Team Awesome"
$package.Metadata.Version = "1.0"
$package.Metadata.Readme = @"
Set of instructions for the user.
"@
$package.Metadata.PostStep = "Spe.Integrations.Install.ScriptPostStep, Spe"
$package.Metadata.Attributes = "scriptId={737CD0CC-12F7-4528-8FBD-E0FDEFC41325}"Write-Log "Processing changes to ensure backwards compatibility."
$oldVersion = New-Object System.Version(10,0)
if($PSVersionTable["SitecoreVersion"] -lt $oldVersion) {
$iseButton = Get-Item -Path "core:{bfc79034-857c-4432-a5c2-2d93af784384}"
$iseButton.Editing.BeginEdit()
$iseButton.Fields["{D25B56D4-23B6-4462-BE25-B6A6D7F38E13}"].Value = "powershell/32x32/ise8.png"
$iseButton.Editing.EndEdit() > $null
$reportButton = Get-Item -Path "core:{74744022-353c-43f1-b8e4-5bc569ca9348}"
$reportButton.Editing.BeginEdit()
$reportButton.Fields["{D25B56D4-23B6-4462-BE25-B6A6D7F38E13}"].Value = "Office/32x32/chart_donut.png"
$reportButton.Editing.EndEdit() > $null
Write-Log "Changes complete."
} else {
Write-Host "No changes required."
}
Close-WindowPS master:\> #Convert original item to xml
PS master:\> $myCliXmlItem = Get-Item -Path master:\content\home | ConvertTo-CliXml
PS master:\> #print the CliXml
PS master:\> $myCliXmlItem
PS master:\> #print the Item converted back from CliXml
PS master:\> $myCliXmlItem | ConvertFrom-CliXml$paths = @("C:\inetpub\wwwroot\Console\Website\App_Config\Include\*")
$patterns = @("Sitecore.Analytics*.config", "Sitecore.ExperienceAnalytics*.config")
$paths | Get-ChildItem -Include $patterns -Recurse | Rename-Item -NewName { $PSItem.Name + ".disabled" }$defaultLayout = Get-LayoutDevice -Default
$rootItem = Get-Item -Path "master:" -ID "{961563FC-3445-4558-BF3A-06DF06BA6298}"
Get-Rendering -Item $rootItem -Device $defaultLayout -FinalLayout$rendering = Get-Item -Path "master:\sitecore\layout\Sublayouts\Sample Sublayout"
$items = Get-ChildItem -Path "master:\sitecore\templates\Sample Item" -Recurse
foreach($item in $items) {
$renderingInstance = Get-Rendering -Item $_ -Rendering $rendering
if ($renderingInstance) {
Set-Rendering -Item $_ -Instance $renderingInstance -Parameter @{
"Lorem" = "Ipsum"
}
Write-Host "Updated $($_.Paths.FullPath)"
}
}Get-Item "master:\layout\Renderings\Feature\Experience Accelerator\Page Content\Page Content" |
Get-ItemReferrer | Where-Object { $_.ContentPath.StartsWith("/Demo/usa/Home") } | Show-ListViewGet-ChildItem -Path "master:\layout\Renderings" -Recurse |
Where-Object { $_.Cacheable -eq "1" } |
Select-Object -Property Name, Cacheable, ClearOnIndexUpdate, VaryBy* |
Sort-Object -Property Name | Show-ListView$query = "fast:/sitecore/content//*[@__renderings='%<conditions%' or @#__Final Renderings#='%<conditions%']"
$items = Get-Item -Path "master:" -Query $query$VerbosePreference = "Continue"
Get-ChildItem -Path "master:\layout\Renderings" -Recurse |
Where-Object { $_.Cacheable -eq "1" } |
ForEach-Object { Write-Verbose "Disabled global caching on $($_.Name)"; $_.Cacheable = "0" }
# VERBOSE: Disabled global caching on Navigation$placeholderMappings = @(
@("/old-placeholder","/new-placeholder"),
@("/another-old-placeholder","/new-placeholder")
)
$rootItem = Get-Item -Path master:/sitecore/content/Home
$defaultLayout = Get-LayoutDevice "Default"
# Toggle for whether to update Shared or Final Layout
$useFinalLayout = $True
# If set to true, the script will only list the renderings that need fixing, rather than fixing them.
$reportOnly = $False
foreach ( $item in Get-ChildItem -Item $rootItem -Recurse )
{
# Only interested in items that have a layout
if (Get-Layout $item)
{
foreach( $mapping in $placeholderMappings )
{
# Get renderings in this item that have renderings in the placeholder we want to update
$renderings = Get-Rendering -Item $item -Placeholder ($mapping[0] + '/*') -Device $defaultLayout -FinalLayout:$useFinalLayout
foreach ( $rendering in $renderings )
{
# Only update the rendering if we're not in "Report Only" mode
if (!$reportOnly)
{
# Update the placeholder in the rendering and set it back in the item
$rendering.Placeholder = $rendering.Placeholder -replace $mapping[0], $mapping[1]
Set-Rendering -Item $item -Instance $rendering -FinalLayout:$useFinalLayout
}
Write-Host "$($item.FullPath) - Rendering $($rendering.UniqueID) - Placeholder: $($mapping[0]) --> $($mapping[1])"
}
}
}
}Get-Rendering -Item $item -PlaceHolder "main" |
Foreach-Object { Set-Rendering -Item $item -Instance $_ -DataSource $null -FinalLayout }$rendering = Get-Item master:\layout\path\to\your\rendering
$renderingPageContainer = Get-Rendering -Item $item "{F39BAC93-1EEC-446B-A4A1-AB7F7C1B6267}" -Device $defaultLayout
$renderingPageContainer.ItemID = $rendering.ID
Set-Rendering -Item $item -Instance $renderingPageContainer[Sitecore.Data.Fields.MultilistField]$field = $item.Fields["Allowed Controls"]
$item.Editing.BeginEdit()
$field.Replace("{493B3A83-0FA7-4484-8FC9-4680991CF742}","{493B3A83-0FA7-4484-8FC9-4680991CF743}")
$item.Editing.EndEdit()[Sitecore.Text.ListString]$ids = $item.Fields["Rendering"].Value
$ids.AddAt(0,"{guid1}") > $null
$ids.Add("{guid2}") > $null
$ids.Add("{guid3}") > $null
$item.Editing.BeginEdit()
$item.Fields["Rendering"].Value = $ids.ToString()
$item.Editing.EndEdit() > $null$items = Get-ChildItem -Path "master:\sitecore\content\home" -Recurse -Language *
foreach($item in $items) {
if ($item.Keywords -and $item.Keywords.Length -gt 0) {
$item.Keywords = $item.Keywords + "|{guid}"
} else {
$item.Keywords = "{guid}"
}
}$items = Get-ChildItem -Path "master:\sitecore\content\home" -Recurse -Language *
foreach($item in $items) {
$item.Keywords = (@() + $item.Keywords.GetItems().ID + "{6D1EACDD-0DE7-4F3D-B55A-2CAE8EBFF3D0}" | Select-Object -Unique) -join "|"
}function Get-KeywordsAsString($item) {
[Sitecore.Data.Fields.MultilistField] $field = $item.Fields["Keywords"]
$items = $field.GetItems()
$strArray = $items | Foreach { $_.DisplayName }
$strArray -join ', '
}
Get-ChildItem -Path 'master:\content\home\path-to-item' `
| Show-ListView -Property Name, Language, Version, ID, TemplateName, ItemPath, `
@{ Label = "KeywordsAsString"; Expression = { Get-KeywordsAsString($_) } }$item = Get-Item -Path "master:" -ID "{371EEE15-B6F3-423A-BB25-0B5CED860EEA}"
$nameValues = [System.Web.HttpUtility]::ParseQueryString($item.UrlMapping)
# Here you can add or remove name/value pairs
$nameValues["^/ab[cde]/$"] = "/somewhere/fun?lang=en"
foreach($key in $nameValues.AllKeys) {
$nameValues[$key] = [Uri]::EscapeDataString($nameValues[$key])
}
$item.UrlMapping = [Sitecore.StringUtil]::NameValuesToString($nameValues,"&")PS master:\> Get-Archive -Database "master"
Name Items
---- -----
archive 0
recyclebin 1950PS master:\> Get-UserAgent
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36PS master:\> Close-WindowGet up and running - Start with Getting Started
Watch the basics - View our video series
Learn PowerShell syntax - Study Language Basics
Master commands - Read Commands and Pipelines
Understand providers - Learn
Practice with examples - Try
Avoid mistakes - Review
Retrieve Sitecore items - Learn to query and navigate → Retrieving Items
Modify content - Edit, create, and delete → Editing Items, Creating Items
Move and copy items - Reorganize content → Moving and Copying Items
Use interactive dialogs - Build user interfaces → Interactive Dialogs
Explore integration points - Extend Sitecore UI →
Create custom reports - Build powerful analysis tools → Authoring Reports
Build reusable libraries - Organize your scripts → Libraries and Scripts
Automate with tasks - Schedule automated jobs → Authoring Tasks
Use remoting - Control Sitecore from external scripts → Remoting
Package your work - Deploy scripts as packages →
Plan your next steps - Review
BEFORE deploying to any environment, you MUST review security:
Security Hardening Guide - Overview of security concepts
Security Checklist - Step-by-step hardening
- Configure access control
NEVER install SPE on Content Delivery (CD) servers
NEVER deploy SPE on internet-facing instances
This book - Comprehensive reference for all SPE features
Command Reference - Complete list of SPE cmdlets
Code Snippets - Ready-to-use examples
SPE Video Series - Beginner walkthroughs
Blogs and Videos Collection - Community content
Console - Interactive PowerShell terminal in Sitecore
ISE (Integrated Scripting Environment) - Full-featured script editor with IntelliSense
Built-in help: Use Get-Help <command-name> in the Console
Troubleshooting: Troubleshooting Guide
Community: Join the #module-spe channel on Sitecore Slack
GitHub: Report issues or request features at
Happy scripting!
Shortcut
Usage
Enter
Submits line for execution.
Tab
Autocomplete commands. Press tab again to cycle through commands.
Shift+Tab
Reverse cycle through Autocomplete commands.
Shift+Enter
Inserts new line. Works when the backtick is used.
ArrowUp/Ctrl+P
Show previous command from history
ArrowDown/Ctrl+N
Show next command from history
Delete/backspace
Note: The font family, font size, and other settings can be configured through the ISE.

Context Menu - Visibility can be control using rules made available from within the Interactive field section.
Gutters - Requires the library to be synced (see below).
Insert Item - Visibility can be control using rules made available from within the Interactive field section.
Ribbon - Requires the library to be . Visibility can be control using rules made available from within the Interactive field section.
Warning - Appears as a warning message beneath the ribbon in the Content Editor.
Control Panel - Requires the library to be synced (see below).
Data Sources - Not a formal integration point library, but a good place to add scripts used for Data Source Scripts. Read more about how they work here and here. The Source field simply references the script like script:/sitecore/system/Modules/PowerShell/Script Library/[MODULE NAME]/Data Sources/[SCRIPT NAME].
Event Handlers - Requires a patch file to enable the desired events. Read more about it here.
Functions - Exposes scripts to the command Import-Function.
Internal
ISE Plugins - Appears as a button in the ISE Settings tab.
List View - Represents the ribbon buttons such as for Actions and Exports.
Page Editor (Experience Editor)
Notification - Appears as a notification message beneath the ribbon in the Experience Editor.
LoggedIn
LoggingIn
Logout
Reports - Appears as a shortcut under Sitecore -> Reporting Tools -> PowerShell Reports.
Toolbox - Appears as a shortcut under Sitecore -> Toolbox. Visibility can be control using rules made available from within the Interactive field section.
Tasks - Not a formal integration point library, but a good place to add scripts used for Scheduled Tasks. SPE includes a PowerShellScriptCommand found under /sitecore/system/Tasks/Commands/PowerShellScriptCommand which is used to run scripts from within scheduled tasks.
Web API - Exposes scripts than can be consumed through SPE Remoting. The script can be executed by requesting a specific url.
Remoting - Interact with SPE through the provided web services as described here. A Windows PowerShell module is made available to encapsulate the web service calls into PowerShell commands.
Some integrations need to be synced with the Core database through the ISE. See the Settings section of the Scripting documents for instructions.
Package Generator
Task Management
Platform
This tool provides similar functionality to the Index Viewer module. Search and rebuild the index on-demand.
View the list of user sessions and "kick" them out as needed.
Generate a report using the Sitecore Rules Engine.
View the list of SPE sessions and "kill" them as needed.
This tool provides similar functionality to the Sitecore Rocks module.
Simple tool for generating a site tree using an existing sitemap.
View and manage the configured scheduled tasks.
To create your own Toolbox item take the following steps: 1. Create the Toolbox folder under an SPE module. Use the context menu to simplify the process.
Right click the module name and choose Scripts -> Create libraries for integration points.
Select the Toolbox item and click Proceed.
Create a PowerShell Script under the Toolbox item.
Right click the Toolbox library and choose PowerShell Script.
Open and edit the PowerShell Script using the ISE.
Run the Rebuild All command in the ISE by navigating to the Settings
System Maintenance
Archive Sitecore logs, Clean up deleted items older than 30 days
User Session Management
Remove idle user sessions






Support for Sitecore 7 has discontinued with SPE 5.0.
The following guide should provide you with enough information to setup a development environment configured to contribute to SPE. We'll begin with a single installation of Sitecore 8+.
The solution requires Visual Studio 2015 or later.
This guide assumes a source root location of "C:\Source" and a site root location of "C:\inetput\wwwroot". These are not prerequisites of the project, and you can use whatever folder locations suit you.
Meet the prerequisites found
Install Sitecore 8+ to a folder of your choice, for example C:\inetpub\wwwroot\SitecoreSPE_8
Clone the repo to your local development environment
Any changes you make going foward just require a build of the solution. Remember that when pulling down updates to the source, you should execute a Unicorn sync to ensure your items are up to date.
The SPE deployment process supports multiple sites and multiple versions of Sitecore. The following steps carry on from above to add further support for another Sitecore site, such as 8.x or 9.x.
Complete the steps for a Single Instance.
Install Sitecore 8.x/9.x to a folder of your choice, for example C:\inetpub\wwwroot\SitecoreSPE_91
Edit the sites definition in deploy.user.json to add your new Sitecore web root folder. Set the version property to 9.0
SPE can be deployed to as many Sitecore sites as you like. Each time you first deploy to a new installation, make sure you use Unicorn to sync the latest state of items into Sitecore.
To add the SPE PowerShell Remoting Module scripts into your machine's PowerShell Module path, execute the .\Setup_Module.ps1 script from the source folder. This will add the \Modules folder from source into your PSModulePath environment variable. Once this is done, you can use Import-Module SPE on your development machine to run the remoting scripts.
As part of the SPE deployment process, all of the relevant binary, configuration and sitecore module files are copied over from the projects within the solution. This means that any changes to static files such as JS / CSS files require a full build for these to be deployed to the site. As the build triggers an application pool recycle of your site, this can be a little slow for quick changes.
For more rapid development, you can enable junction deployment on your sites. When this is enabled, rather than copying over the static files, will be setup for various folders so that the folders within the Sitecore installation are directly linked to the source folder. Any changes made in the solution are seen instantly, because the solution and the site are referencing the exact same files.
To enable a junction deployment for a site, add junction property to the site definition and set it to true:
Note that with junction deployments, a solution build is still required if you want to deploy any code or
.configchanges.It is not currently supported for a junction deployment site to be changed back into a non-junction deployment site. If you wish to do this, you should manually delete the following folders from your Sitecore installation before updating the
junctionproperty back tofalse:sitecore modules\PowerShellandsitecore modules\Shell\PowerShell
Retrieves a Sitecore cache.
Get-Cache [[-Name] <String>]
The Get-Cache command retrieves a Sitecore cache.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Name of the cache to retrieve. Supports wildcards.
The output type is the type of the objects that the cmdlet emits.
Sitecore.Caching.Cache
Help Author: Adam Najmanowicz, Michael West
The Integrated Scripting Environment (ISE) is a great way to group together commands and save for later use. This tool helps you write scripts in Powerful Ways!
The default security configuration for SPE requires the ISE to be in an before executing scripts. The following figure shows the ISE when the User Account Controls (UAC) are disabled. While this is a common configuration for developers, we highly encourage you to ensure UAC is enabled in higher environments.
Let's have a quick walk through of each ribbon tab available.
Invoke-JavaScript [-Script] <String> [-OnScriptEnd <SwitchParameter>] [<CommonParameters>]Remove one character from right/left to the cursor
ArrowLeft/Ctrl+B
Move cursor to the left
ArrowRight/Ctrl+F
Move cursor to the right
Ctrl+ArrowLeft
Move cursor to previous word
Ctrl+ArrowRight
Move cursor to next word
Ctrl+A/Home
Move cursor to the beginning of the line
Ctrl+E/End
Move cursor to the end of the line
Ctrl+K/Alt+D
Remove the text after the cursor
Ctrl+H
Remove character before the cursor
Ctrl+D/Delete
Remove character selected by the cursor
Ctrl+C/Escape
Remove all text in the line
Ctrl+U
Remove the text before the cursor
Ctrl+V/Shift+Insert
Insert text from the clipboard
Ctrl+Alt+Shift +
Increase the font size
Ctrl+Alt+Shift -
Decrease the font size
PageUp
Scroll console up
PageDown
Scroll console down
Ctrl+R
Reverse search history
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
C:\Source\Console\deploy.user.json.sampleC:\Source\Console\deploy.user.jsonEdit the sites definition in deploy.user.json to target your Sitecore web root folder, making sure you use double-slashes for paths like in the existing file. For this site, make sure the version property is 8. Remove any other sites in the file that do not apply.
The
deploy.user.jsonfile supports deploying SPE to multiple Sitecore installations. For now, we are just deploying to a single instance, but later on in the tutorial we will cover multiple instances.
Copy C:\Source\Console\UserConfiguration\App_Config\Include\z.Spe.Development.User.config.sample to a file of the same name, without the .sample suffix. This file can be edited to add any SPE-specific configuration that you want in your sites, but don't wish to commit back into the repo.
You may notice there is a %%sourceFolder%% value in this configuration file. This is a special string that gets replaced as part of the SPE deployment with your source folder location. You don't need to update this manually.
Open the solution in Visual Studio.
Compile the solution. Whenever you compile the solution, SPE will be automatically deployed to the site web root paths you have set in deploy.user.json
Login to Sitecore
Navigate to /Unicorn.aspx. Use Unicorn to sync all projects into Sitecore.
SPE uses Unicorn for serializing Sitecore items to the source folder, and for syncing items from disk into Sitecore. For more information on Unicorn, see https://github.com/kamsar/Unicorn
SPE is now installed in Sitecore and you're ready for developing!
9.19.2Follow steps 7 onward from the Single Instance guide above to deploy to your Sitecore 8.x/9.x installation and sync the SPE items into Sitecore.
Required?
false
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
❌ Wrong: $item["Title"] = "New Title" (changes won't save!)
✅ Correct:
Without BeginEdit() and EndEdit(), changes are made to the in-memory object but never persisted to the database.
Always use try-catch to handle errors properly:
Read more: Editing Items
Using -Recurse carelessly can cause performance problems or even crash your session.
On large content trees, this can take minutes or hours
May consume excessive memory
Can cause session timeouts
Locks up the browser
Read more: Find-Item | Best Practices
SPE is powerful, which makes security critical.
❌ NEVER run scripts from unknown sources
❌ NEVER deploy SPE without reviewing security settings
❌ NEVER install SPE on CD (Content Delivery) servers
✅ Always review and understand scripts before running
✅ Use role-based access control
✅ Test in development first
Review the Security Hardening Guide and complete the Security Checklist before deploying to any non-development environment.
PowerShell uses different operators than most programming languages. See Language Basics for the complete comparison operator reference.
Learn more: Language Basics - Comparisons
Items in Sitecore can have multiple language versions, which affects querying and editing.
Read more: Item Languages
Different methods of suppressing output have very different performance characteristics.
Now that you know what to avoid:
Review your scripts: Look for these pitfalls in existing code
Practice safely: Test in development before production
Learn best practices: Read Best Practices
Secure your installation: Complete the Security Checklist
Everyone makes mistakes when learning. The key is learning from them and building better habits!
The Get-Database command retrieves one or more Sitecore Database objects based on name or item passed to it.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Name of the database to be returned.
Required?
false
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Database returned will be taken from the item passed to the command.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
System.String
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Database
Help Author: Adam Najmanowicz, Michael West
cd "C:\Source\Console" // Your local source folder, with a new folder for the solution
git init
git remote add origin https://github.com/SitecorePowerShell/Console.git
git fetch origin
git checkout -b master --track origin/master{
"sites": [
{
"path": "C:\\inetput\\wwwroot\\SitecoreSPE_8\\Website",
"version": 8,
"junction": true
}
]
}PS master:\> Get-Cache -Name master*
Name Enabled Count Size Max Size Default Scavengable
Priority
---- ------- ----- ---- -------- -------- -----------
master[blobIDs] True 0 0 512000 Normal False
master[blobIDs] True 0 0 512000 Normal False
master[blobIDs] True 0 0 512000 Normal False
master[itempaths] True 292 108228 10485760 Normal False
master[standardValues] True 57 38610 512000 Normal False
master[paths] True 108 13608 512000 Normal False
master[items] True 1010 5080300 10485760 Normal False
master[data] True 3427 7420654 20971520 Normal False$item.Editing.BeginEdit()
$item["Title"] = "New Title"
$item.Editing.EndEdit()foreach($item in $items) {
$item.Editing.BeginEdit()
try {
# Make your changes
$item["Title"] = "New Title"
$item["Text"] = "New content"
# Commit changes
$item.Editing.EndEdit()
}
catch {
# Roll back on error
$item.Editing.CancelEdit()
Write-Error "Failed to update $($item.ItemPath): $_"
}
}# DANGEROUS on large content trees!
Get-ChildItem -Path "master:\content" -Recurse# Recurse only within a specific subtree
Get-ChildItem -Path "master:\content\home\articles" -Recurse# Much faster for large queries
$parameters = @{
Index = "sitecore_master_index"
Criteria = @{Filter = "DescendantOf"; Value = "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"}
}
$items = Find-Item @parameters | Initialize-Item$items = Get-ChildItem -Path "master:\content" -Depth 2# WRONG - Using C# operators
if($count == 0) { } # Syntax error!
# RIGHT - Using PowerShell operators
if($count -eq 0) { } # Correct
# WRONG - Case-sensitive by default assumption
if($name -eq "MICHAEL") { } # Will match "michael"!
# RIGHT - Explicit case-sensitive check
if($name -ceq "MICHAEL") { } # Only matches exact case# This gets the item in the DEFAULT language (usually en)
$item = Get-Item -Path "master:\content\home"
$item["Title"] # Returns English title# Get specific language version
$item = Get-Item -Path "master:\content\home" -Language "de-DE"
# Get all language versions
$item = Get-Item -Path "master:\content\home"
$allVersions = Get-ItemField -Item $item -IncludeStandardFields -Name "*" -ReturnType Field
# Edit specific language
$item = Get-Item -Path "master:\content\home" -Language "de-DE"
$item.Editing.BeginEdit()
$item["Title"] = "Deutscher Titel"
$item.Editing.EndEdit()# SLOW - Out-Null is a cmdlet, adds pipeline overhead
$builder.Append("Text") | Out-Null
# FAST - Redirect to $null
$builder.Append("Text") > $null# Slow (don't use for simple suppression)
$list.Add($item) | Out-Null
# Fast (use this instead)
$list.Add($item) > $nullPS master:\> Get-Database
Name Languages Protected Read Only
---- --------- --------- ---------
core {da, pl-PL, ja-JP, en...} False False
master {en, de-DE, es-ES, pt-BR...} False False
web {es-ES, de-DE, pt-BR, pl-PL... False False
filesystem {en, en-US} False TruePS master:\> Get-Database -Name "master"
Name Languages Protected Read Only
---- --------- --------- ---------
master {en, de-DE, es-ES, pt-BR...} False FalsePS master:\> Get-Item . | Get-Database
Name Languages Protected Read Only
---- --------- --------- ---------
master {en, de-DE, es-ES, pt-BR...} False FalseVerify the new toolbox item appears in the Toolbox.




Write:
New - Creates a new script or module.
Open - Opens an existing script for the library.
Save - Saves the current script to the library.
Save As - Saves a copy of the current script to the library.
Reload - Opens the original copy of the current script without saving any modifications.
Script Execution:
Execute - Runs the current script as a background job or in the HttpContext.
Selection - Runs the selected text of the current script.
Debug - Runs the current script with the debugging mode enabled. A temporary file is generated on the file system to support the use of breakpoints.
Abort - Stops the execution of an executing script.
Context:
Context - Specifies the current item in the script. Helpful if you write a script dependent on a specific path, or the current directory is denoted as a . (dot) or _$pwd (_present working directory). An MRU and tree view are provided for choosing a path.
Session - Specifies the session to use when executing the script. Reused sessions live in the HttpSession. Options include the session created for the ISE instance, One-Time session, or the Persistent Session ID configured on the script.
UI Context:
Language - Specifies the context language to use when executing the script.
User - Specifies the context user to impersonate when executing the script. This can be used to emulate UserSwitcher code.
Preferences:
Settings - This is where you configure the Console and ISE font family, font size, and other useful things.
Integration:
Rebuild All - This is where you rebuild the integration points for Control Panel, Gutters, and Ribbons. Without running this you will not see those integrations appear (or disappear).
The plugins feature is a great way to add custom behaviors while in the ISE. Any plugin added can make use of the Enable or Show rules to control how it appears in the ribbon.
Platform: Custom scripts added to the ISE Plugins integration point script library will appear here.
The Open dialog provides both a search and tree view of the scripts stored in the script libraries.
Below are the shortcuts available in the ISE.
Shortcut
Usage
TAB
Indent
Ctrl
Bypass cached variable value when pressed.
Ctrl-Space
Autocomplete commands. Use the up or down direction keys to cycle through options.
Ctrl-Enter
Displays the command help window.
Ctrl-Z
Undo the previous change.
Ctrl-Alt-Shift +
Increase the font size
For more commands built into the script editor see here

See some of the community contributed modules built for SPE.
There are some really amazing contributions and add-ons to SPE from the community.
A well known and widely adopted module Unicorn has published some SPE commands. These commands are available (and optional) after installing Unicorn. Below are some samples ripped off from Kam Figy's blog posts here and here.
Example: The following lists configurations by name.
Example: The following syncs configurations just like you would through the Unicorn Control Panel or the PowerShell API.
The following are Sitecore modules that enhance the SPE experience.
:
:
:
The Sitecore PowerShell Extensions (SPE) module provides powerful cmdlets for managing Sitecore content items. This section covers everything you need to know about working with items programmatically.
The core item management cmdlets mirror standard PowerShell conventions:
Before working with items, understand these foundational concepts:
- PowerShell providers and navigating Sitecore databases
- Built-in variables available in SPE scripts
Learn how to perform essential item operations:
- Find items by path, ID, query, or URI
- Update properties, work with field types, and manage versions
- Create new items and delete existing ones
- Transfer and duplicate items
Handle specific aspects of item management:
- Add, remove, and manage language versions
- Work with presentation details and renderings
- Manage item permissions and access control
Optimize your scripts and follow best practices:
- Performance optimization, bulk operations, and coding patterns
SPE extends standard PowerShell cmdlets with dynamic parameters specific to Sitecore. These parameters appear based on context:
Language - Specify language versions (-Language "en-US" or -Language *)
Version - Specify item versions (-Version 2 or -Version *)
Database - Target specific databases when using IDs
See the page for detailed parameter documentation.
SPE supports multiple path formats for flexibility:
Note: The /sitecore portion is optional when using provider paths.
SPE provides intelligent handling of Sitecore field types through automated PowerShell properties:
See for comprehensive field type examples.
When working with large datasets, consider these performance tips:
Use fast: queries instead of Get-ChildItem -Recurse when possible
Leverage BulkUpdateContext for multiple updates
Use SecurityDisabler judiciously for read operations
See for detailed performance guidance.
- Securing SPE and managing users/roles
- Core cmdlet reference
- Security cmdlet reference
- Automate item operations remotely
This guide helps you quickly secure your Sitecore PowerShell Extensions installation with essential security configurations.
Never install SPE in internet-facing environments!
DO NOT install on Content Delivery (CD) instances
DO NOT deploy on servers facing the Internet
DO NOT expose SPE endpoints to untrusted networks
SPE is a powerful development and administration tool intended for Content Management (CM) servers in protected internal networks only.
Before deploying SPE to any environment beyond your local development machine, complete these essential steps:
By default, all SPE web services are disabled except those required for the Sitecore UI. Keep them disabled unless you have a specific need.
The default security configuration is found in:
App_Config\Include\Spe\Spe.config
Do not modify this file directly. Instead, create configuration patch files.
Create a new configuration file: App_Config\Include\Spe\Custom\Spe.Custom.config
Example: Basic production security configuration:
Protect the SPE services directory at the IIS level.
Edit sitecore modules\PowerShell\Services\web.config:
This denies anonymous access to all SPE web services.
Log in as a non-administrator user
Verify you cannot access the PowerShell Console
Verify you cannot access the PowerShell ISE
Log in as an administrator
For local development machines, you may use relaxed settings:
Never use elevationAction="Allow" in non-development environments!
Use the same strict security as production, but you may extend session timeouts slightly for testing convenience:
Use the strictest settings:
For Azure AD/SSO environments, use:
If using Sitecore 9.1 or later with Identity Server, enable this configuration file:
File: App_Config\Include\Spe\Spe.IdentityServer.config
This prevents infinite loops in the SPE Console when using OWIN cookie authentication.
After completing the initial setup:
Review the to understand the security model
Configure for your environment
If you need external access, carefully review security
Learn about
❌ Don't install on CD servers - SPE is for CM only ❌ Don't expose to the internet - Keep SPE behind firewalls ❌ Don't use Allow elevation in production - Always require password or confirmation ❌ Don't enable unnecessary web services - Only enable what you specifically need ❌ Don't grant broad access - Limit to administrators only ❌ Don't skip session elevation - UAC is critical for production environments
If you need assistance with SPE security:
Review the detailed documentation
Check the
Visit the
Join #module-spe on Sitecore Community Slack
Returns all the clones for the specified item.
Get-ItemClone [-Item] <Item>
Get-ItemClone [-Path] <String>
Get-ItemClone -Id <String> [-Database <String>]
The Get-ItemClone command returns all the clones for the specified item.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The item to be analysed for clones presence.
Path to the item to be analysed for clones presence.
Id of the item to be analysed for clones presence.
Database containing the item to be processed - if item is being provided through Id.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
Returns list of the current sitecore jobs
Get-SitecoreJob
The Get-SitecoreJob command returns the list of the currently running jobs of Sitecore.
© 2010-2019 Implemented by Vangasewinkel Benjamin using the Adam Najmanowicz, Michael West Sitecore PowerShell Extensions. All rights reserved.
None
The output type is the type of the objects that the cmdlet emits.
Sitecore.Jobs.Job
Help Author: Vangansewinkel Benjamin
There are several variables available out of the box for use in running commands and scripts. Many of the variables prefixed with Sitecore derive from the Sitecore.config settings. Run the command Get-Variable to see the complete list available in the currently running session.
Variable
Example
AppPath
C:\Inetpub\wwwroot\Console\Website\
HostSettings
... FontSize : 12 FontFamily : Wingdings ...
me
sitecore\admin
Note: Any new variables created are stored within the current session; when the session ends the variables are removed. Be careful not to overwrite the built-in variables.
Understanding PowerShell providers and the Sitecore provider.
The provider architecture in PowerShell enables a developer to make a command like Get-Item interact with the filesystem files and folders, and then interact with the Sitecore CMS items. This is one of the most powerful concepts in PowerShell!
A provider is an adapter that makes a data store look like a drive. Think of it like this:
File system provider
Hands-on examples to get you started with practical Sitecore automation.
Now that you understand the basics, let's put it all together with practical Sitecore automation tasks. These examples demonstrate real-world scenarios you'll encounter when working with SPE.
Goal: Find all items under /sitecore/content/home that are in a specific workflow state.
What just happened?
The reports which come out of the box provide a wide variety of information regarding your Sitecore installation.
We've built quite a few reports, many similar to the (ASR) module.
The custom reports can be found by navigating to Sitecore -> Reporting Tools -> PowerShell Reports.
As an example, let's run the Unused media items report.
Managing users and roles is a big topic and this section won't cover everything. We aim to show you different problems that have come up and how we solved them.
Example: The following command returns the security commands available.
Managing users should be a pretty straight forward task. While the User Manager provided by Sitecore is handy, you'll likely find yourself wanting to make bulk changes. The following examples should give you a few ideas about how to manage user accounts.
PWD
master:\
PSScript
$PSScript.Appearance.Icon # Returns the icon of the executing script
ScriptSession
... ID : e9fedd64-cad0-4c43-b950-9cd361b151fd ...
SitecoreAuthority
SitecoreContextItem
$SitecoreContextItem.Language.Name # Returns the language name
SitecoreDataFolder
C:\Inetpub\wwwroot\Console\Data
SitecoreDebugFolder
C:\Inetpub\wwwroot\Console\Data\debug
SitecoreIndexFolder
C:\Inetpub\wwwroot\Console\Data\indexes
SitecoreLayoutFolder
C:\Inetpub\wwwroot\Console\Website\layouts
SitecoreLogFolder
C:\Inetpub\wwwroot\Console\Data\logs
SitecoreMediaFolder
C:\Inetpub\wwwroot\Console\Website\upload
SitecorePackageFolder
C:\Inetpub\wwwroot\Console\Data\packages
SitecoreScriptRoot
master:\system\Modules\PowerShell\Script Library\Task Management\Toolbox
SitecoreCommandPath
master:\system\Modules\PowerShell\Script Library\Task Management\Toolbox\Task Manager
SitecoreSerializationFolder
C:\Inetpub\wwwroot\Console\Data\serialization
SitecoreTempFolder
C:\Inetpub\wwwroot\Console\Website\temp
SitecoreVersion
8.2.160729
Ctrl-Alt-Shift -
Decrease the font size
Ctrl-E
Executes the script
Alt-E
Executes the selected text in the script
Ctrl-D
Debugs the script
Ctrl-Shift-E
Aborts the running script
Ctrl-F
Search for keywords in the script



Query - Execute Sitecore queries (query: or fast:)
ID - Work with items by GUID
Uri - Use ItemUri for complete item identification
Batch operations and provide progress feedback
Get-Item
Retrieve a single item
Get-Item -Path "master:\content\home"
Get-ChildItem
Retrieve children and descendants
Get-ChildItem -Path "master:\content" -Recurse
New-Item
Create a new item
New-Item -Path "master:\content\home" -Name "Page" -ItemType "Sample/Sample Item"
Set-ItemProperty
Update item properties
Set-ItemProperty -Path "master:\content\home" -Name "Title" -Value "Welcome"
Copy-Item
Duplicate an item
Copy-Item -Path "master:\content\home\source" -Destination "master:\content\home\target"
Move-Item
Transfer an item
Move-Item -Path "master:\content\home\old" -Destination "master:\content\home\new"
Remove-Item
Delete or recycle an item
Remove-Item -Path "master:\content\home\demo" -Permanently
Review the Session Elevation documentation
Test that scripts execute successfully after elevation
Complete the Security Checklist before deployment
Get-Item
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false

Retrieved the home item using the Sitecore provider → Learn more
Queried all child items recursively
Filtered by workflow field value → Learn more
Displayed results as a report → Learn more
Goal: Update a field value on multiple items.
Key concepts demonstrated:
Filtering by template → Templates
Proper item editing workflow → Editing Items
Using PowerShell loops and variables
Always use BeginEdit() and EndEdit() when modifying items. Changes won't persist without this pattern.
Goal: Create a script that prompts the user for input and processes items based on their choices.
Interactive concepts:
Using Read-Variable for user input
Parameter validation
Conditional logic based on user choices
See Interactive Dialogs for more
Ready to experiment? Follow these steps:
In Sitecore, go to Desktop → Development Tools → PowerShell ISE
Try these commands in the script editor:
Click the Execute button (or press Ctrl+E)
Examine the object properties returned
Try modifying the filters
Experiment with different paths
Test your knowledge with these exercises:
Write a script that finds all items under /sitecore/content that have an empty Title field.
Write a script that counts how many items exist for each template under /sitecore/content/home.
Export all items under a specific path to a CSV file with their Name, Path, Template, and Last Updated date.
Here are some frequently used patterns you'll encounter:
Congratulations! You've completed your first SPE scripts. Now:
Avoid common mistakes: Review Common Pitfalls
Build on this knowledge: Explore Working with Items
Create custom reports: Learn Authoring Reports
Share your scripts: Build a Script Library
The best way to learn is by doing. Try modifying these examples for your own use cases!
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The following gets the cloned Item and returns the available notifications.
The following gets the cloned Item based on the specified type of notification.
The Import-Function command imports a function script from the script library's "Functions" folder.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Name of the script in the "Functions" library or one of its sub-libraries.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Name of the library withing the "Functions" library. Provide this name to disambiguate a script from other scripts of the same name that might exist in multiple sub-librarties of the Functions library.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Name of the module "Functions" are going to be taken from. Provide this name to disambiguate a script from other scripts of the same name that might exist in multiple Modules.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
System.Object
Help Author: Adam Najmanowicz, Michael West
The following imports a Resolve-Error function that you may later use to get a deeper understanding of a problem with script should one occur by xecuting the "Resolve-Error" command that was imported as a result of the execution of the following line
Example: The following generates a batch of test users in the default domain with the out-of-the-box user profile template. The users are then queried filtering on the name.
In case you forgot to set the user profile for accounts, we have a solution for that.
Example: The following queries a user and sets the profile template. Note that changing the profile template requires the user to be authenticated.
Example: The following queries all the user accounts for the default provider and filters those over the age of 18. The age property is custom on the Profile. Finally, export to CSV.
Example: The following queries roles using the specified identity.
Example: The following finds all roles and exports to a report.
Example: The following adds a user to a role.
Example: The following removes a user from a role.
Working with Items - Item Security - Managing item-level security and ACLs
Appendix - Security Commands - Full security cmdlet reference
# Find all items of a specific template and update a field
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" } |
ForEach-Object {
$_.Title = "Updated Title"
}# Create multiple items from a data source
$data = Import-Csv "C:\data\pages.csv"
foreach($row in $data) {
New-Item -Path "master:\content\home" -Name $row.Name -ItemType "Sample/Sample Item"
}# Copy an item tree from master to web
$sourceItem = Get-Item -Path "master:\content\home\campaign"
Copy-Item -Path $sourceItem.ProviderPath -Destination "web:\content\home" -Recurse# Generate a report of items modified in the last 7 days
$startDate = (Get-Date).AddDays(-7)
Get-ChildItem -Path "master:\content" -Recurse |
Where-Object { $_.__Updated -gt $startDate } |
Select-Object Name, ItemPath, __Updated, "__Updated by" |
Show-ListView -Property Name, ItemPath, __Updated, "__Updated by"# Provider path format (recommended)
Get-Item -Path "master:\content\home"
# Sitecore path format (also works)
Get-Item -Path "master:/sitecore/content/home"
# Mixed separators (both work)
Get-Item -Path "master:\content/home"
Get-Item -Path "master:/content\home"$item = Get-Item -Path "master:\content\home"
# DateTime fields return System.DateTime objects
$item.__Created # Returns DateTime
$item.__Created = [DateTime]::Now # Assign DateTime
# Image fields accept item references
$item.Image = Get-Item "master:\media library\logo"
# Link fields accept item references
$item.Link = Get-Item "master:\content\home\page"
# Multilist fields accept arrays of items
$item.RelatedPages = Get-ChildItem "master:\content\home"# List all item-related commands
Get-Command -Noun Item*
# Get help for a specific command
Get-Help Get-Item -Full
Get-Help Get-ChildItem -Examples
# Find commands by capability
Get-Command -Noun Item* | Where-Object { $_.Parameters.Keys -contains "Language" }<configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<!-- Session Elevation (UAC) -->
<userAccountControl>
<tokens>
<token name="Console">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ISE">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ItemSave">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
</tokens>
</userAccountControl>
<!-- Ensure web services remain disabled -->
<services>
<remoting enabled="false" />
<restfulv1 enabled="false" />
<restfulv2 enabled="false" />
<fileDownload enabled="false" />
<fileUpload enabled="false" />
<mediaDownload enabled="false" />
<mediaUpload enabled="false" />
</services>
</powershell>
</sitecore>
</configuration><configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration><token name="Console">
<patch:attribute name="expiration">01:00:00</patch:attribute>
<patch:attribute name="elevationAction">Allow</patch:attribute>
</token><token name="Console">
<patch:attribute name="expiration">00:15:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token><token name="Console">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token><token name="Console">
<patch:attribute name="elevationAction">Confirm</patch:attribute>
</token>PS master:\> Get-ItemClone -Path master:\content\homePS master:\> Get-SitecoreJob
Category : PowerShell
Handle : b62d9129-298a-4630-bb37-d725e5ce3bbf;DCI5CG6011F3Y-sc81u3contact
IsDone : True
Name : PowerShell-ca2a0179-78c5-02a4-5970-17e4909752b0-{347EBAF8-6BE2-4ABC-91D0-36B36FCF414B}
Options : Sitecore.Jobs.JobOptions
Status : Sitecore.Jobs.JobStatus
WaitHandle : System.Threading.ManualResetEvent
QueueTime : 11/13/2017 1:03:18 PM
MessageQueue : Sitecore.Jobs.AsyncUI.MessageQueue
Category : Indexing
Handle : dca83fc7-def7-4564-ac44-987e79ffc3cd;DCI5CG6011F3Y-sc81u3contact
IsDone : True
Name : Index_Update_IndexName=sitecore_analytics_index
Options : Sitecore.Jobs.JobOptions
Status : Sitecore.Jobs.JobStatus
WaitHandle : System.Threading.ManualResetEvent
QueueTime : 11/13/2017 1:03:29 PM
MessageQueue : Sitecore.Jobs.AsyncUI.MessageQueue
Category : PowerShell
Handle : de0a1dce-45f7-44fb-81b5-02b402c1f614;DCI5CG6011F3Y-sc81u3contact
IsDone : False
Name : PowerShell-ca2a0179-78c5-02a4-5970-17e4909752b0-{47666A58-890B-4D13-8F15-3348643750E4}
Options : Sitecore.Jobs.JobOptions
Status : Sitecore.Jobs.JobStatus
WaitHandle : System.Threading.ManualResetEvent
QueueTime : 11/13/2017 1:03:29 PM
MessageQueue : Sitecore.Jobs.AsyncUI.MessageQueuePS master:\> $jobs = Get-SitecoreJob
PS master:\> $jobs[0].Status
Category : PowerShell
Handle : c9215f66-ce60-49e5-9620-bf1ec51b6ef4;DCI5CG6011F3Y-sc81u3contact
IsDone : False
Name : PowerShell-ca2a0179-78c5-02a4-5970-17e4909752b0-{DF4895A6-3EBB-4A2A-9756-3A0EF4B96396}
Options : Sitecore.Jobs.JobOptions
Status : Sitecore.Jobs.JobStatus
WaitHandle : System.Threading.ManualResetEvent
QueueTime : 11/13/2017 1:05:54 PM
MessageQueue : Sitecore.Jobs.AsyncUI.MessageQueuePS master:\> Get-SitecoreJob | Show-ListView -Property "Category", "IsDone", "Name", "QueueTime", `
@{Label="Status Expiry"; Expression={$_.Status.Expiry} },
@{Label="Status Failed"; Expression={$_.Status.Failed} },
@{Label="Status State"; Expression={$_.Status.State} },
@{Label="Status Processed"; Expression={$_.Status.Processed} },
@{Label="Status Total"; Expression={$_.Status.Total} },
@{Label="Status Message"; Expression={$_.Status.Messages} }Get-ChildItem -Path "master:\content" -Recurse |
Where-Object {
[string]::IsNullOrEmpty($_.Fields["Title"].Value)
} |
Show-ListView -Property Name, ItemPath, TemplateName$items = Get-ChildItem -Path "master:\content\home" -Recurse
$templateCounts = $items | Group-Object TemplateName |
Select-Object Name, Count |
Sort-Object Count -Descending
$templateCounts | Show-ListView$items = Get-ChildItem -Path "master:\content\home" -Recurse
$export = $items | Select-Object Name,
@{Name="Path";Expression={$_.ItemPath}},
@{Name="Template";Expression={$_.TemplateName}},
@{Name="Updated";Expression={$_."__Updated"}}
$export | Export-Csv -Path "$($SitecoreDataFolder)\items-export.csv" -NoTypeInformation
Write-Host "Exported $($items.Count) items"# Navigate to the home item
$homeItem = Get-Item -Path "master:\content\home"
# Get all descendants
$items = Get-ChildItem -Path $homeItem.ProviderPath -Recurse
# Filter items in "Draft" workflow state
$draftItems = $items | Where-Object {
$_.Fields["__Workflow state"] -ne $null -and
$_."__Workflow state" -match "{190B1C84-F1BE-47ED-AA41-F42193D9C8FC}"
}
# Display results in an interactive list
$draftItems | Show-ListView -Property Name, ItemPath, "__Updated", "__Updated by"# Get items to update
$items = Get-ChildItem -Path "master:\content\home\articles" -Recurse |
Where-Object { $_.TemplateName -eq "Article" }
# Update each item
foreach($item in $items) {
# Begin editing
$item.Editing.BeginEdit()
# Update field
$item["Category"] = "Updated"
# Save changes
$item.Editing.EndEdit()
}
Write-Host "Updated $($items.Count) items" -ForegroundColor Green# Prompt user for input
$rootPath = Get-Item -Path "master:\content\home"
$publishItems = $true
$props = @{
Parameters = @(
@{Name="rootPath"; Title="Root Path"; Tooltip="Select the starting location"},
@{Name="templateName"; Title="Template Name";
Source="DataSource=/sitecore/templates&DatabaseName=master&IncludeTemplatesForDisplay=Node,Folder,Template,Template Folder&IncludeTemplatesForSelection=Template";
editor="groupeddroplist"; }
)
Title = "Bulk Item Processor"
Description = "Select items to process"
Width = 500
Height = 300
}
$result = Read-Variable @props
if($result -ne "ok") {
Exit
}
# Process items based on user input
$items = Get-ChildItem -Path $rootPath.ProviderPath -Recurse |
Where-Object { $_.TemplateName -eq $templateName }
Write-Host "Found $($items.Count) items"# Get your home item
Get-Item -Path "master:\content\home"
# List its children
Get-ChildItem -Path "master:\content\home"
# Find items by name
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.Name -like "*Sample*" }foreach($item in $items) {
$item.Editing.BeginEdit()
try {
$item["FieldName"] = "Value"
$item.Editing.EndEdit() | Out-Null
}
catch {
$item.Editing.CancelEdit()
Write-Error "Failed to update $($item.ItemPath): $_"
}
}$itemPath = "master:\content\home\test"
if(Test-Path $itemPath) {
$item = Get-Item $itemPath
# Process item
}
else {
Write-Host "Item not found" -ForegroundColor Yellow
}$items = Get-ChildItem -Path "master:\content" -Recurse
$total = $items.Count
$current = 0
foreach($item in $items) {
$current++
Write-Progress -Activity "Processing Items" `
-Status "$current of $total" `
-PercentComplete (($current / $total) * 100)
# Process item here
}Get-ItemCloneNotification [-Item] <Item> [-NotificationType <Notification | ChildCreatedNotification | FieldChangedNotification | FirstVersionAddedNotification | ItemMovedChildCreatedNotification | ItemMovedChildRemovedNotification | ItemMovedNotification | ItemTreeMovedNotification | ItemVersionNotification | OriginalItemChangedTemplateNotification | VersionAddedNotification>] [-Language <String[]>]
Get-ItemCloneNotification [-Path] <String> [-NotificationType <Notification | ChildCreatedNotification | FieldChangedNotification | FirstVersionAddedNotification | ItemMovedChildCreatedNotification | ItemMovedChildRemovedNotification | ItemMovedNotification | ItemTreeMovedNotification | ItemVersionNotification | OriginalItemChangedTemplateNotification | VersionAddedNotification>] [-Language <String[]>]
Get-ItemCloneNotification -Id <String> [-Database <String>] [-NotificationType <Notification | ChildCreatedNotification | FieldChangedNotification | FirstVersionAddedNotification | ItemMovedChildCreatedNotification | ItemMovedChildRemovedNotification | ItemMovedNotification | ItemTreeMovedNotification | ItemVersionNotification | OriginalItemChangedTemplateNotification | VersionAddedNotification>] [-Language <String[]>]$clonedItem = Get-Item -Path "master:" -ID "{9F158637-52C2-4005-8329-21527685CB71}"
Get-ItemCloneNotification -Item $clonedItem$clonedItem = Get-Item -Path "master:" -ID "{9F158637-52C2-4005-8329-21527685CB71}"
$clonedItem | Get-ItemCloneNotification -NotificationType ItemMovedChildRemovedNotificationPS master:\> Import-Function -Name Resolve-ErrorGet-Command -Noun Role*,User,ItemAcl* | Select-Object -Property Name | Sort-Object -Property Nameforeach($num in 0..10) {
$key = -join ((65..90) + (97..122) | Get-Random -Count 7 | % {[char]$_})
New-User -Identity "TestUser$($key)" -Enabled -Password "b" -ProfileItemId "{AE4C4969-5B7E-4B4E-9042-B2D8701CE214}" | Out-Null
}
Get-User -Filter "sitecore\TestUser*"Get-User -Id "michael" -Authenticated |
Set-User -ProfileItemId "{AE4C4969-5B7E-4B4E-9042-B2D8701CE214}"$users = Get-User -Filter * | Where-Object { $_.Profile.GetCustomProperty("age") -gt 18 }
$property = @(
"Name",
@{Name="Age";Expression={ $PSItem.Profile.GetCustomProperty("age") }}
)
$users | Select-Object -Property $property |
Export-CSV -Path "$($SitecoreDataFolder)\export\users-over-eighteen.csv" -NoTypeInformation# Identity can be "[domain]\[name]", "Creator-Owner", and "\Everyone"
Get-Role -Identity "default\Everyone"Get-Role -Filter * | Show-ListView -Property Name, Domain$user = Get-User -Identity "sitecore\author"
$role = Get-Role -Identity "sitecore\Sitecore Client Authoring"
Add-RoleMember -Identity $role -Members $user$user = Get-User -Identity "sitecore\author"
$role = Get-Role -Identity "sitecore\Sitecore Client Authoring"
Remove-RoleMember -Identity $role -Members $userC:\ Registry provider: Makes HKLM:\ look like a navigable drive
Sitecore provider: Makes master:\ look like a navigable drive
This means you can use the same commands (Get-Item, Get-ChildItem, etc.) to work with files, registry keys, and Sitecore items!
The SPE module implements a new provider that bridges the Windows PowerShell platform with the Sitecore API. The following table demonstrates the use of Get-Item for a variety of providers.
Alias
Alias
Get-Item -Path alias:\dir
Sitecore
core, master, web
Get-Item -Path master:\
Environment
Env
Get-Item -Path env:\HOMEPATH
FileSystem
C, D, F, H
Get-Item -Path c:\Windows
The most important provider for SPE is named Sitecore. This provider gives you access to Sitecore databases.
The default provider used by the PowerShell Console and ISE is Sitecore with the drive set to the master database.
The Sitecore provider exposes these databases as drives:
Sitecore provider paths follow this format:
Examples:
Example: The following demonstrates switching between providers using the function cd, an alias for Set-Location, while in the Console.
You may have noticed that the C drive is the only path in which a backslash was used before changing drives. Leaving off the backslash will result in the path changing to C:\windows\system32\inetsrv. This similar behavior can be experienced while in the Windows PowerShell Console, where the path is changed to C:\Windows\System32.
While all providers support basic operations like Get-Item and Get-ChildItem, some have special features:
Understanding providers is crucial because:
Same commands work everywhere - Learn Get-Item once, use it for files, registry, and Sitecore
Path-based navigation - Everything has a path you can navigate
Consistent patterns - If it works on files, it probably works on Sitecore items
Powerful automation - Combine providers to move data between systems
Get item
Get-Item C:\file.txt
Get-Item master:\content\home
List children
Get-ChildItem C:\
Get-ChildItem master:\content
Create
New-Item C:\file.txt
New-Item master:\content\home\item
Remove
Remove-Item C:\file.txt
This introduction covers the basics of the provider architecture and how to use paths in SPE.
For comprehensive details about working with the Sitecore provider (item fields, languages, versions, wildcards, performance optimization, and advanced techniques), see the complete guide: Working with Items - Providers
Now that you understand providers:
Practice with examples: Your First Scripts
Avoid common mistakes: Common Pitfalls
Deep dive into items: Working with Items
Read comprehensive provider docs: Providers
Example: Move an item to a new parent.
Example: Move and rename in one operation.
Example: Get an item and move it using the pipeline.
By default, Move-Item moves the item and all its descendants.
Example: Move an entire content tree.
Use Copy-Item to duplicate items. By default, the copy receives a new ID.
Example: Copy an item to a new location and change display name.
Example: Copy and return the new item.
Example: Copy an entire tree maintaining structure.
Copy items between databases (e.g., from master to web) using transfer options.
Example: Transfer item with same ID to another database.
Using -TransferOptions 0 maintains the same ID. This is useful for publishing workflows but can cause conflicts if the item already exists in the target database.
The -TransferOptions parameter controls how items are copied between databases:
0
Keep original ID
1
Create new ID (default behavior)
2
Allow default values
4
Allow standard values
Example: Copy with new ID (default behavior).
DestinationItem
Move-Item, Copy-Item
Parent item to receive moved/copied item
-DestinationItem $parent
FailSilently
Move-Item, Copy-Item
Suppress unauthorized access errors
-FailSilently
TransferOptions
Copy-Item
Controls ID handling (0=keep, 1=new)
Batch operations - Group multiple moves/copies together
Use BulkUpdateContext - When copying many items with field updates
Progress reporting - Provide feedback for long-running operations
Avoid unnecessary recursion - Only use -Recurse when needed
Test first - Use -WhatIf parameter if available, or test in development
Retrieving Items - Find items to move or copy
Creating and Removing Items - Item lifecycle management
Best Practices - Performance optimization
Appendix - Common Commands - Full cmdlet reference
Once the report completes, the results appear in a report window.
While SPE contains many reports, they don't match identical to ASR reports. We've done our best to build those that seem most relevant or likely to be used. If you find a report in ASR that you would like to exist in SPE please submit a request.
SPE Report
ASR Report
Active Aliases
Aliases
Audit
Broken Links2
Broken Links
Broken Links in publishable items
Item History
Check the reports in SPE under these sections to see the full list.
1 Configuration Audit report
2 Content Audit report
3 Media Audit report
4 Solution Audit report
5 Toolbox
Note: Examples included are in the following modules
Content Reports
You may wish to expose the reports to users such as Content Authors. Here are the steps required to grant access to users in the sitecore\Sitecore Client Authoring role.
Here is what users may see in the event they do not have the appropriate access.
Navigate to the item /sitecore/content/Documents and settings/All users/Start menu/Right/Reporting Tools/PowerShell Reports
Grant access to sitecore\Sitecore Client Authoring
Verify the reports are now visible to the Authoring users.
Note: In verson 6.4 the default access changed from sitecore\Sitecore Client Maintaining to a lower privileged account sitecore\Sitecore Client Authoring.

The setup of the module only requires a few steps: 1. In the Sitecore instance install the Sitecore module package. 2. On the local desktop or server install the SPE Remoting module.
After downloading you may need to unblock the file by right-clicking the zip and unblocking.
Ensure that you have run Set-ExecutionPolicy RemoteSigned in order for the SPE Remoting module will run. This typically requires elevated privileges.
Enable the remoting service through a configuration patch. See the Security page for more details.
Grant the remoting service user account through a configuration patch and granting acess to the appropriate role. See the page for more details.
The remoting services use a combination of a SOAP service (ASMX) and HttpHandler (ASHX). Remoting features are disabled by default and should be configured as needed as can be seen in the security section here. The SOAP service may require additional Windows authentication using the -Credential parameter which is common when logged into a Windows Active Directory domain.
If you have configured the web services to run under Windows Authentication mode in IIS then you'll need to use the Credential parameter for the commands.
You'll definitely know you need it when you receive an error like the following:
Example: The following connects Windows PowerShell ISE to a remote Sitecore instance using Windows credentials and executes the provided script.
Example: The following connects to several remote instances of Sitecore and returns the server name.
We have provided a service for downloading all files and media items from the server. This disabled by default and can be enabled using a patch file. See the Security page for more details about the services available and how to configure.
Example: The following downloads a single file from the Package directory.
Example: The following downloads a single media item from the library.
Inevitably you will need to have long running processes triggered remotely. In order to support this functionality without encountering a timeout using Invoke-RemoteScript you can use the following list of commands.
Get-ScriptSession - Returns details about script sessions.
Receive-ScriptSession - Returns the results of a completed script session.
Remove-ScriptSession - Removes the script session from memory.
Start-ScriptSession - Executes a new script session.
Stop-ScriptSession - Terminates an existing script session.
Wait-ScriptSession - Waits for all the script sessions to complete before continuing.
Example: The following remotely runs the id of a ScriptSession and polls the server until completed.
Example: The following remotely runs a script and checks for any output errors. The LastErrors parameter is available for ScriptSession objects.
Example: The following redirects messages from Write-Verbose to the remote session. The data returned will be both System.String and Deserialized.System.Management.Automation.VerboseRecord so be sure to filter it out when needed. More information about the redirection 4>&1 can be read here.
Example: The following improves upon the previous example.
If you receive the following error when trying to run a script (note the namespace is Microsoft.PowerShell.Commands instead of Spe or similar):
then add the following line as the first line within the Invoke-RemoteScript block: Set-Location -Path "master:"
Example:
This issue occurs due to the fact that the remoting session defaults to the FileSystem provider. Changing the location activates the custom provider included with SPE. As part of the custom provider there are additional parameters added to commands native to PowerShell.

Visual components made available to users in the Content Editor.
The Context Menu integration reveals a list of options to the user in the context menu under a special node called Scripts. The Sitecore rules engine may be used to control visibility and enabled state. The script is only executed when the option is clicked.
Begin by adding a new script to the Context Menu library. The name of the script will appear in the context menu.
Edit the script to perform the appropriate actions. The script can run in the background and show dialogs.
Change the icon of the item to match the script purpose.
Configure any Enable or Show rules as needed.
Note: Examples included in the following modules
Authoring Instrumentation
Copy Renderings
Index On Demand
Media Library Maintenance
See how Adam added .
The Gutter integration reveals a visual notification to the user in the far left gutter. The Sitecore rules engine may be used to control enabled state.
Begin by adding a new script to the Gutters library.
Edit the script to create a new instance of Sitecore.Shell.Applications.ContentEditor.Gutters.GutterIconDescriptor if the right conditions are met.
Set the Icon, Tooltip, and Click properties.
Note: Examples included in the following modules
Publishing Status Gutter
The Insert Item integration reveals a list of options to the user in the context menu under the node called Insert. The Sitecore rules engine may be used to control visibility and enabled state. The script is only executed when the option is clicked.
Begin by adding a new script to the Insert Item library. The name of the script will appear in the context menu.
Edit the script to perform the appropriate actions. The script can run in the background and show dialogs.
Change the icon of the item to match the script purpose.
Configure any Show
Note: Examples included in the following modules
Task Management
Platform
The Ribbon integration reveals commands to the user in the ribbon. The Sitecore rules engine may be used to control visibility and enabled state. The script is only executed when the option is clicked.
Begin by adding a new child script library to the Ribbon library; we'll refer to this library as the Tab library. Choose a name that matches an existing tab to be used, such as Home or Developer, or a new name to create a new tab.
Add a child script library to the Tab library; we'll call this the Chunk library. Choose a name such as Edit or Tools.
Add a new script to the Chunk script library; we'll refer to this library as the Command
Example: The following script gets the selected Context Menu item and displays an alert using the item name.
Button Size:
There is a way to generate small buttons and combo buttons. You simply need to prefix the script name and SPE will generate accordingly.
Small$[SCRIPT_NAME]
Combo$[SCRIPT_NAME]
SmallCombo$[SCRIPT_NAME]
See the birth of by Adam.
Check out an example of the in the wild by Toby.
Similar to the Ribbon integration, this provides a way to show buttons when certain contextual conditions are met. Most common is with media items. The steps are the same as with the standard Ribbon, but the structure is slightly changed.
In the following example, we have a ribbon button that appears whenever the selected item in the Content Editor is a media item. Take note of the "Optimize" button.
The ribbon structure would look like the following:
The Warning integration reveals a notification to the user above content. The Sitecore rules engine can be used to control visibility and enabled state. The scripts are only executed when the rule is met and the command is clicked.
Begin by adding a new script library to the Warning library.
Edit the script to perform the appropriate actions. The script can run in the background and show dialogs.
The warning notification title, text and icon should be configured in the script.
Note: Examples included in the following modules
License Expiration - disabled by default
Alan provided a nice example on setting up the warning with commands.
Modules may contain PowerShell Script Library items and PowerShell Script items. The following section outlines some of the basic concepts you need to know for the following chapters.
The library items represent a collection of scripts, and may be structured with one or more levels of libraries.
You'll find that with the Integration Points some libraries should be created with specific names (i.e. Content Editor, Control Panel).
As a best practice we recommend that the Functions library consist of reusable scripts containing PowerShell functions (i.e. Do-Something) while other libraries contain the solution specific scripts (i.e. MakeScriptingGreatAgain).
Example: The following demonstrates the use of the Functions script library containing Get-DateMessage.
Some names we've used included:
Beginner Tutorials
Content Editor
Content Maintenance
Content Interrogation
Interactive : The following fields support the two custom rules as well as a variety of out-of-the-box rules.
ShowRule (Show if rules are met or not defined) - typically controls visibility of integration points.
PowerShell
where calling the specific PowerShell script returns $True
There are a number of use cases for the EnableRule and ShowRule.
If there is a UI component the ShowRule can be used to ensure it appears while the EnableRule can toggle when it can be clicked.
If there is no UI component, the EnableRule is used to determine when the script should be executed; useful to limit creation of PowerShell runspaces.
The script items represent the code that will be executed.
There are three conventions that we recommend you follow which are shown with an example below.
Title Casing - This should be used when the name will be exposed in places such as the Content Editor, script library names, and Reports root directory.
Sentence casing - This should be used when the name is long and will not be visible to the user or is a report with a very long name.
Noun-Verb - This should be used when the script is stored within the Functions script library and will be imported using the command Import-Function.
Interactive : Refer to the description shown for PowerShell Script Library .
Scripting
Script (Script body) : This is a multi-line text than should be edited using the PowerShell ISE application.
Session Persistency
PersistentSessionId (Persistent Session ID) : Context scripts using this ID will execute in a single session and be reused; leaving empty will cause the session to be discarded after execution. This value should be used for rules requesting the session ID.
Expands tokens in fields for items.
Expand-Token [-Item] <Item> [-Language <String[]>]
Expand-Token [-Path] <String> [-Language <String[]>]
Expand-Token -Id <String> [-Database <String>] [-Language <String[]>]
The Expand-Token command expands the tokens in fields for items.
Some example of tokens include:
$name
$time
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Language that will be processed. If not specified the current user language will be used. Globbing/wildcard supported.
The item to be processed.
Path to the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Id of the the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Database containing the item to be processed - can work with Language parameter to narrow the publication scope.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
The following expands tokens in fields on the item.
The following expands tokens in fields on the item. If the standard value of the field contains a token we modify the field to the token so the expansion will work (Sitecore API does not expand if the field is the same as Standard Values and never modified).
Useful code snippets to help you with those complex scripts.
Example: The following demonstrates how to list all of the fields of a template excluding the Standard Template fields.
Example: The following demonstrates how to generate the public facing url from a media item.
Example: The following demonstrates the use of the HtmlAgilityPack for parsing html.
Example: The following demonstrates how to update text in the document and exclude certain nodes.
Example: The following demonstrates how to remove empty paragraph tags in an html field.
Example: The following demonstrates removing style attributes from the html.
Example: The following prints the workflow history of the home item.
Example: The following restores items in the media library that were removed yesterday. @technomaz.
Example: The following will incrementally purge items from the recycle bin (master db) with a progress counter.
Example: The following logs messages to the browser console and then alerts the user with a message.
Example:
Not seeing what you are looking for? You can always check out some Github Gists that and have shared or the .
Returns all the items referring to the specified item.
Get-ItemReferrer -Item <Item>
Get-ItemReferrer -Item <Item> -ItemLink
Get-ItemReferrer -Path <String> [-Language <String[]>]
Get-ItemReferrer -Path <String> [-Language <String[]>] -ItemLink
Get-ItemReferrer -Id <String> [-Database <String>] [-Language <String[]>]
Get-ItemReferrer -Id <String> [-Database <String>] [-Language <String[]>] -ItemLink
The Get-ItemReferrer command returns all items referring to the specified item. If -ItemLink parameter is used the command will return links rather than items.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The item to be analysed.
Path to the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Id of the the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Database containing the item to be processed - can work with Language parameter to narrow the publication scope.
Language that will be used as source language. If not specified the current user language will be used. Globbing/wildcard supported.
Return ItemLink that define both source and target of a link rather than items linking to the specified item.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Sitecore.Links.ItemLink
Help Author: Adam Najmanowicz, Michael West
Retrieves a list of items found in the specified archive.
The Get-ArchiveItem command returns items found in the "archive" and "recyclebin" archives.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Specifies the archive to use when determining which ArchiveEntry items to process. Use Get-Archive to find the appropriate archive.
Specifies the ID for the original item that should be processed. This is NOT the ArchivalId.
Specifies the user responsible for moving the item to the archive.
None.
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Archiving.ArchiveEntry
Help Author: Adam Najmanowicz, Michael West
The following returns all items found in the specified archive.
The following returns items matching the ItemId found in the specified archive.
The following returns items moved to the recycle bin by the user found in the specified archive.
The following demonstrates changing the archive date on an item followed by retrieving the archived item.
Remove-ArchiveItem
Restore-ArchiveItem
Remove-Item
Remove-ItemVersion
Converts an item from a clone to a fully independent item.
ConvertFrom-ItemClone [-Item] <Item> [-Recurse] [-PassThru]
ConvertFrom-ItemClone [-Path] <String> [-Recurse] [-PassThru]
ConvertFrom-ItemClone -Id <String> [-Database <String>] [-Recurse] [-PassThru]
Converts an item from a clone to a fully independent item.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The item to be converted.
Path to the item to be converted
Id of the item to be converted
Database containing the item to be converted
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
Returns the library item or path to the library where scripts for a particular integration point should be located for a specific module.
Get-SpeModuleFeatureRoot [-Module <Module>] [-ReturnPath] [-Feature] <String>
The Get-SpeModuleFeatureRoot command returns library item or path to the library where scripts for a particular integration point should be located for a specific module.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Module for which the feature root library should be returned. If not provided the feature root will be returned for all modules.
Feature for which the root library should be provided. If root item does not exist and -ReturnPath parameter is not specified - nothing will be returned, If -ReturnPath parameter is provided the path in which the feature root should be located will be returned
Valid features:
contentEditorContextMenu
contentEditorGutters
contentEditorRibbon
controlPanel
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
System.String
Help Author: Adam Najmanowicz, Michael West
Return the library item for "Content Editor Context Menu"
Return the Path to where "List View Export" scripts would be located if this feature was defined
# Default returns all configurations
Get-UnicornConfiguration
# Exact match
Get-UnicornConfiguration -Filter "Foundation.Foo"
# Filter using a wildcard
Get-UnicornConfiguration -Filter "Foundation.*"# Sync one
Sync-UnicornConfiguration "Foundation.Foo"
# Sync multiple by name
Sync-UnicornConfiguration @("Foundation.Foo", "Foundation.Bar")
# Sync multiple from pipeline
Get-UnicornConfiguration "Foundation.*" | Sync-UnicornConfiguration
# Sync all, except transparent sync-enabled configurations
Get-UnicornConfiguration | Sync-UnicornConfiguration -SkipTransparent
# Optionally set log output level (Debug, Info, Warn, Error)
Sync-UnicornConfiguration -LogLevel Warn# Sync a single item (note: must be under Unicorn control)
Get-Item "/sitecore/content" | Sync-UnicornItem
# Sync multiple single items (note: all must be under Unicorn control)
Get-ChildItem "/sitecore/content" | Sync-UnicornItem
# Sync an entire item tree, show only warnings and errors
Get-Item "/sitecore/content" | Sync-UnicornItem -Recurse -LogLevel Warn# Reserialize one
Export-UnicornConfiguration "Foundation.Foo"
# Reserialize multiple by name
Export-UnicornConfiguration @("Foundation.Foo", "Foundation.Bar")
# Reserialize from pipeline
Get-UnicornConfiguration "Foundation.*" | Export-UnicornConfiguration# Reserialize a single item (note: must be under Unicorn control)
Get-Item "/sitecore/content" | Export-UnicornItem
# Reserialize multiple single items (note: all must be under Unicorn control)
Get-ChildItem "/sitecore/content" | Export-UnicornItem
# Reserialize an entire item tree
Get-Item "/sitecore/content" | Export-UnicornItem -Recurse# Convert an item to YAML format (always uses default excludes and field formatters)
Get-Item "/sitecore/content" | ConvertTo-RainbowYaml
# Convert many items to YAML strings
Get-ChildItem "/sitecore/content" | ConvertTo-RainbowYaml
# Disable all field formats and field filtering
# (e.g. disable XML pretty printing,
# and don't ignore the Revision and Modified fields, etc)
Get-Item "/sitecore/content" | ConvertTo-RainbowYaml -Raw# Get IItemDatas from YAML variable
$rawYaml | ConvertFrom-RainbowYaml
# Get IItemData and disable all field filters
# (use this if you ran ConvertTo-RainbowYaml with -Raw)
$yaml | ConvertFrom-RainbowYaml -Raw# Deserialize IItemDatas from ConvertFrom-RainbowYaml
$rawYaml | ConvertFrom-RainbowYaml | Import-RainbowItem
# Deserialize raw YAML from pipeline into Sitecore
# Shortcut bypassing ConvertFrom-RainbowYaml
$yaml | Import-RainbowItem
# Deserialize and disable all field filters
# (use this if you ran ConvertTo-RainbowYaml with -Raw)
$yaml | Import-RainbowItem -Raw
# Deserialize multiple at once
$yamlStringArray | Import-RainbowItem
# Complete example that does nothing but eat CPU
Get-ChildItem "/sitecore/content" | ConvertTo-RainbowYaml | Import-RainbowItem# Create a new Sitecore Package (SPE cmdlet)
$pkg = New-Package -Name MyCustomPackage
# Get the Unicorn Configuration(s) we want to package
$configs = Get-UnicornConfiguration "Foundation.*"
# Pipe the configs into New-UnicornItemSource
# to process them and add them to the package project
# (without -Project, this would emit the source object(s)
# which can be manually added with $pkg.Sources.Add())
$configs | New-UnicornItemSource -Project $pkg
# Export the package to a zip file on disk
Export-Package -Project $pkg -Path "C:\foo.zip" -Zip# When you open the Console, you start here:
PS master:\># Master database
Get-Item -Path "master:\content\home"
# Web database
Get-Item -Path "web:\content\home"
# Core database
Get-Item -Path "core:\content"database:\path\to\itemmaster:\content\home
master:\content\home\articles\my-article
web:\content
core:\systemPS master:\> cd c:\
PS C:\> cd hklm:
PS HKLM:\> cd env:
PS Env:\> cd master:
PS master:\># Get a single item
$home = Get-Item -Path "master:\content\home"
# Get children
$children = Get-ChildItem -Path "master:\content\home"
# Get all descendants
$all = Get-ChildItem -Path "master:\content\home" -Recurse# Create a new item
New-Item -Path "master:\content\home" -Name "My New Item" -ItemType "Sample/Sample Item"# Remove an item (goes to Recycle Bin)
Remove-Item -Path "master:\content\home\test-item"# Check if an item exists
if(Test-Path -Path "master:\content\home\my-item") {
Write-Host "Item exists!"
}# Get item with specific language
Get-Item -Path "master:\content\home" -Language "de-DE"
# Get specific version
Get-Item -Path "master:\content\home" -Version 5
# Include standard fields
Get-Item -Path "master:\content\home" | Get-ItemField -IncludeStandardFields# Get files with filter
Get-ChildItem -Path "C:\temp" -Filter "*.txt"
# Get files with specific attributes
Get-ChildItem -Path "C:\temp" -File
Get-ChildItem -Path "C:\temp" -Directory# Get Sitecore items
$items = Get-ChildItem -Path "master:\content\home\articles"
# Export to file system
$items | Select-Object Name, TemplateName |
Export-Csv -Path "$($SitecoreDataFolder)\articles.csv" -NoTypeInformation$sourcePath = "master:\content\home\sample item"
$destinationPath = "master:\content\home\moved"
Move-Item -Path $sourcePath -Destination $destinationPath# If "new-name" doesn't exist, item is moved and renamed
$oldPath = "master:\content\home\old-name"
$newPath = "master:\content\home\new-name"
Move-Item -Path $oldPath -Destination $newPathGet-Item -Path "master:" -ID "{65736CA0-7D69-452A-A16F-2F42264D21C5}" |
Move-Item -Destination "master:{DFDDF372-3AB7-45B1-9E7C-0D0B27350439}"Move-Item -Path "master:\content\home\old-section" `
-Destination "master:\content\archive\"$originalPath = "master:\content\home\original"
$copyPath = "master:\content\home\copy"
Copy-Item -Path $originalPath -Destination $copyPath$originalPath = "master:\content\home\original"
$copyPath = "master:\content\home\copy"
$newItem = Copy-Item -Path $originalPath -Destination $copyPath -PassThru
$newItem."__Display Name" = "Copy"
Write-Host "New item ID: $($newItem.ID)"$sourceId = "{AF27FAD3-2AF0-4682-9BF7-375197587579}"
$destinationId = "{53F94442-555B-4622-B813-A16ED2CAB01B}"
Get-Item -Path "master:" -ID $sourceId | Copy-Item -Destination $destinationId -RecurseCopy-Item -Path "master:\content\home" `
-Destination "web:\content\home" `
-TransferOptions 0# These are equivalent
Copy-Item -Path "master:\content\home\sampleitem" -Destination "web:\content\home\sampleitem"
Copy-Item -Path "master:\content\home\sampleitem" -Destination "web:\content\home\sampleitem" -TransferOptions 1Get-ChildItem -Path "master:\content\temp" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" } |
ForEach-Object {
Move-Item -Path $_.ProviderPath -Destination "master:\content\archive"
}$templates = @("Sample Item", "Article", "News Item")
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $templates -contains $_.TemplateName } |
ForEach-Object {
Copy-Item -Path $_.ProviderPath -Destination "master:\content\backup"
}# Move all items of a specific template to a new location
$targetTemplate = "Article"
$newParent = Get-Item -Path "master:\content\articles"
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq $targetTemplate } |
ForEach-Object {
Move-Item -Path $_.ProviderPath -Destination $newParent.ProviderPath
Write-Host "Moved: $($_.Name)"
}$itemsToCopy = Get-ChildItem -Path "master:\content\home\original" -Recurse
$total = $itemsToCopy.Count
$current = 0
foreach($item in $itemsToCopy) {
$current++
Write-Progress -Activity "Copying items" `
-Status "Copying $($item.Name)" `
-PercentComplete (($current / $total) * 100)
Copy-Item -Path $item.ProviderPath `
-Destination "master:\content\home\copied" `
-Recurse
}
Write-Progress -Activity "Copying items" -Completed$sourceRoot = Get-Item -Path "master:\content\home\job-search"
$destinationRoot = Get-Item -Path "master:\content\home\careers"
$sourceRoot | Copy-Item -Destination $destinationRoot.ProviderPath -Recurse
# Produces a new tree /sitecore/content/home/careers/job-search
# Existing content remains at /sitecore/content/home/job-search# BAD - if parent doesn't exist, item is renamed
Move-Item -Path "master:\content\home\demo" `
-Destination "master:\content\nonexistent"# GOOD - verify parent exists
$destination = "master:\content\archive"
if (Test-Path $destination) {
Move-Item -Path "master:\content\home\demo" -Destination $destination
} else {
Write-Host "Destination does not exist" -ForegroundColor Red
}# BAD - can't access the new item
Copy-Item -Path "master:\content\home\demo" -Destination "master:\content\copy"
# No reference to the copied item# GOOD - use PassThru to get reference
$sourcePath = "master:\content\home\demo"
$destinationPath = "master:\content\home\demo-copy"
$copiedItem = Copy-Item -Path $sourcePath -Destination $destinationPath -PassThru
$copiedItem.Title = "Updated Title"New-WebServiceProxy : The request failed with HTTP status 401: Unauthorized.Import-Module -Name SPE
$credential = Get-Credential
$session = New-ScriptSession -Username admin -Password b -ConnectionUri https://remotesitecore -Credential $credential
Invoke-RemoteScript -Session $session -ScriptBlock { Get-User -id admin }
Stop-ScriptSession -Session $session
# Name Domain IsAdministrator IsAuthenticated
# ---- ------ --------------- ---------------
# sitecore\admin sitecore True False# If you need to connect to more than one instance of Sitecore add it to the list.
$instanceUrls = @("https://remotesitecore","https://remotesitecore2")
$session = New-ScriptSession -Username admin -Password b -ConnectionUri $instanceUrls
Invoke-RemoteScript -Session $session -ScriptBlock { $env:computername }
Stop-ScriptSession -Session $sessionImport-Module -Name SPE
$session = New-ScriptSession -Username admin -Password b -ConnectionUri https://remotesitecore
Receive-RemoteItem -Session $session -Path "default.js" -RootPath App -Destination "C:\Files\"
Stop-ScriptSession -Session $sessionImport-Module -Name SPE
$session = New-ScriptSession -Username admin -Password b -ConnectionUri https://remotesitecore
Receive-RemoteItem -Session $session -Path "/Default Website/cover" -Destination "C:\Images\" -Database master
Stop-ScriptSession -Session $sessionImport-Module -Name SPE
$session = New-ScriptSession -Username admin -Password b -ConnectionUri https://remotesitecore
$jobId = Invoke-RemoteScript -Session $session -ScriptBlock {
"master", "web" | Get-Database |
ForEach-Object {
[Sitecore.Globals]::LinkDatabase.Rebuild($_)
}
} -AsJob
Wait-RemoteScriptSession -Session $session -Id $jobId -Delay 5 -Verbose
Stop-ScriptSession -Session $session$jobId = Invoke-RemoteScript -Session $session -ScriptBlock {
Get-Session -ParameterDoesNotExist "SomeData"
} -AsJob
# This delay could actually be that you got up to get some coffee or tea.
Start-Sleep -Seconds 2
Invoke-RemoteScript -Session $session -ScriptBlock {
$ss = Get-ScriptSession -Id $using:JobId
$ss | Receive-ScriptSession
if($ss.LastErrors) {
$ss.LastErrors
}
}Invoke-RemoteScript -ScriptBlock {
Write-Verbose "Hello from the other side" -Verbose 4>&1
"data"
Write-Verbose "Goodbye from the other side" -Verbose 4>&1
} -Session $sessionInvoke-RemoteScript -ScriptBlock {
function Write-Verbose {
param([string]$Message)
Microsoft.PowerShell.Utility\Write-Verbose -Message $Message -Verbose 4>&1
}
Write-Verbose "Hello from the other side"
"data"
Write-Verbose "Goodbye from the other side"
} -Session $session + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.NewItemCommandInvoke-RemoteScript -ScriptBlock {
Set-Location -Path "master:"
...
[The rest of your script]
...
}# Create a list of field names on the Standard Template. This will help us filter out extraneous fields.
$standardTemplate = Get-Item -Path "master:" -ID "{1930BBEB-7805-471A-A3BE-4858AC7CF696}"
$standardTemplateTemplateItem = [Sitecore.Data.Items.TemplateItem]$standardTemplate
$standardFields = $standardTemplateTemplateItem.OwnFields + $standardTemplateTemplateItem.Fields | Select-Object -ExpandProperty key -Unique
$itemTemplate = Get-Item -Path "master:" -ID "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
$itemTemplateTemplateItem = [Sitecore.Data.Items.TemplateItem]$itemTemplate
$itemTemplateFields = $itemTemplateTemplateItem.OwnFields + $itemTemplateTemplateItem.Fields | Select-Object -ExpandProperty key -Unique
$filterFields = $itemTemplateFields | Where-Object { $standardFields -notcontains $_ } | Sort-ObjectGet-ArchiveItem -Archive <Archive>
Get-ArchiveItem -Archive <Archive> [-ItemId <ID>]
Get-ArchiveItem -Archive <Archive> [-Identity <AccountIdentity>]Function
Function
Get-Item -Path function:\prompt
Registry
HKLM, HKCU
Get-Item -Path hklm:\SOFTWARE
Variable
Variable
Get-Item -Path variable:\PSVersionTable
Remove-Item master:\content\home\item
Test exists
Test-Path C:\file.txt
Test-Path master:\content\home\item
Move
Move-Item C:\old.txt C:\new.txt
Move-Item master:\a master:\b
Copy
Copy-Item C:\old.txt C:\new.txt
Copy-Item master:\a master:\b
-TransferOptions 0
PassThru
Copy-Item
Returns the new item
-PassThru
Recurse
Copy-Item
Includes all descendants
-Recurse
Items with Invalid Names
Items with security for an account2
Items with Security for an account
Items with Tokens in Fields
Links
Locked Items2
Locked Items
Logged errors
Logged in Session Manager5
Logged in Users
Limit number of versions4
Multiple versions
My Owned Items
Media items last updated before date3
Not recently modified
Media items not used by content items3
Orphaned media assets report
Owned items
Recent workflow history2
Recent Workflow History
Media items last updated after date3
Recently Modified
Regex Item Searcher
Renderings
Index Viewer5
-
Rules based report5
-
Task Manager report5
-










Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false

Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
functions
listViewExport
listViewRibbon
pipelineLoggedIn
pipelineLoggingIn
pipelineLogout
toolbox
startMenuReports
eventHandlers
webAPI
pageEditorNotification
isePlugi
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The Get-SpeModule command returns the object that describes a Sitecore PowerShell Extensions Module.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
A script or library item that is defined within the module to be returned.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Path to a script or library item that is defined within the module to be returned.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Id of a script or library item that is defined within the module to be returned.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database containing the module to be returned.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Name fo the module to return. Supports wildcards.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
System.String
The output type is the type of the objects that the cmdlet emits.
Spe.Core.Modules.Module
Help Author: Adam Najmanowicz, Michael West
Return all modules defined in the provided database
Return all modules defined in the master database Matching the "Content*" wildcard
Return the module the piped script belongs to
Executes a script from Sitecore PowerShell Extensions Script Library.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The following abbreviations are aliases for this cmdlet:
Execute-Script
The script item to be executed.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Path to the script item to be executed. Path can be absolute or Relavie to Script library root. e.g. the following two commands are equivalent:
PS master:> Invoke-Script 'master:\system\Modules\PowerShell\Script Library\Examples\Script Testing\Long Running Script with Progress Demo' PS master:> Invoke-Script 'Examples\Script Testing\Long Running Script with Progress Demo'
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
System.Object
Help Author: Adam Najmanowicz, Michael West
Run a script with arguments passed in.
The arguments are passed and used in the called script like below:
Get-Item -Path "master:\content\home" | Expand-Token$tokens = @('$name', '$id', '$parentId', '$parentname', '$date', '$time', '$now')
$item = Get-Item -Path "master:\content\home"
$standardValueFields = Get-ItemField -Item $item -ReturnType Field -Name "*" `
| Where-Object { $_.ContainsStandardValue }
$item.Editing.BeginEdit()
foreach ($field in $standardValueFields) {
$value = $field.Value
if ($tokens -contains $value) {
$item[$field.Name] = $value
}
}
$item.Editing.EndEdit()
Expand-Token -Item $item$item = Get-Item -Path "master:{04DAD0FD-DB66-4070-881F-17264CA257E1}"
$siteName = "website"
$site = [Sitecore.Sites.SiteContextFactory]::GetSiteContext($siteName)
New-UsingBlock (New-Object Sitecore.Sites.SiteContextSwitcher $site) {
[Sitecore.Resources.Media.MediaManager]::GetMediaUrl($item)
}
# /-/media/default-website/cover.jpg$html = "<ul><li>foo</li><li>bar</li></ul>"
$htmlDocument = New-Object -TypeName HtmlAgilityPack.HtmlDocument
$htmlDocument.LoadHtml($html)
foreach($x in $htmlDocument.DocumentNode.SelectNodes("//li")) {
$x.InnerText;
}$html = @"
<div class="kitchen">
<div class="kitchen">
<blockquote>kitchen<br />
<span class="kitchen">kitchen</span>
</blockquote>
<a><img title="kitchen" src="https://kitchen-sink.local" /></a>
</div>
</div>
"@
$htmlDocument = New-Object -TypeName HtmlAgilityPack.HtmlDocument
$htmlDocument.LoadHtml($html)
foreach($x in $htmlDocument.DocumentNode.Descendants()) {
if($x.Name -ne "img" -and ![string]::IsNullOrEmpty($x.Text)) {
$x.Text = $x.Text.Replace("kitchen", "sink")
}
}
$htmlDocument.DocumentNode.OuterHtml$html = @"
<div style='padding: 10px 10px;'>Some Text</div>
"@
$htmlDocument = New-Object -TypeName HtmlAgilityPack.HtmlDocument
$htmlDocument.LoadHtml($html)
$nodes = $htmlDocument.DocumentNode.SelectNodes("//@style");
foreach($node in $nodes) {
$node.Attributes["style"].Remove()
}
$htmlDocument.DocumentNode.OuterHtml$item = Get-Item -Path "master:" -Id "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
$db = Get-Database -Name "master"
$workflowProvider = $db.WorkflowProvider
foreach($version in $item.Versions.GetVersions()) {
$workflowEvents = $workflowProvider.HistoryStore.GetHistory($version)
foreach($workflowEvent in $workflowEvents) {
"[$($workflowEvent.Date)] ($($workflowEvent.User)) $(($workflowEvent.Text -replace '(\r|\n)',''))"
}
}Write-Host "Restoring items recycled after $($archivedDate.ToShortDateString())"
foreach($archive in Get-Archive -Name "recyclebin") {
Write-Host " - Found $($archive.GetEntryCount()) entries"
$entries = $archive.GetEntries(0, $archive.GetEntryCount())
foreach($entry in $entries) {
if($entry.ArchiveLocalDate -ge $archivedDate) {
Write-Host "Restoring item: $($entry.OriginalLocation) {$($entry.ArchivalId)}on date $($entry.ArchiveLocalDate)"
$archive.RestoreItem($entry.ArchivalId)
} else {
Write-Host "Skipping $($entry.OriginalLocation) on date $($entry.ArchiveLocalDate)"
}
}
}$database = Get-Database -Name "master"
$archiveName = "recyclebin"
$archive = Get-Archive -Database $database -Name $archiveName
$items = Get-ArchiveItem -Archive $archive
$count = 0
$total = $items.Count
foreach($item in $items) {
$count++
if($count % 100 -eq 0) {
Write-Host "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] $([math]::round($count * 100 / $total, 2))% complete"
}
$item | Remove-ArchiveItem
}
Write-Host "Completed processing recycle bin"1..5 | ForEach-Object {
Start-Sleep -Seconds 1
Invoke-JavaScript -Script "console.log('Hello World! Call #$($_) from PowerShell...');"
}
Invoke-JavaScript -Script "alert('hello from powershell');"Import-Module -Name SPE -Force
$packageName = "$($SitecorePackageFolder)\[PACKAGE].zip"
$session = New-ScriptSession -Username "admin" -Password "b" -ConnectionUri "https://remotesitecore"
Test-RemoteConnection -Session $session -Quiet
$jobId = Invoke-RemoteScript -Session $session -ScriptBlock {
[Sitecore.Configuration.Settings+Indexing]::Enabled = $false
Get-SearchIndex | ForEach-Object { Stop-SearchIndex -Name $_.Name }
Import-Package -Path "$($SitecorePackageFolder)\$($using:packageName)" -InstallMode Merge -MergeMode Merge
[Sitecore.Configuration.Settings+Indexing]::Enabled = $true
} -AsJob
Wait-RemoteScriptSession -Session $session -Id $jobId -Delay 5 -Verbose
Stop-ScriptSession -Session $sessionPS master:\>Get-ItemReferrer -Path master:\content\home
Name Children Languages Id TemplateName
---- -------- --------- -- ------------
Home True {en, de-DE, es-ES, pt... {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample Item
Form False {en, de-DE, es-ES, pt... {6D3B4E7D-FEF8-4110-804A-B56605688830} Webcontrol
news True {en, de-DE, es-ES, pt... {DB894F2F-D53F-4A2D-B58F-957BFAC2C848} Article
learn-about-oms False {en, de-DE, es-ES, pt... {79ECF4DF-9DB7-430F-9BFF-D164978C2333} LinkPS master:\>Get-Item master:\content\home | Get-ItemReferrer -ItemLink
SourceItemLanguage : en
SourceItemVersion : 1
TargetItemLanguage :
TargetItemVersion : 0
SourceDatabaseName : master
SourceFieldID : {F685964D-02E1-4DB6-A0A2-BFA59F5F9806}
SourceItemID : {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}
TargetDatabaseName : master
TargetItemID : {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}
TargetPath : /sitecore/content/Home$database = Get-Database -Name "master"
$archiveName = "recyclebin"
$archive = Get-Archive -Database $database -Name $archiveName
Get-ArchiveItem -Archive $archive$database = Get-Database -Name "master"
$archiveName = "recyclebin"
$archive = Get-Archive -Database $database -Name $archiveName
Get-ArchiveItem -Archive $archive -ItemId "{1BB32980-66B4-4ADA-9170-10A9D3336613}"$database = Get-Database -Name "master"
$archiveName = "recyclebin"
$archive = Get-Archive -Database $database -Name $archiveName
Get-ArchiveItem -Archive $archive -Identity "sitecore\admin"$item = Get-Item -Path "master:" -ID "{1BB32980-66B4-4ADA-9170-10A9D3336613}"
$date = $item[[Sitecore.FieldIDs]::ArchiveDate]
$serverTime = [Sitecore.DateUtil]::IsoDateToServerTimeIsoDate($date)
$serverTimeDateTime = [Sitecore.DateUtil]::IsoDateToDateTime($serverTime, [datetime]::MinValue)
# Here you could add more time to the $serverTimeDateTime
$utcTimeDateTime = [Sitecore.DateUtil]::ToUniversalTime($serverTimeDateTime)
$isoTime = [Sitecore.DateUtil]::ToIsoDate($utcTimeDateTime)
$item.Editing.BeginEdit()
$item[[Sitecore.FieldIDs]::ArchiveDate] = $isoTime
$item.Editing.EndEdit()
# Some time after the date has passed
$database = Get-Database -Name "master"
$archiveName = "archive"
$archive = Get-Archive -Database $database -Name $archiveName
Get-ArchiveItem -Archive $archive -ItemId "{1BB32980-66B4-4ADA-9170-10A9D3336613}"PS master:\> ConvertFrom-ItemClone -Path master:\content\home$module = Get-SpeModule -Name "Copy Renderings"
Get-SpeModuleFeatureRoot -Feature contentEditorContextMenu -Module $module$module = Get-SpeModule -Name "Copy Renderings"
Get-SpeModuleFeatureRoot -Module $module -Feature listViewExport -ReturnPathPS master:\> Get-SpeModule -Database (Get-Database "master")PS master:\> Get-SpeModule -Database (Get-Database "master")PS master:\> Get-item "master:\system\Modules\PowerShell\Script Library\Copy Renderings\Content Editor\Context Menu\Layout\Copy Renderings" | Get-SpeModuleInvoke-Script 'Examples\Script Testing\Long Running Script with Progress Demo'$scriptItem = Get-Item -Path "master:" -ID "{35311878-54EF-4E7A-9B95-3B63F5DEE97D}"
$arguments = @{
TemplateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
}
$scriptItem | Invoke-Script -ArgumentList $argumentsparam($params)
$templateId = $params.templateId
Get-ItemReferrer -ID $templateIdPackage Generator
Task Management
Return the gutter object
Configure any Enable rules to ensure the script runs only when necessary.
Rebuild the gutter integration from within the ISE.
Settings tab
Integration chunk
Sync Library with Content Editor Gutter command
Optionally add a short description on the item, which is found as a standard field on the item. The description will appear as a tooltip on the ribbon button.
Edit the script to perform the appropriate actions. The script can run in the background and show dialogs.
Change the icon of the item to match the script purpose.
Configure any Enable or Show rules as needed.
Configure any Enable rules to ensure the script only runs when required.






Event Handlers
Functions
Internal
Page Editor
Pipelines
Profile and Security
Reports
Script Testing
Tasks
Toolbox
User Interaction
Web API
where specific persistent PowerShell session was already initiated #153
where specific persistent PowerShell session was already initiated and has the specific variable defined and not null
where exposed in a specific view #156
Used with the command Show-ListView to allow actions to be visible only on views with a corresponding name.
EnableRule (Enable if rules are met or not defined) - typically controls enabled state of integration points.
Same as above
ISE Plugin
ISE Plugin
Reports List View Action
Reports List View Action
Reports List View Export
Reports List View Export
Page Editor
Page Editor
Content Editor Context Menu
Content Editor Context Menu
Content Editor Gutter
Content Editor Insert Item
Content Editor Ribbon
Content Editor Ribbon
Content Editor Warning
The Get-ItemTemplate command returns the item template and its base templates.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Return the template the item is based on and all of its base templates.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The item to be analysed.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Path to the item to be analysed.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Id of the item to be analysed.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database containing the item to be analysed - required if item is specified with Id.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.TemplateItem
Help Author: Adam Najmanowicz, Michael West
Get template of /sitecore/conent/home item
Get template of /sitecore/conent/home item and all of the templates its template is based on then format it to only show the template name, path and Key
For CI/CD and automation environments where you only need SPE web services (without the full UI), a minimal deployment reduces the attack surface while maintaining remote automation capabilities.
The minimal deployment includes only the files necessary to support SPE web services, removing all UI components (Console, ISE, Content Editor integrations).
Benefits:
Smaller attack surface
Fewer files to maintain
Faster deployment
Ideal for build/deployment servers
Only what's needed for automation
Limitations:
No PowerShell Console
No PowerShell ISE
No Content Editor integration
No Reports UI
Scenario: Build servers need to execute deployment scripts remotely.
Requirements:
Remoting service
Minimal file footprint
No interactive UI
Scenario: Automated systems deploy content packages to Sitecore.
Requirements:
Remote script execution
File upload capability
Package installation commands
Scenario: Sitecore instances that serve as API backends without content authoring.
Requirements:
Remote automation capability
No UI overhead
Security-focused configuration
The following are NOT included in minimal deployment:
❌ PowerShell Console UI files ❌ PowerShell ISE files ❌ Content Editor integration files ❌ Report UI files ❌ Gutter renderers ❌ Ribbon extensions ❌ All UI-related files in sitecore modules\Shell\PowerShell\
SPE provides a pre-built minimal package: SPE.Minimal-6.x.zip
Download SPE.Minimal-8.x.zip from SPE releases
Extract to your Sitecore instance
Enable disabled config files (see below)
Configure security settings
Deploy required files using your favorite scripting language.
Create a config patch to disable UI control sources:
File: App_Config\Include\Spe\Custom\Spe.DisableUI.config
By default, Remoting is disabled. Enable it with proper security:
File: App_Config\Include\Spe\Custom\Spe.Remoting.config
File: sitecore modules\PowerShell\Services\web.config
Network - Firewall rules, VPN if possible
IIS - IP restrictions, Windows Auth (optional), HTTPS
Sitecore - Specific user accounts with minimal roles
SPE - requireSecureConnection, file upload restrictions
Possible causes:
Remoting service not enabled
User not in authorization list
HTTPS required but using HTTP
Anonymous access denied but not providing credentials
Solution: Check configuration, verify credentials, ensure HTTPS.
Cause: controlSources not disabled in configuration.
Solution: Verify Spe.DisableUI.config patch is present and loading.
- Detailed web service configuration
- IIS-level hardening
- Configure upload limits
- Validation checklist
Executes Sitecore Shell command for an item. This command used to be named Execute-ShellCommand - a matching alias added for compatibility with older scripts.
Invoke-ShellCommand [-Item] <Item> [-Name] <String> [-Language <String[]>]
Invoke-ShellCommand [-Path] <String> [-Name] <String> [-Language <String[]>]
Invoke-ShellCommand -Id <String> [-Database <String>] [-Name] <String> [-Language <String[]>]
Executes Sitecore Shell command for an item. e.g. opening dialogs or performing commands that you can find in the Content Editor ribbon or context menu.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The following abbreviations are aliases for this cmdlet:
Execute-ShellCommand
Name of the sitecore command e.g. "item:publishingviewer"
Language that will be used as source language. If not specified the current user language will be used. Globbing/wildcard supported.
The item to be sent to the command.
Path to the item to be sent to the command - additionally specify Language parameter to fetch different item language than the current user language.
Id of the the item to be sent to the command - additionally specify Language parameter to fetch different item language than the current user language.
Database containing the item to be sent to the command - can work with Language parameter to narrow the publication scope.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
Launch Publishing Viewer for /sitecore/content/home item.
Initiate /sitecore/content/home item duplication.
Show properties of the /sitecore/content/home item.
Returns entries from the history store notifying of workflow state change for the specified item.
Get-ItemWorkflowEvent [-Item] <Item> [-Identity <String>] [-Language <String[]>]
Get-ItemWorkflowEvent [-Path] <String> [-Identity <String>] [-Language <String[]>]
Get-ItemWorkflowEvent -Id <String> [-Database <String>] [-Identity <String>] [-Language <String[]>]
The Get-ItemWorkflowEvent command returns entries from the history store notifying of workflow state change for the specified item.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
User that has been associated with the enteries. Wildcards are supported.
Language that will be used as source language. If not specified the current user language will be used. Globbing/wildcard supported.
The item to have its history items returned.
Path to the item to have its history items returned - additionally specify Language parameter to fetch different item language than the current user language.
Id of the the item to have its history items returned - additionally specify Language parameter to fetch different item language than the current user language.
Database containing the item to have its history items returned - can work with Language parameter to narrow the publication scope.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Workflows.WorkflowEvent
Help Author: Adam Najmanowicz, Michael West
Execute-Workflow
Returns one or more task schedule items using the specified criteria.
Get-TaskSchedule -Item <Item>
Get-TaskSchedule -Path <String>
Get-TaskSchedule [[-Database] <Database>] [[-Name] <String>]
The Get-TaskSchedule command returns one or more task schedule items, based on name/database filter, path or simply converting a Sitecore item.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Task item to be converted.
Path to the item to be returned as Task Schedule.
Database containing the task items to be returned. If not provided all databases will be considered for filtering using the "Name" parameter.
Task filter - supports wildcards. Works with "Database" parameter to narrow tassk to only single database.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Tasks.ScheduleItem
Help Author: Adam Najmanowicz, Michael West
Executes Workflow action for an item. This command used to be named Execute-Workflow - a matching alias added for compatibility with older scripts.
Invoke-Workflow [-Item] <Item> [-CommandName <String>] [-Comments <String>] [-Language <String[]>]
Invoke-Workflow [-Path] <String> [-CommandName <String>] [-Comments <String>] [-Language <String[]>]
Invoke-Workflow -Id <String> [-Database <String>] [-CommandName <String>] [-Comments <String>] [-Language <String[]>]
Executes Workflow action for an item. If the workflow action could not be performed for any reason - an appropriate error will be raised.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The following abbreviations are aliases for this cmdlet:
Execute-Workflow
Namer of the workflow command.
Comment to be saved in the history table for the action.
Language that will be used as source language. If not specified the current user language will be used. Globbing/wildcard supported.
The item to have the workflow action executed.
Path to the item to have the workflow action executed - additionally specify Language parameter to fetch different item language than the current user language.
Id of the the item to have the workflow action executed - additionally specify Language parameter to fetch different item language than the current user language.
Database containing the item to have the workflow action executed - can work with Language parameter to narrow the publication scope.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
Submit item to approval, item gotten from path
Reject item, item gotten from pipeline
Understanding the security policies that govern SPE is essential for properly securing your installation. SPE operates under two primary security contexts that work together to control what scripts can do.
SPE security operates on two levels:
Application Pool Service Account - Controls OS-level access (file system, registry, network)
File upload capabilities in SPE can be restricted by file type and destination path. This provides defense in depth by preventing malicious file uploads even if the upload service is enabled.
When the is enabled, SPE enforces restrictions on:
File Types - Which file extensions and MIME types can be uploaded
Retrieves item fields as either names or fields or template fields.
Get-ItemField [-Item] <Item> [-IncludeStandardFields] [-ReturnType <Name | Field | TemplateField>] [-Name <String[]>] [-Language <String[]>]
Get-ItemField [-Path] <String> [-IncludeStandardFields] [-ReturnType <Name | Field | TemplateField>] [-Name <String[]>] [-Language <String[]>]
Get-ItemField -Id <String> [-Database <String>] [-IncludeStandardFields] [-ReturnType <Name | Field | TemplateField>] [-Name <String[]>] [-Language <String[]>]
Creates a new item clone based on the item provided.
New-ItemClone [-Item] <Item> -Destination <Item> [-Name <String>] [-Recurse]
New-ItemClone [-Path] <String> -Destination <Item> [-Name <String>] [-Recurse]
New-ItemClone -Id <String> [-Database <String>] -Destination <Item> [-Name <String>] [-Recurse]
Returns all the items linked to the specified item..
Get-ItemReference -Item <Item>
Get-ItemReference -Item <Item> -ItemLink
Get-ItemReference -Path <String> [-Language <String[]>]
Get-ItemReference -Path <String> [-Language <String[]>] -ItemLink
Get-ItemReference -Id <String> [-Database <String>] [-Language <String[]>]
Add one or more base templates to a template item.
Add-BaseTemplate -Item <Item> -TemplateItem <TemplateItem[]>
Add-BaseTemplate -Item <Item> -Template <String[]>
Add-BaseTemplate -Path <String> -TemplateItem <TemplateItem[]>
Add-BaseTemplate -Path <String> -Template <String[]>
Add-BaseTemplate -Id <String> -TemplateItem <TemplateItem[]>
# Use the notation "." to get the current directory/item.
$item = Get-Item -Path .
Show-Alert -Title $item.Name# /sitecore/system/modules/powershell/script library/spe rocks/functions/get-datemessage
function Get-DateMessage {
"The current date and time is: $(Get-Date)"
}# /sitecore/system/modules/powershell/script library/spe rocks/alerts/show-datemessage
Import-Function -Name Get-DateMessage
Show-Alert (Get-DateMessage)PS master:\> Get-ItemTemplate -Path master:\content\home
BaseTemplates : {Standard template}
Fields : {__Context Menu, __Display name, __Editor, __Editors...}
FullName : Sample/Sample Item
Key : sample item
OwnFields : {Title, Text, Image, State...}
StandardValues : Sitecore.Data.Items.Item
Database : master
DisplayName : Sample Item
Icon : Applications/16x16/document.png
ID : {76036F5E-CBCE-46D1-AF0A-4143F9B557AA}
InnerItem : Sitecore.Data.Items.Item
Name : Sample ItemPS master:\> Get-Item -Path master:/content/Home | Get-ItemTemplate -Recurse | ft Name, FullName, Key -auto
Name FullName Key
---- -------- ---
Sample Item Sample/Sample Item sample item
Standard template System/Templates/Standard template standard template
Advanced System/Templates/Sections/Advanced advanced
Appearance System/Templates/Sections/Appearance appearance
Help System/Templates/Sections/Help help
Layout System/Templates/Sections/Layout layout
Lifetime System/Templates/Sections/Lifetime lifetime
Insert Options System/Templates/Sections/Insert Options insert options
Publishing System/Templates/Sections/Publishing publishing
Security System/Templates/Sections/Security security
Statistics System/Templates/Sections/Statistics statistics
Tasks System/Templates/Sections/Tasks tasks
Validators System/Templates/Sections/Validators validators
Workflow System/Templates/Sections/Workflow workflowTest connectivity
Monitoring - Comprehensive logging and alerts
Logging and Monitoring - Monitoring remote operations
Remoting - Using SPE Remoting features
App_Config\Include\Spe\Spe.config
Core configuration
✓ Yes
App_Config\Include\Spe\Spe.Minimal.config
Minimal deployment config
✓ Yes
bin\Spe.dll
Main assembly
✓ Yes
bin\Spe.Abstractions.dll
Abstractions assembly
✓ Yes
sitecore modules\PowerShell\Services\web.config
IIS configuration
✓ Yes
sitecore modules\PowerShell\Services\RemoteAutomation.asmx
Remoting service
✓ Yes
sitecore modules\PowerShell\Services\RemoteScriptCall.ashx
RESTful/file services
✓ Yes
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
false
Position?
2
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Required?
false
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Retrieves item fields as either names or fields or template fields.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Includes fields that are defined on "Standard template"
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Determines type returned. The possible values include:
Name - strings with field names.
Field - fields on the item
TemplateField - template fields.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Array of names to include - supports wildcards.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Language that will be analysed. If not specified the current user language will be used. Globbing/wildcard supported.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The item to be analysed.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Path to the item to be analysed.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Id of the item to be analysed.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database containing the item to be analysed - can work with Language parameter to narrow the publication scope.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Sitecore.Data.Templates.TemplateField
Sitecore.Data.Fields.Field
Help Author: Adam Najmanowicz, Michael West
Get list of names of non standard fields from /sitecore/content/home item
Get list of fields including standard fields from /sitecore/content/home item and list their Name, DisplayName, SectionDisplayName and Description in a table.
Get-ItemReference -Id <String> [-Database <String>] [-Language <String[]>] -ItemLink
The Get-ItemReference command returns all items linked to the specified item. If -ItemLink parameter is used the command will return links rather than items.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The item to be analysed.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Path to the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Id of the the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database containing the item to be processed - can work with Language parameter to narrow the publication scope.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Language that will be used as source language. If not specified the current user language will be used. Globbing/wildcard supported.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Return ItemLink that define both source and target of a link rather than items that are being linked to from the specified item.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Sitecore.Links.ItemLink
Help Author: Adam Najmanowicz, Michael West
Add-BaseTemplate -Id <String> -Template <String[]>
Add-BaseTemplate [-Database <String>]
The Add-BaseTemplate command adds one or more base templates to a template item.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The item to add the base template to.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
true (ByValue)
Accept Wildcard Characters?
false
Path to the item to add the base template to.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Id of the item to add the base template to.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Sitecore item or list of items of base templates to add.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Path representing the template item to add as a base template. This must be of the same database as the item to be altered. Note that this parameter only supports a single template.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database containing the item to add the base template to - required if item is specified with Id.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West, Alex Washtell
Add base template of /sitecore/templates/User Defined/BaseTemplate to a template, using a path.
Add multiple base templates to a template, using items.
<configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<controlSources>
<source mode="on" namespace="Spe.Client.Controls" assembly="Spe">
<patch:delete />
</source>
<source mode="on" namespace="Spe.Client.Applications"
folder="/sitecore modules/Shell/PowerShell/" deep="true">
<patch:delete />
</source>
</controlSources>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<!-- Enable remoting with HTTPS requirement -->
<remoting>
<patch:attribute name="enabled">true</patch:attribute>
<patch:attribute name="requireSecureConnection">true</patch:attribute>
<!-- Clear default authorization -->
<authorization>
<patch:delete />
</authorization>
<!-- Add specific service account -->
<authorization>
<add Permission="Allow" IdentityType="User" Identity="sitecore\automation-user" desc="CI/CD automation account" />
</authorization>
</remoting>
<!-- Optionally enable file operations for package deployment -->
<fileDownload>
<patch:attribute name="enabled">true</patch:attribute>
</fileDownload>
<fileUpload>
<patch:attribute name="enabled">true</patch:attribute>
</fileUpload>
</services>
</powershell>
</sitecore>
</configuration><configuration>
<system.web>
<authorization>
<!-- Deny anonymous access -->
<deny users="?" />
</authorization>
</system.web>
<system.webServer>
<security>
<!-- Require HTTPS -->
<access sslFlags="Ssl" />
<!-- Optional: IP restrictions for build servers -->
<ipSecurity allowUnlisted="false">
<add ipAddress="10.0.0.100" allowed="true" desc="Build Server 1" />
<add ipAddress="10.0.0.101" allowed="true" desc="Build Server 2" />
</ipSecurity>
</security>
</system.webServer>
</configuration># Test from remote machine using SPE Remoting module
Import-Module SPE
# Create session
$session = New-ScriptSession `
-Username "sitecore\automation-user" `
-Password "SecurePassword123!" `
-ConnectionUri "https://sitecore-instance.local"
# Test script execution
$result = Invoke-RemoteScript -Session $session -ScriptBlock {
Get-Item -Path "master:\content\home" | Select-Object -ExpandProperty Name
}
Write-Host "Result: $result" -ForegroundColor Green
# Close session
Stop-ScriptSession -Session $sessionPS master:\> Get-Item master:\content\home\ | Invoke-ShellCommand "item:publishingviewer"PS master:\> Get-Item master:/content/home | Invoke-ShellCommand "item:duplicate"PS master:\> Get-Item master:/content/home | Invoke-ShellCommand "contenteditor:properties"PS master:\> Get-ItemWorkflowEvent -Path master:\content\home
Date : 2014-07-27 14:23:33
NewState : {190B1C84-F1BE-47ED-AA41-F42193D9C8FC}
OldState : {46DA5376-10DC-4B66-B464-AFDAA29DE84F}
Text : Automated
User : sitecore\admin
Date : 2014-08-01 15:43:29
NewState : {190B1C84-F1BE-47ED-AA41-F42193D9C8FC}
OldState : {190B1C84-F1BE-47ED-AA41-F42193D9C8FC}
Text : Just leaving a note
User : sitecore\adminPS master:\> Get-TaskSchedule
Name Database Active Auto Remove Is Due Expired Completed Last Run Next Run
---- -------- ------ ----------- ------ ------- --------- -------- --------
__Task Schedule master True False True False False 0001-01-01 00:00:00 0001-01-01 00:00:00
Check Bounced Messages master True False False False False 2014-07-29 10:18:43 2014-07-29 22:48:43
Check DSN Messages master True False False False False 2014-07-29 10:19:18 2014-07-29 22:49:18
Clean Confirmation IDs master True False False False False 2014-07-28 22:14:30 2014-07-31 02:14:30
Clean Message History master True False False False False 2014-07-29 10:19:18 2014-07-29 22:49:18
Close Outdated Connections master True False False False False 2014-07-29 12:30:22 2014-07-29 13:30:22
Test-PowerShell master True False False False False 2014-07-28 14:30:06 2014-08-01 17:32:07
__Task Schedule web True False True False False 0001-01-01 00:00:00 0001-01-01 00:00:00
Check Bounced Messages web True False True False False 2013-11-04 08:36:22 2013-11-04 21:06:22
Check DSN Messages web True False True False False 2013-11-04 08:36:22 2013-11-04 21:06:22
Clean Confirmation IDs web True False False False False 2013-11-04 08:36:22 2013-11-04 21:36:22
Clean Message History web True False True False False 2013-11-04 08:36:22 2013-11-04 21:06:22
Close Outdated Connections web True False True False False 2013-11-04 09:36:23 2013-11-04 10:36:23
Test-PowerShell web True False True False False 2013-11-04 09:46:29 2013-11-04 09:46:30PS master:\> Get-TaskSchedule -Name "*Check*"
Name Database Active Auto Remove Is Due Expired Completed Last Run Next Run
---- -------- ------ ----------- ------ ------- --------- -------- --------
Check Bounced Messages master True False False False False 2014-07-29 10:18:43 2014-07-29 22:48:43
Check DSN Messages master True False False False False 2014-07-29 10:19:18 2014-07-29 22:49:18
Check Bounced Messages web True False True False False 2013-11-04 08:36:22 2013-11-04 21:06:22
Check DSN Messages web True False True False False 2013-11-04 08:36:22 2013-11-04 21:06:22PS master:\> Get-TaskSchedule -Name "*Check*" -Database "master"
Name Database Active Auto Remove Is Due Expired Completed Last Run Next Run
---- -------- ------ ----------- ------ ------- --------- -------- --------
Check Bounced Messages master True False False False False 2014-07-29 10:18:43 2014-07-29 22:48:43
Check DSN Messages master True False False False False 2014-07-29 10:19:18 2014-07-29 22:49:18PS master:\> Invoke-Workflow -Path master:/content/home -CommandName "Submit" -Comments "Automated"PS master:\> Get-Item master:/content/home | Invoke-Workflow -CommandName "Reject" -Comments "Automated"PS master:\> Get-ItemField -Path master:\content\home
Text
Title
ImagePS master:\> Get-Item master:\content\home | Get-ItemField -IncludeStandardFields -ReturnType Field -Name "*" | ft Name, DisplayName, SectionDisplayName, Description -auto
Name DisplayName SectionDisplayName Description
---- ----------- ------------------ -----------
__Revision Revision Statistics
__Standard values __Standard values Advanced
__Updated by Updated by Statistics
__Validate Button Validation Rules Validation Button Validation Rules Validation Rules
__Created Created Statistics
__Thumbnail Thumbnail Appearance
__Insert Rules Insert Rules Insert Options
__Short description Short description Help
__Created by Created by Statistics
__Presets Presets Layout
Text Text Data The text is the main content of the document.PS master:\>Get-ItemReference -Path master:\content\home
Name Children Languages Id TemplateName
---- -------- --------- -- ------------
Home True {en, de-DE, es-ES, pt... {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample Item
Home True {en, de-DE, es-ES, pt... {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample ItemPS master:\>Get-Item master:\content\home | Get-ItemReference -ItemLink
SourceItemLanguage : en
SourceItemVersion : 1
TargetItemLanguage :
TargetItemVersion : 0
SourceDatabaseName : master
SourceFieldID : {F685964D-02E1-4DB6-A0A2-BFA59F5F9806}
SourceItemID : {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}
TargetDatabaseName : master
TargetItemID : {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}
TargetPath : /sitecore/content/HomePS master:\> Add-BaseTemplate -Path "master:/sitecore/content/User Defined/Page" -Template "/sitecore/templates/User Defined/BaseTemplate"PS master:\> $baseA = Get-Item -Path master:/sitecore/content/User Defined/BaseTemplateA
PS master:\> $baseB = Get-Item -Path master:/sitecore/content/User Defined/BaseTemplateB
PS master:\> Add-BaseTemplate -Path "master:/sitecore/content/User Defined/Page" -TemplateItem @($baseA, $baseB)✅ Appropriate permissions to access PowerShell tools → Security
✅ Basic understanding of Sitecore concepts (items, templates, fields)
SPE provides two main interfaces for running scripts:
The PowerShell Console is perfect for running quick, one-off commands.
How to open:
Log into Sitecore
Go to Desktop (bottom left icon)
Click PowerShell Console
When to use the Console:
Running single commands
Quick queries and checks
Interactive exploration
Testing command syntax
The PowerShell ISE (Integrated Scripting Environment) is a full-featured script editor.
How to open:
Log into Sitecore
Go to Desktop (bottom left icon)
Click Development Tools
Click PowerShell ISE
When to use the ISE:
Writing multi-line scripts
Developing reusable tools
Saving scripts for later use
Debugging complex logic
Let's run your very first SPE command!
Follow the instructions above to open the PowerShell Console.
Type this command and press Enter:
You should see output showing details about your Home item:
Congratulations! You just retrieved a Sitecore item using PowerShell. This is the foundation of everything you'll do with SPE.
Let's break down that command:
Get-Item - The command (cmdlet) that retrieves an item
-Path - A parameter that specifies which item to get
"master:\content\home" - The location of the item
master: - The database
\content\home - The path to the item
Now that you've run your first command, try these:
This shows all direct children of the Home item.
Be careful with -Recurse on large content trees! It can take a long time. See Common Pitfalls for more.
PowerShell has a default set of properties to format to the output window even though the objects returned still contain all the properties.
Using Select-Object, the properties are trimmed and the output window reflects the specific fields.
Output:
This finds all items under Home that have "Sample" in their name.
The ISE is more powerful for writing longer scripts. Let's try it out.
Follow the instructions above to open the PowerShell ISE.
In the top pane (script editor), type:
Click the Execute button (▶️) or press Ctrl-E.
The bottom pane shows the output of your script.
Variables store data and start with $:
Learn more: Variables
The pipe | chains commands together:
Learn more: Commands and Pipelines
SPE uses providers to access different data stores. The most important is the Sitecore provider:
Learn more: Providers
Here are some common tasks you can do right now:
SPE includes extensive built-in help:
Learn more: Help
The ISE includes a Script Library with ready-to-use examples:
Open the ISE
Click Open in the ribbon
Click to expand SPE in the tree
Expand folders to find examples:
Training - Learning exercises
Reports - Content reports
Tools - Utility scripts
Before you continue, remember these important safety rules:
❌ Don't run scripts in production without testing
✅ Do test in development first
✅ Do understand what a script does before running it
Commands that change data:
Remove-Item - Deletes items (can be recovered from Recycle Bin)
Set-Item - Modifies items
Move-Item - Moves items
Publish-Item - Publishes changes to web database
Save important scripts to source control
Document what your scripts do
Share scripts with your team
IMPORTANT: SPE is powerful and requires proper security configuration. Review the Security Guide before deploying to any non-development environment.
Now that you're up and running:
Learn the syntax: Language Basics
Master commands: Commands and Pipelines
Understand providers: Providers
Write your first scripts: Your First Scripts
Avoid mistakes:
Get-Item
Returns an object at the specified path.
Get-ChildItem
Returns children at the specified path. Supports recursion.
Get-Help
Returns the help documentation for the specified command or document.
Get-Command
Returns a list of commands.
ForEach-Object
Enumerates over the objects passed through the pipeline.
Where-Object
Enumerates over the objects passed through the pipeline and filters objects.
Ready to dive deeper? Continue with Language Basics!
Master the core operations for manipulating Sitecore content:
Working with Items - Complete guide to item manipulation
Retrieving Items - Advanced querying techniques
Editing Items - Proper item editing workflows
Creating and Removing Items - Item lifecycle management
- Reorganizing content
- Working with multilingual content
- Managing permissions with PowerShell
- Tips for writing efficient scripts
Build rich, interactive experiences for your scripts:
Interactive Dialogs - Build rich UI for your scripts
Show-ListView - Display data in tables with actions
Read-Variable - Create custom input forms
Show-FieldEditor - Edit item fields in dialogs
- Display formatted output
Create custom tools that extend Sitecore functionality:
Creating Reports - Build custom content reports
Creating Tasks - Schedule automated jobs
Content Editor Integration - Add context menu items
Toolbox Scripts - Create administrative tools
- Add Control Panel applications
- React to Sitecore events
Take your skills to the next level:
Beyond the learning paths above, you'll find these resources helpful:
Command Reference - Complete list of all SPE cmdlets
Code Snippets - Ready-to-use examples for common scenarios
Interfaces Guide - Deep dive into Console, ISE, and dialogs
Here are some project ideas to practice your skills:
Content Audit Report
Find all items without workflow
List items with empty required fields
Identify orphaned media items
Export results to CSV
Bulk Field Updater
Prompt user for template and field name
Find all items of that template
Update the specified field
Publishing Dashboard
Show items published in last 24 hours
Compare master vs web databases
Display publishing statistics
Content Migration Tool
Copy items between databases
Preserve all field values and versions
Handle item relationships
Create detailed log
Security Auditor
List all users and their roles
Show items with custom security
Identify security inheritance breaks
Template Analyzer
Find all templates
Show template inheritance tree
List fields for each template
Custom Reporting Engine
Build reusable report framework
Support multiple output formats
Add scheduling capabilities
Email reports automatically
Content Health Monitor
Check for broken links
Validate media items exist
Find duplicate items
Deployment Assistant
Compare environments
Package changed items
Generate deployment scripts
CRITICAL: Before deploying SPE to any non-development environment, review Security Hardening and complete the Security Checklist. Remember: SPE should NEVER be installed on CD servers or be accessible from internet-facing instances.
Built-in help: Use Get-Help <command-name> in the Console
Troubleshooting Guide - Common issues and solutions
#module-spe - Sitecore Community Slack channel
GitHub - Report issues or request features
As you continue working with SPE, keep these best practices in mind:
✅ Use full command names (not aliases) in scripts
✅ Write clear, descriptive variable names
✅ Add comments to explain complex logic
✅ Use functions for reusable code
✅ Handle errors with try/catch
✅ Test scripts in development first
✅ Filter early in pipelines
✅ Use Content Search for large queries
✅ Avoid -Recurse on large trees
✅ Use efficient collection types
✅ Suppress output properly (> $null)
✅ Measure performance with Measure-Command
✅ Never run untrusted scripts
✅ Use source control for all scripts
✅ Review security settings regularly
✅ Apply principle of least privilege
✅ Enable audit logging
✅ Test security policies
✅ Document what scripts do
✅ Use consistent naming conventions
✅ Organize scripts in Script Library
✅ Version control your work
✅ Share knowledge with team
✅ Review and refactor regularly
Video Series - Official tutorial videos
Blog Collection - Community articles and examples
Microsoft PowerShell Docs - General PowerShell reference
As you gain experience:
Share your scripts with the community on GitHub
Help answer questions on Slack and Stack Exchange
Write blog posts about solutions you've built
Submit improvements to this documentation
The best way to solidify your learning is to teach others!
You've completed the training and now have the skills to:
✅ Write PowerShell scripts for Sitecore
✅ Understand providers, pipelines, and commands
✅ Avoid common pitfalls
✅ Build useful automation tools
✅ Work safely and securely
Happy scripting! 🚀
Remember: The best way to learn is by doing. Start small, experiment often, and don't be afraid to make mistakes in development. You've got this!
Get-ItemKey uses:
Retrieve a single item by path
Query items using Sitecore query
Get items by ID or URI
Use Get-ChildItem to retrieve children and descendants of an item. This cmdlet is ideal for traversing content trees.
Key uses:
List immediate children
Recursively traverse item trees
Filter by template or other properties
SPE extends the standard PowerShell cmdlets with dynamic parameters. These appear when you specify a Sitecore database path:
AmbiguousPaths
Show all items matching ambiguous criteria
Get-Item
-AmbiguousPaths
Database
Specify database when using ID
Get-Item
-Database "master"
ID
Match item by GUID
Get-Item, Get-ChildItem
The most common way to retrieve items is by their Sitecore path.
Example: Retrieve an item by path.
Output:
Example: The C# equivalent for reference.
Retrieve items in specific languages or all languages using the -Language parameter with wildcards.
When working with multi-language sites, you may find that specifying the -Language parameter results in a more consistent behavior.
Example: Retrieve the Danish version of an item.
Output:
Example: Retrieve latest version for all languages.
Output:
Retrieve specific versions or all versions using the -Version parameter.
Example: Retrieve all versions in all languages.
Output:
Example: Using wildcards for partial matches (all English variants).
Use Get-ChildItem to retrieve an item's children, with optional recursion.
Example: Retrieve immediate children only.
Example: Retrieve all descendants recursively.
Example: Retrieve children in all languages and versions.
Use the -ID parameter to retrieve items by their GUID. This is useful when you know the item ID but not its path.
Example: Retrieve an item by ID.
Output:
ItemUri encodes the database, item ID, language, and version in a single string.
Example: Retrieve an item by URI.
Output:
Use Sitecore query to find items matching complex criteria. This is more efficient than traversing the tree when you need specific items.
Sitecore query paths containing reserved keywords or spaces require # delimiters: #path with spaces#
Example: Find all items with a specific template.
Output:
Example: Query with language and version wildcards.
Example: Query using dates (ISO format required) filtering by the publishing restriction where the item (not version) has a future date.
Sitecore has deprecated this functionality in XM/XP 10.1.
For complex queries using XPath axes, use the Sitecore API directly or prepend the context path.
Example: Use XPath axes to find ancestors.
Use custom property sets with Select-Object to retrieve specific groups of properties.
Example: Retrieve security properties using PSSecurity.
Output:
Example: Retrieve template information using PSTemplate.
Output:
Example: Retrieve image metadata using PSImage.
Output:
Example: Retrieve schedule information using PSSchedule.
Output:
If you retrieve items using the Sitecore API directly, wrap them with Initialize-Item to add SPE's automatic properties.
Example: Query using Sitecore API and wrap with SPE properties.
Use Sitecore query when you need specific items from a large tree
Use Get-ChildItem for small trees or when you need all items
Filter early - use query predicates instead of Where-Object when possible
Limit language/version retrieval - only use -Language * and -Version * when necessary
Editing Items - Update item properties and fields
Best Practices - Performance optimization guidance
Appendix - Common Commands - Full cmdlet reference
Sitecore User Account - Controls Sitecore API access (content, security, configuration)
Both security contexts work together to determine what a PowerShell script can accomplish.
The Windows PowerShell runspace executes under the identity of the IIS application pool service account. This account determines what OS-level resources the script can access through PowerShell providers.
Key Providers Affected:
FileSystem - Read/write files and directories
Registry - Read/write Windows registry keys
Environment - Access environment variables
Certificate - Access certificate stores
The application pool service account gives SPE access to OS-level features. If the service account can delete files from the root directory, SPE can do the same.
Example: If your application pool runs as NETWORK SERVICE or ApplicationPoolIdentity, the script may have:
Read/write access to C:\inetpub\wwwroot
Access to the application directories
Potentially access to other directories on the system
ApplicationPoolIdentity
Limited local access
No user profile ($HOME is empty); may have broader file system access than expected
NetworkService
Network and local access
Similar to ApplicationPoolIdentity; verify file system permissions
Custom Domain Account
Defined by domain policy
Has a user profile; permissions controlled by Active Directory
LocalSystem
Full system access
✅ Do:
Use the principle of least privilege
Audit file system permissions for the service account
Restrict the account to only necessary directories
Use a named service account when you need specific permissions
Test what directories the account can access
❌ Don't:
Run as LocalSystem or Administrator
Grant the service account unnecessary file system permissions
Assume ApplicationPoolIdentity is fully restricted
Allow write access to system directories
Example: Check which directories the service account can access:
You can restrict which directories SPE can access by:
NTFS Permissions - Remove unnecessary file system permissions from the service account
AppLocker - Use Windows AppLocker to restrict PowerShell execution paths
File Upload Restrictions - Configure SPE to only allow uploads to specific locations (see Web Services)
Scripts execute within the security context of the logged-in Sitecore user. The user's Sitecore roles and permissions determine what content and functionality the script can access through the Sitecore API.
Key Areas Controlled:
Content item access (read/write/delete)
Security management (users/roles)
Configuration access
Workflow operations
Publishing operations
The Sitecore security model applies to all script operations that use the Sitecore API:
However, scripts can bypass Sitecore security just like any other Sitecore API code:
Security Note: Scripts can disable Sitecore security checks using SecurityDisabler and other disablers. This is why limiting who can write and execute scripts is critical.
SPE features are protected by Sitecore security at the application level. Access to SPE interfaces is controlled through item-level security in the Core database.
Configuration Location: core:\content\Applications\PowerShell
PowerShell Console
sitecore\Developer (read)
core:\content\Applications\PowerShell\PowerShellConsole
PowerShell ISE
sitecore\Developer (read)
core:\content\Applications\PowerShell\PowerShellIse
PowerShell ListView
sitecore\Sitecore Client Users (read)
core:\content\Applications\PowerShell\PowerShellListView
PowerShell Runner
sitecore\Sitecore Client Users (read)
Note: Security is validated in each SPE application within the OnLoad function.
Context menu items in the Content Editor are also protected by security.
Configuration Location: core:\content\Applications\Content Editor\Context Menues\Default\
Edit with ISE
sitecore\Developer (read)
Enabled when item template is PowerShell Script, otherwise Hidden
Console
sitecore\Developer (read)
Enabled when user is admin or in role sitecore\Sitecore Client Developing, otherwise Hidden
Scripts
sitecore\Sitecore Limited Content Editor (deny read)
Enabled when the service and user are authorized to execute, otherwise Hidden
Note: PowerShell Script Library and PowerShell Script items have additional visibility and enabled rules. Adjust role permissions on these items to control menu visibility.
✅ Do:
Only grant SPE access to trusted administrators
Use Sitecore roles to control feature access
Require Session Elevation (UAC) for production environments
Audit which users have access to Developer and related roles
Review script libraries for appropriate security settings
Use delegated access for controlled privilege escalation
❌ Don't:
Grant sitecore\Developer role to content authors
Assume Sitecore security prevents all unauthorized actions
Allow untrusted users to write or execute scripts
Ignore the fact that scripts can disable security
Give broad access to SPE features
Example: Check current user context and permissions:
Both security contexts work together. A script is limited by whichever context is more restrictive:
Example Scenarios:
Read Sitecore content
Has file access
Has read permission
✅ Success
Read Sitecore content
Has file access
No read permission
❌ Denied by Sitecore
Delete file outside Sitecore
No file permission
Is administrator
Implement defense in depth by restricting both security contexts:
Minimum file system access
No access to sensitive directories
Regular permission audits
Role-based access control
Session elevation required
Regular role membership audits
Script library security reviews
Session Elevation (UAC) - Require reauthentication
Web Services Security - Disable unnecessary endpoints
IIS-Level Security - Block anonymous access
Monitoring and Logging - Detect unauthorized access
Configure Session Elevation to add an additional authentication layer
Review Web Services Security if you need external access
Learn about User and Role Management
Complete the Security Checklist
Upload Locations - Which directories files can be written to
These restrictions apply to uploads via:
SPE Remoting file upload
Custom scripts using upload functionality
By default, SPE allows limited file types and restricts uploads to the Sitecore temp folder:
File types can be restricted using:
File Extensions - Specific extensions like .csv, .txt, .xml
MIME Type Patterns - Wildcards like image/*, text/*, application/json
Images
.jpg, .png, .gif
image/*
Documents
.pdf, .doc, .docx
application/pdf, application/msword
Spreadsheets
.xls, .xlsx, .csv
application/vnd.ms-excel, text/csv
Text Files
.txt, .log
Security Warning: Be extremely careful allowing executable file types like .exe, .dll, .ps1, .bat, .cmd, .vbs, .js. These can be used to compromise the server.
SPE restricts where files can be uploaded using path patterns. These paths support Sitecore variables.
$SitecoreDataFolder
Data folder
C:\inetpub\wwwroot\App_Data
$SitecoreLogFolder
Log folder
C:\inetpub\wwwroot\App_Data\logs
$SitecorePackageFolder
Package folder
C:\inetpub\wwwroot\App_Data\packages
$SitecoreTempFolder
Temp folder
Recommended: Standardize your solution with a folder that you will routinely clean.
❌ Never allow uploads to these locations:
Allow CSV/Excel imports to a dedicated import folder:
✅ Do:
Use the principle of least privilege - only allow necessary file types
Restrict uploads to non-web-accessible folders when possible
Use $SitecoreTempFolder as the primary upload location
Create dedicated subdirectories for different upload purposes
Regularly clean up uploaded files
Monitor upload activity
Use both extension AND MIME type patterns for defense in depth
Test your restrictions before deploying to production
❌ Don't:
Allow executable file types (.exe, .dll, .ps1, etc.)
Allow uploads to the web root or bin folder
Allow uploads to system directories
Use wildcard MIME types like */* (allows everything)
Forget to restrict both file types AND locations
Allow script files that could be executed
Trust client-provided file extensions without validation
Start Restrictive - Begin with minimal allowed types and locations
Add as Needed - Only add permissions when you have a specific use case
Document Reasons - Comment your configuration explaining why each type/location is allowed
Regular Review - Audit allowed types and locations quarterly
Possible causes:
Location is not in allowedLocations
MIME type doesn't match pattern
File extension doesn't match pattern
Solution: Check both file type and location configuration.
Cause: Pattern syntax error or MIME type mismatch.
Solution: Use specific MIME types or verify wildcard syntax (image/*, not image*).
Cause: Variable not recognized by SPE configuration.
Solution: Use supported Sitecore variables or absolute paths.
Web Services Security - Enable/disable file upload service
Security Checklist - Validate your configuration
Logging and Monitoring - Monitor upload activity
GitHub Issue #1362 - Feature introduction
Creates a new item clone based on the item provided.
© 2010-2019 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
Parent item under which the clone should be created.
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Name of the item clone.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Add the parameter to clone thw whole branch rather than a single item.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The item to be cloned.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Path to the item to be cloned.
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Id of the item to be cloned
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Database of the item to be cloned if item is specified through its ID.
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
Clone /sitecore/content/home/ under /sitecore/content/new-target/ with the "New Home" name.

Building reports is a straightforward task. We've provided a variety of examples for you to model when designing your own.
The Authorable Reports module includes reports such as Index Viewer and Rules based report that provide input dialogs to help make the reports dynamic.
Note: The Index Viewer and Rules Based Report are bundled as separate a package on the Sitecore Marketplace.
The Index Viewer report provides a great example at how to build a generic report that queries against the Sitecore index. By navigating to Sitecore -> Toolbox -> Index Viewer you can conveniently launch the report.
First you will be prompted with a dialog to select the index to search.
Next you will be prompted with a variety of buttons and knobs to narrow down the search results.
Finally the report is shown. Each row has an option to show more field results.
The Show Full Info link will then returns the additional fields not shown in the report.
The Authorable Reports module has a few points of interest.
The script library Internal/List View/Ribbon/SearchResultItem instructs the report to show the action scripts when the row contains an entry with the typename SearchResultItem.
The script library Toolbox/Index Viewer represents the shortcut.
Examples:
The Content Reports module includes other reports used for auditing. Below are some examples on how to create your own. You can control the report menu with the Enable and Show rules. This can be helpful if you want to secure specific reports with security roles.
The rules engine can be used the control the report export and action commands. Use the Enable and Show rules to make the necessary changes.
Examples:
Content extracted from article written by Adam.
Actions are simply commands powered by scripts and with visibility dependent on certain conditions like the .Net class of the object that is displayed or perhaps other session settings.
You define an action as a script located in an SPE script library and appears in the Actions panel. In the simplest scenario the action would appear when the script library name matches the .Net class name of the items displayed. In the above scenario the actions are placed under /Platform/Internal/List View/Ribbon/Item/ where Platform is the module and Item is a script library. Let's take a look at the script here /Platform/Internal/List View/Ribbon/Item/Open
The variable $selectedData is provided to the script automatically by SPE in context of the content of the results on Show-ListView.
When your action script is executed the environment is initialized with a number of variables at your disposal as seen below:
$selectedData – the selected objects in the list view (the same will be passed to the $resultSet variable for compatibility with older scripts)
$allData – all objects passed to the list view using the -Data parameter.
$filteredData
Consequently you get the full state of the report the user sees in the UI and you can act upon it.
You can have multiple actions defined with dynamic visibility. The actions are generally only relevant in the context of your report. This is done on two levels. The first level happens based on the location of the script and .Net object type you are displaying in the report. The second level is based on Sitecore rules. For the action to appear all of the following conditions must be met:
All scripts visible in the report should be located in an enabled module.
The action script should be within the path /Internal/List View/Ribbon/[Object type]. The [Object type] is the name of the .Net class for which the action is valid. For example, if you want your action to be visible for Sitecore.Data.Items.Item then save the script at the path /Internal/List View/Ribbon/Item.
Rules add the full power of the Sitecore rules engine – similarly to what you can do on context menu items or ribbon actions in Content Editor. Some examples where this can be useful include only enabling or disabling the action for items located under a specific branch of the tree or if a exists.
The following screenshot shows how to create an action that only appears in reports that list objects of type Item that are of template Schedule.
For specific reports this global state might not always be enough. You can narrow down the rules further by using the report name. Name your report by providing an additional parameter to Show-ListView.
Consider the following script:
The output of the report will be like any other unnamed report but adds support for additional rules. Let's say I want my action to open a new report that lists all the children of the selected items in the report "ListChildren". After running the action my script should display the new report with the children and close the "ListChildren" report. Not very useful but illustrates the point.
Now I need to save my script in the proper Script Library in my enabled module:
At this point my action will show on all reports what list Item objects. But now that my script is saved I can modify its rules to narrow it down only to Show for reports named "ListChildren". For this I can click the Runtime button in the ISE ribbon and edit the Show if rules are met or not defined field.
Now you can specify that you want the action to only appear when the report is named "ListChildren".
Confirm the save on all dialogs to persist your changes. Now our action appears when we run this script in ISE.
The action does not appear if no view name is provided to the -ViewName parameter. Running the script below will produce a report with the action not shown:
The above action works just fine but will close the previous report and open a new report window in the Sitecore desktop. That's not a great user experience. What if you want to update the content of the report in place using the action? That's possible using the Update-ListView command. Consider the following script:
In this case we're not closing the existing report but rather updating the list in place, all you need to do is send the new data to the Update-ListView command.
One last thing that you might wonder is if the Write-Progress command works as it does in case of ISE or the dialog that runs scripts from Content Editor context menu. Let’s copy the following script into your action:
And you will see the following output:
The action runs fully asynchronously so you’re free to show any of the power of the provided commands. This means that you can ask for additional input using the Read-Variable command or Show alert using the Show-Alert command or do just about anything possible otherwise from the context menu, ribbon or other interactive integration points.
The Show-ListView command has one more useful parameter named -ActionData which I mentioned above but is worth mentioning again. Anything passed using this parameter will be set as the $actionData variable – this means your report and actions can pass custom data in them it can be as simple as an object or as complex as a hashtable so there is really no hard limit on what can progress from a report to report. Any object that was passed to Show-ListView using the -ActionData parameter will be available to your action.
The persistent session ID will be respected and your script will run in that persistent session if it's already in memory or create a persistent session if it's not.
Alternatively you can elect to simply freeze the session the initial script that generated report was running in and run actions in that same frozen session by using the -ActionsInSession parameter.
The Show-ListView command provides the Hide parameter to control visibility of the UI elements.
Add parameter -Hide with one or more of the following options:
AllExport - hides all export scripts (left-most ribbon panel)
NonSpecificExport - hides export filters that are not specific to this view as specified by -ViewName (left-most ribbon panel)
Filter - hides filter panel
Example: The following example all of the UI elements in the report.
for Sitecore product has published reports on Github that you can checkout .
Downloads are hosted on Github
Legend: "–" - not supported; "✓" - supported.
[1] Released by Sitecore for SXA which can be download from the however you should be safe simply installing the official SPE release on GitHub.
[2] Some features are not available. It is recommended to upgrade to the latest version available for 9.2.
Publish-Item command unsupported ()
When reviewing the different download packages you may see some names that are not too clear. The following list outlines what those names should mean.
N.X : Full N.X release - This refers to the package used by Standalone and CM roles. This includes what is required to see the PowerShell ISE, Console and their associated services.
N.X Minimal : Server-side remoting only - This refers to the package with only files. Useful for remotely connecting to SPE.
N.X Authorable Reports : Additional reports and tools - This package is a sublemental installation to the full version with additional reports. With version 6.0 this package is no longer needed as the reports are included with the full release.








PowerShell providers expose data stores through a consistent interface that resembles a file system. SPE extends this model with the CmsItemProvider, enabling you to navigate and manipulate Sitecore content as if it were a file system.
Run Get-PSProvider to see all available providers in your SPE session:
This page covers all methods for updating Sitecore items using SPE, from simple property changes to complex field type handling and bulk operations.
SPE provides multiple ways to edit items, each suited to different scenarios:
Automated Properties - Simple, intuitive syntax for single-field updates
Session Elevation provides a User Account Control (UAC) layer for SPE, similar to Windows UAC. This security feature requires users to reauthenticate or confirm before accessing powerful SPE features, even if they already have the necessary role permissions.
Session Elevation adds a time-based authentication layer on top of Sitecore's role-based security. This provides defense in depth by requiring users to:
Have the appropriate Sitecore role (e.g., sitecore\Developer
Delegated Access allows lower-privileged users to run specific scripts with elevated permissions by impersonating a power user. This provides controlled privilege escalation for trusted operations without granting users permanent elevated access.
Delegated Access solves a common problem: You want to give content authors access to specific administrative tasks without making them full administrators.
Without Delegated Access:
Get-Item -Path "master:\content\home"Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Home False en 1 {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample ItemGet-Item -Path "master:\content\home"Get-ChildItem -Path "master:\content\home"Get-ChildItem -Path "master:\content\home" -RecurseGet-Item -Path "master:\content\home" | Select-Object -Property Name, ID, TemplateNameName ID TemplateName
---- -- ------------
Home {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample ItemGet-ChildItem -Path "master:\content\home" | Where-Object { $_.Name -like "*Sample*" }# Get the home item
$homeItem = Get-Item -Path "master:\content\home"
# Show its children
$children = Get-ChildItem -Path $homeItem.ProviderPath
# Display count
Write-Host "Home has $($children.Count) children" -ForegroundColor Green
# Show the list
$children | Select-Object Name, TemplateName$item = Get-Item -Path "master:\content\home"
$name = $item.Name
$count = 5Get-ChildItem -Path "master:\content\home" |
Where-Object { $_.TemplateName -eq "Sample Item" } |
Select-Object Name, ID# Sitecore databases
Get-Item -Path "master:\content\home"
Get-Item -Path "web:\content\home"
Get-Item -Path "core:\content"
# File system
Get-Item -Path "C:\temp"
# Registry
Get-Item -Path "HKLM:\SOFTWARE"if(Test-Path "master:\content\home\test") {
Write-Host "Item exists!" -ForegroundColor Green
} else {
Write-Host "Item not found" -ForegroundColor Yellow
}$items = Get-ChildItem -Path "master:\content\home" -Recurse
$items | Group-Object TemplateName | Select-Object Name, Count | Sort-Object Count -Descending$threshold = (Get-Date).AddDays(-7)
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_."__Updated" -gt $threshold } |
Select-Object Name, ItemPath, "__Updated"$items = Get-ChildItem -Path "master:\content\home"
$items | Select-Object Name, TemplateName, "__Updated" |
Export-Csv -Path "$($SitecoreDataFolder)\export\items.csv" -NoTypeInformationGet-Help Get-ItemAclGet-Help Read-Variable -DetailedGet-Help Find-Item -ExamplesGet-Command | Where-Object { $_.ImplementingType -and $_.ImplementingType.Assembly.GetName().Name -eq "Spe" }database:\path\to\item
Examples:
master:\content\home
web:\content\home\article
core:\content$_ # Current item in pipeline
$PSItem # Same as $_
$true # Boolean true
$false # Boolean false
$null # Null value# Items
Get-Item -Path "master:\content\home"
Get-ChildItem -Path "master:\content" -Recurse
New-Item -Path "master:\content\home" -Name "Item"
Remove-Item -Path "master:\content\home\item"
# Filtering
... | Where-Object { $_.TemplateName -eq "Article" }
... | Select-Object -Property Name, ID, TemplateName
... | Sort-Object -Property Name
# Editing
$item.Editing.BeginEdit()
$item["Title"] = "New Value"
$item.Editing.EndEdit()
# Publishing
Publish-Item -Item $item -PublishMode Smart -Target web
# Help
Get-Help Get-Item
Get-Command *Item*
$item | Get-Member# Safe editing
foreach($item in $items) {
$item.Editing.BeginEdit()
try {
$item["Field"] = "Value"
$item.Editing.EndEdit()
}
catch {
$item.Editing.CancelEdit()
Write-Error $_
}
}
# Progress reporting
$total = $items.Count
for($i = 0; $i -lt $total; $i++) {
Write-Progress -Activity "Processing" `
-Status "$i of $total" `
-PercentComplete (($i / $total) * 100)
# Process item
}Get-Item -Path "master:\content\home"Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Home True en 2 {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample ItemSitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Sitecore.Data.Items.Item item = master.GetItem("/sitecore/content/home");Get-Item -Path "master:\content\home" -Language "da" |
Format-Table DisplayName, Language, Id, Version, TemplateNameDisplayName Language ID Version TemplateName
----------- -------- -- ------- ------------
Hjem da {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample ItemGet-Item -Path "master:\content\home" -Language * |
Format-Table DisplayName, Language, Id, Version, TemplateNameDisplayName Language ID Version TemplateName
----------- -------- -- ------- ------------
Home en {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home de-DE {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home pl-PL {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home en-US {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 3 Sample Item
Home en-GB {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Hjem da {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample ItemGet-Item -Path "master:\content\home" -Language * -Version * |
Format-Table DisplayName, Language, Id, Version, TemplateNameDisplayName Language ID Version TemplateName
----------- -------- -- ------- ------------
Home en {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home de-DE {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home pl-PL {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home en-US {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Home en-US {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 2 Sample Item
Home en-US {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 3 Sample Item
Home en-GB {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample Item
Hjem da {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} 1 Sample ItemGet-Item -Path "master:\content\home" -Language "en","en-*"Get-ChildItem -Path "master:\content"Get-ChildItem -Path "master:\content\home" -RecurseGet-ChildItem -Path "master:\content" -Language * -Version * |
Format-Table DisplayName, Language, Id, Version, TemplateNameGet-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}" -Language *Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Home True en 3 {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample Item
Home True en-CA 2 {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample ItemGet-Item -Path "master:" -Uri "sitecore://master/{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}?lang=en&ver=1"Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Home True en 1 {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample ItemGet-Item -Path "master:" -Query "/sitecore/content//*[@@templatename='Sample Item']"Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Home True en 3 {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} Sample Item
Contact False en 1 {357D85DB-4F6C-42AF-B9A0-C232FD86F679} Sample Item
History False en 1 {49D54DA4-EEB9-463B-AB19-BD8647270442} Sample Item
Team False en 1 {2E4F7BBB-C71C-4CBC-BBA1-B4C05F946138} Sample Item
BulkItem1 False en 1 {81E660ED-0207-4C1F-BCEF-DAD9286B4E02} Sample ItemGet-Item -Path "master:" -Query "/sitecore/content//*[@@templatename='Sample Item']" -Language * -Version * |
Format-Table DisplayName, Language, Id, Version, TemplateName -AutoSize$isoDate = [Sitecore.DateUtil]::ToIsoDate([datetime]::Today)
Get-Item -Path "master:" -Query "/sitecore/content/home//*[@__Publish > '$($isoDate)']" |
Show-ListView -Property ID, Name, ItemPath$query = "ancestor-or-self::*[@@templatename='Sample Item']"
# Option 1: Use Axes directly on an item
$SitecoreContextItem.Axes.SelectItems($query)
# Option 2: Prepend the context path to the query
Get-Item -Path "master:" -Query "$($SitecoreContextItem.Paths.Path)/$query"Get-Item -Path "master:\content\home" | Select-Object -Property PSSecurityName ID __Owner __Security
---- -- ------- ----------
Home {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} sitecore\Admin ar|sitecore\Developer|pd|+item:read|pe|+item:read|Get-Item -Path "master:" -ID "{04DAD0FD-DB66-4070-881F-17264CA257E1}" | Select-Object -Property PSTemplateName ID BaseTemplate
---- -- ------------
cover {04DAD0FD-DB66-4070-881F-17264CA257E1} {Image, File, Standard template, Advanced...}Get-Item -Path "master:\media library\Default Website\cover" | Select-Object -Property PSImageName : cover
ID : {04DAD0FD-DB66-4070-881F-17264CA257E1}
Alt :
Width : 1600
Height : 550
Extension : jpg
Size : 119719Get-Item -Path "master:\system\Tasks\Schedules\Forms\FileStorageCleanup" |
Select-Object -Property PSScheduleName : FileStorageCleanup
ID : {3D8F6795-1C4E-462D-8A81-BE27B1AEC5BD}
Schedule : 20190101|99990101|127|24:00:00
Last run : 11/29/2025 4:46:29 AM
Command : {D4ADAD17-E648-4FDC-BC4C-43F9D1513720}
Items :# Get the root node using Get-Item, then call Axes
$mediaItemContainer = Get-Item -Path "master:\media library"
$items = $mediaItemContainer.Axes.GetDescendants() |
Where-Object { [int]$_.Fields["Size"].Value -gt 100000 } |
Initialize-Item# Using Get-ChildItem with filtering
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" }
# Using Sitecore query (more efficient for large trees)
Get-Item -Path "master:" -Query "/sitecore/content/home//*[@@templatename='Sample Item']"$cutoffDate = (Get-Date).AddDays(-7)
Get-ChildItem -Path "master:\content" -Recurse |
Where-Object { $_.__Updated -gt $cutoffDate }# Using Where-Object
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.Title -like "*Welcome*" }
# Using Sitecore query
Get-Item -Path "master:" -Query "/sitecore/content/home//*[contains(@Title, 'Welcome')]"Get-ChildItem -Path "master:\media library" -Recurse |
Where-Object { $_.Size -gt 1MB } |
Select-Object Name, Size, Extension, ItemPath# Test file system access
Test-Path "C:\Windows\System32" -PathType Container
Test-Path "C:\inetpub\wwwroot" -PathType Container
# Check current identity
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
# Verify HOME directory
$HOME# This respects Sitecore security
Get-Item -Path "master:\content\home"
# This also respects Sitecore security
Get-User -Identity "sitecore\testuser"# This bypasses Sitecore security
New-UsingBlock (New-Object Sitecore.SecurityModel.SecurityDisabler) {
# Code here runs with full Sitecore permissions
Get-Item -Path "master:\content\home"
}# Get current user
$user = Get-User -Current
Write-Host "Current User: $($user.Name)"
# Check if user is in a role
$user.IsInRole("sitecore\Developer")
# List all roles for current user
$user.Roles | ForEach-Object { $_.Name }
# Test item access
$item = Get-Item -Path "master:\content\home"
$item.Access.CanRead()
$item.Access.CanWrite()
$item.Access.CanDelete()<powershell>
<uploadFile>
<allowedFileTypes>
<pattern>image/*</pattern>
<pattern>.xls</pattern>
<pattern>.xlsx</pattern>
<pattern>.csv</pattern>
</allowedFileTypes>
<allowedLocations>
<path>$SitecoreMediaFolder</path>
</allowedLocations>
</uploadFile>
</powershell><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<uploadFile>
<allowedFileTypes>
<pattern>.csv</pattern>
<pattern>.txt</pattern>
<pattern>.xml</pattern>
<pattern>.json</pattern>
</allowedFileTypes>
</uploadFile>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<uploadFile>
<allowedFileTypes>
<!-- All image types -->
<pattern>image/*</pattern>
<!-- All text types -->
<pattern>text/*</pattern>
<!-- Specific MIME type -->
<pattern>application/json</pattern>
<pattern>application/xml</pattern>
</allowedFileTypes>
</uploadFile>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<uploadFile>
<allowedFileTypes>
<!-- Excel -->
<pattern>.xls</pattern>
<pattern>.xlsx</pattern>
<pattern>application/vnd.ms-excel</pattern>
<pattern>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</pattern>
<!-- Word -->
<pattern>.doc</pattern>
<pattern>.docx</pattern>
<pattern>application/msword</pattern>
<pattern>application/vnd.openxmlformats-officedocument.wordprocessingml.document</pattern>
<!-- PowerPoint -->
<pattern>.ppt</pattern>
<pattern>.pptx</pattern>
<pattern>application/vnd.ms-powerpoint</pattern>
<pattern>application/vnd.openxmlformats-officedocument.presentationml.presentation</pattern>
</allowedFileTypes>
</uploadFile>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<uploadFile>
<allowedLocations>
<path>$SitecoreTempFolder</path>
</allowedLocations>
</uploadFile>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<uploadFile>
<allowedLocations>
<path>$SitecoreTempFolder</path>
<path>$SitecoreDataFolder\uploads</path>
<path>$SitecorePackageFolder</path>
</allowedLocations>
</uploadFile>
</powershell>
</sitecore>
</configuration><!-- DO NOT DO THIS -->
<allowedLocations>
<path>C:\</path> <!-- Root drive -->
<path>C:\Windows</path> <!-- Windows directory -->
<path>C:\inetpub\wwwroot</path> <!-- Web root (allows direct access) -->
</allowedLocations><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<uploadFile>
<!-- Only allow data file types -->
<allowedFileTypes>
<pattern>.csv</pattern>
<pattern>.xls</pattern>
<pattern>.xlsx</pattern>
<pattern>text/csv</pattern>
<pattern>application/vnd.ms-excel</pattern>
<pattern>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</pattern>
</allowedFileTypes>
<!-- Only allow specific import locations -->
<allowedLocations>
<path>$SitecoreTempFolder</path>
<path>$SitecoreDataFolder\uploads</path>
</allowedLocations>
</uploadFile>
</powershell>
</sitecore>
</configuration>PS master:\> $newTarget = Get-Item master:\content\new-target\
PS master:\> New-ItemClone -Path master:\content\home -Destination $newTarget -Name "New Home"-ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
Language
Specify language versions
Get-Item, Get-ChildItem
-Language "en-US" or -Language *
Query
Execute Sitecore query
Get-Item
-Query "/sitecore/content//*"
Uri
Match item by ItemUri
Get-Item
-Uri "sitecore://master/{GUID}?lang=en&ver=1"
Version
Specify item versions
Get-Item, Get-ChildItem
-Version 2 or -Version *
WithParent
Include parent in results
Get-ChildItem
-WithParent
❌ Never use - grants unlimited access
core:\content\Applications\PowerShell\PowerShellRunner
PowerShell Reports
sitecore\Sitecore Client Authoring (read)
❌ Denied by Windows
Delete file outside Sitecore
Has file permission
Is administrator
✅ Success (dangerous!)
text/plain, text/*
Data Files
.json, .xml
application/json, application/xml
Archives
.zip
application/zip
C:\inetpub\wwwroot\temp
$SitecoreMediaFolder
Media folder
C:\inetpub\wwwroot\upload
Select-Object
Returns objects from the pipeline with the specified properties and filters objects.
Sort-Object
Sorts the pipeline objects with the specified criteria; usually a property name.
Get-Member
Returns the methods and properties for the specified object.





$exportData – same as $filteredData, however in this case the objects will have additional properties to support easy display with properties processed as text.
$actionData – any object that was passed to Show-ListView using the -ActionData parameter. Useful when you need additional context that the Show-ListView command does not explicitly know about. It’s your custom data.
$formatProperty – the content of the –Property parameter when running the command.
$title – window title of the list view.
$infoTitle – info title of the list view.
$infoDescription – info title of the list view.
Show-ListView that are of the type based on location. Rules will provide more granular control and allow for rule-based conditions that determine action visibility.PagingWhenNotNeeded - hides paging when list is shorter than the page specified
AllActions - hides all actions (right-most ribbon panel)
NonSpecificActions - hides actions that are not specific to this view as specified by -ViewName (right-most ribbon panel)
StatusBar - hides status bar.














✓
✓
✓
✓
6.4
✓
✓
✓
✓
✓
-
6.3
✓
✓
✓
✓
-
-
6.2
✓
✓
✓
-
-
-
6.1
✓
✓
✓
-
-
-
6.0
✓
✓
✓
-
-
-
✓
✓
✓
✓
6.4
✓
✓
✓
✓
✓
✓
6.3
✓
✓
✓
✓
✓
✓
6.2
✓
✓
✓
✓
✓
✓
6.1
✓
✓
✓
✓
✓
✓
6.0
✓
✓
✓
✓
✓
✓
5.1
✓
✓
✓
✓
✓
✓
5.0
✓
✓
✓
✓
✓
✓
4.7
✓
✓
✓
✓
✓
–
4.6
✓
✓
✓
–
–
–
4.5
✓
✓
✓
–
–
–
4.4
✓
✓
✓
–
–
–
4.3
✓
✓
✓
–
–
–
4.2
✓
✓
✓
–
–
–
4.1
✓
✓
✓
–
–
–
4.0
✓
✓
–
–
–
–
N.X Remoting : SPE Remoting module for CI/CD - This provides a Windows PowerShell module for connecting to SPE remotely. Use in combination with the full or minimal packages.
SPE ↓ / Sitecore→
9.3
10.0
10.1
10.2
10.3
10.4
8.0
✓
✓
✓
✓
✓
✓
7.0
✓
SPE ↓ / Sitecore→
8.0
8.1
8.2
9.0
9.1
9.2
8.0
✓
✓
✓
✓
✓
✓
7.0
✓
✓
✓
The Sitecore is the heart of SPE's Sitecore integration. It exposes Sitecore databases as PowerShell drives.
Features:
Navigate Sitecore content trees using paths
Access items by ID, query, or URI
Support for language and version parameters
Filter by template and other properties
Example: Explore the CmsItemProvider.
The FileSystem provider allows interaction with the server's file system.
Example: Access file system from SPE.
Drives are the access points for providers. SPE creates drives for each Sitecore database.
Example: List all available drives.
Each Sitecore database drive has the following structure:
The root of each drive represents /sitecore in Sitecore paths.
Use cd or Set-Location to switch between drives and providers.
Example: Navigate between Sitecore databases.
Example: Navigate between providers.
When using the FileSystem provider, include the backslash (e.g., C:\) to access the root of the drive. Due to w3wp.exe behavior, cd C: may not behave as expected.
The Sitecore provider supports multiple path formats for flexibility.
Both forward and backward slashes work interchangeably:
Use relative paths when you're already in a specific location:
When using the Sitecore provider, cmdlets gain Sitecore-specific dynamic parameters:
Example: Using dynamic parameters.
The Sitecore provider exposes Sitecore item properties through PowerShell properties:
Example: Access item properties.
Common cmdlets work across all providers:
Get-Location / pwd
Show current location
Get-Location
Set-Location / cd
Change location
cd master:\content
Push-Location
Save location
Push-Location
Pop-Location
Restore location
Pop-Location
Example: Verify item existence.
Example: Conditional operations based on existence.
Get the full provider path for an item:
Example: Access provider path.
While rare, you can create custom drives:
Example: Create a drive pointing to a specific location.
Check what a provider can do:
Example: View provider capabilities.
Symptom: Parameters like -Language or -ID are not available.
Solution: Ensure you're specifying a database path:
Symptom: cd C: doesn't go to C:\ root.
Solution: Always include the backslash for FileSystem provider root:
Symptom: "Cannot find path" error.
Solution: Verify the item exists and the path is correct:
The Sitecore provider adds convenience but may have overhead for large operations:
Providers may cache data. If you're seeing stale data:
Variables - Built-in variables for paths
Retrieving Items - Finding items using providers
Best Practices - Performance optimization
Set-ItemProperty - PowerShell-standard cmdlet for property updates
BeginEdit/EndEdit - Explicit editing for multiple fields or special cases
BulkUpdateContext - High-performance updates for large datasets
The most convenient way to edit items is through SPE's automated properties. These properties automatically handle BeginEdit and EndEdit operations.
Example: Update a field using automated properties.
Example: Update a field with spaces in the name.
Example: Update system fields.
Example: Dynamically reference fields by variable.
The PowerShell-standard approach using Set-ItemProperty is also supported.
Example: Update a property using Set-ItemProperty.
For multiple field updates or special scenarios, use explicit BeginEdit and EndEdit calls.
Example: Update multiple fields in a single edit context.
Always match BeginEdit() with EndEdit(). If an error occurs between them, the item remains locked. Consider using try/finally blocks for safety.
Example: Safe edit context with error handling.
SPE provides intelligent handling for different Sitecore field types through automated properties.
DateTime fields automatically convert between Sitecore's string format and .NET DateTime objects.
Example: Read and write DateTime fields.
Image fields accept item references from the Media Library.
Example: Assign an image to an Image field.
Link fields accept item references and automatically create the link XML.
Example: Assign a content item to a GeneralLink field.
Multi-value fields (Multilist, Treelist, etc.) accept arrays of items.
Example: Assign multiple items to a list field.
Result in Content Editor:
Use the ._ or .PSFields property to access strongly-typed field objects.
Example: Access typed Image field properties.
Example: Access typed LinkField properties.
Output:
Example: Find all TextField instances on an item.
Updating a single field or a few fields
Readability is important
Working with small datasets
Example:
Updating many fields on a single item
Needing explicit control over save timing
Working with system properties (like BranchId)
Example:
Updating many items (hundreds or thousands)
Performance is critical
You need to bypass certain Sitecore events
Example:
Automated properties call BeginEdit/EndEdit on every assignment, which can impact performance when updating many fields. Use explicit BeginEdit/EndEdit for multiple updates on the same item.
SPE provides the New-UsingBlock function for working with Sitecore context switchers and disposable objects.
Example: Generate relative URL with site context.
Use these classes with New-UsingBlock for various scenarios:
Sitecore.SecurityModel.SecurityDisabler - Bypass security checks
Sitecore.Data.BulkUpdateContext - Optimize bulk updates
Sitecore.Globalization.LanguageSwitcher - Switch language context
Sitecore.Sites.SiteContextSwitcher - Switch site context
Sitecore.Data.DatabaseSwitcher - Switch database context
Sitecore.Security.Accounts.UserSwitcher - Switch user context
Sitecore.Data.Items.EditContext - Item editing context
Sitecore.Data.Proxies.ProxyDisabler - Disable proxies
Sitecore.Data.DatabaseCacheDisabler - Disable database cache
Sitecore.Data.Events.EventDisabler - Disable events
Example: Read items with security disabled (use with caution).
Example: Update items with events disabled.
Retrieving Items - Find items to edit
Best Practices - Performance optimization
Item Languages - Manage language versions
Appendix - Common Commands - Full cmdlet reference
Example: Create an item by specifying template name.
Output:
Example: Create an item using template ID.
By default, Sitecore generates a new GUID for each item. Use -ForceId to specify a custom ID.
Example: Create an item with a predefined ID.
Output:
Using -ForceId with an existing ID will cause an error. Only use this when migrating content or when you need a specific ID for integration purposes.
Instead of specifying the full path, you can pass a parent item using the -Parent parameter.
Example: Create a child item under a parent.
Output:
Use the -Language parameter to create items in specific language versions.
Example: Create an item with a specific language version.
Output:
Use the -StartWorkflow parameter to initiate the default workflow after item creation.
Example: Create an item and start its workflow.
After creating an item, you can immediately set field values.
Example: Create and populate an item.
Use Remove-Item to delete items. By default, items are moved to the Recycle Bin unless you specify -Permanently.
Example: Remove an item (sends to Recycle Bin).
Example: Remove an item permanently (bypasses Recycle Bin).
Using -Permanently cannot be undone. Items are deleted from the database immediately. Use with extreme caution, especially in production environments.
Example: Remove items from pipeline.
Example: Remove multiple items matching criteria.
Both New-Item and Remove-Item support dynamic parameters when working with Sitecore paths:
ForceId
New-Item
Forces specific GUID for new item
-ForceId "{GUID}"
Language
New-Item
Creates item in specific language
-Language "en-CA"
Parent
New-Item
Specifies parent item
When creating items, Sitecore applies item naming rules:
Alphanumeric characters (a-z, A-Z, 0-9)
Hyphens and underscores (-, _)
Spaces (converted to hyphens in URLs)
Sitecore automatically filters or replaces these characters:
Forward slash (/)
Backslash ()
Question mark (?)
Hash (#)
Colon (:)
Semicolon (;)
Brackets ([, ])
Example: Create items with special character handling.
Always handle potential errors when creating or removing items.
Batch operations - Create or remove many items in a single script execution
Use BulkUpdateContext - When creating many items with field values
Use SecurityDisabler - If creating items programmatically (no user context needed)
Disable events - For large migrations where events aren't needed
Progress reporting - Always provide feedback for long-running operations
Example: Optimized bulk creation.
Retrieving Items - Find items to work with
Editing Items - Update item properties
Moving and Copying Items - Transfer items
Best Practices - Performance optimization
- Full cmdlet reference
AND provide additional authentication or confirmation
This protects against:
Hijacked sessions being used to execute malicious scripts
Accidental execution of dangerous operations
Unauthorized access when a user leaves their workstation unlocked
Session Elevation consists of three key components:
Entry points where scripts enter Sitecore through built-in interfaces.
Built-in Gates:
Console - PowerShell Console application
ISE - Integrated Scripting Environment
ItemSave - Saving PowerShell script items in Content Editor
Each gate can reference a token that controls its elevation requirements.
Configuration objects that define elevation behavior and session lifetime.
Token Attributes:
name
Unique identifier referenced by gates
String (e.g., "Console", "ISE")
expiration
How long an elevated session lasts
Timespan (hh:mm:ss)
elevationAction
What happens when elevation is needed
Allow, Block, Password, Confirm
The behavior when a user attempts to access a gate without an active elevated session.
Use Case: Development environments only
Always allows access without prompting. The session runs elevated immediately.
Never use Allow in production! This completely disables session elevation and should only be used on local development machines.
Use Case: Completely disable a feature
Always blocks access. The gate cannot be used at all.
When to use:
Disable the Console entirely in production
Prevent script editing via Content Editor
Lock down specific gates for security compliance
Use Case: Standard authentication (recommended for most environments)
Prompts the user to enter their password to elevate the session.
How it works:
User attempts to access the Console/ISE
If no elevated session exists or it has expired, a password prompt appears
User enters their Sitecore password
Upon successful authentication, session is elevated for the expiration duration
During the expiration window, no further prompts appear
Best for:
Standard Sitecore authentication
Production environments
QA and staging environments
Environments with local user accounts
Use Case: Single Sign-On (SSO) and federated authentication
Prompts the user to confirm (click a button) to elevate the session. No password is entered.
When to use:
Azure AD authentication
ADFS/SAML authentication
Any SSO provider where password re-entry isn't possible
Identity Server configurations
Why Confirm instead of Password: When using federated authentication, users don't have a password stored in Sitecore. The Confirm action provides a "speed bump" to prevent accidental operations without requiring credentials that don't exist.
When accessing the Console without an elevated session:
Password prompt appears (if using Password action)
Enter credentials to elevate
Console becomes accessible for the token expiration duration
Before Elevation:
The ISE displays a warning banner:
After Elevation:
The warning changes to show the session is elevated with a "Drop" option:
Users can manually drop the elevated session if they finish working early.
Before Elevation:
When editing PowerShell Module, Script Library, or Script items, sensitive fields are hidden and a warning appears:
Click "Elevate session" to authenticate and reveal the fields.
After Elevation:
Fields become editable with an option to drop the session:
Relaxed settings for local development:
Strict settings with password requirement:
Settings for federated authentication:
Lock down the Console while allowing ISE access:
Multiple gates can share the same token. When a user elevates through one gate, all gates sharing that token are also elevated.
Example: Share a single token across all gates:
Each gate can have its own token for fine-grained control:
Development
30-60 minutes
Minimize interruptions during active development
QA/Staging
10-15 minutes
Balance security with testing needs
Production
3-5 minutes
Maximum security, minimal exposure window
Local Dev
Allow
Convenience for solo developers
Shared Dev
Password
Prevent unauthorized access
QA/Staging
Password
Match production security
Production (Standard Auth)
Password
✅ Do:
Use short expiration times in production (5 minutes or less)
Require Password or Confirm in all non-dev environments
Test your configuration in each environment
Train users on the "Drop session" functionality
Document your elevation strategy
❌ Don't:
Use Allow in production
Set expiration times longer than 15 minutes in production
Forget to configure all three gates (Console, ISE, ItemSave)
Ignore the difference between Password and Confirm for SSO
Possible causes:
Token elevationAction is set to Allow
Gate is not configured to use a token
Configuration patch is not being applied
Solution: Verify configuration and check Sitecore logs.
Cause: Configuration shows Password instead of Confirm.
Solution: Change to elevationAction="Confirm" for SSO environments.
Cause: Expiration time is too short.
Solution: Increase the expiration attribute (but keep it under 15 minutes in production).
Cause: Session elevation is set to Block or user doesn't complete elevation.
Solution: Check configuration and verify elevation action is appropriate.
Configure Web Services Security for external access
Learn about Delegated Access for controlled privilege escalation
Review User and Role Management
Complete the Security Checklist
Risk: Users have more permissions than needed
Violates principle of least privilege
With Delegated Access:
Users keep limited permissions
Specific scripts run with elevated permissions
All actions are logged with both user identities
Scenario: Content authors need to publish items but shouldn't have global publish rights.
Solution: Create a script that publishes specific items, configured to run as an administrator via delegated access.
Scenario: Managers need to run reports that query all items, but they have limited content access.
Solution: Configure the report script to impersonate an administrator, allowing full content access for the report only.
Scenario: A user needs to perform bulk updates on items they normally can't modify.
Solution: Create a controlled script with delegated access that performs the specific operation.
Scenario: Users need to trigger workflow commands that require elevated permissions.
Solution: Workflow scripts run with delegated access to perform administrative actions.
Delegated Access Item - Configuration item that defines the delegation
Requester Role - Sitecore role containing lower-privileged users
Impersonated User - Power user account whose permissions are used
Delegated Scripts - Specific scripts that run with elevated permissions
Navigate in Content Editor to where delegated access configurations are stored and use the insert option.
Enter the role that contains the lower-privileged users who should have delegated access.
Field: Requester Role
Example Values:
sitecore\Elevated Unlock - Custom role for editors
Why use roles instead of users?
Easier to manage
Follows role-based access control (RBAC) best practices
Changes apply to all role members automatically
Enter the user account whose permissions will be used when scripts execute.
Field: Impersonated User
Example Values:
sitecore\Admin - Full administrative access
sitecore\PowerUser - Custom account with specific elevated permissions
Security Consideration: The impersonated user should have the minimum permissions needed for the delegated scripts. Don't always use sitecore\Admin - create dedicated service accounts with specific permissions instead.
Choose which scripts and libraries should run with delegated access and ensure the appropriate rules are configured.
See the Security Management script module for more examples:
/sitecore/system/Modules/PowerShell/Script Library/SPE/Tools/Security Management
What to include:
Scripts that should run with elevated permissions
Script libraries containing those scripts
Scripts with rules that check for delegated access
Multilist Field: Select from available PowerShell scripts and script libraries.
Check the "Enabled" field to activate the delegated access configuration.
Field: Enabled (checkbox)
Important: Test thoroughly before enabling in production. Delegated access grants powerful permissions to lower-privileged users.
All delegated access operations are logged to the SPE log file.
Log Entry Format:
Log Components:
Timestamp: When the script executed
Script ID: Unique identifier for the script
Context User: The actual logged-in user
Impersonated User: The elevated account used for execution
Regular log review should include:
✅ Monitor for:
Unexpected impersonation attempts
Scripts running as admin that shouldn't
Failed delegated access attempts
Unusual patterns (same user repeatedly, odd times)
Example log analysis query:
✅ Do:
Use dedicated service accounts instead of sitecore\Admin when possible
Limit delegated scripts to specific, necessary operations
Regularly audit who has delegated access (review role membership)
Monitor SPE logs for delegated access usage
Test delegated access configurations in non-production first
Document why each delegated access configuration exists
Use confirmation dialogs in delegated scripts for destructive operations
Implement input validation in all delegated scripts
Set appropriate item-level security on delegated access items
❌ Don't:
Grant delegated access to broad roles like "Everyone"
Always impersonate sitecore\Admin - use least privilege
Allow arbitrary code execution in delegated scripts
Forget to enable logging in delegated scripts
Skip user confirmations for destructive operations
Create delegated access "just in case" - only when needed
Allow users to modify delegated access configurations
Delegate scripts that can modify security or create users
Impersonated User
Dedicated service account
Easier to audit, limited permissions
Requester Role
Specific, narrow role
Limits who can use delegation
Script Scope
Single, focused operation
Reduces risk of abuse
Logging
Always log delegated actions
Audit trail for compliance
When writing scripts for delegated access:
Validate All Input:
Limit Scope:
Confirm Destructive Operations:
Log Actions:
Possible causes:
Delegated access item is not enabled
User is not in the requester role
Script is not selected in the delegated scripts field
Script library containing the script is not selected or enabled.
Solution: Verify all configuration fields and ensure the user is in the correct role.
Cause: Script or script library not included in delegated scripts selection.
Solution: Add both the script AND its parent library to the delegated scripts field.
Cause: Insert options not configured or user lacks permissions.
Solution: Verify insert options are configured on the parent item and user has write access.
Cause: Impersonated user account lacks necessary Sitecore permissions.
Solution: Grant the impersonated user account the required Sitecore roles and item permissions.
Privilege Escalation Abuse
Limit scripts to specific operations, validate input
Over-Privileged Impersonation
Use dedicated accounts with minimal required permissions
Broad Role Assignment
Only grant delegated access to specific, trusted roles
Script Modification
Protect script items with item-level security
Logging Gaps
Ensure all delegated operations are logged
Layer multiple security controls:
Role Membership - Only trusted users in requester role
Script Security - Item-level security on delegated scripts
Input Validation - Scripts validate and limit operations
Confirmations - User must confirm destructive actions
Logging - All operations logged
Auditing - Regular log review
Least Privilege - Impersonated users have minimum permissions
Security Policies - Understand SPE security model
Session Elevation - Additional authentication layer
User and Role Management - Managing Sitecore roles
Logging and Monitoring - Audit delegated access usage
GitHub Issue #1283 - Feature introduction


This page covers how to manage item-level security using SPE, including access control lists (ACLs), item locking, and protection.
Sitecore's security model controls who can access items through Access Control Lists (ACLs). SPE provides cmdlets to programmatically manage these security settings, enabling bulk security operations and automated security configuration.
The Sitecore API utilizes a combination of parameters to represent an AccessRule. The following tables outline possible values for each parameter.
Common access rights you can grant or deny:
Control how access rules propagate through the content tree:
Example: The sitecore\Author role allowed access to read the item.
Example: The sitecore\Author role denied access to read the item descendants.
Example: Security rights for the parent item are not passed to the child items. Inheritance to descendants are denied for the sitecore\Author role.
Example: The sitecore\Developer role is allowed access to read the item and descendants.
Use Get-Command to discover all security-related commands:
ACLs define which users and roles have what permissions on items. SPE provides commands to create, read, and modify ACLs programmatically.
Example: View current security settings on an item.
Output:
Example: Get detailed ACL information.
Output:
Use New-ItemAcl to create new access rules that can be applied to items.
Example: Create an ACL granting read access to Developers.
Example: Create an ACL denying inheritance.
Use Add-ItemAcl to apply access rules to items.
Example: Apply an ACL to an item.
Example: Grant role-specific access.
Output:
Use Set-ItemAcl to replace existing access rules.
Example: Replace all access rules on an item.
Use Clear-ItemAcl to remove access rules from items.
Example: Clear all custom access rules.
Use Test-ItemAcl to check if a user has specific rights on an item.
Example: Test if a role can read an item.
Prevent other users from editing items by locking them.
Example: Lock an item for editing.
Example: Lock items in bulk.
Example: Unlock an item.
Example: Unlock all items in a tree.
Example: Check if an item is locked.
Protect items from accidental deletion or modification.
Example: Protect an item from deletion.
Example: Protect critical content.
Example: Remove item protection.
Example: Unprotect items in bulk.
Use roles over individual users - Assign permissions to roles, then add users to roles
Apply security at parent level - Use propagation to apply security to entire trees
Document security decisions - Keep records of why security was applied
Regular security audits - Periodically review who has access to what
- Managing users and roles
- Update item properties
- Performance and security patterns
- Full security cmdlet reference

Learn PowerShell command syntax, pipelines, and essential commands.
foreach($item in $selectedData){
# Run Sheer application on Desktop
Show-Application `
-Application "Content Editor" `
-Parameter @{id ="$($item.ID)"; fo="$($item.ID)";
la="$($item.Language.Name)"; vs="$($item.Version.Number)";
sc_content="$($item.Database.Name)"}
}Get-ChildItem master:\ | Show-ListView -ViewName ListChildrenGet-ChildItem master:\ | Show-ListView -ViewName ListChildren -Property Name, ProviderPathGet-ChildItem master:\ | Show-ListView -Property Name, ProviderPathfor($i = 0; $i -le 10; $i++){
Write-Progress -Activity "I need to do something important for 5 seconds" `
-Status "I'm quite on track..." `
-PercentComplete ($i*10) -SecondsRemaining (5-$i/2) `
-CurrentOperation "Trying to look busy.";
Start-Sleep -m 500
}
Write-Progress -Activity "Now I'm doing something else..." `
-Status "Should take me about 3 seconds but I'm not quite sure...";
Start-Sleep -s 3;
for($i = 0; $i -le 10; $i++){
Write-Progress -Activity "Ok let me revisit one more thing..." `
-Status "Just 5 more seconds" `
-PercentComplete ($i*10) -SecondsRemaining (5-$i/2) `
-CurrentOperation "Just making sure.";
Start-Sleep -m 500;
}
Write-Progress -Completed -Activity "Done."Get-ChildItem master:\ |
Show-ListView `
-Hide AllActions, AllExport, Filter, PagingWhenNotNeeded, StatusBar `
-Property Name, DisplayName, ProviderPath, __Updated, "__Updated By"Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Registry ShouldProcess, Transactions {HKLM, HKCU}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C}
Function ShouldProcess {Function}
Variable ShouldProcess {Variable}
Certificate ShouldProcess {Cert}
WSMan Credentials {WSMan}
Sitecore Filter, ExpandWildcards, ShouldProcess {master, web, core}Get-PSProvider -PSProvider Sitecore
Name Capabilities Drives
---- ------------ ------
Sitecore Filter, ExpandWildcards, ShouldProcess {master, web, core}# List files in the Data folder
Get-ChildItem -Path "$SitecoreDataFolder\logs"
# Read a log file
Get-Content -Path "$SitecoreLogFolder\log.txt" -Tail 50
# Create a temp file
New-Item -Path "$SitecoreTempFolder\myfile.txt" -ItemType File -Value "Content"Get-PSDrive
ame Used (GB) Free (GB) Provider Root CurrentLocation
---- --------- --------- -------- ---- ---------------
Alias Alias
C 0.42 126.46 FileSystem C:\ windows\system32\inetsrv
Cert Certificate \
core Sitecore core:
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
master Sitecore master: content\Home
Variable Variable
web Sitecore web:
WSMan WSManmaster:\
├── content\
├── layout\
├── media library\
├── system\
└── templates\# Start in master
PS master:\>
# Switch to core database
PS master:\> cd core:
PS core:\>
# Switch to web database
PS core:\> cd web:
PS web:\>
# Return to master
PS web:\> Set-Location -Path master:
PS master:\># Switch to file system
PS master:\> cd C:\
PS C:\>
# Return to master database
PS C:\> cd master:
PS master:\>Get-Item -Path "master:\content\home"Get-Item -Path "master:/sitecore/content/home"Get-Item -Path "master:\content/home"
Get-Item -Path "master:/content\home"PS master:\content> Get-Item -Path ".\home"
PS master:\content> cd home
PS master:\content\home> Get-Item -Path ".." # Returns parent (\content)# Language parameter (only available with Sitecore provider)
Get-Item -Path "master:\content\home" -Language "da"
# ID parameter (only available with Sitecore provider)
Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
# Query parameter (only available with Sitecore provider)
Get-Item -Path "master:" -Query "/sitecore/content//*[@@templatename='Sample Item']"$item = Get-Item -Path "master:\content\home"
# Standard properties
$item.Name
$item.ID
$item.TemplateName
$item.ItemPath
$item.Language
$item.Version
# Field values
$item.Title
$item.Text
$item.__Created
$item.__Updated$databases = @("master", "core", "web")
foreach($db in $databases) {
$itemCount = (Get-ChildItem -Path "$($db):\content" -Recurse).Count
Write-Host "$db database: $itemCount items"
}$masterItem = Get-Item -Path "master:\content\home"
$webItem = Get-Item -Path "web:\content\home"
if ($masterItem.__Updated -gt $webItem.__Updated) {
Write-Host "Master is newer than Web"
} else {
Write-Host "Web is up to date"
}# Export items to file system
$items = Get-ChildItem -Path "master:\content\home" -Recurse
$report = $items | Select-Object Name, Template Name, ItemPath
$report | Export-Csv -Path "C:\reports\items.csv" -NoTypeInformation
# Read configuration files
$configPath = Join-Path $SitecoreDataFolder "serialization\config"
Get-ChildItem -Path $configPath -Filter "*.yml"# Save current location
Push-Location
# Do work in another location
cd "master:\templates"
# ... perform operations ...
# Return to previous location
Pop-Location# Export Sitecore items to JSON files
$items = Get-ChildItem -Path "master:\content\data" -Recurse
foreach($item in $items) {
$data = [PSCustomObject]@{
Name = $item.Name
ID = $item.ID
Template = $item.TemplateName
Title = $item.Title
Text = $item.Text
}
$fileName = "$($item.ID).json"
$filePath = Join-Path $SitecoreTempFolder $fileName
$data | ConvertTo-Json | Set-Content -Path $filePath
Write-Host "Exported: $fileName"
}if (Test-Path "master:\content\home") {
Write-Host "Item exists"
$item = Get-Item -Path "master:\content\home"
} else {
Write-Host "Item not found"
}$targetPath = "master:\content\import"
if (-not (Test-Path $targetPath)) {
New-Item -Path "master:\content" -Name "import" -ItemType "Common/Folder"
Write-Host "Created import folder"
}
# Now safe to use
$importFolder = Get-Item -Path $targetPath$item = Get-Item -Path "master:\content\home"
$item.ProviderPath
# master:\content\homeNew-PSDrive -Name "content" -PSProvider Sitecore -Root "master:\content"
# Now you can use:
Get-Item -Path "content:\home"(Get-PSProvider -PSProvider Sitecore).Capabilities
# Filter, ExpandWildcards, ShouldProcess# WRONG - no database specified
Get-Item -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
# CORRECT - database specified
Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"# WRONG
cd C:
# CORRECT
cd C:\# Check if path exists
if (Test-Path "master:\content\home") {
$item = Get-Item -Path "master:\content\home"
} else {
Write-Host "Path not found. Check spelling and database."
}# Provider-based (convenient)
$items = Get-ChildItem -Path "master:\content" -Recurse
# Direct API (faster for large datasets)
$db = Get-Database -Name "master"
$root = $db.GetItem("/sitecore/content")
$items = $root.Axes.GetDescendants() | Initialize-Item# Clear caches
$db = Get-Database -Name "master"
$db.Caches.ItemCache.Clear()
$db.Caches.DataCache.Clear()$item = Get-Item -Path "master:\content\home"
$item.Title = "New Title"$item = Get-Item -Path "master:\content\home"
$item."Closing Date" = [datetime]::Today$item = Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
$item."__Display name" = "Custom Display Name"$item = Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
$fieldName = "Title"
# All variations work
Write-Host ($item.$fieldName)
Write-Host ($item."$fieldName")
Write-Host ($item."$($fieldName)")
# To update (all variations work)
$item.$fieldName = "New Value"Set-ItemProperty -Path "master:\content\home" -Name "Title" -Value "New Title"$item = Get-Item -Path "master:\content\home"
$item.Editing.BeginEdit()
$item["Title"] = "New Title"
$item["Text"] = "New text content"
$item.BranchId = [Guid]::Empty
$item.Editing.EndEdit()$item = Get-Item -Path "master:\content\home"
$item.Editing.BeginEdit()
try {
$item["Title"] = "New Title"
$item["Text"] = "New text content"
$item.Editing.EndEdit()
} catch {
$item.Editing.CancelEdit()
throw
}$item = Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
# Read returns System.DateTime
$item.__Created
# Monday, April 07, 2008 1:59:00 PM
# Write accepts System.DateTime
$item.__Created = [DateTime]::Now
$item.__Created
# Tuesday, March 17, 2020 12:00:00 PM$homeItem = Get-Item -Path "master:\content\home"
$homeItem.Image = Get-Item -Path "master:\media library\logo"$homeItem = Get-Item -Path "master:\content\home"
$homeItem.GeneralLink = Get-Item -Path "master:\content\home\about-us"$homeItem = Get-Item -Path "master:\content\home"
$homeItem.ItemList = Get-ChildItem -Path "master:\content\home"$item = Get-Item -Path "master:\content\home"
$item._.Image.Alt # Access Alt property
$item._.Image.Width # Access Width property
$item._.Image.Height # Access Height property$currentItem = Get-Item -Path "master:\content\home\sample-item"
$linkField = $currentItem.PSFields."LinkFieldName"
# Access all LinkField properties
$linkField.Anchor
$linkField.IsInternal
$linkField.LinkType
$linkField.TargetID
$linkField.TargetItem
$linkField.Text
$linkField.UrlAnchor :
Class :
InternalPath : /sitecore/content/home/sample-item/
IsInternal : True
IsMediaLink : False
LinkType : internal
MediaPath :
QueryString :
Target :
TargetID : {263293D3-B1B3-4C2C-9A75-6BD418F376BC}
TargetItem : Sitecore.Data.Items.Item
Text : CLICK HERE
Title :
Url :$item = Get-Item -Path "master:\content\home"
foreach($field in $item.Fields) {
$typedField = $item.PSFields."$($field.Name)"
if ($typedField -is [Sitecore.Data.Fields.TextField]) {
Write-Host "$($field.Name): $($typedField.Value)"
}
}Get-ChildItem -Path "master:\content\home" |
ForEach-Object {
$_.Title = "Updated: $($_.Name)"
}$item = Get-Item -Path "master:\content\home"
$item.Editing.BeginEdit()
$item["Title"] = "Sample Item"
$item["Text"] = "Sample Text"
$item["Date"] = [datetime]::Now.ToString("yyyyMMddTHHmmss")
$item.BranchId = [Guid]::Empty
$item.Editing.EndEdit()New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
foreach($item in Get-ChildItem -Path "master:\content\home" -Recurse) {
$item.Editing.BeginEdit()
$item["Title"] = "Sample Item"
$item["Text"] = "Sample Item"
$item.Editing.EndEdit() > $null
}
}$items = Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" }
New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
foreach($item in $items) {
$item.Editing.BeginEdit()
$item["Title"] = "Updated Title"
$item["Text"] = "Updated Text"
$item.Editing.EndEdit() > $null
}
}$items = Get-ChildItem -Path "master:\content\home" -Recurse
$total = $items.Count
$current = 0
foreach($item in $items) {
$current++
Write-Progress -Activity "Updating items" -Status "Processing $($item.Name)" `
-PercentComplete (($current / $total) * 100)
$item.Title = "Updated: $($item.Name)"
}
Write-Progress -Activity "Updating items" -CompletedGet-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" -and [string]::IsNullOrEmpty($_.Title) } |
ForEach-Object {
$_.Title = $_.Name # Use item name as title if title is empty
}$data = Import-Csv "$($SitecoreDataFolder)\import\updates.csv"
foreach($row in $data) {
$item = Get-Item -Path "master:" -ID $row.ItemId
if ($item) {
$item.Title = $row.Title
$item.Text = $row.Text
}
}$site = [Sitecore.Sites.SiteContextFactory]::GetSiteContext("usa")
$relativeUrl = New-UsingBlock (New-Object Sitecore.Sites.SiteContextSwitcher $site) {
$pageItem = Get-Item -Path "master:" -Id "{50BE527C-7241-4613-A7A9-20D0217B264B}"
[Sitecore.Links.LinkManager]::GetItemUrl($pageItem)
}New-UsingBlock (New-Object Sitecore.SecurityModel.SecurityDisabler) {
$items = Get-ChildItem -Path "master:\content" -Recurse
# Process items without security checks
}New-UsingBlock (New-Object Sitecore.Data.Events.EventDisabler) {
foreach($item in $itemsToUpdate) {
$item.Title = "Updated"
}
}$item = Get-Item -Path "master:\content\home" -Language "en-US"
$item.Title = "English Title"
$itemDanish = Get-Item -Path "master:\content\home" -Language "da"
$itemDanish.Title = "Danish Title"$item = Get-Item -Path "master:\content\home" -Language "en-US" -Version 2
$item.Title = "Updated Version 2"$sourceItem = Get-Item -Path "master:\content\source"
$targetItem = Get-Item -Path "master:\content\target"
$targetItem.Editing.BeginEdit()
foreach($field in $sourceItem.Fields) {
if (-not $field.Name.StartsWith("__")) { # Skip system fields
$targetItem[$field.Name] = $sourceItem[$field.Name]
}
}
$targetItem.Editing.EndEdit()$template = Get-Item -Path "master:\templates\Sample\Sample Item"
$standardValues = Get-Item -Path "$($template.ProviderPath)\__Standard Values"
$standardValues.Title = "Default Title"# Inefficient - calls BeginEdit/EndEdit for each field
foreach($item in $items) {
$item.Title = "Title" # BeginEdit/EndEdit
$item.Text = "Text" # BeginEdit/EndEdit
$item.Date = [datetime]::Now # BeginEdit/EndEdit
}# Efficient - single BeginEdit/EndEdit per item
foreach($item in $items) {
$item.Editing.BeginEdit()
$item["Title"] = "Title"
$item["Text"] = "Text"
$item["Date"] = [Sitecore.DateUtil]::ToIsoDate([datetime]::Now)
$item.Editing.EndEdit()
}# Most efficient for bulk operations
New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
foreach($item in $items) {
$item.Editing.BeginEdit()
$item["Title"] = "Title"
$item["Text"] = "Text"
$item.Editing.EndEdit() > $null
}
}# BAD - item remains locked if error occurs
$item.Editing.BeginEdit()
$item["Title"] = "New Title" # If this throws, EndEdit never called
$item.Editing.EndEdit()# GOOD - use try/finally
$item.Editing.BeginEdit()
try {
$item["Title"] = "New Title"
$item.Editing.EndEdit()
} catch {
$item.Editing.CancelEdit()
throw
}# Be careful with system fields - some should not be modified
$item."__Updated" = [DateTime]::Now # OK - updating audit field
$item."__Updated by" = "sitecore\admin" # OK - updating audit field
# Avoid modifying these unless you know what you're doing:
# $item."__Revision"
# $item."__Created"
# $item."__Created by"# BAD - throws error if item doesn't exist
$item = Get-Item -Path "master:\content\missing"
$item.Title = "New Title"# GOOD - check for existence
$item = Get-Item -Path "master:\content\maybe-exists" -ErrorAction SilentlyContinue
if ($item) {
$item.Title = "New Title"
}$itemPath = "master:\content\home\Sample Item 3"
New-Item -Path $itemPath -ItemType "Sample/Sample Item"
Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Sample Item 3 False en 1 {29A68114-5137-4A46-A87C-3789B8D898FB} Sample Item$itemPath = "master:\content\home\Sample Item 4"
$templateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
New-Item -Path $itemPath -ItemType $templateId$itemPath = "master:\content\home\Sample Item 5"
$templateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
$itemId = "{9459ADDD-4471-4ED3-A041-D33E559BD321}"
New-Item -Path $itemPath -ItemType $templateId -ForceId $itemId
Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Sample Item 5 False en 1 {9459ADDD-4471-4ED3-A041-D33E559BD321} Sample Item$templateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
$parentItem = Get-Item -Path "master:" -ID "{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}"
New-Item -Parent $parentItem -Name "Sample Item 6" -ItemType $templateId
Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Sample Item 6 False en 1 {E7A73426-B9BB-4056-A15C-2E835796A4DD} Sample Item$itemPath = "master:\content\home\Sample Item 7"
New-Item -Path $itemPath -ItemType "Sample/Sample Item" -Language "en-CA"
Name Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Sample Item 7 False en-CA 1 {5303A55C-5853-409D-AFC8-0DF04F4C1065} Sample Item$itemPath = "master:\content\home\Sample Item 8"
New-Item -Path $itemPath -ItemType "Sample/Sample Item" -StartWorkflow$item = New-Item -Path "master:\content\home\demo" -Name "New Page" -ItemType "Sample/Sample Item"
$item.Title = "Welcome to Our Site"
$item.Text = "This is the page content"
$item."Meta Description" = "SEO description for this page"# Assumes you uploaded a file to a folder on the server hosting Sitecore
$data = Import-Csv "$($SitecoreDataFolder)\import\pages.csv"
$parentPath = "master:\content\home"
$templateId = "{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"
foreach($row in $data) {
$item = New-Item -Parent (Get-Item $parentPath) -Name $row.Name -ItemType $templateId
$item.Title = $row.Title
$item.Text = $row.Text
}$itemsToCreate = @("Page 1", "Page 2", "Page 3", "Page 4", "Page 5")
$total = $itemsToCreate.Count
$current = 0
foreach($name in $itemsToCreate) {
$current++
Write-Progress -Activity "Creating items" -Status "Creating $name" `
-PercentComplete (($current / $total) * 100)
New-Item -Path "master:\content\home" -Name $name -ItemType "Sample/Sample Item"
}
Write-Progress -Activity "Creating items" -Completed$structure = @{
"Products" = @("Category A", "Category B", "Category C")
"Services" = @("Consulting", "Training", "Support")
"About" = @("Team", "History", "Contact")
}
foreach($section in $structure.Keys) {
$sectionItem = New-Item -Path "master:\content\home" -Name $section -ItemType "Common/Folder"
foreach($page in $structure[$section]) {
New-Item -Parent $sectionItem -Name $page -ItemType "Sample/Sample Item"
}
}$json = Get-Content "$($SitecoreDataFolder)\import\structure.json" | ConvertFrom-Json
foreach($item in $json.items) {
$newItem = New-Item -Path "master:\content\home" -Name $item.name -ItemType $item.template
$newItem.Title = $item.title
$newItem.Text = $item.text
}Remove-Item -Path "master:\content\home\Sample Item 3"Remove-Item -Path "master:\content\home\Sample Item 3" -PermanentlyGet-Item -Path "master:\content\home\delete-me" | Remove-ItemGet-ChildItem -Path "master:\content\temp" -Recurse |
Where-Object { $_.Name -like "Test*" } |
Remove-Item$cutoffDate = (Get-Date).AddYears(-2)
Get-ChildItem -Path "master:\content\archive" -Recurse |
Where-Object { $_.__Created -lt $cutoffDate } |
Remove-Item -PermanentlyGet-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Temporary Item" } |
Remove-ItemGet-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Folder" -and -not $_.HasChildren } |
Remove-Item$itemsToRemove = Get-ChildItem -Path "master:\content\home\temp" -Recurse
foreach($item in $itemsToRemove) {
$response = Show-Confirm -Title "Remove $($item.ItemPath)?"
if ($response -eq 'yes') {
Remove-Item -Path $item.ProviderPath
Write-Host "Removed: $($item.ItemPath)" -ForegroundColor Green
}
}$itemsToRemove = Get-ChildItem -Path "master:\content\temp" -Recurse
$report = @()
foreach($item in $itemsToRemove) {
try {
Remove-Item -Path $item.ProviderPath -Permanently
$report += [PSCustomObject]@{
ItemPath = $item.ItemPath
Status = "Deleted"
Error = ""
}
} catch {
$report += [PSCustomObject]@{
ItemPath = $item.ItemPath
Status = "Failed"
Error = $_.Exception.Message
}
}
}
New-Item -Path "$($SitecoreDataFolder)\export" -ItemType Directory -Force
$report | Export-Csv "$($SitecoreDataFolder)\export\deletion-report.csv" -NoTypeInformation$name = [Sitecore.Data.Items.ItemUtil]::ProposeValidItemName('Page: About Us')
# These names will be automatically cleaned
New-Item -Path "master:\content\home" -Name $name -ItemType "Sample/Sample Item"
# Results in item name: "Page About Us" or similar$name = [Sitecore.Data.Items.ItemUtil]::ProposeValidItemName('Page: About Us')
# Use Display Name for formatted names
$item = New-Item -Path "master:\content\home" -Name "page-about-us" -ItemType "Sample/Sample Item"
$item."__Display name" = $nametry {
$item = New-Item -Path "master:\content\home\new-page" -Name "New Page" -ItemType "Sample/Sample Item" -ErrorAction Stop
Write-Host "Created: $($item.ItemPath)" -ForegroundColor Green
} catch {
Write-Host "Error creating item: $($_.Exception.Message)" -ForegroundColor Red -BackgroundColor White
}$results = @()
foreach($name in $itemNames) {
try {
$item = New-Item -Path "master:\content\home" -Name $name -ItemType "Sample/Sample Item" -ErrorAction Stop
$results += [PSCustomObject]@{
Name = $name
Status = "Success"
ItemId = $item.ID
Error = ""
}
} catch {
$results += [PSCustomObject]@{
Name = $name
Status = "Failed"
ItemId = ""
Error = $_.Exception.Message
}
}
}
New-Item -Path "$($SitecoreDataFolder)\export" -ItemType Directory -Force
$results | Export-Csv "$($SitecoreDataFolder)\export\creation-results.csv" -NoTypeInformation$largeDataset = @(
[PSCustomObject]@{"Name"="BulkItem1";"Template"="Sample/Sample Item";"Title"="BulkItem1 Title";"Text"="BulkItem1 Text";},
[PSCustomObject]@{"Name"="BulkItem2";"Template"="Sample/Sample Item";"Title"="BulkItem2 Title";"Text"="BulkItem2 Text";},
[PSCustomObject]@{"Name"="BulkItem3";"Template"="Sample/Sample Item";"Title"="BulkItem3 Title";"Text"="BulkItem3 Text";}
)
New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
New-UsingBlock (New-Object Sitecore.Data.Events.EventDisabler) {
foreach($data in $largeDataset) {
$item = New-Item -Path "master:\content\home" -Name $data.Name -ItemType $data.Template
$item.Editing.BeginEdit()
$item["Title"] = $data.Title
$item["Text"] = $data.Text
$item.Editing.EndEdit() > $null
}
}
}
# Clear all the caches may be required if working in the Content Editor
# [Sitecore.Caching.CacheManager]::ClearAllCaches()<token name="Console">
<patch:attribute name="elevationAction">Allow</patch:attribute>
</token><token name="Console">
<patch:attribute name="elevationAction">Block</patch:attribute>
</token><token name="Console">
<patch:attribute name="elevationAction">Password</patch:attribute>
<patch:attribute name="expiration">00:05:00</patch:attribute>
</token><token name="Console">
<patch:attribute name="elevationAction">Confirm</patch:attribute>
<patch:attribute name="expiration">00:05:00</patch:attribute>
</token><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<userAccountControl>
<tokens>
<token name="Console">
<patch:attribute name="expiration">01:00:00</patch:attribute>
<patch:attribute name="elevationAction">Allow</patch:attribute>
</token>
<token name="ISE">
<patch:attribute name="expiration">01:00:00</patch:attribute>
<patch:attribute name="elevationAction">Allow</patch:attribute>
</token>
<token name="ItemSave">
<patch:attribute name="expiration">01:00:00</patch:attribute>
<patch:attribute name="elevationAction">Allow</patch:attribute>
</token>
</tokens>
</userAccountControl>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<userAccountControl>
<tokens>
<token name="Console">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ISE">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ItemSave">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
</tokens>
</userAccountControl>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<userAccountControl>
<tokens>
<token name="Console">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Confirm</patch:attribute>
</token>
<token name="ISE">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Confirm</patch:attribute>
</token>
<token name="ItemSave">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Confirm</patch:attribute>
</token>
</tokens>
</userAccountControl>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<userAccountControl>
<tokens>
<token name="Console">
<patch:attribute name="elevationAction">Block</patch:attribute>
</token>
<token name="ISE">
<patch:attribute name="expiration">00:10:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ItemSave">
<patch:attribute name="expiration">00:10:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
</tokens>
</userAccountControl>
</powershell>
</sitecore>
</configuration><userAccountControl>
<gates>
<gate name="Console" token="SharedToken" />
<gate name="ISE" token="SharedToken" />
<gate name="ItemSave" token="SharedToken" />
</gates>
<tokens>
<token name="SharedToken">
<patch:attribute name="expiration">00:10:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
</tokens>
</userAccountControl><userAccountControl>
<gates>
<gate name="Console" token="ConsoleToken" />
<gate name="ISE" token="ISEToken" />
<gate name="ItemSave" token="ItemSaveToken" />
</gates>
<tokens>
<token name="ConsoleToken">
<patch:attribute name="expiration">00:03:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ISEToken">
<patch:attribute name="expiration">00:15:00</patch:attribute>
<patch:attribute name="elevationAction">Password</patch:attribute>
</token>
<token name="ItemSaveToken">
<patch:attribute name="expiration">00:05:00</patch:attribute>
<patch:attribute name="elevationAction">Confirm</patch:attribute>
</token>
</tokens>
</userAccountControl>if ([string]::IsNullOrWhiteSpace($itemPath)) {
Show-Alert "Invalid item path"
return
}# Only allow operations under /sitecore/content/Home
if (-not $item.Paths.FullPath.StartsWith("/sitecore/content/Home")) {
Show-Alert "Operation not allowed for this item"
return
}$result = Show-Confirm "This will delete $($items.Count) items. Continue?"
if ($result -ne "yes") { return }Write-Log "Delegated access: $([Sitecore.Context]::User.Name) published $($item.Paths.FullPath)"1. Content Author (limited permissions) clicks report
2. SPE checks for delegated access configuration
3. If found, script executes as Administrator
4. Script can access/modify content beyond author's permissions
5. Actions are logged showing both identities2304 14:02:32 INFO [Gutter] Executing script {CFE81AF6-2468-4E62-8BF2-588B7CC60F80} for Context User sitecore\contentauthor as sitecore\Admin.# Find all delegated access operations
$logfiles = Get-ChildItem -Path $SitecoreLogFolder -Filter "SPE.log.*"
foreach($logfile in $logfiles) {
$logEntries = Get-Content -Path $logfile.FullName | Where-Object {
$_ -match "Executing script .* for Context User .* as .*"
}
$logEntries | ForEach-Object {
if ($_ -match "Context User (?<context>\S+) as (?<impersonated>\S+)") {
[PSCustomObject]@{
ContextUser = $matches['context']
ImpersonatedUser = $matches['impersonated']
LogLine = $_
}
}
}
}Get-Item
Get item at path
Get-Item -Path "master:\content\home"
Get-ChildItem / ls
List children
Get-ChildItem -Path "master:\content"
Test-Path
Check if path exists
Test-Path "master:\content\home"
-Parent $parentItem
StartWorkflow
New-Item
Initiates default workflow
-StartWorkflow
Permanently
Remove-Item
Bypasses Recycle Bin
-Permanently
FailSilently
Remove-Item
Suppresses errors
-FailSilently
Require reauthentication
Production (SSO/Azure AD)
Confirm
Provide confirmation step









field:read
Read specific fields
field:write
Write specific fields
*
Rights may be inherited by decendants
!
Deny inheritance
+
Allow access
-
Deny access
Test before production - Always test security changes in development first
Use SecurityDisabler cautiously - Only in controlled, administrative scripts
Principle of least privilege - Grant minimum permissions necessary
item:read
Read item content and properties
item:write
Modify item fields
item:rename
Rename items
item:create
Create child items
item:delete
Delete items
item:admin
Administer item security
Any
Applies to item and descendants
Descendants
Applies only to descendants, not the item itself
Entity
Applies only to this specific item
AllowAccess
Allow access to item/descendants
DenyAccess
Deny access to item/descendants
AllowInheritance
Allow inheritance of access to item/descendants
DenyInheritance
Deny inheritance of access to item/descendants
ar
Role account type
au
User account type
pd
Propagate descendants
pe
Propagate entity (item)
p*
Propagate any
^
Allow inheritance

ar|sitecore\Author|pe|+item:read|ar|sitecore\Author|pd|-item:read|ar|sitecore\Author|pd|^*|ar|sitecore\Developer|pd|+item:read|pe|+item:read|Get-Command -Noun Role*,User,ItemAcl* | Select-Object -Property Name | Sort-Object -Property NameGet-Item -Path "master:\content\home" | Select-Object -Property PSSecurityName ID __Owner __Security
---- -- ------- ----------
Home {110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9} sitecore\Admin ar|sitecore\Developer|pd|+item:read|pe|+item:read|$item = Get-Item -Path "master:\content\home"
Get-ItemAcl -Item $itemAccount AccessRight PermissionType PropagationType SecurityPermission
------- ----------- -------------- --------------- ------------------
sitecore\Developer item:read Access Descendants AllowAccess
sitecore\Developer item:read Access Entity AllowAccess$devRead = @{
"Identity" = "sitecore\Developer"
"PropagationType" = "Any"
"SecurityPermission" = "AllowInheritance"
"AccessRight" = "item:read"
}
$acl = New-ItemAcl @devRead$everyoneDeny = @{
"Identity" = "\Everyone"
"PropagationType" = "Any"
"SecurityPermission" = "DenyInheritance"
"AccessRight" = "*"
}
$acl = New-ItemAcl @everyoneDeny$aclForEveryone = @{
"Identity" = "\Everyone"
"PropagationType" = "Any"
"SecurityPermission" = "DenyInheritance"
"AccessRight" = "*"
}
$acl = New-ItemAcl @aclForEveryone
Get-Item -Path "master:\content\home" |
Add-ItemAcl -AccessRules $acl -PassThru$authorAclRead = @{
"Identity" = "sitecore\Author"
"PropagationType" = "Any"
"SecurityPermission" = "AllowAccess"
"AccessRight" = "item:read"
}
$authorAclInherit = @{
"Identity" = "sitecore\Author"
"PropagationType" = "Any"
"SecurityPermission" = "AllowInheritance"
"AccessRight" = "*"
}
$acl1 = New-ItemAcl @authorAclRead
$acl2 = New-ItemAcl @authorAclInherit
Get-Item -Path "master:\content\home\sample2" |
Add-ItemAcl -AccessRules $acl1,$acl2 -PassThru
Get-ItemAcl -Path "master:\content\home\sample2" | Format-TableName Children Language Version Id TemplateName
---- -------- -------- ------- -- ------------
Sample2 True en 1 {91E814D3-78C8-44FA-B78B-E0A1B2374D8F} Sample Item
Account AccessRight PermissionType PropagationType SecurityPermission
------- ----------- -------------- --------------- ------------------
sitecore\Author item:read Access Descendants AllowAccess
sitecore\Author * Inheritance Descendants AllowInheritance
sitecore\Author item:read Access Entity AllowAccess
sitecore\Author * Inheritance Entity AllowInheritance$authorAccessRights = @(
"item:read",
"item:write",
"item:delete"
)
$authorAcl = @{
"Identity" = "sitecore\Author"
"PropagationType" = "Any"
"SecurityPermission" = "AllowAccess"
}
$accessRules = @()
foreach($accessRight in $authorAccessRights) {
$accessRules += @(New-ItemAcl @authorAcl -AccessRight $accessRight)
}
Set-ItemAcl -Item (Get-Item "master:\content\home") -AccessRules $accessRules -PassThruGet-Item -Path "master:\content\home" | Clear-ItemAcl$item = Get-Item -Path "master:\content\home"
$user = Get-Role -Identity "sitecore\Author"
Test-ItemAcl -Item $item -User $user -AccessRight "item:read"$authorAccessRights = @(
"item:read",
"item:write",
"item:rename",
"item:create",
"item:delete"
)
$authorAcl = @{
"Identity" = "sitecore\Author"
"PropagationType" = "Descendants"
"SecurityPermission" = "AllowAccess"
}
$accessRules = @()
foreach($accessRight in $authorAccessRights) {
$accessRules += @(New-ItemAcl @authorAcl -AccessRight $accessRight)
}
Get-Item -Path "master:\content\home\sample2" |
Add-ItemAcl -AccessRules $accessRules -PassThru$authorAccessRights = @(
"item:read",
"item:write",
"item:rename",
"item:create",
"item:delete"
)
$authorAcl = @{
"Identity" = "sitecore\Author"
"PropagationType" = "Entity"
"SecurityPermission" = "AllowAccess"
}
$accessRules = @()
foreach($accessRight in $authorAccessRights) {
$accessRules += @(New-ItemAcl @authorAcl -AccessRight $accessRight)
}
$items = Get-ChildItem -Path "master:\content\home" -Recurse
foreach($item in $items) {
Add-ItemAcl -Item $item -AccessRules $accessRules
Write-Host "Applied security to: $($item.ItemPath)"
}$items = Get-ChildItem -Path "master:\content\home" -Recurse
$report = @()
foreach($item in $items) {
$acls = Get-ItemAcl -Item $item
foreach($acl in $acls) {
$report += [PSCustomObject]@{
ItemPath = $item.ItemPath
Identity = $acl.Account.Name
AccessRights = $acl.AccessRight -join ", "
PropagationType = $acl.PropagationType
SecurityPermission = $acl.SecurityPermission
}
}
}
$report | Show-ListView -Property ItemPath, Identity, AccessRights, PropagationType# Copy security from one item to another
$sourceItem = Get-Item -Path "master:\content\home"
$targetItem = Get-Item -Path "master:\content\home\sample1"
# A combinination of Clear, Add, and Set may be used to alter item security
Write-Host "Cleared security for: $($sourceItem.ItemPath)"
Clear-ItemAcl -Item $targetItem
$sourceAcls = Get-ItemAcl -Item $sourceItem
if($sourceAcls) {
# Use Set-ItemAcl if you wish to replace the rules
Add-ItemAcl -Item $targetItem -AccessRules $sourceAcls
Write-Host "Cloned security to: $($targetItem.ItemPath)"
} else {
Write-Host "Cloned security to: $($targetItem.ItemPath)"
}$item = Get-Item -Path "master:\content\home"
Lock-Item -Item $itemGet-ChildItem -Path "master:\content\protected" -Recurse |
ForEach-Object {
Lock-Item -Item $_
Write-Host "Locked: $($_.ItemPath)"
}$item = Get-Item -Path "master:\content\home"
Unlock-Item -Item $itemGet-ChildItem -Path "master:\content\protected" -Recurse |
Where-Object { $_.Locking.IsLocked() } |
ForEach-Object {
Unlock-Item -Item $_
Write-Host "Unlocked: $($_.ItemPath)"
}$item = Get-Item -Path "master:\content\home"
if ($item.Locking.IsLocked()) {
Write-Host "Item is locked by: $($item.Locking.GetOwner())"
} else {
Write-Host "Item is not locked"
}$item = Get-Item -Path "master:\content\protected"
Protect-Item -Item $item$criticalItems = Get-ChildItem -Path "master:\content\critical" -Recurse
foreach($item in $criticalItems) {
Protect-Item -Item $item
Write-Host "Protected: $($item.ItemPath)"
}$item = Get-Item -Path "master:\content\home"
Unprotect-Item -Item $itemGet-ChildItem -Path "master:\content\temp" -Recurse |
ForEach-Object {
Unprotect-Item -Item $_
}PowerShell commands follow a Verb-Noun syntax. Notice that all properly named commands start with a verb such as Get, Set, or Remove and end with a noun such as Item, User, or Role.
Examples:
Get-Item - Retrieves an item
Set-Item - Modifies an item
Remove-Item - Deletes an item
New-Item - Creates an item
Move-Item - Moves an item
The verbs are considered "approved" if they align with those that Microsoft recommends. See the following URL https://msdn.microsoft.com/en-us/library/ms714428(v=vs.85).aspx for a list of approved verbs and a brief explanation on why they were chosen. They are intended to be pretty generic so they apply for multiple contexts like the filesystem, registry, and even Sitecore!
The parameters follow the command and usually require arguments. In our example above we have a parameter called SomeParameter followed by an argument of type SomeType. The final parameter SomeSwitch is called a switch.
Parameter types:
Required parameters - Must be provided
Optional parameters - May be omitted (shown in [square brackets])
Positional parameters - Can be provided without the parameter name (shown with [[double brackets]])
Switch parameters - Boolean flags that enable/disable behavior
Example: The following provides possible permutations for the fake command.
Instead of passing parameters inline, you can "splat" them using a hashtable:
When to use splatting:
Commands with many parameters
Reusable parameter sets
Conditional parameters
Improved readability
Allow scripts to be written with the full command and parameter names:
✅ Do use full command names (not aliases)
✅ Do use full parameter names (not abbreviations)
✅ Do specify parameter names explicitly
❌ Avoid relying on positional parameters in scripts
❌ Avoid abbreviating parameter names
❌ Avoid using command aliases (e.g. dir, cd) in scripts
Example:
Some of the most useful commands to learn can be seen in the table below. These come with vanilla PowerShell.
Get-Item
Returns an object at the specified path
Get-Item -Path "master:\content\home"
Get-ChildItem
Returns children at the specified path. Supports recursion
Get-ChildItem -Path "master:\content" -Recurse
Get-Help
Returns the help documentation for the specified command or document
Get-Help Get-Item
Get-Command
Returns a list of commands
Get-Command *Item*
PowerShell supports chaining of commands through a feature called "Pipelines" using the pipe "|". Similar to Sitecore in that you can short circuit the processing of objects using Where-Object.
The pipeline passes objects from one command to the next:
Command1 produces output
Command2 receives that output, processes it, and produces new output
Command3 receives Command2's output and produces final output
Example: The following queries a Sitecore item and removes it.
Example: The following gets children and displays specific properties.
PowerShell also comes with a set of useful commands for filtering and sorting. Let's see those in action.
Example: The following queries a tree of Sitecore items and returns only those that meet the criteria. The item properties are reduced and then sorted.
Windows PowerShell is bundled with a ton of documentation that could not possibly be included with this book; we can however show you how to access it.
Example: The following examples demonstrate ways to get help…with PowerShell.
Example: The following demonstrates how commands can be written clearly with little confusion on the intent, then how aliases and abbreviations can get in the way. Always think about the developer that comes after you to maintain the code.
Why use the longhand?
Easier to read
Self-documenting
No ambiguity
Works even if aliases change
Better for team collaboration
While you shouldn't use aliases in scripts, it's helpful to recognize them:
?
Where-Object
Filter objects
%
ForEach-Object
Process each object
select
Select-Object
Choose properties
sort
Sort-Object
Sort objects
View all aliases:
Now that you understand commands and pipelines:
Learn about providers: Providers
Practice with examples: Your First Scripts
Avoid common mistakes: Common Pitfalls
Deepen your knowledge: Working with Items
The pipeline is PowerShell's superpower! Master it and you'll be able to accomplish complex tasks with surprisingly little code.
Testing
Test in QA first
Catch security issues before production
Review
Quarterly access review
Remove unused delegations
We've provided a few commands to interact with the user through dialogs.
Simple in the sense that the dialogs present the user with a short message and one or two buttons.
The Alert dialog is a way to notify the user of important information with an "OK" button.
Example: The following display a modal dialog.
No return value.
The Confirmation dialog is a way to verify with the user before proceeding.
Example: The following displays a modal dialog with an OK or Cancel confirmation.
Example: The following displays an input dialog for text.
Example: The following displays an input dialog with a error validation message.
The Read-Variable command provides a way to prompt the user for information and then generate variables with those values.
Example: The following displays a dialog with a dropdown.
Note: The name selectedOption will result in a variable that contains the selected option.
Supported Parameter Values
Editor Types
bool
check
date
date time
The Confirmation Choice dialog allows for multiple combinations like that seen with a "Yes, Yes to all, No, No to all" scenario.
Example: The following displays a modal dialog with choices.
Note: The hashtable keys should be incremented like btn_0, btn_1, and so on. The return value is the key name.
The Upload dialog provides a way to upload files from a local filesystem to the media library or server filesystem.
Example: The following displays an advanced upload dialog.
No return value.
The Download dialog provides a way to download files from the server to a local filesystem.
Example: The following displays a download dialog.
The Field Editor dialog offers a convenient way to present the user with fields to edit.
Example: The following displays a field editor dialog.
The File Browser is an obvious choice when you need to upload, download, or delete files.
Example: The following displays a file browser dialog for installation packages.
Example: The following displays a simple file browser dialog.
Example: The following displays a Sheer UI control without any additional parameters.
The "Data List" is essentially a report viewer which supports custom actions, exporting, and filtering.
Example: The following displays a list view dialog with the child items under the Sitecore tree.
The Results dialog resembles the Console but does not provide a prompt to the user. This is useful for when logging messages.
Example: The following displays a dialog with the all the information written to the ScriptSession output buffer.
Creates a version of the item in a new language based on an existing language version.
Creates a new version of the item in a specified language based on an existing language/version. Based on parameters you can make the command bahave differently when a version in the target language already exists and define which fields if any should be copied over from the original language.
© 2010-2020 Adam Najmanowicz, Michael West. All rights reserved. Sitecore PowerShell Extensions
The following abbreviations are aliases for this cmdlet:
Add-ItemLanguage
Process the item and all of its children.
Default value is Append. Accepts one of 3 values:
Append - [Default] if language version exists create a new version with values copied from the original language
Skip - if language version exists don't do anything
OverwriteLatest - if language version exists overwrite the last version with values copied from the original language
Default value is Skip. Accepts one of 2 values:
Skip - [Default] if the source item has no versions don't do anything
Add - if the source item has no versions create a version without any copied values
Language or a list of languages that should be created
Creates a new version in the target language but does not copy field values from the original language
List of fields that should not be copied over from original item. As an example, use "__Security" if you don't want the new version to have the same restrictions as the original version.
In addition to the fields in -IgnoredFields the following fields are ignored as configured in Spe.config file in the following location: configuration/sitecore/powershell/translation/ignoredFields.
Fields ignored out of the box include:
__Archive date
__Archive Version date
__Lock
__Owner
Language that will be used as source language. If not specified the current user language will be used.
The item / version to be processed.
Path to the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Id of the item to be processed - additionally specify Language parameter to fetch different item language than the current user language.
Database containing the item to be processed - can work with Language parameter to narrow the publication scope.
The input type is the type of the objects that you can pipe to the cmdlet.
Sitecore.Data.Items.Item
The output type is the type of the objects that the cmdlet emits.
Sitecore.Data.Items.Item
Help Author: Adam Najmanowicz, Michael West
Translate the Home Item from English to US and Polish leaving the "Title" field blank. If a version exists don't do anything
Translate the children of Home item (but only those of Template Name "Sample Item") from English to US and Polish. If a version exists create a new version for that language. Display results in a table listing item name, language and created version number.
New-Item
Learn PowerShell syntax by comparing it to C#.
PowerShell is built on the Microsoft .NET technology; you will find that most APIs in your libraries can be accessed from within the PowerShell runtime. In this section we will see similarities between the C# and PowerShell syntax.
If you're not familiar with C#, don't worry! The examples below show both languages side-by-side so you can see the patterns.
Note: Variables in PowerShell are denoted by the $ character followed by the name. You will see this through the examples below.
Get-Something [[-SomeParameter] <sometype[]>] [-AnotherParameter <anothertype>] [-SomeSwitch]<#
All of the parameters in the command are surrounded by square brackets
indicating they are optional.
#>
Get-Something<#
SomeParameter has double brackets around the parameter name and argument
indicating the name is optional and when an argument is passed the name
can be skipped.
#>
Get-Something "data"<#
AnotherParameter has single brackets indicating that the parameter is
optional. If the argument is used so must the name. The same reasoning
can be applied to the switch.
#>
Get-Something "data","data2" -AnotherParameter 100 –SomeSwitch# Define parameters in a hashtable
$props = @{
"SomeParameter" = @("data","data2")
"AnotherParameter" = 100
"SomeSwitch" = $true
}
# Splat with @props instead of $props
Get-Something @props# GOOD - explicit and clear
Get-ChildItem -Path "master:\content\home" -Recurse |
Where-Object { $_.TemplateName -eq "Article" } |
Select-Object -Property Name, ID
# BAD - abbreviated and unclear
gci "master:\content\home" -r |
? { $_.TemplateName -eq "Article" } |
select Name, IDCommand1 | Command2 | Command3Get-ChildItem -Path "master:\content\home" |
Where-Object { $_.TemplateName -eq "Article" }
# $_ represents each item as it flows through# The remove command accepts pipeline input
Get-Item -Path "master:\content\home\sample item" | Remove-Item
# If multiple items are passed through the pipeline each are removed individually
$items | Remove-ItemGet-ChildItem -Path "master:\content\home" |
Select-Object -Property Name, TemplateName, ID# Use variables for parameters such as paths to make scripts easier to read
$path = "master:\content\home\"
Get-ChildItem -Path $path -Recurse |
Where-Object { $_.Name -like "*Sample*" } |
Select-Object -Property ID, Name, ItemPath |
Sort-Object -Property Name# Filter by property value
Get-ChildItem -Path "master:\content\home" |
Where-Object { $_.TemplateName -eq "Sample Item" }# Filter by multiple conditions
Get-ChildItem -Path "master:\content\home" |
Where-Object {
$_.TemplateName -eq "Sample Item" -and
$_.PSFields."__Updated".DateTime -gt (Get-Date).AddDays(-7)
}# Filter and negate
Get-ChildItem -Path "master:\content\home" |
Where-Object { $_.Name -notlike "*Test*" }# Select specific properties
Get-ChildItem -Path "master:\content\home" |
Select-Object Name, TemplateName, ID# Create calculated properties
Get-ChildItem -Path "master:\content\home" |
Select-Object Name,
@{Name="Updated";Expression={$_.PSFields."__Updated".DateTime}},
@{Name="Age";Expression={(Get-Date) - $_.PSFields."__Updated".DateTime}}$items = Get-ChildItem -Path "master:\content\home"
# Expand single property to array of values
$items | Select-Object -ExpandProperty Name
# Returns: @("Name1", "Name2", "Name3")# Count items by template
Get-ChildItem -Path "master:\content\home" -Recurse |
Group-Object TemplateName |
Select-Object Name, Count |
Sort-Object Count -Descending# Sort by name
$items | Sort-Object Name
# Sort descending
$items | Sort-Object Name -Descending
# Sort by multiple properties
$items | Sort-Object TemplateName, Name
# Sort by custom expression
$items | Sort-Object { $_.Name.Length }# Process each item
Get-ChildItem -Path "master:\content\home" |
ForEach-Object {
Write-Host "Processing: $($_.Name)"
# Do something with $_
}
# Transform each item
Get-ChildItem -Path "master:\content\home" |
ForEach-Object { $_.Name.ToUpper() }# Displays all of the about help documents
help about_*
# Displays help documentation on the topic of Splatting
help about_Splatting
# Displays help documentation on the specified command
help Get-Member
# Get detailed help with examples
Get-Help Get-Item -Detailed
# Get just the examples
Get-Help Get-Item -Examples
# Get help online (opens in browser)
Get-Help Get-Item -Online# List all commands
Get-Command
# Search for commands by name
Get-Command *Item*
# Search for SPE commands
Get-Command | Where-Object { $_.ImplementingType -and $_.ImplementingType.Assembly.GetName().Name -eq "Spe" }
# Get command details
Get-Command Get-Item | Select-Object *# See what properties and methods an object has
$item = Get-Item -Path "master:\content\home"
$item | Get-Member
# Filter to just properties
$item | Get-Member -MemberType Property
# Filter to just methods
$item | Get-Member -MemberType Method# Longhand - recommended for scripts
Get-Command -Name ForEach-Object –Type cmdlet |
Select-Object -ExpandProperty ParameterSets
# Shorthand - OK for interactive use, NOT recommended for scripts
gcm -na foreach-object -ty cmdlet | select -exp parametersetsGet-AliasAdd-ItemVersion [-Item] <Item> [-Recurse] [-IfExist <Append | Skip | OverwriteLatest>] [-TargetLanguage <String[]>] [-DoNotCopyFields] [-IgnoredFields <String[]>] [-Language <String[]>]
Add-ItemVersion [-Path] <String> [-Recurse] [-IfExist <Append | Skip | OverwriteLatest>] [-TargetLanguage <String[]>] [-DoNotCopyFields] [-IgnoredFields <String[]>] [-Language <String[]>]
Add-ItemVersion -Id <String> [-Database <String>] [-Recurse] [-IfExist <Append | Skip | OverwriteLatest>] [-TargetLanguage <String[]>] [-DoNotCopyFields] [-IgnoredFields <String[]>] [-Language <String[]>]ForEach-Object
Enumerates over the objects passed through the pipeline
$items | ForEach-Object { $_.Name }
Where-Object
Enumerates over the objects passed through the pipeline and filters objects
$items | Where-Object { $_.Name -like "*Test*" }
Select-Object
Returns objects from the pipeline with the specified properties and filters objects
$items | Select-Object Name, ID
Sort-Object
Sorts the pipeline objects with the specified criteria; usually a property name
$items | Sort-Object Name
Get-Member
Returns the methods and properties for the specified object
$item | Get-Member
Measure-Object
Calculates statistics on objects
$items | Measure-Object
Group-Object
Groups objects by property value
$items | Group-Object TemplateName
group
Group-Object
Group by property
measure
Measure-Object
Calculate statistics
gci
Get-ChildItem
Get children
gi
Get-Item
Get item
cd
Set-Location
Change directory
dir
Get-ChildItem
List directory
ls
Get-ChildItem
List directory
Tooltip (optional)
string
Short description or tooltip
"Check to run quietly
Tab (optional)
string
Tab title
"Simple"
Placeholder (optional)
string
Textbox placeholder
"Search text..."
Lines (optional)
int
Line count
3
Editor (optional)
string
Control type
"date time"
Domain (optional)
string
Domain name for security editor
"sitecore"
Options (optional)
string OrderedDictionary Hashtable
Data for checklist or dropdown
@{"Monday"=1;"Tuesday"=2}
Columns
int string
Number between 1 and 12 and string 'first' or 'last'
6 first
droplist
droptree
groupeddroplink
groupeddroplist
info
item
link
marquee
multilist
multilist search
multiple user
multiple user role
multiple role
multitext
number
pass
radio
rule
rule action
tree
treelist
tristate
time
OK
yes
Cancel
no
OK
< user input >
Cancel
$null
OK
ok
Cancel
cancel
< variables >
< selection >
Name
string
Variable name
isSilent
Value
bool string int float datetime Item
Default value
$true
Title
string
Header or Label
< first button >
btn_0
< second button >
btn_1
< third button >
btn_2
OK
ok
Cancel
cancel
OK
< selected file >
Cancel
undetermined
OK
< selected file >
Cancel
undetermined













"Proceed Silently
__Page Level Test Set Definition
__Reminder date
__Reminder recipients
__Reminder text
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
true (ByValue, ByPropertyName)
Accept Wildcard Characters?
false
Required?
true
Position?
1
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
true
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Required?
false
Position?
named
Default Value
Accept Pipeline Input?
false
Accept Wildcard Characters?
false
Show-Alert -Title "SPE is great!"Show-Confirm -Title "Click OK to acknowledge SPE is great!"Show-Input "Please provide 5 characters at most" -MaxLength 5$inputProps = @{
Prompt = "Enter a new name for the item:"
Validation = [Sitecore.Configuration.Settings]::ItemNameValidation
ErrorMessage = "'`$Input' is not a valid name."
MaxLength = [Sitecore.Configuration.Settings]::MaxItemNameLength
}
Show-Input @inputProps$options = @{
"A"="a"
"B"="b"
}
$props = @{
Parameters = @(
@{Name="selectedOption"; Title="Choose an option"; Options=$options; Tooltip="Choose one."}
)
Title = "Option selector"
Description = "Choose the right option."
Width = 300
Height = 300
ShowHints = $true
}
Read-Variable @propsShow-ModalDialog -Control "ConfirmChoice" -Parameters @{btn_0="Yes - returns btn_0"; btn_1="No - returns btn_1"; btn_2="returns btn_2"; te="Have you downloaded SPE?"; cp="Important Questions"} -Height 120 -Width 650Receive-File (Get-Item "master:\media library\Files") -AdvancedDialogGet-Item -Path "master:\media library\Files\readme" | Send-FileGet-Item "master:\content\home" | Show-FieldEditor -Name "*" -PreserveSectionsShow-ModalDialog -HandleParameters @{
"h"="Create an Anti-Package";
"t" = "Select a package that needs an anti-package";
"ic"="People/16x16/box.png";
"ok"="Pick";
"ask"="";
"path"= "packPath:$SitecorePackageFolder";
"mask"="*.zip";
} -Control "Installer.Browse"Show-ModalDialog -HandleParameters @{
"h"="FileBrowser";
} -Control "FileBrowser" -Width 500Show-ModalDialog -Control "SetIcon"Get-Item -Path master:\* | Show-ListView -Property Name, DisplayName, ProviderPath, TemplateName, Languagefor($i = 0; $i -lt 10; $i++) {
Write-Verbose "Index = $($i)" -Verbose
}
Show-Result -TextPS master:\> Add-ItemVersion -Path "master:\content\home" -Language "en" -TargetLanguage "pl-pl", "en-us" -IfExist Skip -IgnoredFields "Title"Add a Japanese version to /sitecore/content/home item in the master database based on itself
PS master:\> Add-ItemVersion -Path "master:\content\home" -Language ja-JP -IfExist AppendGet-ChildItem "master:\content\home" -Language "en" -Recurse | `
Where-Object { $_.TemplateName -eq "Sample Item" } | `
Add-ItemVersion -TargetLanguage "pl-pl" -IfExist Append | `
Format-Table Name, Language, Version -autoUse the tables below to aid in translating from C# to PowerShell. Some of the examples below are not "exact" translations, but should give you a good idea on what it would look like.
Operators are the same:
Addition: +
Subtraction: -
Multiplication: *
Division: /
Modulus: %
Working with Dynamic and Fixed dimensional arrays.
Using += with arrays in PowerShell is slow because it creates a new array each time. See Performance Considerations for better alternatives.
Working with hashtables (dictionaries).
Working with dictionaries that preserve insertion order.
Switch statements:
Important: PowerShell uses different comparison operators than C#!
==
-eq
Equal to
!=
-ne
Not equal to
<
-lt
Less than
>
-gt
Greater than
&&
-and
Logical AND
||
-or
Logical OR
!
-not or !
Logical NOT
Most comparisons in PowerShell are case-insensitive by default. Use operators starting with c (like -ceq) for case-sensitive comparisons.
Both work the same:
!$value - Shorter syntax
-not $value - More explicit
Escape double quotes in string. Alternatively you can use a single quote.
Escape character: PowerShell uses backtick ` instead of backslash \
Creating arrays with += is slow. Use these instead:
Different methods have different performance:
Variables
var name
$name
Equals
==
-eq
Not equals
!=
-ne
And
&&
-and
Now that you understand the syntax:
Learn commands: Commands and Pipelines
Understand providers: Providers
Practice with examples: Your First Scripts
Avoid mistakes: Common Pitfalls
As you can see, the language syntax is not all that different between C# and PowerShell. Within a few minutes you might even be able to translate code from your library classes into SPE scripts!
Get-Item by path
Single known item
⭐⭐⭐
✓
✓
Get-ChildItem
Small trees (<500 items)
⭐⭐
✓
✓
Example: Performance comparison for finding items by template.
When updating many items, use appropriate context objects to improve performance:
Example: Performance tiers for bulk updates.
For large datasets, process items in batches to avoid memory issues. Use Find-Item with pagination to retrieve items server-side rather than loading everything into memory:
Example: Efficient batch processing with search index pagination.
//TODO
//TODO
//TODO
Create reusable functions with proper error handling:
Example: Well-structured function.
Implement comprehensive error handling:
Example: Robust error handling pattern.
Always provide feedback for long-running operations:
Example: Comprehensive progress reporting.
Note: Use the Bulk Data Generator found under the Toolbox to create test items.
Be explicit about language handling:
Example: Multi-language update pattern.
Handle versions carefully to avoid unintended consequences:
Example: Safe version operations.
Use typed field access when working with complex fields:
Example: Safe field type handling.
Always use ISO format for date fields:
Example: Proper date handling.
Implement dry-run mode for destructive operations:
Example: Dry-run pattern.
Validate data before making changes:
//TODO
Log operations for audit trails:
Example: Logging pattern.
//TODO
Use Measure-Command to identify bottlenecks:
Example: Performance comparison.
Retrieving Items - Query optimization techniques
Editing Items - Update performance patterns
Item Security - Security best practices
Appendix - Common Commands - Cmdlet reference
Comprehensive logging and monitoring are essential for detecting security incidents, troubleshooting issues, and maintaining compliance. This guide covers how to configure and use SPE logging for security purposes.
SPE provides logging capabilities that record:
Script execution
User authentication and authorization
Session elevation events
Delegated access usage
Web service calls
Errors and exceptions
Security Best Practice: Enable comprehensive logging in all non-development environments to create an audit trail.
SPE logs are written to:
Typically resolves to:
SPE supports standard log4net levels:
Edit your log4net configuration (typically in App_Config\Sitecore.config or a patch file):
Recommended Settings:
Format:
Format:
Format:
Includes:
Script ID
Context user (actual logged-in user)
Impersonated user (elevated account)
This is critical for audit trails showing privilege escalation.
Format:
Logged Events:
Remoting connections
File uploads/downloads
RESTful API calls
Authorization failures
Format:
Logged Events:
Successful authentication
Failed authentication
Authorization denials
Format:
Includes:
Exception details
Stack traces
User context
Operation being performed
Create a scheduled task to analyze logs daily:
IIS logs provide additional context for web service access:
Location:
Find SPE web service requests:
Find failed authentication (401) to SPE services:
Create alerts for critical security events:
Run this script via Task Scheduler every 5 minutes.
For enterprise environments, integrate SPE logs with your Security Information and Event Management (SIEM) system.
Common SIEM Solutions:
Splunk
ELK Stack (Elasticsearch, Logstash, Kibana)
Azure Sentinel
ArcSight
Different compliance frameworks have different retention requirements:
Note: The requirements may have changed since the publishing of this document. Please confirm with your organization and legal team as to the requirements you must meet.
The configuration of log retention will be dependent on your solution.
The archival strategy implementation will be dependent on your solution.
Track these metrics for security monitoring:
✅ Do:
Enable INFO level logging in production
Monitor logs daily for suspicious activity
Set up alerts for critical security events
Retain logs per compliance requirements
❌ Don't:
Disable logging in production
Ignore failed authentication attempts
Delete logs prematurely
Log sensitive data (passwords, tokens)
Possible causes:
log4net configuration incorrect
File permissions prevent writing
Disk space full
SPE logger disabled
Solution: Check log4net config, verify permissions, ensure disk space.
Cause: DEBUG level in production or high activity.
Solution: Change to INFO or WARN level, implement log rotation.
Cause: Log rotation moved old logs or logs were deleted.
Solution: Check archived logs, adjust retention period.
- Includes logging validation
- Monitoring delegated access usage
- Monitoring web service security
- IIS log integration
Your Sitecore implementation may require vendor-specific documentation as log4net is bundled/compiled in the Sitecore libraries.

Sitecore PowerShell Extensions (SPE) is a powerful administrative tool that requires proper security configuration. This guide provides comprehensive security documentation to help you secure your SPE installation.
Critical Warning: SPE is a powerful tool that should NEVER be installed on Content Delivery (CD) instances or internet-facing servers. Always implement security best practices and follow the principle of least privilege.
Adding security at the IIS (Internet Information Services) level provides an additional layer of protection for SPE web services. This creates defense in depth by blocking unauthorized access before requests even reach the Sitecore application.
IIS-level security complements Sitecore-level security by:
Denying anonymous access to SPE services
SPE provides several web services for external access and automation. By default, most services are disabled to minimize the attack surface. This guide explains each service and how to secure them when enabled.
Web services enable powerful capabilities like:
Remote script execution (SPE Remoting)
// C# - declare and assign
var name = "Michael";
string title = "Developer";
int count = 5;# PowerShell - assign (type is inferred)
$name = "Michael"
$title = "Developer"
$count = 5
# Optionally specify type
[string]$title = "Developer"
[int]$count = 5// Perform simple math in C#
var total = 1 + 1;
total += 2;
var result = total * 3 / 2;# Perform simple math in PowerShell
$total = 1 + 1
$total += 2
$result = $total * 3 / 2/*
Create a new dynamic list of strings in C#
*/
var names = new List<string>();
names.Add("Michael");
names.Add("Adam");<#
Create a new fixed list of strings in PowerShell
#>
[string[]]$names = @()
$names += "Michael"
$names += "Adam"// Create a hashtable of data in C#
var table = new Hashtable();
table["Name"] = "Michael";
table["Age"] = 33;# Create a new hashtable of data in PowerShell
$table = @{}
$table["Name"] = "Michael"
$table["Age"] = 33
# Or create inline
$table = @{
Name = "Michael"
Age = 33
}// Ordered Dictionary in C#
var od = new OrderedDictionary();
od.Add("z","Last Letter");
od.Add("a","First Letter");# Ordered Dictionary in PowerShell
$od = [ordered]@{}
$od.Add("z","Last Letter")
$od.Add("a","First Letter")// Check if the string is null or empty using a static method in C#
if(string.IsNullOrEmpty(name)) {
...
}
else {
...
}# Check if the string is null or empty using a static method in PowerShell
if([string]::IsNullOrEmpty($name)) {
...
} else {
...
}// C# switch
switch(value) {
case "A":
DoSomething();
break;
case "B":
DoSomethingElse();
break;
default:
DoDefault();
break;
}# PowerShell switch
switch($value) {
"A" {
Do-Something
}
"B" {
Do-SomethingElse
}
default {
Do-Default
}
}// Compare values in C#
name == "Michael"
total <= 3
names.Count() > 2 && name[0] != "Adam"# Compare values in PowerShell
$name -eq "Michael"
$total -le 3
$names.Count -gt 2 -and $name[0] -ne "Adam"# Case-insensitive (default)
$name -eq "Michael" # Matches "michael", "MICHAEL", "Michael"
# Case-sensitive
$name -ceq "Michael" # Only matches exact case
# Wildcard matching
$name -like "*Smith" # Matches "John Smith", "Jane Smith"
$name -notlike "*Test*" # Excludes items with "Test"
# Regular expressions
$name -match "^\d{3}" # Matches names starting with 3 digits// Negate value in C#
var isTrue = !false;
var isNotEmpty = !string.IsNullOrEmpty(value);# Negate value in PowerShell
$isTrue = !$false
$isTrue = -not $false
$isNotEmpty = ![string]::IsNullOrEmpty($value)
$isNotEmpty = -not [string]::IsNullOrEmpty($value)// String interpolation in C#
var message = $"Hello, {name}";
var result = $"Total: {count * 2}";# String interpolation in PowerShell
$message = "Hello, $name"
$result = "Total: $($count * 2)"// Escape characters in C#
string message = "They said, \"SPE is the greatest!\".";
message = 'I said, "Thanks!"';
message = "We celebrated together, 'Go SPE!'";# Escape characters in PowerShell
$message = "They said, `"SPE is the greatest!`"."
$message = 'I said, "Thanks!".'
$message = "We celebrated together, 'Go SPE!'."// C# multi-line
var text = @"
Line 1
Line 2
Line 3
";# PowerShell here-string
$text = @"
Line 1
Line 2
Line 3
"@# Concatenation
$fullName = $firstName + " " + $lastName
$fullName = "$firstName $lastName"
# Length
$length = $name.Length
# Substring
$sub = $name.Substring(0, 5)
# Replace
$updated = $name.Replace("old", "new")
# Split
$parts = $name.Split(" ")
# Join
$joined = $parts -join ", "
# To upper/lower
$upper = $name.ToUpper()
$lower = $name.ToLower()// C# for loop
for(int i = 0; i < 10; i++) {
Console.WriteLine(i);
}# PowerShell for loop
for($i = 0; $i -lt 10; $i++) {
Write-Host $i
}// C# foreach
foreach(var item in items) {
ProcessItem(item);
}# PowerShell foreach
foreach($item in $items) {
Process-Item $item
}// C# while
while(count < 100) {
count++;
}# PowerShell while
while($count -lt 100) {
$count++
}// Access static property in C#
var today = DateTime.Today;
var guid = Guid.NewGuid();# Access static property in PowerShell
$today = [datetime]::Today
$guid = [guid]::NewGuid()# DateTime
$now = [datetime]::Now
$today = [datetime]::Today
$parsed = [datetime]::Parse("2024-01-15")
$custom = Get-Date -Year 2024 -Month 1 -Day 15
# String
$empty = [string]::Empty
$isNullOrEmpty = [string]::IsNullOrEmpty($value)
$joined = [string]::Join(", ", $array)
# Math
$max = [math]::Max(5, 10)
$min = [math]::Min(5, 10)
$rounded = [math]::Round(3.7)
# Guid
$newGuid = [guid]::NewGuid()
$parsed = [guid]::Parse("{110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9}")
# Path
$combined = [System.IO.Path]::Combine("C:\temp", "file.txt")
$extension = [System.IO.Path]::GetExtension("file.txt")// C# - create object
var list = new List<string>();
var dict = new Dictionary<string, int>();# PowerShell - create object
$list = New-Object System.Collections.Generic.List[string]
$dict = New-Object 'System.Collections.Generic.Dictionary[string,int]'
# Alternative syntax
$list = [System.Collections.Generic.List[string]]::new()// C# - Single line comment
/*
C# - Multi-line comment
More text here
*/# PowerShell - Single line comment
<#
PowerShell - Multi-line comment
More text here
#>// C# - call method
string upper = name.ToUpper();
items.Add("new item");# PowerShell - call method
$upper = $name.ToUpper()
$items.Add("new item")
# Note: Some methods return values you may want to suppress
$items.Add("new item") > $null// C# - define function
public string GetFullName(string first, string last) {
return first + " " + last;
}
var name = GetFullName("John", "Smith");# PowerShell - define function
function Get-FullName {
param(
[string]$First,
[string]$Last
)
return "$First $Last"
}
$name = Get-FullName -First "John" -Last "Smith"// C# - try/catch
try {
DoSomething();
}
catch(Exception ex) {
Console.WriteLine(ex.Message);
}
finally {
Cleanup();
}# PowerShell - try/catch
try {
Do-Something
}
catch {
Write-Host $_.Exception.Message
}
finally {
Clean-up
}# SLOW - creates new array each time
$names = @()
$names += "Michael"
$names += "Adam"
# FAST - use ArrayList
$names = [System.Collections.ArrayList]@()
$names.Add("Michael") > $null
$names.Add("Adam") > $null
# FAST - use List<T>
$names = [System.Collections.Generic.List[string]]@()
$names.Add("Michael") > $null
$names.Add("Adam") > $null
# FAST - use HashSet for distinct values
$names = New-Object System.Collections.Generic.HashSet[string]
$names.Add("Michael") > $null# SLOW - Out-Null is a cmdlet
$list.Add($item) | Out-Null
# FAST - redirect to $null
$list.Add($item) > $null# SLOW - Retrieves all items then filters
$items = Get-ChildItem -Path "master:\content" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" }
# FASTER - Uses Sitecore query to filter server-side
$items = Get-Item -Path "master:" -Query "/sitecore/content//*[@@templatename='Sample Item']"
# FASTEST - Uses the search index
# See Find-Item# SLOWEST - Automated properties call BeginEdit/EndEdit each time
foreach($item in $items) {
$item.Title = "Title" # BeginEdit/EndEdit
$item.Text = "Text" # BeginEdit/EndEdit
$item.Date = [datetime]::Now # BeginEdit/EndEdit
}
# BETTER - Manual BeginEdit/EndEdit once per item
foreach($item in $items) {
$item.Editing.BeginEdit()
$item["Title"] = "Title"
$item["Text"] = "Text"
$item["Date"] = [Sitecore.DateUtil]::ToIsoDate([datetime]::Now)
$item.Editing.EndEdit() > $null
}
# BEST - BulkUpdateContext for large datasets
New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
foreach($item in $items) {
$item.Editing.BeginEdit()
$item["Title"] = "Title"
$item["Text"] = "Text"
$item.Editing.EndEdit() > $null
}
}
# OPTIMAL - Combine with EventDisabler when events aren't needed
New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
New-UsingBlock (New-Object Sitecore.Data.Events.EventDisabler) {
foreach($item in $items) {
$item.Editing.BeginEdit()
$item["Title"] = "Title"
$item["Text"] = "Text"
$item.Editing.EndEdit() > $null
}
}
}$batchSize = 250
$offset = 0
$totalProcessed = 0
# Define search criteria
$criteria = @(
@{Filter = "Equals"; Field = "_templatename"; Value = "Sample Item"},
@{Filter = "DescendantOf"; Value = (Get-Item "master:\content").ID}
)
$props = @{
Index = "sitecore_master_index"
Criteria = $criteria
}
do {
# Query batch from search index (server-side pagination)
$searchItems = @(Find-Item @props -Skip $offset -First $batchSize)
if ($searchItems.Count -eq 0) { break }
# Process batch with bulk update context
New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
foreach($searchItem in $searchItems) {
# Convert search result to full Sitecore item
# Pipe items to Initialize-Item or call Get-Item with the ID
# The prefix `$script is required because of the ScriptBlock closure created by New-UsingBlock
$script:totalProcessed++
}
}
$offset += $searchItems.Count
Write-Host "Processed: $totalProcessed items"
} while ($searchItems.Count -eq $batchSize)
Write-Host "Completed processing $totalProcessed items"
# Processed: 1 items
# Completed processing 1 itemsfunction Update-ItemTitle {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[Sitecore.Data.Items.Item]$Item,
[Parameter(Mandatory)]
[string]$Title
)
process {
try {
# Validation
if (-not $Item) {
Write-Error "Item is null"
return
}
# WhatIf support
if ($PSCmdlet.ShouldProcess($Item.ItemPath, "Update title to '$Title'")) {
$Item.Editing.BeginEdit()
try {
$Item["Title"] = $Title
$Item.Editing.EndEdit()
Write-Verbose "Updated: $($Item.ItemPath)"
} catch {
$Item.Editing.CancelEdit()
throw
}
}
} catch {
Write-Error "Failed to update $($Item.ItemPath): $($_.Exception.Message)"
}
}
}
# Usage
Get-ChildItem -Path "master:\content\" |
Update-ItemTitle -Title "New Title" -Verbose -WhatIf$itemPaths = @(
"master:/content/Home"
)
$results = @()
$errors = @()
foreach($itemPath in $itemPaths) {
try {
$item = Get-Item -Path $itemPath -ErrorAction Stop
$item.Editing.BeginEdit()
try {
$item["Title"] = "Updated"
$item.Editing.EndEdit()
$results += [PSCustomObject]@{
ItemPath = $item.ItemPath
Status = "Success"
Error = ""
}
} catch {
$item.Editing.CancelEdit()
throw
}
} catch {
$errors += [PSCustomObject]@{
ItemPath = $itemPath
Status = "Failed"
Error = $_.Exception.Message
}
}
}
# Report results
$results | Show-ListViewfunction Update-ItemsWithProgress {
param(
[Sitecore.Data.Items.Item[]]$Items,
[scriptblock]$UpdateAction
)
$total = $Items.Count
$current = 0
$sw = [System.Diagnostics.Stopwatch]::StartNew()
foreach($item in $Items) {
$current++
# Calculate ETA
$percentComplete = ($current / $total) * 100
$elapsedSeconds = $sw.Elapsed.TotalSeconds
$estimatedTotalSeconds = ($elapsedSeconds / $current) * $total
$remainingSeconds = $estimatedTotalSeconds - $elapsedSeconds
Write-Progress -Activity "Processing items" `
-Status "Processing $($item.Name) ($current of $total)" `
-PercentComplete $percentComplete `
-SecondsRemaining $remainingSeconds
& $UpdateAction $item
}
$sw.Stop()
Write-Progress -Activity "Processing items" -Completed
Write-Host "Completed $total items in $($sw.Elapsed.TotalSeconds.ToString('F2')) seconds"
}
# Usage
$items = Get-ChildItem -Path "master:\content\" -Recurse
Update-ItemsWithProgress -Items $items -UpdateAction {
param($item)
$item.Title = "Updated: $($item.Name)"
}$languages = @("en", "de-DE", "da", "es-ES")
foreach($lang in $languages) {
$item = Get-Item -Path "master:\content\home" -Language $lang -ErrorAction SilentlyContinue
if ($item) {
$item.Title = "Localized Title for $lang"
Write-Host "Updated $lang version"
} else {
Write-Warning "No $lang version exists"
}
}# Get latest version
$item = Get-Item -Path "master:\content\home" -Language "en"
# Create new version before updating
$newVersion = $item.Versions.AddVersion()
$newVersion.Editing.BeginEdit()
$newVersion["Title"] = "Updated in new version"
$newVersion.Editing.EndEdit()
Write-Host "Created version $($newVersion.Version)"$item = Get-Item -Path "master:\content\home"
# Use the Automatic Properties
Write-Host "Title: $($item.Title)"
# Use Typed Fields
$textField = $item.PSFields.Text
if($textField.Value) {
Write-Host "Text: $($item.PSFields.Text.Value)"
}
# Use typed fields for complex types
$linkField = [Sitecore.Data.Fields.LinkField]$item.Fields["Link"]
if ($linkField -and $linkField.LinkType -eq "internal") {
$targetItem = $linkField.TargetItem
Write-Host "Links to: $($targetItem.ItemPath)"
}
# Use typed fields for images
$imageField = [Sitecore.Data.Fields.ImageField]$item.Fields["Image"]
if ($imageField -and $imageField.MediaItem) {
Write-Host "Image: $($imageField.MediaItem.Name)"
Write-Host "Alt: $($imageField.Alt)"
Write-Host "Size: $($imageField.Width)x$($imageField.Height)"
}$item = Get-Item -Path "master:\content\home"
# CORRECT - Use ISO format for manual field assignment
$item.Editing.BeginEdit()
$item["MyDateField"] = [Sitecore.DateUtil]::ToIsoDate([datetime]::Now)
$item.Editing.EndEdit()
# ALSO CORRECT - Automatic properties handle conversion
$item.MyDateField = [datetime]::Now
# Reading dates
$createdDate = [Sitecore.DateUtil]::IsoDateToDateTime($item["__Created"])
# Or using automated properties
$createdDate = $item.__Created # Returns System.DateTimefunction Remove-TestContent {
param(
[switch]$WhatIf
)
$itemsToDelete = Get-ChildItem -Path "master:\content\" -Recurse
foreach($item in $itemsToDelete) {
if ($WhatIf) {
Write-Host "WHATIF: Would delete $($item.ItemPath)" -ForegroundColor Yellow
} else {
#Remove-Item -Path $item.ProviderPath -Permanently
Write-Host "Deleted: $($item.ItemPath)" -ForegroundColor Red -BackgroundColor White
}
}
}
Remove-TestContent -WhatIfWrite-Log "Starting item updates"
$items = Get-ChildItem -Path "master:\content"
foreach($item in $items) {
try {
$item.Title = "Updated"
Write-Log "Updated: $($item.ItemPath)"
} catch {
Write-Log "Failed: $($item.ItemPath) - $($_.Exception.Message)" -Log Error
}
}
Write-Log "Completed item updates"# BAD
$item = Get-Item -Path "master:\content\maybe-exists"
$item.Title = "New Title" # Throws if item doesn't exist# GOOD
$item = Get-Item -Path "master:\content\maybe-exists" -ErrorAction SilentlyContinue
if ($item) {
$item.Title = "New Title"
} else {
Write-Warning "Item not found"
}# BAD
foreach($item in $items) {
try {
$item.Title = "Updated"
} catch {
# Silent failure
}
}# GOOD
$items = Get-ChildItem -Path "master:\content"
$errors = @()
foreach($item in $items) {
try {
$item.Title = "Updated"
} catch {
$errors += [PSCustomObject]@{
Item = $item.ItemPath
Error = $_.Exception.Message
}
}
}
if ($errors.Count -gt 0) {
$errors | Show-ListView
}# Method 1
$time1 = Measure-Command {
$items = Get-ChildItem -Path "master:\content" -Recurse |
Where-Object { $_.TemplateName -eq "Sample Item" }
}
# Method 2
$time2 = Measure-Command {
$items = Get-Item -Path "master:" -Query "/sitecore/content//*[@@templatename='Sample Item']"
}
Write-Host "Method 1: $($time1.TotalSeconds)s"
Write-Host "Method 2: $($time2.TotalSeconds)s"
Write-Host "Improvement: $(($time1.TotalSeconds / $time2.TotalSeconds).ToString('P0'))"<=
-le
Less than or equal
>=
-ge
Greater than or equal
Or
||
-or
Not
!
-not or !
Escape char
\
`
String interpolation
$"text {var}"
"text $var"
Static access
DateTime.Today
[datetime]::Today
Comments
// or /* */
# or <# #>
Sitecore Query
Specific criteria, medium trees
⭐⭐
✓
✓
Find-Item
Large trees (>500 items)
⭐⭐⭐⭐
✓
Partial


FATAL
Critical errors
Always enabled
cs-User-Agent
User agent string
Identify automation vs browsers
File Upload Attempts
File upload failures
Monitor for patterns
Script Errors
Script execution errors
Monitor trends
Integrate with SIEM if available
Document your monitoring procedures
Review delegated access usage regularly
Track failed authentication patterns
Monitor web service usage for anomalies
Forget to monitor IIS logs too
Ignore ERROR and WARN messages
Let log files consume all disk space
Quarterly Report
Quarterly
Executive summary
DEBUG
Detailed diagnostic information
Development and troubleshooting
INFO
Informational messages
Production (recommended)
WARN
Warning messages
Production (recommended)
ERROR
Error messages
Always enabled
Development
DEBUG
Maximum detail for troubleshooting
QA/Staging
INFO
Balance detail and volume
Production
INFO or WARN
Important events without excessive detail
c-ip
Client IP address
Identify source of requests
cs-username
Authenticated username
Track who accessed services
cs-uri-stem
Requested URI
Identify which services were called
sc-status
HTTP status code
PCI-DSS
1 year (3 months online)
HIPAA
6 years
SOC 2
1+ years
GDPR
Varies by data type
Failed Auth Rate
Failed authentications per hour
Alert if > 10
Elevation Denials
Session elevation denials
Alert if > 5
Delegated Access
Delegated access usage
Monitor trends
Web Service 401/403
Unauthorized web service calls
Alert if > 20
Real-time Alerts
Continuous
Automated scripts/SIEM
Daily Review
Daily
Automated summary email
Weekly Analysis
Weekly
Manual review of trends
Monthly Audit
Monthly
Comprehensive security review
Find authorization failures (401, 403)
Requiring Windows Authentication
Blocking access at the web server level
Protecting against attacks before they reach Sitecore
Defense in Depth: Even if Sitecore security is bypassed, IIS security provides a second barrier.
SPE web services are located in:
Key Files:
web.config - IIS configuration for the services directory
RemoteAutomation.asmx - Remoting service
RemoteScriptCall.ashx - RESTful and file services
PowerShellWebService.asmx - Client service (Console/ISE)
The most basic IIS security is denying anonymous users.
Edit sitecore modules\PowerShell\Services\web.config:
Anonymous
?
Denied
Authenticated
*
Allowed (by default)
Effect:
All anonymous requests are blocked with 401 Unauthorized
Users must authenticate with Sitecore credentials
Protects web services from unauthenticated access
✅ Always use this configuration unless you have a specific reason not to.
Scenarios where you might not:
Public API endpoints (rare and dangerous)
Authentication handled by a different layer
For environments using Windows/Active Directory authentication, you can require Windows credentials at the IIS level.
Open IIS Manager
Navigate to sitecore modules\PowerShell\Services\
Open "Authentication" feature
Disable "Anonymous Authentication"
Enable "Windows Authentication"
Optionally add explicit deny rule:
When using Windows Authentication, SPE Remoting commands require the Credential parameter:
Best for:
Internal corporate networks
Environments with Active Directory
Servers requiring domain authentication
High-security environments
Not suitable for:
Internet-facing servers (which shouldn't have SPE anyway)
Environments without Active Directory
Mixed authentication scenarios
Restrict access to specific Windows users or roles.
Rules are evaluated top to bottom. First match wins.
Example:
Limit access to specific IP addresses or ranges using IIS IP Address and Domain Restrictions.
Open IIS Manager
Navigate to sitecore modules\PowerShell\Services\
Open "IP Address and Domain Restrictions"
Click "Add Allow Entry..." or "Add Deny Entry..."
Enter IP address or range
Allow specific IPs:
Deny specific IPs:
Best for:
Limiting access to build servers
Allowing only internal network ranges
Blocking known malicious IPs
CI/CD automation from specific servers
Example Use Case: Only allow remoting from build server at 10.0.0.100:
Require HTTPS for all SPE web service access.
SSL Flags:
Ssl
Require SSL/TLS connection
SslNegotiateCert
Negotiate client certificate
SslRequireCert
Require client certificate
Ssl128
Require 128-bit SSL
For maximum security, require client certificates:
Use IIS URL Rewrite module to block or redirect requests.
Use IIS Request Filtering to block dangerous requests.
Strict security with deny anonymous:
Allow only build server, require HTTPS:
Require Windows auth with specific roles:
Multiple layers of protection:
✅ Do:
Always deny anonymous access (minimum requirement)
Require HTTPS for all external access
Use IP restrictions for CI/CD scenarios
Implement request filtering to block dangerous patterns
Layer multiple security controls (defense in depth)
Test authentication requirements before deploying
Document your IIS security configuration
Review IIS logs for unauthorized access attempts
❌ Don't:
Allow anonymous access unless absolutely necessary
Use HTTP for sensitive operations
Open access to all IPs without restriction
Forget to configure both IIS and Sitecore security
Assume IIS security alone is sufficient
Deploy without testing authentication workflows
Local Dev
Minimal (allow anonymous for convenience)
Shared Dev
Deny anonymous
QA/Staging
Deny anonymous + HTTPS
Production
Deny anonymous + HTTPS + IP restrictions + request filtering
CI/CD
IP restrictions + HTTPS + specific user/role
Combine multiple security layers:
Network - Firewall rules, VPN requirements
IIS - Authentication, IP restrictions, HTTPS
Sitecore - Role-based authorization, web service controls
SPE - Session elevation, file upload restrictions
Monitoring - Log analysis, alerting
Possible causes:
Denied anonymous but using anonymous access
Windows Authentication not configured correctly
User not in allowed users/roles list
Solution: Verify authentication method and user permissions.
Possible causes:
IP address not in allowed list
SSL required but using HTTP
Client certificate required but not provided
Solution: Check IP restrictions, URL protocol, and certificate configuration.
Possible causes:
Windows Authentication not enabled in IIS
Browser not configured for Windows Auth
User in same domain (auto-authentication)
Solution: Check IIS authentication settings and browser configuration.
Possible causes:
IP restrictions blocking remote IP
Firewall blocking access
Authentication failing for remote user
Solution: Check IP restrictions and firewall rules.
Web Services Security - Sitecore-level web service configuration
Security Policies - Understanding SPE security model
Security Checklist - Validate your complete security configuration
Logging and Monitoring - Monitor for unauthorized access attempts
$SitecoreLogFolder\SPE.log.{date}.txtC:\inetpub\wwwroot\App_Data\logs\SPE.log.20260101.txt<configuration>
<log4net>
<appender name="PowerShellExtensionsFileAppender" type="log4net.Appender.SitecoreLogFileAppender, Sitecore.Logging">
<file value="$(dataFolder)/logs/SPE.log.{date}.txt"/>
<appendToFile value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%4t %d{ABSOLUTE} %-5p %m%n"/>
</layout>
<encoding value="utf-8"/>
</appender>
<logger name="Spe" additivity="false">
<level value="INFO"/>
<appender-ref ref="PowerShellExtensionsFileAppender"/>
</logger>
</log4net>
</configuration>INFO Arbitrary script execution in ISE by user: 'sitecore\Admin'WARN Session state elevated for 'ISE' by user: sitecore\AdminINFO [Gutter] Executing script {CFE81AF6-2468-4E62-8BF2-588B7CC60F80} for Context User sitecore\test as sitecore\Admin.INFO A request to the remoting service was made from IP 10.0.0.27
INFO A request to the mediaUpload service was made from IP 10.0.0.27
WARN A request to the mediaUpload service could not be completed because the provided credentials are invalid.INFO [Runner] Executing script {BD07C7D1-700D-450C-B79B-8526C6643BF3} for Context User sitecore\test2 as sitecore\Admin.# TODO# Tail the SPE log file
# Note that the SPE Console doesn't exit when using -Wait
Get-Content -Path "$($SitecoreLogFolder)\SPE.log.20251201.txt" -Tail 10# Tail the latest SPE log file dynamically
Get-ChildItem -Path $SitecoreLogFolder -Filter "SPE.log.*.txt" | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 1 | ForEach-Object { Get-Content -Path $_.FullName -Tail 10}# Watch for tasks
Get-Content "$SitecoreLogFolder\SPE.log.20251201.txt" | Where-Object { $_ -match "\[Task\]" }# Watch for warnings
Get-Content "$SitecoreLogFolder\SPE.log.20251201.txt" | Where-Object { $_ -match "WARN" }$logPath = "$SitecoreLogFolder\SPE.log.20251201.txt"
$failedAuth = Get-Content $logPath |
Where-Object { $_ -match "credentials are invalid" } |
ForEach-Object {
if ($_ -match "(\d{2}:\d{2}:\d{2}).*WARN\s*(\S+)") {
[PSCustomObject]@{
Timestamp = $matches[1]
User = $matches[2]
LogLine = $_
}
}
}
$failedAuth
# Timestamp User LogLine
# --------- ---- -------
# 11:20:23 A 1508 11:20:23 WARN A request to the mediaUpload service could not be completed because the provided credentials are invalid.$logPath = "$SitecoreLogFolder\SPE.log.20251201.txt"
$delegated = Get-Content $logPath |
Where-Object { $_ -match "Executing script" } |
ForEach-Object {
if ($_ -match "(?<time>\d{2}:\d{2}:\d{2}).*Runner\s*.*Context User\s(?<user>[0-9a-zA-Z\\]*)\sas\s(?<impersonated>[0-9a-zA-Z\\]*).*") {
[PSCustomObject]@{
Timestamp = $matches["time"]
ContextUser = $matches["user"]
ImpersonatedAs = $matches["impersonated"]
LogLine = $_
}
}
}
$delegated | Group-Object ContextUser |
Select-Object Name, Count |
Sort-Object Count -Descending
# Name Count
# ---- -----
# sitecore\test2 1$logPath = "$SitecoreLogFolder\SPE.log.20251201.txt"
$unauthorized = Get-Content $logPath |
Where-Object { $_ -match "credentials are invalid" }
$unauthorized | ForEach-Object {
Write-Host $_ -ForegroundColor Red -BackgroundColor White
}
# 1508 11:20:23 WARN A request to the mediaUpload service could not be completed because the provided credentials are invalid.$logPath = "$SitecoreLogFolder\SPE.log.20251201.txt"
$webServiceCalls = Get-Content $logPath |
Where-Object { $_ -match "remoting" }
# Group by IP address
$webServiceCalls | ForEach-Object {
if ($_ -match "IP\s*(?<ip>[\d\.]+)") {
[PSCustomObject]@{
IP = $matches['ip']
LogLine = $_
}
}
} | Group-Object IP |
Select-Object Name, Count |
Sort-Object Count -Descending
# Name Count
# ---- -----
# 10.0.0.27 105# TODO: Example using Send-MailMessageC:\inetpub\logs\LogFiles\W3SVC1\# TODO Inspect IIS Logs# TODO Inspect IIS Logs# TODO Example with Send-MailMessagesitecore modules\PowerShell\Services\<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration><configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration># Create credential object
$credential = Get-Credential
# Create session with Windows credentials
$session = New-ScriptSession `
-Username "sitecore\sitecore-user" `
-Password "password" `
-ConnectionUri "https://sitecore.local" `
-Credential $credential
# Or use credential parameter directly
$session = New-ScriptSession `
-ConnectionUri "https://sitecore.local" `
-Credential (Get-Credential)<configuration>
<system.web>
<authorization>
<deny users="?" />
<allow users="DOMAIN\username1, DOMAIN\username2" />
<deny users="*" />
</authorization>
</system.web>
</configuration><configuration>
<system.web>
<authorization>
<deny users="?" />
<allow roles="DOMAIN\Sitecore Administrators" />
<deny users="*" />
</authorization>
</system.web>
</configuration><authorization>
<!-- 1. Deny anonymous -->
<deny users="?" />
<!-- 2. Allow specific users -->
<allow users="DOMAIN\username1" />
<!-- 3. Allow specific roles -->
<allow roles="DOMAIN\Sitecore Administrators" />
<!-- 4. Deny everyone else -->
<deny users="*" />
</authorization><configuration>
<system.webServer>
<security>
<ipSecurity allowUnlisted="false">
<add ipAddress="10.0.0.1" allowed="true" />
<add ipAddress="10.0.0.2" allowed="true" />
<add ipAddress="192.168.1.0" subnetMask="255.255.255.0" allowed="true" />
</ipSecurity>
</security>
</system.webServer>
</configuration><configuration>
<system.webServer>
<security>
<ipSecurity allowUnlisted="true">
<add ipAddress="203.0.113.1" allowed="false" />
<add ipAddress="198.51.100.0" subnetMask="255.255.255.0" allowed="false" />
</ipSecurity>
</security>
</system.webServer>
</configuration><system.webServer>
<security>
<ipSecurity allowUnlisted="false">
<add ipAddress="10.0.0.100" allowed="true" />
</ipSecurity>
</security>
</system.webServer><configuration>
<system.webServer>
<security>
<access sslFlags="Ssl, SslNegotiateCert" />
</security>
</system.webServer>
</configuration><system.webServer>
<security>
<access sslFlags="Ssl" />
</security>
</system.webServer><system.webServer>
<security>
<access sslFlags="Ssl, SslRequireCert" />
</security>
</system.webServer><configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Block requests with suspicious query strings -->
<rule name="Block Malicious Query Strings" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{QUERY_STRING}" pattern="(eval|exec|system|cmd\.exe)" />
</conditions>
<action type="CustomResponse" statusCode="403" statusReason="Forbidden" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration><rewrite>
<rules>
<rule name="Force HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite><configuration>
<system.webServer>
<security>
<requestFiltering>
<fileExtensions>
<add fileExtension=".exe" allowed="false" />
<add fileExtension=".dll" allowed="false" />
<add fileExtension=".bat" allowed="false" />
<add fileExtension=".cmd" allowed="false" />
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>
</configuration><system.webServer>
<security>
<requestFiltering>
<!-- Max 10MB requests -->
<requestLimits maxAllowedContentLength="10485760" />
</requestFiltering>
</security>
</system.webServer><system.webServer>
<security>
<requestFiltering>
<verbs>
<add verb="TRACE" allowed="false" />
<add verb="TRACK" allowed="false" />
<add verb="OPTIONS" allowed="false" />
</verbs>
</requestFiltering>
</security>
</system.webServer><configuration>
<system.web>
<authorization>
<!-- Deny anonymous access -->
<deny users="?" />
</authorization>
</system.web>
<system.webServer>
<security>
<!-- Require HTTPS -->
<access sslFlags="Ssl" />
<!-- Request filtering -->
<requestFiltering>
<requestLimits maxAllowedContentLength="10485760" />
<fileExtensions>
<add fileExtension=".exe" allowed="false" />
<add fileExtension=".dll" allowed="false" />
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>
</configuration><configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
<system.webServer>
<security>
<!-- Require HTTPS -->
<access sslFlags="Ssl" />
<!-- Only allow build server -->
<ipSecurity allowUnlisted="false">
<add ipAddress="10.0.0.100" allowed="true" />
</ipSecurity>
</security>
</system.webServer>
</configuration><configuration>
<system.web>
<authorization>
<deny users="?" />
<allow roles="DOMAIN\Sitecore Administrators, DOMAIN\Sitecore Developers" />
<deny users="*" />
</authorization>
</system.web>
<system.webServer>
<security>
<access sslFlags="Ssl" />
</security>
</system.webServer>
</configuration><configuration>
<system.web>
<authorization>
<deny users="?" />
<allow users="DOMAIN\sitecore-admin" />
<deny users="*" />
</authorization>
</system.web>
<system.webServer>
<security>
<!-- Require HTTPS and client certificate -->
<access sslFlags="Ssl, SslRequireCert" />
<!-- IP restriction to internal network -->
<ipSecurity allowUnlisted="false">
<add ipAddress="10.0.0.0" subnetMask="255.0.0.0" allowed="true" />
</ipSecurity>
<!-- Request filtering -->
<requestFiltering>
<requestLimits maxAllowedContentLength="5242880" />
<verbs>
<add verb="TRACE" allowed="false" />
<add verb="OPTIONS" allowed="false" />
</verbs>
</requestFiltering>
</security>
<!-- URL rewrite to block patterns -->
<rewrite>
<rules>
<rule name="Block Suspicious Patterns" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{QUERY_STRING}" pattern="(eval|exec|cmd)" />
</conditions>
<action type="CustomResponse" statusCode="403" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>New to SPE security? Start here:
Getting Started - Essential security setup for new installations
Security Policies - Understand the SPE security model
Security Checklist - Validate your deployment before going live
Understand the two-layer security model that governs SPE:
Application Pool Service Account (OS-level access)
Sitecore User Account (API-level access)
Application and menu item security
Best practices for both security contexts
Configure User Account Control to require reauthentication:
How Session Elevation works
Elevation actions (Allow, Block, Password, Confirm)
Token configuration and expiration
Environment-specific recommendations
Interface behaviors (Console, ISE, Content Editor)
Control external access to SPE through web services:
Service descriptions and security implications
Enable/disable individual services
HTTPS and requireSecureConnection
Role-based authorization
Configuration examples for different scenarios
Prevent malicious file uploads:
File type restrictions (extensions and MIME types)
Upload location restrictions
Dangerous file types to never allow
Configuration examples
Testing upload restrictions
Grant controlled privilege escalation:
How delegated access works
Configuration steps
Use cases (publishing, reports, bulk operations)
Script implementation patterns
Security best practices and monitoring
Add defense in depth at the web server level:
Deny anonymous access
Windows Authentication
IP address restrictions
SSL/TLS requirements
Request filtering and URL rewrite rules
Manage Sitecore users and roles:
Bulk user operations
Role queries and management
Item Access Control Lists (ACL)
Active Directory integration
PowerShell examples for user management
Deploy only what's needed for CI/CD:
Required files for web services only
Disable UI components
Configuration for automation scenarios
Security best practices
Common deployment patterns
Track security events and detect incidents:
What gets logged
Log levels and configuration
Real-time monitoring strategies
Log analysis examples
Integration with SIEM systems
Security metrics and dashboards
Comprehensive validation before deployment:
Pre-deployment validation
Configuration checklist
Testing procedures
Environment-specific checklists
Post-deployment monitoring
Emergency procedures
Priority: Productivity with basic security
Recommendations:
Session Elevation: Relaxed (Allow or long timeouts)
Web Services: Enable as needed for testing
Logging: DEBUG level for troubleshooting
IP Restrictions: Not required
Start here: Getting Started - Development
Priority: Match production security for testing
Recommendations:
Session Elevation: Password or Confirm (5-15 minute timeout)
Web Services: Match production configuration
Logging: INFO level
IP Restrictions: Optional
Start here: Getting Started - QA/Staging
Priority: Maximum security
Recommendations:
Session Elevation: Password or Confirm (3-5 minute timeout)
Web Services: Only handleDownload, client, execution (disable remoting)
Logging: INFO or WARN level
IP Restrictions: Recommended
HTTPS: Required
Start here: Security Checklist - Production
Priority: Automation with strict access control
Recommendations:
Minimal Deployment: Use minimal package
Remoting: Enabled with IP restrictions
Web Services: Only required services
Logging: INFO level with monitoring
HTTPS: Required
Start here: Minimal Deployment
SPE security uses multiple layers for comprehensive protection:
Each layer provides additional protection. If one layer is compromised, others provide continued security.
Goal: Secure SPE for production content management server
Steps:
Review Security Policies to understand the model
Configure Session Elevation with 5-minute Password timeout
Disable unnecessary Web Services
Configure IIS Security to deny anonymous access
Enable
Complete the
Goal: Enable remote automation from build servers
Steps:
Use Minimal Deployment package
Enable Remoting in Web Services with specific user
Configure IIS Security with IP restrictions to build servers
Configure File Upload Restrictions for packages only
Set up for automation activity
Test with
Goal: Allow content authors to run administrative reports
Steps:
Understand Delegated Access concepts
Create delegated access configuration for reporting role
Configure impersonated user with read-only administrative access
Test report access as content author
Monitor usage via
Goal: Configure SPE with Sitecore Identity Server
Steps:
Enable Spe.IdentityServer.config
Configure Session Elevation with Confirm action (not Password)
Test Console and ISE with federated authentication
Configure Web Services if needed
Always deny anonymous access at IIS level
Always use Session Elevation (UAC) in production
Always require HTTPS for any enabled web services
Always follow principle of least privilege
Always monitor logs for suspicious activity
Only enable web services you specifically need
Use short session elevation timeouts in production (3-5 minutes)
Restrict SPE access to trusted administrators only
Configure file upload restrictions when upload service is enabled
Regular security audits and role membership reviews
Document your security configuration
Test security in non-production before deploying
Never install SPE on Content Delivery (CD) servers
Never expose SPE to internet-facing servers
Never use elevationAction="Allow" in production
Never enable all web services "just in case"
Never grant broad role access (e.g., "Everyone")
Never allow dangerous file types (.exe, .dll, .ps1, .bat)
Don't skip Session Elevation configuration
Don't ignore failed authentication attempts in logs
Don't use administrator accounts for automation
Don't forget to configure authorization when enabling remoting
App_Config\Include\Spe\Spe.config
Core SPE configuration
App_Config\Include\Spe\Spe.IdentityServer.config
Identity Server integration
App_Config\Include\Spe\Custom\*.config
Your security patches
All topics
sitecore modules\PowerShell\Services\web.config
IIS-level security
Application Visibility
core:\content\Applications\PowerShell
Menu Item Security
core:\content\Applications\Content Editor\Context Menues\Default\
Script Library Security
Item-level security on scripts
Delegated Access
SPE configuration items
sitecore\Developer
Console, ISE
Keep restricted to developers only
sitecore\Sitecore Client Users
ListView, Runner
Appropriate for content authors
sitecore\Sitecore Client Authoring
Reports
Appropriate for content authors
sitecore\PowerShell Extensions Remoting
Remoting (when enabled)
New to SPE Security? Start with Getting Started
Deploying to production? Use the Security Checklist
Setting up automation? See Minimal Deployment
Need to debug? Check Logging and Monitoring
Configuring a specific feature? See topic-specific guides below
GitHub Issues: SitecorePowerShell/Console
Slack: #module-spe on Sitecore Community Slack
Documentation: Full SPE Documentation
If you suspect a security breach:
Immediately lock down SPE using Emergency Procedures
Review logs using Logging and Monitoring guidance
Document the incident
Contact your security team
Report to SPE maintainers if it's a product vulnerability
Installation - Initial SPE installation
Interfaces - Console, ISE, and Interactive Dialogs
Remoting - Using SPE Remoting for automation
Modules - Integration points and features
- PowerShell security commands
Enable the Identity Server configuration:
File: App_Config\Include\Spe\Spe.IdentityServer.config
Purpose: Prevents infinite loop in SPE Console
Use elevationAction="Confirm" instead of "Password"
Consult the latest SPE documentation for XM Cloud-specific security configurations.
Remember: Security is not a one-time configuration. Regular reviews, monitoring, and updates are essential to maintaining a secure SPE installation.
Last Updated: 2025 Maintained By: SPE Community
RESTful API access
File and media uploads/downloads
Report exports
Security Warning: Only enable web services you specifically need. Each enabled service increases your attack surface. Never enable services on internet-facing servers.
Services are configured in App_Config\Include\Spe\Spe.config:
Service File: PowerShellWebService.asmx
Purpose: Powers the SPE Console and ISE user interfaces.
Required For:
PowerShell Console
PowerShell ISE (Integrated Scripting Environment)
Security Considerations:
Required for basic SPE functionality
Access controlled by Sitecore user permissions
Protected by Session Elevation (UAC)
Should you disable it? No - this breaks the Console and ISE.
Service File: Various pipeline integrations
Purpose: Checks if users have permission to run SPE applications.
Required For:
Download File dialogs
PowerShell Script Runner
Content Editor integrations (Context Menu, Insert Options, Ribbon)
Security Considerations:
Authorization check service
Does not execute arbitrary code
Validates permissions before allowing access
Should you disable it? No - this breaks SPE integration points.
Service File: RemoteScriptCall.ashx
Purpose: Enables file downloads through the Sitecore interface.
Required For:
Out-Download command
Report exports (CSV, Excel, etc.)
ISE script exports
Security Considerations:
Only works for authenticated users
Requires active Sitecore session
Downloads are temporary and time-limited
Should you disable it? Only if you never need to download files from SPE (rare).
Service File: RemoteAutomation.asmx
Purpose: Allows external clients to execute PowerShell scripts remotely.
Required For:
SPE Remoting module
Automated CI/CD scripts
External automation tools
Security Considerations:
⚠️ HIGH RISK - enables remote code execution
Must be protected with role-based authorization
Should require HTTPS
Ideal for CI/CD environments with proper security
Example Use Case: Automated content deployment from build servers.
Enable with HTTPS requirement:
Restrict to specific users:
Load Balancer Note: When using requireSecureConnection behind a load balancer that handles TLS termination, you may receive 403 errors. The backend server receives HTTP traffic and .NET doesn't recognize it as secure. Consider network-level security instead.
Service File: RemoteScriptCall.ashx
Purpose: Execute scripts via RESTful URLs with all parameters in the URL.
Required For:
PowerShell Web API
RESTful script endpoints
External integrations
Security Considerations:
⚠️ MEDIUM-HIGH RISK - exposes script execution via HTTP
URL-based parameters may be logged
Should require HTTPS
Should use POST instead of GET when possible
Example Use Case: Providing a web API for external systems to query Sitecore content.
Service File: RemoteScriptCall.ashx
Purpose: Download files from the server file system via URL.
Required For:
SPE Remoting file downloads
External file retrieval
Security Considerations:
⚠️ MEDIUM RISK - exposes file system
Restricted by file type and location configuration
Only works with allowed paths
Should you enable it? Only if using SPE Remoting and need file downloads.
Service File: RemoteScriptCall.ashx
Purpose: Upload files to the server file system via URL.
Required For:
SPE Remoting file uploads
External file deployment
Security Considerations:
⚠️ HIGH RISK - allows writing to file system
Restricted by file type and location configuration
Can be used to deploy malicious files if misconfigured
Must be carefully controlled
Should you enable it? Only if absolutely necessary, with strict restrictions.
See File Upload Restrictions for detailed configuration.
Service File: RemoteScriptCall.ashx
Purpose: Download media library items via URL.
Required For:
SPE Remoting media downloads
External media retrieval
Security Considerations:
⚠️ LOW-MEDIUM RISK - exposes media library
Respects Sitecore security
May expose sensitive media items
Should you enable it? Only if using SPE Remoting and need media downloads.
Service File: RemoteScriptCall.ashx
Purpose: Upload files as media library items via URL.
Required For:
SPE Remoting media uploads
External media deployment
Security Considerations:
⚠️ MEDIUM RISK - allows media library uploads
Restricted by file type configuration
Can bloat media library if misused
Should you enable it? Only if using SPE Remoting and need media uploads.
Service File: RemoteScriptCall.ashx
Purpose: Legacy RESTful API from early SPE versions.
Security Considerations:
⚠️ DEPRECATED - avoid using
Use RESTful v2 instead
Should you enable it? No - migrate to v2.
Default configuration - only services needed for Console and ISE:
Enable remoting for build automation, with strict security:
Enable RESTful v2 for web API endpoints:
Enable all remoting capabilities (use with caution):
Restrict remoting access to specific roles or users.
By default, these roles can use remoting (when enabled):
Remove default roles and add your own:
Grant access to individual users:
Add an additional security layer by configuring IIS authentication.
Edit sitecore modules\PowerShell\Services\web.config:
This denies all anonymous users from accessing SPE web services.
For environments with Windows Authentication:
Disable Anonymous Authentication in IIS for sitecore modules\PowerShell\Services\
Enable Windows Authentication
Use the Credential parameter in remoting commands:
✅ Do:
Only enable services you specifically need
Require HTTPS for all external services (requireSecureConnection="true")
Use role-based authorization to limit access
Deny anonymous access at the IIS level
Regularly audit which services are enabled
Use dedicated service accounts for automation
Monitor web service access logs
Disable services in Content Delivery (CD) environments
❌ Don't:
Enable all services "just in case"
Allow HTTP for remoting or file upload
Grant broad role access (e.g., "Everyone")
Use administrator accounts for automation
Enable services on internet-facing servers
Forget to configure authorization when enabling remoting
Leave default passwords on service accounts
Local Dev
All enabled (if needed)
Convenience for development and testing
Shared Dev
handleDownload, client, execution
Only UI features
QA/Staging
Match production
Test with production security
Production CM
handleDownload, client, execution
client
Using Console/ISE (always)
Sitecore user auth + Session Elevation
execution
Using SPE features (always)
Sitecore user auth
handleDownload
Need to download reports/files (usually)
Sitecore user auth
remoting
Need external automation
Cause: Load balancer terminates TLS and forwards HTTP to backend.
Solution:
Configure network-level security instead
Remove requireSecureConnection and secure at network/firewall level
Or configure load balancer to forward HTTPS
Possible causes:
User/role not in authorization list
IIS denies anonymous access but credentials not provided
User doesn't exist or password is incorrect
Solution: Check configuration and verify credentials.
Cause: File type or location not allowed.
Solution: Configure file upload restrictions (see File Upload Restrictions).
File Upload Restrictions - Configure allowed file types and paths
IIS Security - Additional IIS-level hardening
Remoting - Using SPE Remoting features
Web API - Building RESTful APIs with SPE

1. Network Security
- Firewall rules
- VPN/private network
- Not internet-facing
2. IIS-Level Security
- Deny anonymous access
- IP restrictions
- HTTPS requirements
- Request filtering
3. Sitecore User Security
- Role-based access control
- Application-level permissions
- Item-level security
4. SPE Security Hardening
- Session Elevation (UAC)
- Web service controls
- File upload restrictions
- Delegated access controls
5. Logging and Monitoring
- Comprehensive logging
- Real-time alerting
- Regular audit reviews
- SIEM integration<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:security="http://www.sitecore.net/xmlconfig/security/">
<sitecore role:require="Standalone or ContentManagement or XMCloud" security:require="Sitecore">
<pipelines>
<owin.cookieAuthentication.validateIdentity>
<processor type="Sitecore.Owin.Authentication.Pipelines.CookieAuthentication.ValidateIdentity.ValidateSiteNeutralPaths, Sitecore.Owin.Authentication">
<siteNeutralPaths hint="list">
<!-- This entry corrects the infinite loop of ExecuteCommand in the SPE Console -->
<path hint="spe">/sitecore%20modules/PowerShell</path>
</siteNeutralPaths>
</processor>
</owin.cookieAuthentication.validateIdentity>
</pipelines>
</sitecore>
</configuration><sitecore>
<powershell>
<services>
<restfulv1 enabled="false" />
<restfulv2 enabled="false" />
<remoting enabled="false" />
<fileDownload enabled="false" />
<fileUpload enabled="false" />
<mediaDownload enabled="false" />
<mediaUpload enabled="false" />
<handleDownload enabled="true" />
<client enabled="true" />
<execution enabled="true" />
</services>
</powershell>
</sitecore><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<remoting>
<patch:attribute name="enabled">true</patch:attribute>
<patch:attribute name="requireSecureConnection">true</patch:attribute>
<authorization>
<add Permission="Allow" IdentityType="Role" Identity="sitecore\PowerShell Extensions Remoting" />
</authorization>
</remoting>
</services>
</powershell>
</sitecore>
</configuration><remoting>
<patch:attribute name="enabled">true</patch:attribute>
<patch:attribute name="requireSecureConnection">true</patch:attribute>
<authorization>
<add Permission="Allow" IdentityType="User" Identity="sitecore\automation-user" />
</authorization>
</remoting><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<restfulv2>
<patch:attribute name="enabled">true</patch:attribute>
</restfulv2>
</services>
</powershell>
</sitecore>
</configuration><services>
<restfulv1 enabled="false" />
<restfulv2 enabled="false" />
<remoting enabled="false" />
<fileDownload enabled="false" />
<fileUpload enabled="false" />
<mediaDownload enabled="false" />
<mediaUpload enabled="false" />
<handleDownload enabled="true" />
<client enabled="true" />
<execution enabled="true" />
</services><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<remoting>
<patch:attribute name="enabled">true</patch:attribute>
<patch:attribute name="requireSecureConnection">true</patch:attribute>
<authorization>
<patch:delete />
</authorization>
<authorization>
<add Permission="Allow" IdentityType="User" Identity="sitecore\build-automation" />
</authorization>
</remoting>
<fileDownload>
<patch:attribute name="enabled">true</patch:attribute>
</fileDownload>
</services>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<restfulv2>
<patch:attribute name="enabled">true</patch:attribute>
</restfulv2>
</services>
</powershell>
</sitecore>
</configuration><configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<remoting>
<patch:attribute name="enabled">true</patch:attribute>
<patch:attribute name="requireSecureConnection">true</patch:attribute>
</remoting>
<fileDownload>
<patch:attribute name="enabled">true</patch:attribute>
</fileDownload>
<fileUpload>
<patch:attribute name="enabled">true</patch:attribute>
</fileUpload>
<mediaDownload>
<patch:attribute name="enabled">true</patch:attribute>
</mediaDownload>
<mediaUpload>
<patch:attribute name="enabled">true</patch:attribute>
</mediaUpload>
</services>
</powershell>
</sitecore>
</configuration><authorization>
<add Permission="Allow" IdentityType="Role" Identity="sitecore\PowerShell Extensions Remoting" />
</authorization><authorization>
<patch:delete />
</authorization>
<authorization>
<add Permission="Allow" IdentityType="Role" Identity="sitecore\Automation" />
<add Permission="Allow" IdentityType="Role" Identity="sitecore\Developers" />
</authorization><authorization>
<add Permission="Allow" IdentityType="User" Identity="sitecore\ci-user" />
<add Permission="Allow" IdentityType="User" Identity="sitecore\deployment-user" />
</authorization><authorization>
<add Permission="Allow" IdentityType="Role" Identity="sitecore\PowerShell Extensions Remoting" />
<add Permission="Allow" IdentityType="User" Identity="sitecore\admin" />
<add Permission="Allow" IdentityType="User" Identity="sitecore\build-agent" />
</authorization><configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>$session = New-ScriptSession -Username "domain\user" -Password "password" -ConnectionUri "https://sitecore.local"Only UI features unless remoting needed
Production CD
None - don't install SPE
CD servers should not have SPE
HTTPS + role auth + IIS deny anonymous
restfulv2
Building web APIs
HTTPS + script-level security
fileDownload
Using SPE Remoting file operations
HTTPS + role auth + path restrictions
fileUpload
Using SPE Remoting file operations
HTTPS + role auth + strict file/path restrictions
mediaDownload
Using SPE Remoting media operations
HTTPS + role auth
mediaUpload
Using SPE Remoting media operations
HTTPS + role auth + file type restrictions
restfulv1
Never (deprecated)
N/A - don't use
Use custom role instead

STOP: If any of the above are not true, DO NOT proceed with SPE installation.
Review App_Config\Include\Spe\Spe.config (via patch file):
Services Status:
If Remoting is Enabled:
Documentation: Web Services Security
Token Configuration:
Quick Test:
Documentation: Session Elevation
Sitecore Security:
Application Pool Account:
Documentation: Security Policies, Users and Roles
Configuration:
Quick Test:
Documentation: File Upload Restrictions
Web.config Configuration (sitecore modules\PowerShell\Services\web.config):
Additional IIS Security:
IP restrictions configured (if applicable for CI/CD)
HTTPS requirement configured (production environments)
Request filtering configured to block dangerous patterns
Request size limits configured appropriately
Dangerous HTTP verbs (TRACE, OPTIONS) are blocked
Quick Test:
Tested that anonymous access is denied (401 response)
Tested that authenticated access works
Tested that HTTP is blocked/redirected (if HTTPS required)
Tested that unauthorized IPs are blocked (if IP restrictions configured)
Documentation: IIS Security
If Using Delegated Access:
Delegated access items are properly configured
Requester roles are specific (not broad like "Everyone")
Impersonated users follow least privilege (not always Admin)
Delegated scripts are reviewed for security
Delegated scripts validate input
Delegated scripts include confirmations for destructive operations
Delegated scripts log actions
Item-level security protects delegated access configurations
If NOT Using Delegated Access:
No delegated access items are enabled
Documentation: Delegated Access
For Sitecore 9.1+ with Identity Server:
Spe.IdentityServer.config is enabled
Configuration prevents infinite loop in SPE Console
Tested Console works with Identity Server authentication
Documentation: Getting Started - Identity Server
For CI/CD Environments:
Using minimal deployment package if full SPE not needed
Only required files are deployed:
Spe.config
Spe.Minimal.config
Spe.dll and Spe.Abstractions.dll
Services web.config
Service files (asmx/ashx)
Control sources are disabled (patch applied)
Remoting is enabled with proper security
Documentation: Minimal Deployment
As Non-Administrator User:
Cannot see PowerShell Console in Sitecore menu
Cannot see PowerShell ISE in Sitecore menu
Cannot see PowerShell context menus
Cannot access /sitecore/shell/Applications/PowerShell directly
As Administrator User (without elevated session):
See Console/ISE in menu
Prompted for elevation when accessing Console
Prompted for elevation when accessing ISE
Prompted for elevation when editing script items
Content Editor shows warning on PowerShell items
As Administrator User (with elevated session):
Can access Console successfully
Can access ISE successfully
Can edit PowerShell script items
Session drops after configured timeout
Can manually drop elevated session
Web Services (if enabled):
Anonymous access is denied (401)
Authenticated access works
Unauthorized users are denied (403)
File upload restrictions work as expected
IP restrictions work as expected (if configured)
Attack Surface:
Web services return 401/403 for unauthorized access
Cannot upload dangerous file types
Cannot upload to dangerous locations
Cannot bypass authentication
Cannot bypass Session Elevation
HTTPS is enforced (if configured)
Privilege Escalation:
Non-privileged users cannot access SPE features
Non-privileged users cannot modify scripts
Delegated access works as intended (if configured)
Delegated access is properly restricted
Logging Configuration:
SPE logging is enabled
Log level is appropriate (INFO for production)
Logs are being written to expected location
Log rotation is configured
Monitoring:
Reviewing SPE logs regularly for suspicious activity
Monitoring for failed authentication attempts
Monitoring for delegated access usage
Monitoring for Session Elevation denials
IIS logs are reviewed for web service access
Alert system configured for security events (optional)
Documentation: Logging and Monitoring
Required Documentation:
Security configuration is documented
Roles and their access levels are documented
Enabled web services and reasons are documented
Delegated access configurations are documented (if used)
IP restrictions and reasons are documented (if configured)
Session elevation timeouts and rationale are documented
Emergency procedures are documented
Contact information for security issues is documented
Organizational Requirements:
Security configuration reviewed by security team
Configuration meets organizational security standards
Any exceptions are documented and approved
Change management process followed
Security sign-off obtained (if required)
Regulatory Compliance (if applicable):
GDPR requirements addressed (if applicable)
PCI-DSS requirements addressed (if applicable)
HIPAA requirements addressed (if applicable)
SOC 2 requirements addressed (if applicable)
Deployment Approval:
All checklist items completed
Security testing passed
Documentation complete
Stakeholders notified
Approved By:
Developer: _________________ Date: _________
Security Team: _____________ Date: _________
IT Operations: _____________ Date: _________
Within 24 Hours:
Monitor logs for errors
Monitor logs for unauthorized access attempts
Verify Session Elevation is working in production
Verify web services respond appropriately
Test key SPE features (Console, ISE, Reports)
Within 1 Week:
Review all logs for security events
Verify no unexpected errors
Confirm monitoring/alerting is working
Document any issues and resolutions
Monthly:
Review role membership
Review enabled web services
Review delegated access configurations
Audit logs for suspicious activity
Review and update documentation
Minimum Requirements:
Session Elevation configured (can be relaxed)
Web services disabled unless needed for testing
Basic authentication configured
Optional:
IP restrictions
Strict session timeouts
HTTPS enforcement
Must Match Production:
Identical Session Elevation configuration
Identical web service configuration
Identical authentication requirements
Similar HTTPS requirements
Strictest Security:
Session Elevation with Password or Confirm (never Allow)
Short timeout (3-5 minutes)
All unnecessary web services disabled
Anonymous access denied
HTTPS required
IP restrictions (if applicable)
Request filtering enabled
Comprehensive logging
Regular monitoring
Automation-Focused:
Minimal deployment package
Remoting enabled with strict authorization
IP restrictions to build servers
HTTPS required
Service account configured
Comprehensive logging
Web Services
Spe.config (via patch)
Services enabled/disabled
Session Elevation
Spe.config (via patch)
Token expiration and action
File Upload
Spe.config (via patch)
Allowed types and locations
IIS Auth
Services\web.config
Getting Started - Initial security setup
Security Policies - Understanding the security model
Session Elevation - UAC configuration
Web Services - Web service security
- IIS-level protection
- Upload security
- Controlled privilege escalation
- Audit and monitoring
- User management
If you suspect a security breach:
Immediate Actions:
Disable all SPE web services
Block access at firewall level
Review recent logs for suspicious activity
Document the incident
Investigation:
Check IIS logs for unauthorized access
Check SPE logs for unusual script execution
Review user activity
Remediation:
Change service account passwords
Review and tighten security configuration
Apply security patches if needed
Recovery:
Restore from backup if necessary
Re-enable services with enhanced security
Monitor closely for 48 hours
To immediately lock down SPE:
Add to Services\web.config:
Track when security reviews were completed:
YYYY-MM-DD
Name
Production
✓ Pass
Initial deployment
YYYY-MM-DD
Name
QA
✓ Pass
Quarterly review
Last Updated: {{DATE}} Next Review: {{DATE + 3 months}}
<!-- Add to config patch to disable all external access -->
<configuration xmlns:patch="https://www.sitecore.net/xmlconfig/">
<sitecore>
<powershell>
<services>
<remoting enabled="false" />
<restfulv1 enabled="false" />
<restfulv2 enabled="false" />
<fileDownload enabled="false" />
<fileUpload enabled="false" />
<mediaDownload enabled="false" />
<mediaUpload enabled="false" />
</services>
<userAccountControl>
<tokens>
<token name="Console">
<patch:attribute name="elevationAction">Block</patch:attribute>
</token>
<token name="ISE">
<patch:attribute name="elevationAction">Block</patch:attribute>
</token>
</tokens>
</userAccountControl>
</powershell>
</sitecore>
</configuration><authorization>
<deny users="*" />
</authorization>Deny anonymous
Sitecore Security
Core DB items
Role permissions
Remoting Auth
Spe.config (via patch)
Authorization roles/users
Examples for managing complex interactive dialogs.
<#
.SYNOPSIS
Demonstrates basic text input controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use single-line text, multi-line text, password fields,
and placeholder text in SPE dialogs.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
Title = "Basic Text Controls"
Description = "Examples of text input fields available in SPE dialogs."
Width = 500
Height = 400
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "singleLineText"
Value = ""
Title = "Single Line Text"
Tooltip = "A simple single-line text input"
Placeholder = "Enter text here..."
},
@{
Name = "multiLineText"
Value = ""
Title = "Multi-Line Text"
Lines = 3
Tooltip = "A multi-line text area for longer content"
Placeholder = "Enter multiple lines of text..."
},
@{
Name = "passwordField"
Value = ""
Title = "Password"
Editor = "password"
Tooltip = "Password input - characters are masked"
Placeholder = "Enter password..."
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Single Line Text: $singleLineText" -ForegroundColor Green
Write-Host "Multi-Line Text: $multiLineText" -ForegroundColor Green
Write-Host "Password: $passwordField" -ForegroundColor Green
}<#
.SYNOPSIS
Demonstrates number input controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use integer and floating-point number inputs in SPE dialogs.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
Title = "Number Input Controls"
Description = "Examples of numeric input fields."
Width = 400
Height = 300
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "integerValue"
Value = 100
Editor = "number"
Title = "Integer Value"
Tooltip = "Enter a whole number"
Columns = 6
},
@{
Name = "floatValue"
Value = 1.5
Editor = "number"
Title = "Decimal Value"
Tooltip = "Enter a decimal number"
Columns = 6
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Integer Value: $integerValue" -ForegroundColor Green
Write-Host "Float Value: $floatValue" -ForegroundColor Green
# Demonstrate the returned types
Write-Host "`nReturned Types:" -ForegroundColor Cyan
Write-Host "Integer Type: $($integerValue.GetType().Name)"
Write-Host "Float Type: $($floatValue.GetType().Name)"
}<#
.SYNOPSIS
Demonstrates checkbox control in Read-Variable dialogs.
.DESCRIPTION
Shows how to use checkbox inputs that return boolean values.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize default value
$enableFeature = $true
$dialogParams = @{
Title = "Checkbox Control"
Description = "Example of checkbox input that returns a boolean value."
Width = 400
Height = 250
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "enableFeature"
Value = $true
Title = "Enable Feature"
Tooltip = "Check to enable, uncheck to disable"
Editor = "checkbox"
},
@{
Name = "includeSubitems"
Value = $false
Title = "Include Subitems"
Tooltip = "Process child items as well"
Editor = "checkbox"
},
@{
Name = "publishAfterSave"
Value = $false
Title = "Publish After Save"
Tooltip = "Automatically publish changes"
Editor = "checkbox"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Enable Feature: $enableFeature" -ForegroundColor Green
Write-Host "Include Subitems: $includeSubitems" -ForegroundColor Green
Write-Host "Publish After Save: $publishAfterSave" -ForegroundColor Green
# Example conditional logic based on checkbox values
if ($enableFeature) {
Write-Host "`nFeature is enabled!" -ForegroundColor Cyan
}
}<#
.SYNOPSIS
Demonstrates dropdown (combo) controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to create dropdown lists with predefined options and tooltips.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Define options as an ordered hashtable
# Format: @{ "Display Text" = "Value" }
$priorityOptions = [ordered]@{
"Low" = "1"
"Medium" = "2"
"High" = "3"
"Critical" = "4"
}
# Options with tooltips
$actionOptions = [ordered]@{
"Create" = "create"
"Update" = "update"
"Delete" = "delete"
"Archive" = "archive"
}
$actionTooltips = [ordered]@{
"create" = "Create a new item in Sitecore"
"update" = "Modify an existing item"
"delete" = "Remove the item permanently"
"archive" = "Move the item to archive"
}
$dialogParams = @{
Title = "Dropdown Controls"
Description = "Examples of combo/dropdown selection controls."
Width = 450
Height = 350
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedPriority"
Value = "2"
Title = "Priority Level"
Options = $priorityOptions
Tooltip = "Select the priority for this task"
Editor = "combo"
},
@{
Name = "selectedAction"
Value = "update"
Title = "Action Type"
Options = $actionOptions
OptionTooltips = $actionTooltips
Tooltip = "Choose the action to perform"
Editor = "combo"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Selected Priority: $selectedPriority" -ForegroundColor Green
Write-Host "Selected Action: $selectedAction" -ForegroundColor Green
}<#
.SYNOPSIS
Demonstrates checklist control for multiple selections in Read-Variable dialogs.
.DESCRIPTION
Shows how to create a checklist that allows users to select multiple options.
The checklist uses bitmask values for selections.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Define options with bitmask values
# Each value should be a power of 2 for proper bitmask operations
$daysOfWeek = [ordered]@{
"Monday" = 1
"Tuesday" = 2
"Wednesday" = 4
"Thursday" = 8
"Friday" = 16
"Saturday" = 32
"Sunday" = 64
}
# Pre-select some items by providing an array of values
$selectedDays = @(1, 4, 16) # Monday, Wednesday, Friday
$languageOptions = [ordered]@{
"English" = 1
"German" = 2
"French" = 4
"Spanish" = 8
"Japanese" = 16
}
$selectedLanguages = @(1) # English pre-selected
$dialogParams = @{
Title = "Checklist Controls"
Description = "Select multiple options using checklists."
Width = 450
Height = 450
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedDays"
Title = "Days of the Week"
Options = $daysOfWeek
Tooltip = "Select which days to run the scheduled task"
Editor = "checklist"
},
@{
Name = "selectedLanguages"
Title = "Target Languages"
Options = $languageOptions
Tooltip = "Select languages for content translation"
Editor = "checklist"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Selected Days (values): $($selectedDays -join ', ')" -ForegroundColor Green
Write-Host "Selected Languages (values): $($selectedLanguages -join ', ')" -ForegroundColor Green
# Map values back to display names
Write-Host "`nSelected Day Names:" -ForegroundColor Cyan
foreach ($day in $daysOfWeek.GetEnumerator()) {
if ($selectedDays -contains $day.Value) {
Write-Host " - $($day.Key)"
}
}
}<#
.SYNOPSIS
Demonstrates radio button control for single selection in Read-Variable dialogs.
.DESCRIPTION
Shows how to create radio button groups that allow users to select exactly one option.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Define options for radio buttons
$publishMode = [ordered]@{
"Smart Publish" = 1
"Incremental Publish" = 2
"Full Republish" = 3
}
$targetDatabase = [ordered]@{
"Web" = "web"
"Preview" = "preview"
"Staging" = "staging"
}
# Pre-select an option
$selectedPublishMode = 1
$selectedDatabase = "web"
$dialogParams = @{
Title = "Radio Button Controls"
Description = "Select exactly one option from each group."
Width = 450
Height = 400
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedPublishMode"
Title = "Publish Mode"
Options = $publishMode
Tooltip = "Choose how content should be published"
Editor = "radio"
},
@{
Name = "selectedDatabase"
Title = "Target Database"
Options = $targetDatabase
Tooltip = "Select the destination database"
Editor = "radio"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Selected Publish Mode: $selectedPublishMode" -ForegroundColor Green
Write-Host "Selected Database: $selectedDatabase" -ForegroundColor Green
# Use the selection in logic
switch ($selectedPublishMode) {
1 { Write-Host "`nPerforming Smart Publish..." -ForegroundColor Cyan }
2 { Write-Host "`nPerforming Incremental Publish..." -ForegroundColor Cyan }
3 { Write-Host "`nPerforming Full Republish..." -ForegroundColor Cyan }
}
}<#
.SYNOPSIS
Demonstrates date and time picker controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use date-only and date-time picker controls.
Both return System.DateTime objects.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Set default values
$startDateTime = [System.DateTime]::Now.AddDays(-7)
$endDateTime = [System.DateTime]::Now
$publishDate = [System.DateTime]::Now.AddDays(1)
$dialogParams = @{
Title = "Date and Time Controls"
Description = "Select dates and times for your operation."
Width = 500
Height = 400
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "startDateTime"
Value = [System.DateTime]::Now.AddDays(-7)
Title = "Start Date/Time"
Tooltip = "Select the starting date and time"
Editor = "date time"
},
@{
Name = "endDateTime"
Value = [System.DateTime]::Now
Title = "End Date/Time"
Tooltip = "Select the ending date and time"
Editor = "date time"
},
@{
Name = "publishDate"
Value = [System.DateTime]::Now.AddDays(1)
Title = "Publish Date (Date Only)"
Tooltip = "Select the date for publishing"
Editor = "date"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Date/Time Controls return System.DateTime objects:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Start DateTime: $startDateTime" -ForegroundColor Green
Write-Host " Type: $($startDateTime.GetType().FullName)"
Write-Host ""
Write-Host "End DateTime: $endDateTime" -ForegroundColor Green
Write-Host " Type: $($endDateTime.GetType().FullName)"
Write-Host ""
Write-Host "Publish Date: $publishDate" -ForegroundColor Green
Write-Host " Type: $($publishDate.GetType().FullName)"
Write-Host ""
# Calculate duration
$duration = $endDateTime - $startDateTime
Write-Host "Duration: $($duration.Days) days, $($duration.Hours) hours" -ForegroundColor Yellow
}<#
.SYNOPSIS
Demonstrates single item picker control in Read-Variable dialogs.
.DESCRIPTION
Shows how to use the item picker to select a single Sitecore item.
Returns a Sitecore Item object.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variables with default Item objects
# Read-Variable requires item variables to be pre-initialized
$selectedItem = Get-Item -Path "master:\content\Home"
$templateItem = Get-Item -Path "master:\templates\System\Templates\Template"
$dialogParams = @{
Title = "Single Item Picker"
Description = "Select a single item from the content tree."
Width = 500
Height = 350
OkButtonName = "Select"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedItem"
Title = "Select Content Item"
Root = "/sitecore/content/"
Tooltip = "Browse and select an item from the content tree"
},
@{
Name = "templateItem"
Title = "Select Template"
Root = "/sitecore/templates/"
Tooltip = "Browse and select a template"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Item Picker returns Sitecore Item objects:" -ForegroundColor Cyan
Write-Host ""
if ($selectedItem) {
Write-Host "Selected Content Item:" -ForegroundColor Green
Write-Host " Name: $($selectedItem.Name)"
Write-Host " Path: $($selectedItem.ItemPath)"
Write-Host " ID: $($selectedItem.ID)"
Write-Host " Template: $($selectedItem.TemplateName)"
} else {
Write-Host "No content item selected" -ForegroundColor Yellow
}
Write-Host ""
if ($templateItem) {
Write-Host "Selected Template:" -ForegroundColor Green
Write-Host " Name: $($templateItem.Name)"
Write-Host " Path: $($templateItem.ItemPath)"
Write-Host " ID: $($templateItem.ID)"
} else {
Write-Host "No template selected" -ForegroundColor Yellow
}
}<#
.SYNOPSIS
Demonstrates treelist control for multiple item selection in Read-Variable dialogs.
.DESCRIPTION
Shows how to use treelist to select multiple items with a tree-based interface.
Returns an array of Sitecore Item objects.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize with an array of Item objects (can be empty array or pre-selected items)
$selectedTemplates = @(Get-Item -Path "master:\templates\System\Templates\Template")
$dialogParams = @{
Title = "Treelist Control"
Description = "Select multiple items using the treelist interface."
Width = 600
Height = 500
OkButtonName = "Select"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedTemplates"
Title = "Select Templates"
Source = "DataSource=/sitecore/templates&DatabaseName=master&IncludeTemplatesForDisplay=Node,Folder,Template,Template Folder&IncludeTemplatesForSelection=Template"
Editor = "treelist"
Tooltip = "Select one or more templates from the tree"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Treelist returns an array of Sitecore Item objects:" -ForegroundColor Cyan
Write-Host ""
if ($selectedTemplates -and $selectedTemplates.Count -gt 0) {
Write-Host "Selected $($selectedTemplates.Count) template(s):" -ForegroundColor Green
Write-Host ""
foreach ($template in $selectedTemplates) {
Write-Host " - $($template.Name)" -ForegroundColor White
Write-Host " Path: $($template.ItemPath)"
Write-Host " ID: $($template.ID)"
Write-Host ""
}
} else {
Write-Host "No templates selected" -ForegroundColor Yellow
}
}
<#
TREELIST SOURCE PARAMETERS:
The Source parameter uses a query string format with these options:
- DataSource: Root path for the tree (e.g., /sitecore/templates)
- DatabaseName: Target database (master, web, core)
- IncludeTemplatesForDisplay: Templates to show in tree (comma-separated)
- IncludeTemplatesForSelection: Templates that can be selected (comma-separated)
- ExcludeTemplatesForDisplay: Templates to hide
- ExcludeTemplatesForSelection: Templates that cannot be selected
Example configurations:
# Select pages under content
Source = "DataSource=/sitecore/content&DatabaseName=master&IncludeTemplatesForSelection=Page,Article"
# Select media items
Source = "DataSource=/sitecore/media library&DatabaseName=master&IncludeTemplatesForSelection=Image,Jpeg,Png"
#><#
.SYNOPSIS
Demonstrates multilist control for multiple item selection in Read-Variable dialogs.
.DESCRIPTION
Shows how to use multilist and multilist search controls.
Both return arrays of Sitecore Item objects.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variable - required for item picker
$selectedItems = @(Get-Item -Path "master:\templates\System\Templates\Template")
$searchableItems = @(Get-Item -Path "master:\templates\System\Templates\Standard template")
$dialogParams = @{
Title = "Multilist Controls"
Description = "Select multiple items using multilist interfaces."
Width = 650
Height = 600
OkButtonName = "Select"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedItems"
Title = "Multilist (Standard)"
Source = "DataSource=/sitecore/templates/System&DatabaseName=master&IncludeTemplatesForDisplay=Template Folder,Template&IncludeTemplatesForSelection=Template"
Editor = "multilist"
Height = "200px"
Tooltip = "Select items by moving them between lists"
},
@{
Name = "searchableItems"
Title = "Multilist with Search"
Source = "DataSource=/sitecore/templates&DatabaseName=master&IncludeTemplatesForDisplay=Template Folder,Template&IncludeTemplatesForSelection=Template"
Editor = "multilist search"
Height = "200px"
Tooltip = "Search and select items - great for large lists"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Multilist controls return arrays of Sitecore Item objects:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Standard Multilist Selection:" -ForegroundColor Green
if ($selectedItems -and $selectedItems.Count -gt 0) {
foreach ($item in $selectedItems) {
Write-Host " - $($item.Name) [$($item.ID)]"
}
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Multilist Search Selection:" -ForegroundColor Green
if ($searchableItems -and $searchableItems.Count -gt 0) {
foreach ($item in $searchableItems) {
Write-Host " - $($item.Name) [$($item.ID)]"
}
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
}
<#
MULTILIST vs MULTILIST SEARCH:
Standard Multilist:
- Shows all available items in a scrollable list
- Best for smaller datasets (< 100 items)
- Drag-and-drop interface
Multilist Search:
- Includes a search box to filter items
- Best for larger datasets where browsing isn't practical
- Same selection behavior as standard multilist
Both use the same Source parameter format as treelist.
#><#
.SYNOPSIS
Demonstrates droplist control for single item selection in Read-Variable dialogs.
.DESCRIPTION
Shows how to use droplist to select a single item from a flat list.
Returns a Sitecore Item object.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variable - required for item picker
$selectedTemplate = Get-Item -Path "master:\templates\sample\sample item"
$dialogParams = @{
Title = "Droplist Control"
Description = "Select a single item from a dropdown list."
Width = 500
Height = 300
OkButtonName = "Select"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedTemplate"
Title = "Select a Template"
Source = "DataSource=/sitecore/templates/sample&DatabaseName=master&IncludeTemplatesForDisplay=Template Folder,Template&IncludeTemplatesForSelection=Template"
Editor = "droplist"
Tooltip = "Choose a single template from the dropdown"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Droplist returns a single Sitecore Item object:" -ForegroundColor Cyan
Write-Host ""
if ($selectedTemplate) {
Write-Host "Selected Template:" -ForegroundColor Green
Write-Host " Name: $($selectedTemplate.Name)"
Write-Host " Path: $($selectedTemplate.ItemPath)"
Write-Host " ID: $($selectedTemplate.ID)"
Write-Host " Type: $($selectedTemplate.GetType().FullName)"
} else {
Write-Host "No template selected" -ForegroundColor Yellow
}
}
<#
DROPLIST vs COMBO:
Droplist:
- Displays Sitecore items from a data source
- Returns a Sitecore Item object
- Uses Source parameter with DataSource path
Combo:
- Displays key-value pairs defined in script
- Returns the value (usually a string or number)
- Uses Options parameter with hashtable
Use Droplist when you need to select from Sitecore items.
Use Combo when you need predefined options.
#><#
.SYNOPSIS
Demonstrates grouped dropdown controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use groupeddroplink and groupeddroplist controls.
These display items grouped by their parent folders.
- groupeddroplink: Returns the selected Item object
- groupeddroplist: Returns the item's string value (path or ID)
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
Title = "Grouped Dropdown Controls"
Description = "Select items from grouped dropdown lists."
Width = 550
Height = 350
OkButtonName = "Select"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedGroupedDroplink"
Title = "Grouped Droplink (Returns Item)"
Source = "DataSource=/sitecore/templates&DatabaseName=master&IncludeTemplatesForDisplay=Node,Folder,Template,Template Folder&IncludeTemplatesForSelection=Template"
Editor = "groupeddroplink"
Tooltip = "Items grouped by folder - returns Item object"
},
@{
Name = "selectedGroupedDroplist"
Title = "Grouped Droplist (Returns String)"
Source = "DataSource=/sitecore/templates&DatabaseName=master&IncludeTemplatesForDisplay=Node,Folder,Template,Template Folder&IncludeTemplatesForSelection=Template"
Editor = "groupeddroplist"
Tooltip = "Items grouped by folder - returns string value"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Grouped Dropdown Controls:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Grouped Droplink (returns Item):" -ForegroundColor Green
if ($selectedGroupedDroplink) {
Write-Host " Name: $($selectedGroupedDroplink.Name)"
Write-Host " Path: $($selectedGroupedDroplink.ItemPath)"
Write-Host " Type: $($selectedGroupedDroplink.GetType().Name)"
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Grouped Droplist (returns String):" -ForegroundColor Green
if ($selectedGroupedDroplist) {
Write-Host " Value: $selectedGroupedDroplist"
Write-Host " Type: $($selectedGroupedDroplist.GetType().Name)"
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
}
<#
GROUPED DROPDOWNS:
Both groupeddroplink and groupeddroplist display items organized
by their parent folders, making it easier to navigate large item sets.
Key Difference:
- groupeddroplink: Returns the actual Sitecore Item object
- groupeddroplist: Returns a string representation
Use groupeddroplink when you need to work with the Item object.
Use groupeddroplist when you only need the item's path or ID.
#><#
.SYNOPSIS
Demonstrates user and role picker controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use user, role, and combined user/role selection controls.
These are essential for security and permission-related scripts.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
Title = "User and Role Pickers"
Description = "Select users and roles for permission management."
Width = 550
Height = 450
OkButtonName = "Select"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "selectedUser"
Title = "Select User(s)"
Editor = "user multiple"
Tooltip = "Select one or more users"
},
@{
Name = "selectedRole"
Title = "Select Role(s)"
Editor = "role multiple"
Domain = "sitecore"
Tooltip = "Select one or more roles from the sitecore domain"
},
@{
Name = "selectedUserOrRole"
Title = "Select User(s) or Role(s)"
Editor = "user role multiple"
Domain = "sitecore"
Tooltip = "Select any combination of users and roles"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "User and Role Pickers return string values:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Selected Users:" -ForegroundColor Green
if ($selectedUser) {
$selectedUser | ForEach-Object { Write-Host " - $_" }
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Selected Roles:" -ForegroundColor Green
if ($selectedRole) {
$selectedRole | ForEach-Object { Write-Host " - $_" }
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Selected Users or Roles:" -ForegroundColor Green
if ($selectedUserOrRole) {
$selectedUserOrRole | ForEach-Object { Write-Host " - $_" }
} else {
Write-Host " (none selected)" -ForegroundColor Yellow
}
}
<#
USER AND ROLE EDITOR VARIANTS:
Single Selection:
- "user" : Select one user
- "role" : Select one role
- "user role" : Select one user or role
Multiple Selection:
- "user multiple" : Select multiple users
- "role multiple" : Select multiple roles
- "user role multiple" : Select multiple users and/or roles
Domain Parameter:
The Domain parameter filters roles to a specific security domain.
Common domains: "sitecore", "extranet", custom domains
Return Values:
- Single selection returns a string
- Multiple selection returns an array of strings
- Format: "domain\username" or "domain\rolename"
#><#
.SYNOPSIS
Demonstrates rule editor controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use rule and rule action editors for creating
Sitecore rules with conditions and actions.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# You can pre-populate with an existing rule
# Get a sample rule from an existing item
$existingRule = $null
$ruleItem = Get-Item -Path "master:" -ID "{D00BD134-EB15-41A7-BEF1-E6455C6BC9AC}" -ErrorAction SilentlyContinue
if ($ruleItem) {
$existingRule = $ruleItem | Select-Object -ExpandProperty ShowRule -ErrorAction SilentlyContinue
}
$dialogParams = @{
Title = "Rule Editor Controls"
Description = "Create rules with conditions and optional actions."
Width = 700
Height = 500
OkButtonName = "Save Rules"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "conditionRule"
Title = "Condition Rule"
Editor = "rule"
Tooltip = "Define conditions only (no actions)"
},
@{
Name = "actionRule"
Title = "Rule with Actions"
Editor = "rule action"
Tooltip = "Define conditions and actions to execute"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Rule Editors return XML string values:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Condition Rule:" -ForegroundColor Green
if ($conditionRule) {
Write-Host " Length: $($conditionRule.Length) characters"
Write-Host " Preview: $($conditionRule.Substring(0, [Math]::Min(100, $conditionRule.Length)))..."
} else {
Write-Host " (no rule defined)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Rule with Actions:" -ForegroundColor Green
if ($actionRule) {
Write-Host " Length: $($actionRule.Length) characters"
Write-Host " Preview: $($actionRule.Substring(0, [Math]::Min(100, $actionRule.Length)))..."
} else {
Write-Host " (no rule defined)" -ForegroundColor Yellow
}
}
<#
RULE EDITOR TYPES:
"rule" Editor:
- Conditions only (WHERE clauses)
- Use for filtering, visibility rules, validation
- Example: Show field when template is X
"rule action" Editor:
- Conditions AND actions
- Use for automation, workflows, scheduled tasks
- Example: When item is created, set default values
Return Value:
Both editors return an XML string representing the rule definition.
This XML can be stored in a rule field or parsed for processing.
Common Use Cases:
- Content validation rules
- Conditional rendering rules
- Workflow state transitions
- Scheduled task filters
- Personalization conditions
#><#
.SYNOPSIS
Demonstrates information display controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to use info and marquee controls to display
read-only information and messages to users.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
Title = "Information Display Controls"
Description = "Display important information to users."
Width = 550
Height = 400
OkButtonName = "Continue"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "marqueeMessage"
Title = "Marquee - Scrolling Message"
Value = "This is an important scrolling message that catches attention!"
Editor = "marquee"
},
@{
Name = "infoMessage"
Title = "Info - Static Information"
Value = "This is static informational text that provides context or instructions to the user. It does not scroll and is easier to read for longer messages."
Editor = "info"
},
@{
Name = "userInput"
Title = "Your Response"
Value = ""
Tooltip = "Enter your response after reading the information above"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "User acknowledged the information and provided:" -ForegroundColor Cyan
Write-Host "Response: $userInput" -ForegroundColor Green
}
<#
DISPLAY CONTROLS (Read-Only):
"marquee" Editor:
- Displays scrolling text
- Good for alerts or important notices
- Catches user attention with animation
"info" Editor:
- Displays static text
- Good for instructions, context, or longer messages
- No animation, easier to read
Common Use Cases:
- Display warnings before destructive operations
- Show instructions for complex forms
- Provide context about selected items
- Display calculated values or status information
Note: These are display-only controls. The Value is shown
but not returned or modified by user interaction.
#><#
.SYNOPSIS
Demonstrates variable binding in Read-Variable dialogs.
.DESCRIPTION
Shows how to bind existing PowerShell variables to dialog controls
using the Variable parameter instead of Name/Value.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Get an existing item to use as a variable
$parentItem = Get-Item -Path "master:\content\Home" -ErrorAction SilentlyContinue
if (-not $parentItem) {
$parentItem = Get-Item -Path "master:\content" -ErrorAction SilentlyContinue
}
# Define other variables
$searchQuery = "sample query"
$maxResults = 50
$dialogParams = @{
Title = "Variable Binding Example"
Description = "Bind existing variables directly to dialog controls."
Width = 500
Height = 400
OkButtonName = "Process"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
# Use Variable instead of Name to bind directly to existing variable
Variable = Get-Variable "parentItem"
Title = "Parent Item (Variable Binding)"
Tooltip = "This control is bound to the `$parentItem variable"
},
@{
Variable = Get-Variable "searchQuery"
Title = "Search Query (Variable Binding)"
Tooltip = "Bound to `$searchQuery variable"
},
@{
Variable = Get-Variable "maxResults"
Title = "Max Results (Variable Binding)"
Editor = "number"
Tooltip = "Bound to `$maxResults variable"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Variable Binding Results:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Parent Item:" -ForegroundColor Green
if ($parentItem) {
Write-Host " Name: $($parentItem.Name)"
Write-Host " Path: $($parentItem.ItemPath)"
}
Write-Host ""
Write-Host "Search Query: $searchQuery" -ForegroundColor Green
Write-Host "Max Results: $maxResults" -ForegroundColor Green
}
<#
VARIABLE BINDING vs NAME/VALUE:
Name/Value Approach:
- Creates a new variable with the specified Name
- Initial value set with Value parameter
@{ Name = "myVar"; Value = "initial" }
Variable Binding:
- Binds directly to an existing PowerShell variable
- Use Get-Variable to reference the variable
- Variable is updated in-place when dialog closes
@{ Variable = Get-Variable "existingVar" }
When to Use Variable Binding:
- When you already have variables with values from previous operations
- When you want to modify existing context variables
- When working with items from the current context (like $item)
Benefits:
- Less boilerplate code
- Variables retain their type information
- Direct modification of existing state
#><#
.SYNOPSIS
Demonstrates tabbed dialogs in Read-Variable.
.DESCRIPTION
Shows how to organize controls into multiple tabs for complex dialogs.
Use the Tab parameter to assign controls to specific tabs.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variable - required for item picker
$template = Get-Item -Path "master:\templates\sample\sample item"
$dialogParams = @{
Title = "Tabbed Dialog Example"
Description = "Controls organized into logical tabs."
Width = 600
Height = 500
OkButtonName = "Save"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
# General Tab
@{
Name = "itemName"
Title = "Item Name"
Value = ""
Tooltip = "Enter the name for the new item"
Tab = "General"
Placeholder = "Enter name..."
},
@{
Name = "itemTitle"
Title = "Display Title"
Value = ""
Tooltip = "The title shown to users"
Tab = "General"
Placeholder = "Enter title..."
},
@{
Name = "description"
Title = "Description"
Value = ""
Lines = 3
Tooltip = "Describe this item"
Tab = "General"
},
# Settings Tab
@{
Name = "isActive"
Title = "Active"
Value = $true
Editor = "checkbox"
Tooltip = "Enable or disable this item"
Tab = "Settings"
},
@{
Name = "priority"
Title = "Priority"
Value = 100
Editor = "number"
Tooltip = "Sort order priority"
Tab = "Settings"
},
@{
Name = "publishDate"
Title = "Publish Date"
Value = [DateTime]::Now
Editor = "date time"
Tooltip = "When to publish"
Tab = "Settings"
},
# Advanced Tab
@{
Name = "template"
Title = "Template"
Root = "/sitecore/templates/"
Tooltip = "Select a template"
Tab = "Advanced"
},
@{
Name = "targetUser"
Title = "Owner"
Editor = "user"
Tooltip = "Select the owner"
Tab = "Advanced"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Tabbed Dialog Results:" -ForegroundColor Cyan
Write-Host ""
Write-Host "General Tab:" -ForegroundColor Green
Write-Host " Item Name: $itemName"
Write-Host " Title: $itemTitle"
Write-Host " Description: $description"
Write-Host ""
Write-Host "Settings Tab:" -ForegroundColor Green
Write-Host " Active: $isActive"
Write-Host " Priority: $priority"
Write-Host " Publish Date: $publishDate"
Write-Host ""
Write-Host "Advanced Tab:" -ForegroundColor Green
Write-Host " Template: $($template.Name)"
Write-Host " Owner: $targetUser"
}
<#
TAB ORGANIZATION:
Use the Tab parameter to organize controls:
@{ Name = "field"; Tab = "Tab Name" }
Tips:
- Tabs appear in the order of their first control
- Group related controls on the same tab
- Use clear, concise tab names
- Limit to 4-5 tabs maximum for usability
Common Tab Patterns:
- "General" / "Settings" / "Advanced"
- "Content" / "Metadata" / "Publishing"
- "Source" / "Target" / "Options"
- "Basic" / "Security" / "Workflow"
#><#
.SYNOPSIS
Demonstrates conditional visibility of controls in Read-Variable dialogs.
.DESCRIPTION
Shows how to show/hide controls based on other control values using
GroupId, ParentGroupId, and HideOnValue parameters.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Define options for the controlling dropdown
$modeOptions = [ordered]@{
"Simple Mode" = "simple"
"Advanced Mode" = "advanced"
"Expert Mode" = "expert"
}
$dialogParams = @{
Title = "Conditional Visibility Example"
Description = "Controls appear/disappear based on your selection."
Width = 550
Height = 450
OkButtonName = "Continue"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
# Checkbox controlling visibility
@{
Name = "showAdvanced"
Title = "Show Advanced Options"
Value = $true
Editor = "checkbox"
Tooltip = "Toggle to show/hide advanced options"
GroupId = 1 # This control is the "parent" group
},
@{
Name = "advancedOption1"
Title = "Advanced Option 1"
Value = ""
Tooltip = "This field shows when checkbox is checked"
ParentGroupId = 1 # Linked to group 1
HideOnValue = "0" # Hide when checkbox value is 0 (unchecked)
},
@{
Name = "advancedOption2"
Title = "Advanced Option 2"
Value = ""
Tooltip = "This field also shows when checkbox is checked"
ParentGroupId = 1
HideOnValue = "0"
},
# Dropdown controlling visibility
@{
Name = "operationMode"
Title = "Operation Mode"
Value = "simple"
Options = $modeOptions
Editor = "combo"
Tooltip = "Select mode to see different options"
GroupId = 2 # This dropdown controls group 2
},
@{
Name = "simpleField"
Title = "Simple Mode Field"
Value = ""
Tooltip = "Visible only in Simple Mode"
ParentGroupId = 2
ShowOnValue = "simple" # Hidden when advanced or expert selected
},
@{
Name = "advancedField"
Title = "Advanced Mode Field"
Value = ""
Tooltip = "Visible only in Advanced Mode"
ParentGroupId = 2
ShowOnValue = "advanced" # Hidden when simple or expert selected
},
@{
Name = "expertField"
Title = "Expert Mode Field"
Value = ""
Tooltip = "Visible only in Expert Mode"
ParentGroupId = 2
ShowOnValue = "expert" # Hidden when simple or advanced selected
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Conditional Visibility Results:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Show Advanced: $showAdvanced" -ForegroundColor Green
if ($showAdvanced) {
Write-Host " Advanced Option 1: $advancedOption1"
Write-Host " Advanced Option 2: $advancedOption2"
}
Write-Host ""
Write-Host "Operation Mode: $operationMode" -ForegroundColor Green
switch ($operationMode) {
"simple" { Write-Host " Simple Field: $simpleField" }
"advanced" { Write-Host " Advanced Field: $advancedField" }
"expert" { Write-Host " Expert Field: $expertField" }
}
}
<#
CONDITIONAL VISIBILITY PARAMETERS:
GroupId:
- Assigns a numeric ID to a "controlling" control
- This control's value determines visibility of child controls
ParentGroupId:
- Links a control to a parent group
- This control's visibility depends on the parent's value
HideOnValue:
- Specifies which parent values hide this control
- For checkboxes: "0" = unchecked, "1" = checked
- For combos/radios: Use the option values (not display text)
- Multiple values: Comma-separated list
Common Patterns:
1. Checkbox Toggle:
Parent: @{ Editor="checkbox"; GroupId=1 }
Child: @{ ParentGroupId=1; HideOnValue="0" } # Show when checked
Child: @{ ParentGroupId=1; HideOnValue="1" } # Show when unchecked
2. Dropdown Selection:
Parent: @{ Editor="combo"; Options=$opts; GroupId=2 }
Child: @{ ParentGroupId=2; HideOnValue="optionA,optionB" }
3. Radio Selection:
Parent: @{ Editor="radio"; Options=$opts; GroupId=3 }
Child: @{ ParentGroupId=3; HideOnValue="1,2" } # Hide for values 1 and 2
#><#
.SYNOPSIS
Demonstrates column layout in Read-Variable dialogs.
.DESCRIPTION
Shows how to arrange controls in columns using the Columns parameter.
The dialog uses a 12-column grid system.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
Title = "Column Layout Example"
Description = "Controls arranged in a responsive grid layout."
Width = 650
Height = 500
OkButtonName = "Save"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
# Full width (12 columns - default)
@{
Name = "fullWidthField"
Title = "Full Width Field (12 columns)"
Value = ""
Tooltip = "This field spans the full width"
# Columns = 12 is the default
},
# Two columns side by side (6 + 6)
@{
Name = "firstName"
Title = "First Name"
Value = ""
Tooltip = "Half width"
Columns = 6
},
@{
Name = "lastName"
Title = "Last Name"
Value = ""
Tooltip = "Half width"
Columns = 6
},
# Three columns (4 + 4 + 4)
@{
Name = "city"
Title = "City"
Value = ""
Tooltip = "One third width"
Columns = 4
},
@{
Name = "state"
Title = "State"
Value = ""
Tooltip = "One third width"
Columns = 4
},
@{
Name = "zip"
Title = "ZIP Code"
Value = ""
Tooltip = "One third width"
Columns = 4
},
# Unequal columns (8 + 4)
@{
Name = "email"
Title = "Email Address"
Value = ""
Tooltip = "Two thirds width"
Columns = 8
},
@{
Name = "extension"
Title = "Ext"
Value = ""
Tooltip = "One third width"
Columns = 4
},
# Mixed with checkbox (small column)
@{
Name = "notes"
Title = "Additional Notes"
Value = ""
Lines = 2
Tooltip = "Main content area"
Columns = 9
},
@{
Name = "isUrgent"
Title = "Urgent"
Value = $false
Editor = "checkbox"
Tooltip = "Mark as urgent"
Columns = 3
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Column Layout Results:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Full Width: $fullWidthField" -ForegroundColor Green
Write-Host "Name: $firstName $lastName" -ForegroundColor Green
Write-Host "Location: $city, $state $zip" -ForegroundColor Green
Write-Host "Email: $email (ext: $extension)" -ForegroundColor Green
Write-Host "Notes: $notes" -ForegroundColor Green
Write-Host "Urgent: $isUrgent" -ForegroundColor Green
}
<#
COLUMN LAYOUT (12-Column Grid):
The Columns parameter uses a 12-column grid system:
Full Width: Columns = 12 (default)
Half Width: Columns = 6
Third Width: Columns = 4
Quarter Width: Columns = 3
Two-Thirds: Columns = 8
Common Patterns:
Two Equal Columns:
@{ Columns = 6 }, @{ Columns = 6 }
Three Equal Columns:
@{ Columns = 4 }, @{ Columns = 4 }, @{ Columns = 4 }
Main + Sidebar:
@{ Columns = 8 }, @{ Columns = 4 }
Four Equal Columns:
@{ Columns = 3 }, @{ Columns = 3 }, @{ Columns = 3 }, @{ Columns = 3 }
Tips:
- Column values should add up to 12 for a complete row
- Controls wrap to next row automatically
- Combine with tabs for complex layouts
- Consider dialog width when using many columns
#><#
.SYNOPSIS
Demonstrates mandatory fields and validation in Read-Variable dialogs.
.DESCRIPTION
Shows how to mark fields as required using the Mandatory parameter.
Required fields must have a value before the dialog can be submitted.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variable - required for item picker
$requiredItem = Get-Item -Path "master:\content\home"
$dialogParams = @{
Title = "Required Fields Example"
Description = "Fields marked with * are required."
Width = 500
Height = 400
OkButtonName = "Submit"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
@{
Name = "requiredField"
Title = "Required Text Field"
Value = ""
Tooltip = "This field must be filled in"
Placeholder = "This field is required..."
Mandatory = $true
},
@{
Name = "optionalField"
Title = "Optional Text Field"
Value = ""
Tooltip = "This field is optional"
Placeholder = "This field is optional..."
Mandatory = $false
},
@{
Name = "requiredNumber"
Title = "Required Number"
Value = $null
Editor = "number"
Tooltip = "A number must be entered"
Mandatory = $true
},
@{
Name = "requiredItem"
Title = "Required Item Selection"
Root = "/sitecore/content/"
Tooltip = "An item must be selected"
Mandatory = $true
},
@{
Name = "optionalMultiline"
Title = "Optional Notes"
Value = ""
Lines = 3
Tooltip = "Additional notes (optional)"
Mandatory = $false
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Form submitted successfully!" -ForegroundColor Cyan
Write-Host ""
Write-Host "Required Field: $requiredField" -ForegroundColor Green
Write-Host "Optional Field: $optionalField" -ForegroundColor Green
Write-Host "Required Number: $requiredNumber" -ForegroundColor Green
if ($requiredItem) {
Write-Host "Required Item: $($requiredItem.Name)" -ForegroundColor Green
}
Write-Host "Optional Notes: $optionalMultiline" -ForegroundColor Green
} else {
Write-Host "Dialog was cancelled" -ForegroundColor Yellow
}
<#
MANDATORY FIELDS:
The Mandatory parameter enforces that a field has a value:
@{ Name = "field"; Mandatory = $true }
Behavior:
- Required fields show an asterisk (*) in the label
- Dialog cannot be submitted until all required fields have values
- An error message appears if user tries to submit with empty required fields
- Default is Mandatory = $false
Supported Field Types:
- Text fields (single and multi-line)
- Number fields
- Item pickers
- User/Role selectors
- Dropdowns and lists
- Date/time fields
Notes:
- Checkboxes don't support Mandatory (they always have a value)
- For item pickers, the user must select an item
- Empty strings "" are considered invalid for mandatory text fields
- Consider using Placeholder text to guide users on required fields
#><#
.SYNOPSIS
Demonstrates dialog customization options in Read-Variable.
.DESCRIPTION
Shows how to customize dialog appearance including title, description,
icon, dimensions, button labels, and hint display.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
$dialogParams = @{
# Dialog Title - appears in the title bar
Title = "Custom Dialog Example"
# Description - appears below the title
Description = "This dialog demonstrates all available customization options for Read-Variable dialogs."
# Icon - Sitecore icon path (various icon sets available)
Icon = "Office/32x32/coffee.png"
# Dimensions
Width = 550
Height = 400
# Button Labels
OkButtonName = "Process Items"
CancelButtonName = "Abort"
# Show tooltips for controls
ShowHints = $true
# Controls
Parameters = @(
@{
Name = "inputText"
Title = "Sample Input"
Value = ""
Tooltip = "This tooltip appears when ShowHints is enabled"
Placeholder = "Enter something..."
},
@{
Name = "confirm"
Title = "I understand the implications"
Value = $false
Editor = "checkbox"
Tooltip = "Check to confirm"
}
)
}
$result = Read-Variable @dialogParams
if ($result -eq "ok") {
Write-Host "Dialog completed with custom settings!" -ForegroundColor Green
Write-Host "Input: $inputText"
Write-Host "Confirmed: $confirm"
} else {
Write-Host "User clicked the custom cancel button" -ForegroundColor Yellow
}
<#
DIALOG CUSTOMIZATION OPTIONS:
Title (string):
- Text shown in the dialog title bar
- Keep concise but descriptive
Description (string):
- Explanatory text below the title
- Use for instructions or context
- Can span multiple lines
Icon (string):
- Sitecore icon path
- Format: "IconSet/Size/iconname.png"
- Common sets: Office, Business, Software, People, Officewhite
- Sizes: 16x16, 24x24, 32x32, 48x48
- Examples:
- "Office/32x32/document.png"
- "Business/32x32/users.png"
- "Software/32x32/gear.png"
- "Officewhite/32x32/knife_fork_spoon.png"
Width / Height (integer):
- Dialog dimensions in pixels
- Minimum recommended: 400x300
- Default: 500x500 approximately
OkButtonName (string):
- Custom label for the OK/Submit button
- Examples: "Continue", "Process", "Save", "Apply"
CancelButtonName (string):
- Custom label for the Cancel button
- Examples: "Abort", "Skip", "Close", "Back"
ShowHints (boolean):
- When true, tooltips appear for controls with Tooltip set
- Recommended: $true for complex dialogs
Return Values:
- "ok" - User clicked the OK button
- "cancel" - User clicked Cancel or closed the dialog
#><#
.SYNOPSIS
Demonstrates a simple dialog without tabs in Read-Variable.
.DESCRIPTION
Shows how to create a straightforward dialog for common operations
without using tabs or complex layouts.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variable - required for item picker
$targetItem = Get-Item -Path "master:\content\home"
$dialogParams = @{
Title = "Simple Dialog Example"
Description = "A straightforward dialog for quick data collection."
Width = 500
Height = 450
OkButtonName = "Finish"
CancelButtonName = "Cancel"
Parameters = @(
@{
Name = "inputText"
Value = "Some Text"
Title = "Single Line Text"
Tooltip = "Enter a single line of text"
Placeholder = "Enter text here..."
},
@{
Name = "multiLineText"
Value = "Multiple lines\nof text"
Title = "Multi Line Text"
Lines = 3
Tooltip = "Enter multiple lines"
Placeholder = "Enter detailed text..."
},
@{
Name = "startDate"
Value = [System.DateTime]::Now.AddDays(-5)
Title = "Start Date"
Tooltip = "Select a start date"
Editor = "date time"
},
@{
Name = "selectedUser"
Value = ""
Title = "Select User"
Tooltip = "Choose a user for this operation"
Editor = "user multiple"
},
@{
Name = "targetItem"
Title = "Target Item"
Root = "/sitecore/content/"
Tooltip = "Select the target location"
}
)
}
$result = Read-Variable @dialogParams
if ($result -ne "ok") {
Write-Host "Operation cancelled by user" -ForegroundColor Yellow
Exit
}
# Process the collected data
Write-Host "Dialog Results:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Text: $inputText" -ForegroundColor Green
Write-Host "Multi-line: $multiLineText" -ForegroundColor Green
Write-Host "Start Date: $startDate" -ForegroundColor Green
Write-Host "User: $selectedUser" -ForegroundColor Green
if ($targetItem) {
Write-Host "Target Item: $($targetItem.ItemPath)" -ForegroundColor Green
}
<#
SIMPLE DIALOG PATTERN:
For many scripts, a simple dialog without tabs is sufficient.
This pattern is ideal when you have:
- 5-8 related fields
- A single, focused task
- No need for complex organization
Best Practices:
1. Order fields logically (most important first)
2. Use clear, descriptive titles
3. Provide helpful tooltips
4. Use placeholder text for text inputs
5. Set sensible default values
6. Keep the dialog focused on one task
When to Use Tabs Instead:
- More than 8-10 fields
- Fields can be grouped into logical categories
- Complex operations with multiple phases
- Advanced options that most users won't need
#><#
.SYNOPSIS
Comprehensive example combining multiple dialog features.
.DESCRIPTION
Demonstrates how to combine tabs, columns, conditional visibility,
and various control types in a real-world scenario.
.NOTES
Documentation: https://doc.sitecorepowershell.com
#>
# Initialize item variable - required for item picker
$sourceItem = Get-Item -Path "master:\content\home"
# Pre-define some default values
$publishModes = [ordered]@{
"Smart Publish" = "smart"
"Republish" = "republish"
"Incremental" = "incremental"
}
$targetDatabases = [ordered]@{
"Web" = 1
"Preview" = 2
}
$languageOptions = [ordered]@{
"English" = 1
"German" = 2
"French" = 4
"Spanish" = 8
}
$selectedLanguages = @(1) # English pre-selected
# Build the dialog parameters
$dialogParams = @{
Title = "Content Publishing Wizard"
Description = "Configure and execute content publishing operations."
Icon = "Office/32x32/document_up.png"
Width = 650
Height = 600
OkButtonName = "Publish"
CancelButtonName = "Cancel"
ShowHints = $true
Parameters = @(
# === SOURCE TAB ===
@{
Name = "sourceItem"
Title = "Source Item"
Root = "/sitecore/content/"
Tooltip = "Select the root item to publish"
Tab = "Source"
Mandatory = $true
},
@{
Name = "includeSubitems"
Title = "Include Subitems"
Value = $true
Editor = "checkbox"
Tooltip = "Publish all descendant items"
Tab = "Source"
Columns = 6
},
@{
Name = "includeRelated"
Title = "Include Related Items"
Value = $false
Editor = "checkbox"
Tooltip = "Also publish referenced items"
Tab = "Source"
Columns = 6
},
# === TARGETS TAB ===
@{
Name = "targetDbs"
Title = "Target Databases"
Options = $targetDatabases
Editor = "checklist"
Tooltip = "Select destination databases"
Tab = "Targets"
},
@{
Name = "selectedLanguages"
Title = "Languages"
Options = $languageOptions
Editor = "checklist"
Tooltip = "Select languages to publish"
Tab = "Targets"
},
# === OPTIONS TAB ===
@{
Name = "publishMode"
Title = "Publish Mode"
Value = "smart"
Options = $publishModes
Editor = "radio"
Tooltip = "Select publishing mode"
Tab = "Options"
},
@{
Name = "schedulePublish"
Title = "Schedule for Later"
Value = $false
Editor = "checkbox"
Tooltip = "Check to schedule publication"
Tab = "Options"
GroupId = 1
},
@{
Name = "scheduledTime"
Title = "Scheduled Time"
Value = [DateTime]::Now.AddHours(1)
Editor = "date time"
Tooltip = "When to publish"
Tab = "Options"
ParentGroupId = 1
HideOnValue = "0"
},
# === NOTIFICATIONS TAB ===
@{
Name = "sendNotification"
Title = "Send Notification"
Value = $false
Editor = "checkbox"
Tooltip = "Notify users when complete"
Tab = "Notifications"
GroupId = 2
},
@{
Name = "notifyUsers"
Title = "Notify Users"
Editor = "user multiple"
Tooltip = "Select users to notify"
Tab = "Notifications"
ParentGroupId = 2
HideOnValue = "0"
},
@{
Name = "notifyRoles"
Title = "Notify Roles"
Editor = "role multiple"
Domain = "sitecore"
Tooltip = "Select roles to notify"
Tab = "Notifications"
ParentGroupId = 2
HideOnValue = "0"
},
@{
Name = "notificationMessage"
Title = "Custom Message"
Value = ""
Lines = 3
Tooltip = "Add a custom message to the notification"
Tab = "Notifications"
ParentGroupId = 2
HideOnValue = "0"
Placeholder = "Optional message to include..."
}
)
}
$result = Read-Variable @dialogParams
if ($result -ne "ok") {
Write-Host "Publishing cancelled by user" -ForegroundColor Yellow
Exit
}
# Display collected settings
Write-Host ("=" * 50) -ForegroundColor Cyan
Write-Host "PUBLISHING CONFIGURATION" -ForegroundColor Cyan
Write-Host ("=" * 50) -ForegroundColor Cyan
Write-Host ""
Write-Host "SOURCE:" -ForegroundColor Green
Write-Host " Item: $($sourceItem.ItemPath)"
Write-Host " Include Subitems: $includeSubitems"
Write-Host " Include Related: $includeRelated"
Write-Host ""
Write-Host "TARGETS:" -ForegroundColor Green
Write-Host " Databases: $($targetDbs -join ', ')"
Write-Host " Languages: $($selectedLanguages -join ', ')"
Write-Host ""
Write-Host "OPTIONS:" -ForegroundColor Green
Write-Host " Mode: $publishMode"
if ($schedulePublish) {
Write-Host " Scheduled: $scheduledTime"
} else {
Write-Host " Scheduled: Immediate"
}
Write-Host ""
if ($sendNotification) {
Write-Host "NOTIFICATIONS:" -ForegroundColor Green
Write-Host " Users: $($notifyUsers -join ', ')"
Write-Host " Roles: $($notifyRoles -join ', ')"
if ($notificationMessage) {
Write-Host " Message: $notificationMessage"
}
}
Write-Host ""
Write-Host "Ready to execute publishing operation!" -ForegroundColor Yellow