Download all content in a site collection

Hi,

I’ve been working on a script that will allow you to download all files that are stored in SharePoint in a given site collection.

If the path does not exist, the script will prompt you to create it for you. Before the script runs, it also checks if the site collection exists.

Run the script like this:

.\Get-SPContent.ps1 -SiteCollection "<SiteCollectionURL>" -Destination "<Path>"

Preview

The console shows which libraries were exported to your file system.

—– * Advanced * —–

If you have specific requirements as to which (type of) libraries you want to export, you can change the following line to fit your requirements:

$lists = $web.lists | ?{$_.itemcount -ge "1" -And $_.Hidden -eq $false -And $_.BaseType -eq "DocumentLibrary"} #Excludes all hidden libraries and empty libraries

Below is the code you can save as Get-SPContent.ps1

param
(
[Parameter(Mandatory=$true)]
[ValidateScript({asnp *sh* -EA SilentlyContinue;if (Get-SPSite $_){$true}else{Throw "Site collection $_ does not exist"}})]
[string]$SiteCollection,
[Parameter(Mandatory=$true)]
[ValidateScript(
{
if (Test-Path $_)
{$true}
else{
$d = $_
$title = "Create Folder?";
$message = "$_ doesn't exist, do you want the script to create it?";
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Creates directory $_";
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Exits script";
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no);
$result = $host.ui.PromptForChoice($title,$message,$options,1);
switch($result)
{
0 {New-Item $d -Type Directory;$true}
1 {Throw "Please create the folder before running the script again. `nExiting script"}
}
}
})]
[string]$Destination
)

Asnp *sh* -EA SilentlyContinue

Start-SPAssignment -Global | Out-Null

function Get-SPWebs($SiteCollection){
$SiteCollection = Get-SPSite $SiteCollection
$webs = @()
$SiteCollection.allwebs | %{$webs += $_.url}
return $webs
}

function Get-SPFolders($webs)
{
foreach($web in $webs)
{
$web = Get-SPWeb $web
Write-Host "`n$($web.url)"

$lists = $web.lists | ?{$_.itemcount -ge "1" -And $_.Hidden -eq $false -And $_.BaseType -eq "DocumentLibrary"} #Excludes all hidden libraries and empty libraries
#$lists = $web.lists | ?{$_.title -eq "Documents" -and $_.itemcount -ge "1" -And $_.BaseType -eq "DocumentLibrary"} #Change any identifier here
foreach($list in $lists)
{
Write-Host "- $($list.RootFolder.url)"

#Download files in root folder
$rootfolder = $web.GetFolder($list.RootFolder.Url)
Download-SPContent($rootfolder)

#Download files in subfolders
foreach($folder in $list.folders)
{
$folder = $web.GetFolder($folder.url)
Download-SPContent($folder)

}

}
$web.dispose()
}
}

function Download-SPContent($folder)
{
foreach($file in $folder.Files)
{
$binary = $file.OpenBinary()
$stream = New-Object System.IO.FileStream($destination + "/" + $file.Name), Create
$writer = New-Object System.IO.BinaryWriter($stream)
$writer.write($binary)
$stream.Close()
$writer.Close()
}
}

$webs = Get-SPWebs -SiteCollection $Sitecollection
Get-SPFolders -Webs $webs

Stop-SPAssignment -Global

Add-PSSnapIn Microsoft.SharePoint.PowerShell shortcut

Are you tired of typing Add-PSSnapIn Microsoft.SharePoint.PowerShell every time you open your PowerShell console?
You can do this by Adding/Editing profile.ps1 (I don’t do this because I have too many machines where I should change this)

If you find you do not want to change the profile.ps1 on every server you are working on, you can type this:

asnp *sh*

This adds all SnapIns that contain *sh*. In most cases, this will only add the Microsoft.SharePoint.PowerShell SnapIn.
Credits go to Koen Zomers!

Happy PowerShelling!

 

Add PDF mimetype for all Web Applications one-liner

By default, PDF files cannot be opened directly from SharePoint 2010/SharePoint 2013.

To add the PDF mimetype to all Web Applications (Instead of doing it seperately for each Web Application), you can use the following one-liner:

Get-SPWebApplication | %{$_.AllowedInlineDownloadedMimeTypes.Add("application/pdf");$_.Update()}

Get all subsites of a subsite

Getting a list of all subsites of a particular site (not a site collection) was a little more work than I expected, so here is how I did it.

Let’s say we have the following situation site structure:

SiteStructure

What if we want an overview of all sites under “Https://portal.sharepointrelated.com/Projects”?

My first thought was to use the “Webs” property of the SPWeb object. Unfortunately, this only shows the direct subsites for this site. This means that for “Https://portal.sharepointrelated.com/projects”, it only shows the Level 3 sites.

Solution

To work around this, I used the “AllWebs” property of the SPSite object and filtered the URL’s starting with “Https://portal.sharepointrelated.com/projects”.

Here is the code used: (Download .zip file)


param ( [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] [String]$StartWeb, [Boolean]$IncludeStartWeb = $true )

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$subsites = ((Get-SPWeb $StartWeb).Site).allwebs | ?{$_.url -like "$StartWeb*"}

foreach($subsite in $subsites) { Write-Host $subsite.url }

As you can see in the source code, I added 2 parameters to the script:

StartWeb: String. This is the starting URL. All subsites under this site will be showed in the result.

IncludeStartWeb: Boolean. When set to $false, the output will not include the URL provided in the StartWeb parameter.

Update a Secure Store Application information using PowerShell

*This will also work for SharePoint 2013 Preview*
You can use the following script to update information for one of your Secure Store Applications.
I want to change the Contact E-mail property for this Secure Store Application to "NewEmail@xxx.com"

Used Configuration
For this part, I have set up the following:

– 1 Web Application (My intranet)
– 1 Secure Store Service Application
– Created 1 Application: "TestID":

image

Pre-requisites
I found that before this works, you need the following:
– Site Collection Administrator for the root of the web application (my intranet)
– Full Control on the Secure Store Service Application. You can set this by going to:
Central Administration -> Application Management -> Manage Service Application -> Highlight the Secure Store Service Application -> Select "Administrators" from the ribbon.

image

Changing the desired property

#Add the PowerShell Snapin
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Retrieve the Service context
$site = new-object Microsoft.SharePoint.SPSite("https://demo.contoso.com&quot;);
$ServiceContext = [Microsoft.SharePoint.SPServiceContext]::GetContext($site);

#Get the Secure Store Application and save the new information into a variable
$Application = Get-SPSecureStoreApplication -Name "TestID" -ServiceContext $ServiceContext
$TargetApplication = $Application.TargetApplication
$TargetApplication.ContactEmail = "NewEmail@xxx.com"

#Set the saved information to the Target Application
Set-SPSecureStoreApplication -Identity $Application -TargetApplication $TargetApplication

Result

image

Content Database FAQ – SharePoint 2010

Last update: 09-11-2012
Since there is a lot of misconception on how different SharePoint components relate to each other, I will try to answer some common questions. Please feel free to comment or ask additional questions in the comment section. I will add them to the FAQ list.

The below figure shows the infrastructure of Content databases related to Web Applications and site collections.

SharePoint_Infrastructure

FAQ

1. Can we create a site collection in a specific Content Database?

Yes, but you can only do this by using PowerShell using the New-SPSite cmdlet. You can use the "-ContentDatabase" parameter to specify in which Content Database the site collection will be created.

2. When using the "-ContentDatabase" parameter in the New-SPSite cmdlet, does the content database get automatically created if it does not exist?
No, if you enter a Content Database name that does not exist, you will get an error saying the content database could not be found.

3. My site collection is getting very big, can I add a second Content Database to spread the load?
Because of the way SharePoint is designed, you cannot have 1 site collection spread over multiple Content Databases. If you want to split up your site collection in to multiple site collections, you can do this by exporting and importing subsites, or by using 3rd party tools.

4. What site collections are currently in my Content Database?
For this specific question, I have written a PowerShell one-liner that will return every Content Database with their respective site collections. You can find this one liner here: http://sharepointrelated.com/2012/03/09/get-site-collections-per-content-database-one-liner/

5. How can I check the size of my Content Database?
The easiest way to accomplish this is by looking at the database file on your SQL Server. But there may be some scenario’s where this is not possible. Insufficient permissions being the most common one. In this case, you can use this article to find out the approximate Content Database size: http://sharepointrelated.com/2012/03/07/content-database-size-report-using-powershell/

6. What Content Databases are attached to my Web Applications?
For this question, I have also written a small blog post. It will return all Web Applications with their respective Content Databases: http://sharepointrelated.com/2012/05/28/get-content-databases-per-web-application-one-liner/

7. Why are my Content Databases named WSS_Content_<Guid>?
The moment you create a Web Application, you will be asked to fill in details regarding your content database. By default, SharePoint will fill in this field for you with the following syntax: WSS_Content. If a content database with this name already exists, it will add a GUID to it.

8. What if I want to move my site collection to another Content Database?
In this case, there are 2 scenario’s:
– Move the site collection to another Content Database that is attached to the same Web Application
You can use the Move-SPSite cmdlet to move the site collection.
– Move the site collection to another Content Database that is attached to another Web Application
You can use the Backup-SPSite and Restore-SPSite functionality to accomplish this task.

9. I have multiple site collections in my Content Database, can I use PowerShell to see their sizes?
Yes, you can. You can use the following line of code to check the approximate size of your site collection (From Todd’s blog: Using PowerShell to find site collection size in SharePoint 2010)

Get-SPSite "http://someurl.com&quot; | select url, @{label="Size in MB";Expression={$_.usage.storage/1MB}}

10. Is it possible to maintain the same Content Database for more than one Web Application?
No, this is not possible. A Content Database can only be attached to a single Web Application.

Error using Move-SPSite cmdlet

This post discusses the following error:

Move-SPSite : Cannot insert duplicate key row in object ‘dbo.AllSites’ with unique index ‘Sites_Id’. The duplicate key value is <GUID>.

Let’s say you have 1 Web Application with 2 content databases:
– Database 1
– Database 2

Database 1 contains a site collection with the following URL: http://portal.contoso.com.
For some reason, you moved the site collection using the following cmdlet:

Move-SPSite http://portal.contoso.com -DestinationDatabase "Database 2" -Confirm:$false

image

So far so good. Now let’s say you want to move this site collection back to Database 1.
You would run:

Move-SPSite http://portal.contoso.com -DestinationDatabase "Database 1" -Confirm:$false

This produces the following error:

image

Solution
This is happening because the site collection has not been completely deleted from the content database.
When you run Move-SPSite, the site collection gets moved to the new content database.
However, the site collection in the source Content Database was not completely removed. The site collection "Deleted" flag was set to 1.

This means it is scheduled for deletion. The Gradual site delete timer jobs will delete the site collection from the content database. By default, this timer job runs once a day. To ensure the site is completely deleted, run the timer job. As this timer job runs for each Web Application, make sure you select the correct Web Application

image

After you ran the Gradual Site Delete timer job, you will be able to move the site collection back to Database 1.