Creating information policies in SharePoint OnPremises using PowerShell

Published on Monday, 28 March 2022

The last time I created an information policy in PowerShell was so long ago, that I could't remember how to this. Documentation on this topic has always been scarce.

The steps are as follows:

  1. Get the list
  2. Get the content type for which the retention policy should be created
  3. Add or get the policy for that content type
  4. Add the schedule to the policy

In code this looks like (example for "move to recycle bin, one year after creation"):

$webUrl = "https://some.url/to/a/site"
$listTitle = "ListTitle here..."
$contentTypeId = "0x01"; # this is the "parent" - not the actual CT of the list

# Get List and ContentType
$web = Get-SPWeb $webUrl
$list = $web.Lists[$listTitle]
$itemCt = $list.ContentTypes[$list.ContentTypes.BestMatch($contentTypeId)]

# make sure UseListPolicy is not set, so we can use per-contentType policies.
$listPolicy = [Microsoft.Office.RecordsManagement.InformationPolicy.ListPolicySettings]($list)
if ($listPolicy.UseListPolicy)
{
 $listPolicy.UseListPolicy = $false
 $listPolicy.Update()
}

# remove an existing policy (Maybe should ask before doing this...)
$ctPolicy = [Microsoft.Office.RecordsManagement.InformationPolicy.Policy]::GetPolicy($itemCt)
if($ctPolicy -ne $null) {
  [Microsoft.Office.RecordsManagement.InformationPolicy.Policy]::DeletePolicy($itemCt)
}

# create a new policy
[Microsoft.Office.RecordsManagement.InformationPolicy.Policy]::CreatePolicy($itemCt, $null)
$ctPolicy = [Microsoft.Office.RecordsManagement.InformationPolicy.Policy]::GetPolicy($itemCt)
$ctPolicy.Description = "Delete after 1 year"

# add the schedule to the policy
$featureXml = @"
<Schedules nextStageId="2">
    <Schedule type="Default">
        <stages>
            <data stageId="1">
                <formula id="Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn">
                    <number>1</number>
                    <property>Created</property>
                    <propertyId>8c06beca-0777-48f7-91c7-6da68bc07b69</propertyId>
                    <period>years</period>
                </formula>
                <action type="action" id="Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Action.MoveToRecycleBin" />
            </data>
        </stages>
    </Schedule>
</Schedules>
"@

$ctPolicy.Items.Add("Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration", $featureXml)
$ctPolicy.Update()

If I find some nice documentation on the XML, I'll add it here. My workflow has always been to create the policy in some development SharePoint somewhere and then extract the XML from there.

Also, there was the possibility to create fully customized policies by deploying a custom IPolicyFeature. Though I do not know whether this still works (worked) in 2013 or later.