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.

Reset filter on view using PowerShell

If you want to reset the filter for multiple views, you can use PowerShell to accomplish this.

Below is the script to do this for a single view:

#Variables
$web = "http://portal.contoso.com"
$listName = "Demo Library"
$viewName = "view2”

#Script
$lib = (Get-SPWeb $web).Lists[$listName]
$view = $lib.Views | ?{$_.title -eq $viewName}
$view.Query = ‘<OrderBy><FieldRef Name="FileLeafRef" /></OrderBy>’
$view.Update()
$lib.Update()

This should do the trick.

Get Content Databases per Web Application one-liner

Another one in the series of one-liners. This one will show you all Web Applications, and all associated Content Databses for these Web Applications:

Get-SPWebApplication | %{Write-Output "`n- $($_.url)"; foreach($cd in $_.contentdatabases){Write-Output $cd.name}}

The output will look similar to this:

image

You can output this to a text file by running the following:

Get-SPWebApplication | %{Write-Output "`n- $($_.url)"; foreach($cd in $_.contentdatabases){Write-Output $cd.name}} >> D:\filename.txt

Add/Edit list items using PowerShell in SharePoint 2010

During the last few months I have been asked a few times to help think of a way to edit list values for lists that contain a lot of data. I immediately thought of PowerShell. This is why I want to show you what you can do with PowerShell.

Used set up for this demo
I have created a test environment for this demonstration. I will be using the following:
http://portal.contoso.com (SPWeb URL)
– Demo List (Custom List). This list has 1 extra added column: Information (Multiple lines of text)

image

Basics
To work with a list, you will have to start off by retrieving the list in PowerShell. For demonstration purposes, I will try to make it as easy and clear as possible:

#Add SharePoint PowerShell Snapin which adds SharePoint specific cmdlets
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue

#Variables that we are going to use for list editing
$webURL = <a href="http://portal.contoso.com">http://portal.contoso.com</a>
$listName = "Demo List"

#Get the SPWeb object and save it to a variable
$web = Get-SPWeb $webURL

#Get the SPList object to retrieve the "Demo List"
$list = $web.Lists[$listName]

These are the basics. With this, we can start to add items to this list or modify existing items.

Add items to the Demo List
So we got the list in our $list variable, now what?
To add an item to this list, we will need to use the Items.Add() method.

#Create a new item
$newItem = $list.Items.Add()

#Add properties to this list item
$newItem["Title"] = "My first item!"
$newItem["Information"] = "This is a multiple lines of text field `nSo I can use multiple lines"

#Update the object so it gets saved to the list
$newItem.Update()

Here is the output:

image

The `n part in: $newItem[“Information”] = “This is a multiple lines of text field `nSo I can use multiple lines”, is a New line. This works if you use the “Plain text” type, but not when you use “Rich text” or “Enhanced rich text”.

That was pretty easy right?

Add attachments to items
In the comments section, Nino asked if it was possible to add attachments for each new item created. Here is the way to do this.

$filebytes = [System.IO.File]::ReadAllBytes("D:\dummyfile.txt")
$newItem.Attachments.Add("DummyFile Title",$filebytes)

Edit existing list items
Now let’s say you want to edit the Information for this “first item”. We can do this with PowerShell too. Of course, if you would only change 1 item, you should do it by using the GUI, but what happens if you have to do the same thing for 5000+ items?

#Get all items in this list and save them to a variable
$items = $list.items

#Go through all items
foreach($item in $items)
{
#If the "Title" column value equals "My first item!" do something with it
if($item["Title"] -eq "My first item!")
{
#Change the value of the "Title" column
$item["Title"] = "My first edited item!"

#Update the item
$item.Update()
}
}

After running this part, we get the following result:

image

Hooray! It worked.

Now imagine all the things you can do with PowerShell and huge lists!
You could add column information for every item, or have a .csv or xml file which contains the items that should be changed. The possibilities are endless!