Size of a sharepoint web application - sharepoint

How do you figure out the current size of the sharepoint web application? Better yet, the size of a site collection or a subsite.
I am planning to move a site collection from one farm to another. I need to plan the storage capacity first.

All content for SharePoint is stored in Content Database (unless you are using some sort of 3rd party external BLOB provider).
A site collection (aka top level site) is stored in a single content database but each content database can have multiple site collections.
You can work out the site of the content databases using SQL Management Studio, stored procedures (though beware that these can include overhead like logfiles or allocated but unused space)
You can use the open source SPUsedSpaceInfo utility
You can use free tools like BLOBulator.
Programatically you can loop through the folders and subwebs of an SPWeb and add up the size of all the contents
These are going to give slightly different results -e.g. one is looking at the size of documents stored, the other is the size of the content database storing those documents. None of these is going to include the files in C:\Inetpub\wwwroot\wss\VirtualDirectories\80 or C:\Program Files\Common Files\Microsoft Shared\web server extensions\12 but these are nearly always insignificant compared to the size of the documents stored in SharePoint.

You can see the size (in bytes) opening Sharepoint 2010 Management Shell (run it with as Administrator) and execute:
> Start-SPAssignment -Global
> (Get-SPSiteAdministration -Identity http://YourSharePointURL/urlToYourSite/).DiskUsed
Also, you would like to know each subsite size. To do that, run the following script under the Sharepoint Management Shell:
function GetWebSizes ($StartWeb)
{
$web = Get-SPWeb $StartWeb
[long]$total = 0
$total += GetWebSize -Web $web
$total += GetSubWebSizes -Web $web
$totalInMb = ($total/1024)/1024
$totalInMb = "{0:N2}" -f $totalInMb
$totalInGb = (($total/1024)/1024)/1024
$totalInGb = "{0:N2}" -f $totalInGb
write-host "Total size of all sites below" $StartWeb "is" $total "Bytes,"
write-host "which is" $totalInMb "MB or" $totalInGb "GB"
$web.Dispose()
}
function GetWebSize ($Web)
{
[long]$subtotal = 0
foreach ($folder in $Web.Folders)
{
$subtotal += GetFolderSize -Folder $folder
}
write-host "Site" $Web.Title "is" $subtotal "KB"
return $subtotal
}
function GetSubWebSizes ($Web)
{
[long]$subtotal = 0
foreach ($subweb in $Web.GetSubwebsForCurrentUser())
{
[long]$webtotal = 0
foreach ($folder in $subweb.Folders)
{
$webtotal += GetFolderSize -Folder $folder
}
write-host "Site" $subweb.Title "is" $webtotal "Bytes"
$subtotal += $webtotal
$subtotal += GetSubWebSizes -Web $subweb
}
return $subtotal
}
function GetFolderSize ($Folder)
{
[long]$folderSize = 0
foreach ($file in $Folder.Files)
{
$folderSize += $file.Length;
}
foreach ($fd in $Folder.SubFolders)
{
$folderSize += GetFolderSize -Folder $fd
}
return $folderSize
}
Then:
GetWebSizes -StartWeb <startURL>
I hope this will help you... :)
Source: http://get-spscripts.com/2010/08/check-size-of-sharepoint-2010-sites.html

Related

Azure storage account backup (tables and blobs)

I need to periodically backup all blobs and tables in an Azure storage account so that we can restore all that data at a later time if we for any reason corrupt our data.
While I trust that data that we store in Azure is durable and recoverable in case of data center failures, we still need data in our storage accounts to be backed up to prevent from accidental overwrites and deletions (the human error factor).
We have implemented a solution for this that periodically lists all blobs and copies them over to a backup storage account. When a blob has been modified or deleted we simply create a snapshot of the old version in the backup account.
This approach has worked OK for us. But it only handles blobs, not table entities. We now need to support backing up table entities too.
Faced with this task now, I'm thinking that someone else probably have had this requirement before and come up with a smart solution. Or maybe there are commercial products that will do this?
It is not a requirement that the backup target is another Azure storage account. All we need is a way to recover all blobs and tables as they were at the time we ran the backup.
Any help is appreciated!
There are a variety of ways this can be handled.
If you want to do this on your own you can use the storage libraries and write code to just run through the table and pull down the data.
There are also a few services that can do this for you as well (FULL Disclosure: I work for a company that provides this as a service). Here is an article by Troy Hunt talking about our option: http://www.troyhunt.com/2014/01/azure-will-save-you-from-unexpected_28.html. We also have PowerShell Cmdlets that can pull table data down for you (cerebrata.com). To be fair we are not the only players in this space and there are others who have similar services.
Finally, at Tech Ed they announced that the AZCopy tool will be updated later this year so that it can pull down entire tables, which is just automating the reading through tables and pulling them down. There is currently no way to "Snapshot" a table so all of the methods above will result in a copy as the data is copied over, it might have changed in the source table by the time the copy is completed.
I've recently put together a simple solution to backup table storage. It uses the AzCopy tool and the Storage Rest Api to pull down a list of all the tables and do a backup to JSON.
Hope it's useful!
param(
[parameter(Mandatory=$true)]
[string]$Account,
[parameter(Mandatory=$true)]
[string]$SASToken,
[parameter(Mandatory=$true)]
[string]$OutputDir
)
$ErrorActionPreference = "Stop"
##Example Usage
#.\Backup-TableStorage.ps1 -OutputDir "d:\tablebackup" -Account "examplestorageaccount" -SASToken "?sv=2015-04-05&ss=t&srt=sco&sp=rl&st=2016-04-08T07%3A44%3A00Z&se=2016-04-09T07%3A55%3A00Z&sig=CNotAREALSIGNITUREBUTYOURESWOUDLGOHERE3D"
if (-not (Test-Path "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\AzCopy\AzCopy.exe"))
{
throw "Azcopy not installed - get it from here: https://azure.microsoft.com/en-gb/documentation/articles/storage-use-azcopy/"
}
Write-host ""
Write-Host "Starting backup for account" -ForegroundColor Yellow
Write-host "--------------------------" -ForegroundColor Yellow
Write-Host " -Account: $Account"
Write-Host " -Token: $SASToken"
$response = Invoke-WebRequest -Uri "https://$Account.table.core.windows.net/Tables/$SASToken"
[xml]$tables = $response.Content
$tableNames = $tables.feed.entry.content.properties.TableName
Write-host ""
Write-host "Found Tables to backup" -ForegroundColor Yellow
Write-host "--------------------------" -ForegroundColor Yellow
foreach ($tableName in $tableNames)
{
Write-Host " -Table: $tableName"
}
foreach ($tableName in $tableNames)
{
$url = "https://$Account.table.core.windows.net/$tableName"
Write-host ""
Write-Host "Backing up Table: $url"-ForegroundColor Yellow
Write-host "--------------------------" -ForegroundColor Yellow
Write-host ""
& "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\AzCopy\AzCopy.exe" /Source:$url /Dest:$OutputDir\$account\ /SourceSAS:$SASToken /Z:"$env:temp\$([guid]::NewGuid()).azcopyJournal"
Write-host ""
Write-host "Backup completed" -ForegroundColor Green
Write-host ""
Write-host ""
}
For more details on usage have a look here:
https://gripdev.wordpress.com/2016/04/08/backup-azure-table-storage-quick-powershell-script/
You can backup any Azure Table Storage table (not blobs though) with free software like Slazure Light. The following C# code backup all your Azure Tables to json files:
Download NuGet packages first:
Install-Package Azure.Storage.Slazure.Light
Create a console application in Visual Studio and add the following code:
using System;
using System.Linq;
using Microsoft.WindowsAzure.Storage.Table;
using Newtonsoft.Json;
using SysSurge.Slazure.AzureTableStorage;
namespace BackupAzureTableStore
{
class Program
{
/// <summary>
/// Usage: BackupAzureTableStore.exe "UseDevelopmentStorage=true"
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
var storage = new DynStorage(args.Length == 0 ? "UseDevelopmentStorage=true" : args[0]);
foreach (var cloudTable in storage.Tables)
{
var tableName = cloudTable.Name;
var fileName = $"{tableName}.json";
using (var file = new System.IO.StreamWriter(fileName))
{
var dynTable = new DynTable(storage.StorageAccount, tableName);
TableContinuationToken token = null; // Continuation token required if > 1,000 rows per table
do
{
var queryResult =
dynTable.TableClient.GetTableReference(tableName)
.ExecuteQuerySegmented(new TableQuery(), token);
file.WriteLine("{{{0} : [", JsonConvert.SerializeObject(tableName));
var cntr = 0;
foreach (var entity in queryResult.Results)
{
var dynEntity = dynTable.Entity(entity.PartitionKey, entity.RowKey);
dynEntity.LoadAll().ToList(); // Force pre-downloading of all properties
file.WriteLine("{0}{1}", cntr++ > 0 ? "," : string.Empty,
JsonConvert.SerializeObject(dynEntity));
}
file.WriteLine("]}");
token = queryResult.ContinuationToken;
} while (token != null);
}
}
Console.WriteLine("Done. Press a key...");
Console.ReadKey();
}
}
}

Get user details from SharePoint with PowerShell

I'm using this PowerShell script to get site owners:
$siteUrl = Read-Host "enter site url here:"
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication
foreach($site in $spWebApp.Sites)
{
foreach($siteAdmin in $site.RootWeb.SiteAdministrators)
{
Write-Host "$($siteAdmin.ParentWeb.Url) - $($siteAdmin.DisplayName)"
}
$site.Dispose()
}
$rootSite.Dispose()
I want that it will print some details of the site owner like phone number and email. How can I achieve that?
You have two choices I think. Access the SPUser properties or get information from active directory.
In the first case, are you not able to access the properties as you did for DisplayName? I mean if you have a SPUser object to get the email just use:
write-output "$($siteAdmin.Email)"
For information about to get the user properties from active directory, you can easily implement the solution provided in the following question. It worked fine for me.
Hope this helps
EDIT with improvement
Standing from MS Documentation you have some properties avaialble, see SPUSer Members. FOr example you have not phone.
To get something from the active directory try to change the following function so that it returns the attributes you need (tested on windows 2k8 server):
function Get-AD-Data {
$strFilter = "(&(objectCategory=User))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
$objSearcher.FindAll() | select #{L="User";E={$_.properties.displayname}},
#{L="Department";E={$_.properties.department}},
#{L="MemberOf";E={$_.properties.memberof}}
}
This function returns all users from AD along with the selected attributes. To get information from a specific user you would use (I guess):
$ad_userdetails = Get-AD-Data | ? {$_.user -eq $siteAdmin.Name}
Cheers

Update SharePoint Default Alternate Access Mapping Programmatically

I'm enabling HTTPS on my IIS server where I have SharePoint Services 3.0 installed and I'd like to programatically update the default alternate access mappings for a single web application and my central administration instance (both on the same machine). Here's the code I have so far (Powershell), it adds a mapping for HTTPS but I get and error when trying to remove the original one.
Here's my code:
[void][system.reflection.assembly]::LoadWithPartialName("Microsoft.Sharepoint")
$SPWebServiceCollection = new-object Microsoft.SharePoint.Administration.SPWebServiceCollection ([Microsoft.SharePoint.Administration.SPFarm]::Local)
foreach ($SPWebService in $SPWebServiceCollection) {
foreach ($webApplication in $SPWebService.WebApplications) {
Write-Host ('Updating {0}' -f $webApplication.Name)
foreach ($alternateUrl in $webApplication.AlternateUrls) {
$incomingUrl = [System.URI] $alternateUrl.IncomingUrl
$newURL = 'https://{0}{1}' -f $incomingUrl.Authority, $incomingUrl.PathAndQuery
$newAltURL = New-Object Microsoft.SharePoint.Administration.SPAlternateUrl ($newURL, $alternateUrl.UrlZone)
$webApplication.AlternateUrls.Add($newAltURL)
$webApplication.AlternateUrls.Update($true)
$webApplication.AlternateUrls.Remove($alternateUrl) #Throws Exception
$webApplication.AlternateUrls.Update($true)
}
}
}
Here is the error I get when I try to remove the original:
Exception calling "Remove" with "1" argument(s): "An object in the SharePoint administrative framework, "SPAlternateUrlCollection Name=SharePoint - 1000 Parent=SPFarm Name=SharePoint_Config_8ddd3701-a332-4e79-98e4-fa11c1b6c17c", could not be deleted because other objects depend on it. Update all of these dependants to point to null or different objects and retry this operation. The dependant objects are as follows:
SPWebApplication Name=SharePoint - 1000 Parent=SPWebService
However, i'm not sure how to do what the exception suggests.
Ah... it looks like you are trying to remove the URL the Webservice is using...
It turns out there's another method for the exiting default entry that I overlooked:
$webApplication.AlternateUrls.SetResponseUrl($newAltURL)
[void][system.reflection.assembly]::LoadWithPartialName("Microsoft.Sharepoint")
$SPWebServiceCollection = new-object Microsoft.SharePoint.Administration.SPWebServiceCollection ([Microsoft.SharePoint.Administration.SPFarm]::Local)
foreach ($SPWebService in $SPWebServiceCollection) {
foreach ($webApplication in $SPWebService.WebApplications) {
Write-Host ('Updating {0}' -f $webApplication.Name)
foreach ($alternateUrl in $webApplication.AlternateUrls) {
$incomingUrl = [System.URI] $alternateUrl.IncomingUrl
$newURL = 'https://{0}{1}' -f $incomingUrl.Authority, $incomingUrl.PathAndQuery
$newAltURL = New-Object Microsoft.SharePoint.Administration.SPAlternateUrl ($newURL, $alternateUrl.UrlZone)
$webApplication.AlternateUrls.SetResponseUrl($newAltURL)
$webApplication.AlternateUrls.Update($true)
}
}
}

Manage views for content types (or add a view to multiple lists)

I'm surprised that I cannot find on the net a solution where I could manage views for content types. Do I really have to visit each task list with my browser to add/modify a view?
Is there any solutions available that would allow me to just define a view for content type and thus make this view available on all lists where content type is?
Directly speaking, no, a view cannot be assigned to a content type. Lists are what hold an actual view collection, and the corresponding aspx page that is created with it. A view also has a dependent existence with its list: you cannot have a view that is not associated with a list. There is also no "event handler" for adding a content type to a list, either, so you can't have some automatic process that occurs whenever you add a content type to the list (and it would be cumbersome anyway as you'd have to attach the event handler to the list in the first place!).
This isn't to say you have to manually muck about in the UI to accomplish the task, though. Using the object model in something like a custom code workflow, you can sweep across your entire SPWeb and create a new view on each list that has the specified content type. All you need is a workflow with a single code activity, which iterates across all of the SPLists in SPWeb.Lists, and check if that SPList has the content type with the same name as your target content type. If it does, create a new SPView with the parameters you need. Since you cannot simply create one SPView and clone it, as an SPView must be associated with a list and cloning an SPView just clones it onto the same list, you'll have to run the whole SPView creation in each loop. But you only have to write it once, it's the system that'll have to run it multiple times. And by heavens, it'll certainly get that done a lot more productively than if you had to dance about in the UI for a few hours.
Simply run the workflow any time you need to reassert the existence of that SPView.
I found this solution in c#, however I have not yet tested it.
I will test it in the future, and update this if necessary.
Apparently, it is for SharePoint 2010, however it may work in later versions too.
private void CreateView(string strViewName)
{
try
{
string fieldName = //Get Field Internal Name
var docquery = "<Where><Eq><FieldRef Name='" + fieldName.ToString() + "' /><Value Type='Choice'>" + strViewName.ToString() + "</Value></Eq></Where>";
System.Collections.Specialized.StringCollection viewFields = new System.Collections.Specialized.StringCollection();
viewFields.Add("Type");
viewFields.Add("Name");
viewFields.Add("Modified");
viewFields.Add("Modified By");
viewFields.Add(fieldName.ToString());
oViewCollection.Add(strViewName, viewFields, docquery, 100, true, false);
web.Update();
}
catch (Exception e)
{
throw new SPException(e.Message.ToString());
}
}
I also found this solution in PowerShell...
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA silentlycontinue
#Title View
$viewTitle = "Sort by modified date"
#Add the column names from the ViewField property to a string collection
$viewFields = New-Object System.Collections.Specialized.StringCollection
$viewFields.Add("DocIcon") > $null
$viewFields.Add("LinkFilename") > $null
$viewFields.Add("Modified") > $null
$viewFields.Add("Editor") > $null
$viewFields.Add("FileSizeDisplay") > $null
#Query property
$viewQuery = "<OrderBy><FieldRef Name='Modified' Ascending='FALSE'/></OrderBy>"
#RowLimit property
$viewRowLimit = 50
#Paged property
$viewPaged = $true
#DefaultView property
$viewDefaultView = $false
$ListsToUpdate = #()
$App = Get-SPWebApplication http://....
foreach ($Site in $App.Sites)
{
foreach ($Web in $Site.AllWebs)
{
foreach ($List in $Web.Lists)
{
if($List.BaseType -eq "DocumentLibrary" -and $List.Title -eq "Documents" )
{
$ListsToUpdate += $Web.Lists[$List.Title]
}
}
}
}
foreach($List in $ListsToUpdate)
{
Write-Host $List.Title
#Create the view in the destination list
$newview = $List.Views.Add($viewTitle, $viewFields, $viewQuery, $viewRowLimit, $viewPaged, $viewDefaultView)
}

Script to delete files older than a day in Sharepoint document library

I need a script which can delete all files which are older than a day and this script needs to be invoked every day automatically in the Sharepoint server.
How can i do this and any hints as how to write the script?
I think an easier way to do it would be to create a site collection policy with an expiration. Set the retention period for one day. You can then attach the disposition workflow to your list which acn be used to clean these files up. You should be able to do all of this without writing any code.
Here is a link with more information about disposition workflow.
http://office.microsoft.com/en-us/sharepointserver/HA101544291033.aspx
Thanks,
Corey
If you really need a script rather than writing code (such as a timer job) then use Powershell to access the SharePoint .NET objects with a scripting engine. Once you've written the script, set up a Windows scheduled task to run it every day.
In the script follow Lars' guidance on using one of those two query classes. Then from the query results you can obtain a reference to each SPListItem you'd like to delete. Either use SPListItem.Delete or SPListItem.Recycle to remove the item.
Here's an example that uses SPQuery:
[System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
$site = new-object Microsoft.SharePoint.SPSite("http://yoursite/")
$web = $site.OpenWeb("Web Title")
$documentLibrary = $web.Lists["Document Library Name"]
$yesterdaysDate = [Microsoft.SharePoint.Utilities.SPUtility]::CreateISO8601DateTimeFromSystemDateTime([System.DateTime]::UtcNow.AddDays(-1.0))
$query = new-object Microsoft.SharePoint.SPQuery
$query.ViewFields = "<FieldRef Name='Modified' />"
$query.Query = "<Where><Leq><FieldRef Name='Modified' /><Value Type='DateTime' IncludeTimeValue='TRUE'>" + $yesterdaysDate + "</Value></Leq></Where>"
$queryItems = $documentLibrary.GetItems($query)
foreach ($item in $queryItems)
{
echo $item.Url
$item.Delete()
}
$web.Dispose()
$site.Dispose()
You could create a custom timer job in SharePoint using .NET and the WSS API to do the job. Use the SPQuery class to query files by date in a document library. Use the SPSiteDataQuery class if you need to query across multiple document libraries.
Here is C# code to delete only files on SharePoint site which are older than a day, to run this every day you need to create SharePoint Timer Job and add below code inside execute method of timer job.
SPSite spSite = new SPSite("http://YourSiteUrl");
SPWeb oWebsite = spSite.OpenWeb();
SPListCollection collLists = oWebsite.Lists;
foreach (SPList oList in collLists)
{
if (oList.BaseType == SPBaseType.DocumentLibrary)
{
SPDocumentLibrary oDocumentLibrary = (SPDocumentLibrary)oList;
if (!oDocumentLibrary.IsCatalog && oList.BaseTemplate != SPListTemplateType.XMLForm)
{
SPListItemCollection collListItems = oDocumentLibrary.Items;
foreach (SPListItem oListItem in collListItems)
{
if (oListItem.File != null)
{
if ((DateTime.Now - oListItem.File.TimeCreated).TotalDays > 1)
{
oListItem.Delet();
}
}
}
}
}
}

Resources