Powershellklasse: DisableEvent Firing

Bei umfangreichen Powershell-Entwicklungen oder aber auch im administrativen Umfeld kann es erforderlich sein, das Auslösen von Standard- oder Custom Eventreceivern in SharePoint zu unterdrücken.

Hier ein Beispiel, wie das realisiert werden kann.

Im Zusammenhang mit einer kleinen administrativen Hürde wurde es erforderlich, den SharePoint einmal kurz aus den Angeln zu heben, um eine Itemlöschung möglich zu machen. Im Standard verhindert der SharePoint (on premise) die Löschung von Items, welches einen aktiven Eventreceiver auf einem Elternelement aktiv haben, welches nicht mehr vorhanden ist. Über die GUI kommt man da nicht weiter.

Um hier den „Knüppel“ anzusetzen, definiert man sich eine PowerShell basierte Klasse, auf welche man dann entsprechend aus dem eigentlichen Code referenziert. Wichtig dabei zu wissen ist es, dass sich dieses immer auf das aktuelle Web bzw. die aktuelle Session bezieht. Ein klassisches Dispose hebt das Ganze wieder auf und es wird wieder auf Events reagiert.

Die Klasse

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

# Helper-Klasse nur definieren, wenn sie noch nicht existiert
if (-not ("EventFiringDisabler" -as [type])) {

# Pfad der bereits geladenen Microsoft.SharePoint-Assembly ermitteln
$spAsmPath = [Microsoft.SharePoint.SPWeb].Assembly.Location

$refAssemblies = @(
"System.dll",
$spAsmPath
)

Add-Type -ReferencedAssemblies $refAssemblies @"
using System;
using Microsoft.SharePoint;

public class EventFiringDisabler : SPItemEventReceiver, IDisposable
{
public EventFiringDisabler()
{
this.EventFiringEnabled = false;
}

public void Dispose()
{
this.EventFiringEnabled = true;
}
}
"@
}

Die Funktion/das Script zur Itemlöschung (Beispiel)

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$webUrl = "https://deine-site/beispiel/"
$listName = "Aufgaben"
$itemId = 5

$web = Get-SPWeb $webUrl

try {
$list = $web.Lists[$listName]
if ($list -eq $null) {
Write-Host "Liste '$listName' nicht gefunden." -ForegroundColor Red
return
}

$item = $list.GetItemById($itemId)
if ($item -eq $null) {
Write-Host "Item $itemId existiert nicht (vielleicht schon weg?)." -ForegroundColor Yellow
return
}

Write-Host "Gefunden: Item $itemId in Liste '$($list.Title)'. Versuche hartes Löschen ohne Event-Receiver..." -ForegroundColor Cyan

$web.AllowUnsafeUpdates = $true

# Events deaktivieren (Konstruktor)
$disabler = New-Object EventFiringDisabler
try {
$item.Delete()
Write-Host "Item $itemId wurde ohne Event-Receiver gelöscht." -ForegroundColor Green
}
finally {
# Events wieder aktivieren
$disabler.Dispose()
$web.AllowUnsafeUpdates = $false
}
}
finally {
if ($web -ne $null) { $web.Dispose() }
}

Hintergrund:

Eine auf einem Listitem basierter Evenreceiverworkflow konnte nicht beendet werden, da das Elternelement bereits gelöscht wurde. Eine Löschung des Kindelements, der „normalen“ Aufgabe, war auf Grund dieses Sachverhaltes ebenso nicht möglich, da ein CheckEvent dieses aktiv verhinderte und in der GUI entsprechend darauf hingewiesen hat.