PowerShell to attach event receiver to a list

In this article I want to share how to use PowerShell to attach event receiver to a list, provide configuration values from an xml. And also, how to use PowerShell to view a list of existing event receivers.

Recently, in our production environment, the functionality added by an event handler was not working. I had used the visual studio to add an event receiver, which automatically adds CAML markup to attach the event handler.

We had already provisioned the document library. So, activation of the feature containing the above CAML to attach the event handler did not seem to work.

In order to confirm that the event handler was not attached, I wrote a PowerShell script to list all the event handlers attached to that particular library.

I loop the EventReceivers in descending order of index. This is because if we were to add code to remove the existing event handers, we can insert the following command:

[ps]
$Receiver.Delete();
[/ps]

Within the loop, we cannot add or remove items from the collection if we are looping the index in the ascending order i.e start with 0 till the end of the loop (we get an error that the collection was modified if we do that). In this case, since we are just listing the event receivers we can even use ascending loop.

Also, in case you are planning to remove any event receivers, ensure that you take a backup of the list of event receivers. Because, if we don’t and we remove the event receivers in a loop, we do not have the information to add them back.

To copy the information of existing event receivers, insert a line such as

[ps]
$list.EventReceivers | Out-File -filepath "C:\ListName-EventReceivers.txt"
[/ps]

[ps]
# Add the SharePoint module
if ((Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin Microsoft.SharePoint.PowerShell
}

#Read the data from the Xml file
$config = (Get-Content "Config.xml")

if ($config -eq $null ) {
Write-Host "Parameter XML not Loaded "
exit
}

$site = $config.EventHandlerInfo.Web;
$webUrl = $site.WebUrl;
Write-Host($webUrl);

## open the web site
Write-Host "Opening web $webUrl" -nonewline
$web = Get-SPWeb $webUrl
Write-Host "$web"
Write-host " – done " -foreground green

foreach($handler in $site.EventHandler)
{
$ListName = $handler.ListName
$assembly = $handler.Assembly
$class = $handler.Class

## open the list
Write-Host "Opening ‘$ListName’ list" -nonewline
$list = $web.Lists[$ListName]
if ($list -eq $null)
{
Write-host " – can’t open list " -foreground red
return
}
else
{
Write-host " – done " -foreground green
}

## list the existing event receivers
Write-Output "Existing event receivers:"
$count = $list.EventReceivers.Count
if ($count -gt 0)
{
for($i = $count -1; $i -gt -1; $i–-)
{
$Receiver = $list.EventReceivers[$i] ;
$type = $Receiver.Type ;
$asm = $Receiver.Assembly ;
$cls = $Receiver.Class;
Write-Host " [$i] – $type – $asm – $cls";
}
}
else
{
Write-Host " – no existing EventReceivers found." -foreground green
}
}
[/ps]

We could have probably used code (feature activated code or console application) to attach the event handler. However, I think for these kinds of one time activities, it would be better to use PowerShell.

Below PowerShell attaches the event handler to a document library. I have initialized a sequence number and increment this number every time we attach an event handler. This is because, we need to specify a different sequence number for each event handler to indicate the order in which they should be executed.

[ps]
# Setup the module for SharePoint
if ((Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin Microsoft.SharePoint.PowerShell
}

#Read the data from the Xml file
$config = (Get-Content "Config.xml")

if ($config -eq $null ) {
Write-Host "Parameter XML not Loaded "
exit
}

$site = $config.EventHandlerInfo.Web;

$webUrl = $site.WebUrl;

Write-Host($webUrl);
## open the web site
Write-Host "Opening web $webUrl" -nonewline
$web = Get-SPWeb $webUrl
Write-Host "$web"
Write-host " – done " -foreground green

foreach($handler in $site.EventHandler)
{
$ListName = $handler.ListName
$assembly = $handler.Assembly
$class = $handler.Class

## open the list
Write-Host "Opening $ListName …" -nonewline
$list = $web.Lists[$ListName]
if ($list -eq $null)
{
Write-host " – can’t open list " -foreground red
return
}
else
{
Write-host " – done " -foreground green
}

$seqNum = 1001;

foreach($typeInfo in $handler.Types.Type)
{
$type = $typeInfo.Id
$sync = $typeInfo.Sync
## add new event receivers
Write-Host "Adding new event receivers: $class $type"

$spEventReceiver = $list.EventReceivers.Add();
$spEventReceiver.Assembly = $assembly
$spEventReceiver.Class = $class
$spEventReceiver.Type = $type
$spEventReceiver.SequenceNumber = $seqNum;
$seqNum= $seqNum +1;
$spEventReceiver.Synchronization = $sync;
$spEventReceiver.Update();
}
}
[/ps]

Note that we need to provide the full path with the namespace while specifying the Class attribute.

The Type -> Id is used for the Type of event handler. Below is a full list of types for event receivers.

InvalidReceiver = -1,
ItemAdding = 1,
ItemUpdating = 2,
ItemDeleting = 3,
ItemCheckingIn = 4,
ItemCheckingOut = 5,
ItemUncheckingOut = 6,
ItemAttachmentAdding = 7,
ItemAttachmentDeleting = 8,
ItemFileMoving = 9,
FieldAdding = 101,
FieldUpdating = 102,
FieldDeleting = 103,
ListAdding = 104,
ListDeleting = 105,
SiteDeleting = 201,
WebDeleting = 202,
WebMoving = 203,
WebAdding = 204,
WorkflowStarting = 501,
ItemAdded = 10001,
ItemUpdated = 10002,
ItemDeleted = 10003,
ItemCheckedIn = 10004,
ItemCheckedOut = 10005,
ItemUncheckedOut = 10006,
ItemAttachmentAdded = 10007,
ItemAttachmentDeleted = 10008,
ItemFileMoved = 10009,
ItemFileConverted = 10010,
FieldAdded = 10101,
FieldUpdated = 10102,
FieldDeleted = 10103,
ListAdded = 10104,
ListDeleted = 10105,
SiteDeleted = 10201,
WebDeleted = 10202,
WebMoved = 10203,
WebProvisioned = 10204,
WorkflowStarted = 10501,
WorkflowPostponed = 10502,
WorkflowCompleted = 10503,
EmailReceived = 20000,
ContextEvent = 32766

We used the below configuration file Config.xml to provide the configuration values to the powershell script.

<EventHandlerInfo>
  <Web>
    <WebUrl>http://server/sites/siteColl/web</WebUrl>
    <EventHandler>
      <ListName>Document Library</ListName>
      <Assembly>Company.Namespace.Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=replacetoken</Assembly>
      <Class>Company.Namespace.EventReceiverClass</Class>
      <Types>
        <Type>
          <Id>10001</Id>
          <Sync>0</Sync>
        </Type>
        <Type>
          <Id>3</Id>
          <Sync>0</Sync>
        </Type>
      </Types>
     </EventHandler>
    </Web>
</EventHandlerInfo>

Leave a Reply

Your email address will not be published. Required fields are marked *