Using PowerShell to Delete a Site with Subsites in SharePoint Server 2010
When using the "DR.DADA" approach to SharePoint development, I often find myself deleting sites (in DEV and TEST environments) and subsequently re-activating features or running some migration utility to recreate the site hierarchy.
In fact, a few years ago this became such a common task on the Agilent Technologies project that I wrote a simple "DeleteWeb" program to overcome the fact that stsadm.exe -o deleteweb doesn't work on sites that have subsites.
Note that there really wasn't much to the DeleteWeb program. Almost all of the work was performed by the DeleteHelper class:
using System;
using System.Diagnostics;
using System.Globalization;
using Microsoft.SharePoint;
namespace DeleteWeb
{
public sealed class DeleteHelper
{
private DeleteHelper() { } // all members are static
public static void DeleteWeb(
string siteUrl)
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.OpenWeb())
{
if (string.Compare(web.Url, siteUrl, true,
CultureInfo.InvariantCulture) != 0)
{
throw new InvalidOperationException(
"Invalid Web URL. Verify the URL and try again.");
}
DeleteWeb(web);
}
}
}
public static void DeleteWeb(
SPWeb web)
{
SPWebCollection subwebs = web.GetSubwebsForCurrentUser();
if (subwebs.Count > 0)
{
foreach (SPWeb subweb in subwebs)
{
DeleteWeb(subweb);
subweb.Dispose();
}
}
Debug.WriteLine("Deleting web: " + web.ServerRelativeUrl);
web.Delete();
return;
}
}
}
I was hoping that SharePoint Server 2010 would address this scenario out-of-the-box, but that doesn't appear to be the case.
Suppose that you have a site (e.g. https://foobar/Test) that has subsites (e.g. https://foobar/Test/foo and https://foobar/Test/bar). If you attempt to use the Remove-SPWeb cmdlet in SharePoint Server 2010 to delete the site...
Remove-SPWeb "https://foobar/Test" -Confirm:$false
...then you will encounter an error similar to the following:
Remove-SPWeb : Error deleting Web site "/Test". You can't delete a site that has subsites.
At line:1 char:13
+ Remove-SPWeb <<<< "https://foobar/Test" -Confirm:$false
+ CategoryInfo : InvalidData: (Microsoft.Share...CmdletRemoveWeb:SPCmdletRemoveWeb) [Remove-SPWeb], SPException
+ FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletRemoveWeb
In order to delete a site that has subsites using PowerShell, we simply need to convert the C# code shown above into a corresponding PowerShell function, as shown below:
# Completely deletes the specified Web (including all subsites)
function RemoveSPWebRecursively(
[Microsoft.SharePoint.SPWeb] $web)
{
Write-Debug "Removing site ($($web.Url))..."
$subwebs = $web.GetSubwebsForCurrentUser()
foreach($subweb in $subwebs)
{
RemoveSPWebRecursively($subweb)
$subweb.Dispose()
}
$DebugPreference = "SilentlyContinue"
Remove-SPWeb $web -Confirm:$false
$DebugPreference = "Continue"
}
$DebugPreference = "SilentlyContinue"
$web = Get-SPWeb "https://foobar/Test"
$DebugPreference = "Continue"
If ($web -ne $null)
{
RemoveSPWebRecursively $web
$web.Dispose()
}
Note that the script handles the case where $web
is null -- in other words, when the specified Web doesn't exist (for example, when running the script a second time).