Tag Archives: SharePoint

Upgrading/Migrating from an older SharePoint version to a newer SharePoint

This is my checklist for when I am upgrading content from an older SharePoint to a newer one. Like from SharePoint 2010 to SharePoint 2013.

  • Make sure that you disable the outgoing Email address from the Central Administration in the web applications own settings. This is if you have events or other functionality that is to send emails based on some logic. You do not want to send emails confusing end users about emails which should not be send.
  • Install you needed packages for the migration process. This is important. If you do not do this the content database upgrade will have multiple errors and you might not be able to retrieve them.
    1. Notice another important reason why this is important is that lists and libraries are feature dependent. If there is a missing feature your lists or libraries will show empty views or will not function. Even if there is an access point through a URL, SharePoint will not be able to show you the content.
  • Next take a database backup in SQL Server from your old environment. You do this by: Pressing the secondary mouse button on a database > Tasks > Back Up… . Make sure that you check the checkbox named “Copy-only backup”. This is important, if you do not do this this will cause problems for the current database being used by the old SharePoint farm.
  • Next start the process of upgrading the content. More details here: https://technet.microsoft.com/en-us/library/cc303436.aspx
    • For a SharePoint 2010 upgrade, you might need to create a classic authentication application. More details here: https://technet.microsoft.com/en-us/library/gg251985.aspx
    • Sample command: New-SPWebApplication -name “ClassicAuthApp2” -Port 100 -ApplicationPool “ClassicAuthAppPool” -ApplicationPoolAccount (Get-SPManagedAccount “<domainname>\<user>”)
    • Before you perform the actual upgrade test the database with the following command: Test-SPContentDatabase -Name DatabaseName -WebApplication URL > TestLog.txt
      1. This will output a log file in the same folder where you are in the SharePoint management shell. Look at the log file and fix the errors found. It may not be necessary to fix them all if the errors do not affect the content you need.
      2. Notice: The WebApplication URL is the same as the classic application URL created earlier if you created it.
    • The next step is to mount the database. This is the actual upgrade process.
      1. Sample Command: Mount-SPContentDatabase -Name DatabaseName -DatabaseServer ServerName -WebApplication URL
        1. Notice: If your SharePoint farm is using SQL Aliases then open the following program and see your SQL Server database name: C:\Windows\System32\cliconfg.exe
        2. Notice: The WebApplication URL is the same as the classic application URL created earlier if you created it.
      2. If you created the classic authentication application then the next step is to convert it to a claims application.
        1. Sample command: Convert-SPWebApplication -Identity <yourWebAppUrl> -To Claims -RetainPermissions [ -Force]
      3. Moving the needed content from one content database to the other. More details here: https://technet.microsoft.com/en-us/library/cc825328.aspx
        1. Create new a content database (or multiple ones if needed) and use the Move-SPSite command to move them from one location to the other. Notice: The new content database(s) must be in the same application for the command to work.
        2. Sample command: Move-SPSite <http://ServerName/Sites/SiteName> -DestinationDatabase <DestinationContentDb>
        3. When ready with the move operation of content, then detach your new content database(s) and attach it to the new location.
  • Check that if you have XSLT based list or library field customizations that they work. If not consider using JSLink functionality in webparts of by defining it in a field through a powershell script like the one below. There is also a sample how to do it in the JavaScript file
  • Check that you calculated columns are working in your new environment.
  • If you are having problems with you quick edit functionality try this script:
    1. https://lionadi.wordpress.com/2016/06/02/fix-quick-edit-for-sharepoint-lists-after-migration-from-sharepoint-2010-to-sharepoint-2013/
  • If you have different threshold definitions in the old environment check that your old content and functionality behaves correctly in the new environment.
  • Next step upgrade your SharePoint sites look. This is offered automatically by the new version of SharePoint but if not then:
    1. /_layouts/siteupgrade.aspx ja /_layouts/siteupgradestatus.aspx
  • Next configure your search:
    1. Make sure that your new content is in one of your content sources.
    2. Run a full crawl.
  • Feature installation problems:
    1. “Check that the feature has been installed. For example, if you are performing Update-SPSolution and a new feature has been added between solution deployments then the feature is not installed by default.
    2. To check do the following:-
    3. Run SharePoint 2010 Management Shell from one of the SharePoint servers Type Install-SPFeature -ScanForFeatures
      1. This will show you any features that are available in the SharePoint Root but have not been installed. You can install any missing features using the command :-
    4. Install-SPFeature -AllExistingFeatures
      1. See the following TechNet Article for more information:
        1. http://technet.microsoft.com/en-us/library/ff607825(v=office.14).aspx
    5. Get-SPFeature| Sort -Property Scope,DisplayName | FT -GroupBy Scope DisplayName,ID
  1. If you have problems with some of your views in a list or library while others views work, then a work around is to create the view using the problem view as the base view.
</pre>
param (

[string]$SPSiteFilter = "app url"

)

&nbsp;

if ((Get-PSSnapin 'Microsoft.SharePoint.PowerShell' -ErrorAction SilentlyContinue) -eq $null){Add-PSSnapin 'Microsoft.SharePoint.PowerShell'}

&nbsp;

&nbsp;

&nbsp;

$spWebApp = Get-SPWebApplication $SPSiteFilter

foreach($site in $spWebApp.Sites)

{

$ddField = $site.rootweb.Fields["field name"]

Write-Host $site.Url

if($ddField -ne $null)

{

&nbsp;

$ddField.JSLink = "~sitecollection/Style Library/JSLinkFix.js"

$ddField.Update($true)

Write-Host "Updated"

&nbsp;

}

&nbsp;

&nbsp;

&nbsp;

&nbsp;

$site.Dispose();

}

 

 

SharePoint site collection access 404 page not found error

If you encounter some of the errors below and especially when trying to access a page or the front page of a site collection or site then the problem might be related to missing page layout or master page references.

This may be due to the fact that you have migrated content from an older SharePoint version and the content database is referencing an older hive version.

So check that you solution packages are installed using compatibility mode:

install-spsolution -identity solution.wsp -webapplication “site url” -gacdeployment -CompatibilityLevel All

Relying on fallback logic in VghostPageManager::getGhostDocument() for document: ‘C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Template\SiteTemplates\somesite\default.aspx’

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

Fix deleted AD users from SharePoint

This is a small PowerShell script that will fix issues with removed SharePoint users. You may encounter problems if you remove an AD user but the later re-create it with the same AD user login. If such cases this script might help you with possible SharePoint issues. If this does not help then try to remove the user profile and run a full user profile synchronization and run the script again.


$sites = Get-SPSite http://portal.spdev.com

foreach ($site in $sites) {
$groups = $site.RootWeb.sitegroups
foreach ($group in $groups) {
foreach ($user in $group.users) {
# Skip All Authenticated Users, General groups
if ($user.userlogin -eq "c:0(.s|true" -or $user.userlogin -eq "c:0!.s|windows") {
continue;
}
if ($user.IsDomainGroup) {
# Skip Security Groups
}
else {
# Get user login
$splitline = $user.userlogin.split("\");
$samid = $splitline[1];
if ($user.userlogin.contains("AD domain name"))
{
if ($user.userlogin.contains("part of your login name")) {
Write-Host "user Found" $user.userlogin
$group.removeuser($user);
$site.RootWeb.SiteUsers.Remove($user.userlogin);
}
else {
Write-Host $user.userlogin
}
}
}
}
}
}

How to Fix Quick Edit for SharePoint lists after migration from SharePoint 2010 to Sharepoint 2013

Once again with annoying problem in SharePoint. The problem will most likely occur after you have migrated a content database from SP2010 to SP2013. Thanks to the internet the solution is to make sure that list views have in ther JSLink property the following file in them: clienttemplates.js

Thanks to the following site for the tip on how to fix it:

http://www.rickvanrousselt.com/updating/

Here is a sample C# code that will fix the problem. Using powershell I was unable to get a hold of views in lists after the migration.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;

using Microsoft.SharePoint;
namespace SP2013MigrationListFix
{
class Program
{
static void Main(string[] args)
{
using(var site = new SPSite(ConfigurationManager.AppSettings["site"]))
{
for (int siteCount = site.WebApplication.Sites.Count - 1; siteCount >= 0; siteCount--)
{
Console.WriteLine();
Console.WriteLine("----------------------------------------------------------------------");
SPSite innerSite = site.WebApplication.Sites[siteCount];
Console.Write("Site: " + innerSite.RootWeb.Title);
try
{
for (int webCount = innerSite.AllWebs.Count - 1; webCount >= 0; webCount--)
{

SPWeb web = innerSite.AllWebs[webCount];
Console.WriteLine();
Console.WriteLine("Web: " + web.Title);
try
{

for (int listCount = web.Lists.Count - 1; listCount >= 0; listCount--)
{
SPList list = web.Lists[listCount];
Console.WriteLine("Web: " + list.Title);
if (list != null)
{
Console.WriteLine("View count: " + list.Views.Count);
for (int x = list.Views.Count - 1; x >= 0; x--)
{
SPView view = list.Views[x];
Console.WriteLine("View name: " + view.Title);
Console.WriteLine("JSLink before fix: " + view.JSLink);
if (String.IsNullOrWhiteSpace(view.JSLink))
{
view.JSLink = "clienttemplates.js";
view.Update();
Console.WriteLine("JSLink after fix: " + view.JSLink);
}

}
}
else
{
Console.WriteLine("List not found");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " " + ex.StackTrace);
}
finally
{
if (web != null)
web.Dispose();
}
}
}
finally
{
if (innerSite != null)
innerSite.Dispose();
}
}

}
Console.ReadLine();
}
}
}

SharePoint change document set and items content type to a new content type

I’ll put it simply:

This is a PowerShell script that you can use to change a content type of a library or list to another one. This script can identify between Document Sets and library or list items.


param (
[string]$WebsiteUrl = "http://portal.spdev.com/",
[string]$OldCTName = "DSTestCT",
[string]$NewCTName = "DSTestCT"
)

if ( (Get-PSSnapin -Name MicroSoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin MicroSoft.SharePoint.PowerShell
}

function Reset-ListContentType ($WebUrl, $ListName, $OldCTName, $NewCTName)
{
$web = $null
try
{
$web = Get-SPWeb $WebUrl

$list = $web.Lists.TryGetList($ListName)
$oldCT = $list.ContentTypes[$OldCTName]

$isChildOfCT = $list.ContentTypes.BestMatch($rootNewCT.ID).IsChildOf($rootNewCT.ID);
if($oldCT -ne $null -and $isChildOfCT -eq $false)
{
$hasOldCT = $true
$isFoldersCTReseted = Reset-SPFolderContentType –web $web -list $list –OldCTName $OldCTName –NewCTName $NewCTName
Reset-SPFileContentType –web $web -list $list –OldCTName $OldCTName –NewCTName $NewCTName
Remove-ListContentType –web $web -list $list –OldCTName $OldCTName –NewCTName $NewCTName
if($hasOldCT -eq $true)
{
Add-ListContentType –web $web -list $list –OldCTName $OldCTName –NewCTName $NewCTName
if($isFoldersCTReseted -eq $true)
{
Set-SPFolderContentType –web $web -list $list –OldCTName $OldCTName –NewCTName $NewCTName
}
}
}


}catch
{

}
finally
{
if($web)
{
$web.Dispose()
}
}

}

function Remove-ListContentType ($web, $list, $OldCTName, $NewCTName)
{


$oldCT = $list.ContentTypes[$OldCTName]

$isChildOfCT = $list.ContentTypes.BestMatch($oldCT.ID).IsChildOf($oldCT.ID);

if($isChildOfCT -eq $true)
{
$list.ContentTypes.Delete($oldCT.ID)
}
$web.Dispose()

return $isChildOfCT
}

function Add-ListContentType ($web, $list, $OldCTName, $NewCTName)
{



$list.ContentTypes.Add($rootNewCT)

$web.Dispose()
}

function Reset-SPFolderContentType ($web, $list, $OldCTName, $NewCTName)
{
#Get web, list and content type objects

$isFoldersCTReseted = $false


$isChildOfCT = $list.ContentTypes.BestMatch($rootNewCT.ID).IsChildOf($rootNewCT.ID);

$oldCT = $list.ContentTypes[$OldCTName]
$folderCT = $list.ContentTypes["Folder"]
$newCT = $rootNewCT

$newCTID = $newCT.ID

#Check if the values specified for the content types actually exist on the list
if (($oldCT -ne $null) -and ($newCT -ne $null))
{
$list.Folders | ForEach-Object {

if ($_.ContentType.ID.IsChildOf($rootNewCT.ID) -eq $false -and $_.ContentType.ID.IsChildOf($oldCT.ID) -eq $true -and $_.Folder.ProgID -eq "Sharepoint.DocumentSet")
{
Write-Host "Found a document set: " $_.Name "Processing document set"
$item = $list.GetItemById($_.ID);
$item["ContentTypeId"] = $folderCT.Id
$item.Update()
$isFoldersCTReseted = $true
}
}
}

$web.Dispose()

return $isFoldersCTReseted
}

function Set-SPFolderContentType ($web, $list, $OldCTName, $NewCTName)
{
#Get web, list and content type objects



$folderCT = $list.ContentTypes["Folder"]
$newCT = $list.ContentTypes[$NewCTName]

#Check if the values specified for the content types actually exist on the list
if (($newCT -ne $null))
{
$list.Folders | ForEach-Object {
if ($_.ContentType.ID.IsChildOf($newCT.ID) -eq $false -and $_.ContentType.ID.IsChildOf($folderCT.ID) -eq $true -and $_.Folder.ProgID -eq "Sharepoint.DocumentSet")
{
$item = $list.GetItemById($_.ID);
$item["ContentTypeId"] = $newCT.Id
$item.Update()
}
}
}

$web.Dispose()
}


function Reset-SPFileContentType ($web, $list, $OldCTName, $NewCTName)
{
#Get web, list and content type objects



$isChildOfCT = $list.ContentTypes.BestMatch($rootNewCT.ID).IsChildOf($rootNewCT.ID);

$oldCT = $list.ContentTypes[$OldCTName]
$folderCT = $list.ContentTypes["Folder"]
$newCT = $rootNewCT

$newCTID = $newCT.ID

#Check if the values specified for the content types actually exist on the list
if (($oldCT -ne $null) -and ($newCT -ne $null))
{
$list.Folders | ForEach-Object {
if ($_.ContentType.ID.IsChildOf($rootNewCT.ID) -eq $false -and $_.ContentType.ID.IsChildOf($oldCT.ID) -eq $true)
{
$_["ContentTypeId"] = $folderCT.Id
$_.Update()
}
}
#Go through each item in the list
$list.Items | ForEach-Object {
Write-Host "Item present CT ID :" $_.ContentType.ID
Write-Host "CT ID To change from :" $oldCT.ID
Write-Host "NEW CT ID to change to:" $rootNewCT.ID

#Check if the item content type currently equals the old content type specified
if ($_.ContentType.ID.IsChildOf($rootNewCT.ID) -eq $false -and $_.ContentType.ID.IsChildOf($oldCT.ID) -eq $true)
{
#Check the check out status of the file
if ($_.File.CheckOutType -eq "None")
{
Change the content type association for the item
$item = $list.GetItemById($_.ID);
$item.File.CheckOut()
write-host "Resetting content type for file: " $_.Name "from: " $oldCT.Name "to: " $newCT.Name

$item["ContentTypeId"] = $newCTID
$item.UpdateOverwriteVersion()
Write-Host "Item changed CT ID :" $item.ContentType.ID
$item.File.CheckIn("Content type changed to " + $newCT.Name, 1)
}
else
{
write-host "File" $_.Name "is checked out to" $_.File.CheckedOutByUser.ToString() "and cannot be modified"
}
}
else
{
write-host "File" $_.Name "is associated with the content type" $_.ContentType.Name "and shall not be modified"
}
}
}
else
{
write-host "One of the content types specified has not been attached to the list"$list.Title
return
}

$web.Dispose()
}

$web = Get-SPWeb $WebsiteUrl
$rootWeb = $web.Site.RootWeb;
$rootNewCT = $rootWeb.AvailableContentTypes[$NewCTName]

Foreach ($list in $web.Lists) {
Write-Host $list.BaseType
if($list.Hidden -eq $false -and $list.BaseType -eq "DocumentLibrary")
{
Write-Host "Processing list: " $list.Title
Reset-ListContentType –WebUrl $WebsiteUrl –ListName $list.Title –OldCTName $OldCTName –NewCTName $NewCTName
}
}

$web.Dispose()

 

How to display all of the refinement options in SharePoint 2013 Search results

By default for some reason, I could not show all of the items, I could define how many items are shown and but not get rid of the “show more” links under the refinements.

This JavaScript snippet can help you. It will hide the “short list” containing a minimum of items to be displayed, then it will show the long list and finally it will hide the “show more” link.

</pre>
<script>
 $( document ).ready(function() {
$('#unselLongList').show();
$('#unselShortList').hide();
$('#unselToggle').hide();

});
</script> 

SharePoint Search and changing the Created and LastModified fields

If you want to change the LastModified and Created fields of a list item or a document you can use this code to do that:


SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite("site + web url"))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPListItem listItem = web.GetListItem(this.tbItemURL.Text);

if (this.cCreatedDate.SelectedDate != new DateTime())
listItem[SPBuiltInFieldId.Created] = this.cCreatedDate.SelectedDate;
else
listItem[SPBuiltInFieldId.Created] = listItem[SPBuiltInFieldId.Created];

if (this.cModifiedDate.SelectedDate != new DateTime())
listItem[SPBuiltInFieldId.Modified] = this.cModifiedDate.SelectedDate;
else
listItem[SPBuiltInFieldId.Modified] = listItem[SPBuiltInFieldId.Modified];

listItem.UpdateOverwriteVersion();
if (listItem.ParentList.EnableMinorVersions)
{
listItem.File.Publish("SPFileUpload");
}
if (listItem.ModerationInformation != null)
{
listItem.File.Approve("SPFileUpload");
}




web.AllowUnsafeUpdates = false;
}
}
});

The reason why the above is done is because if you simply change the date values and use the UpdateOverwireVersion() it will not be enough. The search will not be able to index right values EVEN if you check the UI or use PowerShell or SharePoint Manager etc. All of those show that the value is OK but actually is not. The manually inserted dates will not show up in search unless the item or document is published and approved. So no matter that SP says remember this :).

another thing is that this code above does not allow to set a LastModified IF you have publishing/versioning enabled. After calling the UpdateOverwriteVersion function the item or document will be checked out and remains in that state until something is done. Once you do that you are back to where you started the modified date is changed automatically by SP.

Do not have a solution yet. Maybe you have?

PowerShell script how to backup lists and restore them in another location through list templates

Ok, this is one way of doing this. Perhaps this is useful in a situation where you need to backup lists with their data from an older SharePoint version and restore it in another SharePoint version. Preferably doing this quickly without worrying about site templates or something more than the list and its data.

The script below gets lists in a target web location, saves them as list templates and download them in the hard drive.

Approach 1: Export the list through Export-SPWeb and restore with Import-SPWeb

param (
 [string]$SPSiteFilter = "http://portal.spdev.com/",
 [string]$SPWebFilter = "http://portal.spdev.com/",
 [string]$SPWebFilterRelative = "",
 [string]$destination = "C:\\temp"
 )
 
 $site = Get-SPWeb $SPSiteFilter
 
 
 # Get the webs lists and save them as list templates
 $lists = $site.lists
Foreach ($list in $lists) {
Write-Host $list.BaseType
 if($list.Hidden -eq $false -and $list.BaseType -eq "GenericList")
 {
 Write-Host $list.Title + " " + $list.RootFolder.ServerRelativeUrl
 
 $filePath = $destination + "\" + $list.Title + ".cmp"
 $itemURL = $SPWebFilterRelative + $list.RootFolder.ServerRelativeUrl
 Write-Host $filePath
 Write-Host $itemURL
 Write-Host $SPWebFilter
 export-spweb -identity $SPWebFilter -path $filePath -itemurl $itemURL –includeusersecurity
 #$list.SaveAsTemplate($list.Title+ " " + $ListTempalteIDPostFix,$list.Title,"Site list Backup",1)
 }
 }

 $site.Dispose()
param (
 [string]$SPSiteFilter = "http://portal.spdev.com/subsite/",
 [string]$source = "C:\\temp"
 )
 
 $site = Get-SPWeb $SPSiteFilter
 
 Get-ChildItem $source -Filter *.cmp | 
Foreach-Object {
 Write-Host $_.FullName
 #Upload the list temaplte to the list templates gallery
 Import-SPWeb -identity $SPSiteFilter -path $_.FullName –force
 
}

$site.Dispose()

Approach 2: As list templates


param (
[string]$SPSiteFilter = &quot;http://site/&quot;,
[string]$SPWebFilter = &quot;http://site/myweb/&quot;,
[string]$ListTempalteIDPostFix = &quot;SU&quot;,
[string]$destination = &quot;C:\\temp&quot;
)

$site = Get-SPSite $SPSiteFilter
$web = Get-SPWeb $SPWebFilter
$templatesLibrary = $site.RootWeb.GetListFromUrl(&quot;/_catalogs/lt/Forms/AllItems.aspx&quot;)

if(!$templatesLibrary)
{
Write-Host &quot;List template gallery not found. Program execution halted.&quot;
return
}

# Get the webs lists and save them as list templates
$lists = $web.lists
Foreach ($list in $lists) {
Write-Host $list.BaseType
if($list.Hidden -eq $false -and $list.BaseType -eq &quot;GenericList&quot;)
{
Write-Host $list.Title
$list.SaveAsTemplate($list.Title+ &quot; &quot; + $ListTempalteIDPostFix,$list.Title,&quot;Site list Backup&quot;,1)
}
}

# Read the list templates from the gallery and save them to the hard drive
$folder = $templatesLibrary.RootFolder
foreach ($file in $folder.Files) {
#Ensure destination directory
$destinationfolder = $destination

#Download file
$binary = $file.OpenBinary()
$stream = New-Object System.IO.FileStream($destinationfolder + &quot;/&quot; + $file.Name), Create
$writer = New-Object System.IO.BinaryWriter($stream)
$writer.write($binary)
$writer.Close()

}
For ($i=$folder.Files.Count; $i -gt 0 -or $i -eq 0; $i--)
{
$folder.Files[$i].Delete()
}

$web.Dispose()
$site.Dispose()

This script uploads the list templates into the targeted SharePoint site.

param (
[string]$SPSite = &quot;http://portal3.dev.com/sites/sc&quot;,
[string]$SiteTemplatesLocation = &quot;C:\\temp&quot;,
[string]$SiteTemplatesGalleryName = &quot;List Template Gallery&quot;
)
# $site = Get-SPSite $SPSiteFilter
# $web = Get-SPWeb $SPSiteFilter
# $templatesLibrary = $site.RootWeb.GetListFromUrl(&quot;/_catalogs/lt/Forms/AllItems.aspx&quot;)
# $Files = $templatesLibrary.RootFolder.Files

Function UploadListTemplate($WebURL, $TemplateFilePath)
{
#Get the Web
$web = Get-SPWeb $WebURL
#Get the List template Gallery Folder
$TemplateFolder = $web.GetFolder($SiteTemplatesGalleryName)
#Get the Files collection
$TemplateFileCollection = $TemplateFolder.Files
#Get the Template file from Local File system
$TemplateFile = Get-ChildItem $TemplateFilePath

#Open the File in Read mode and Add to Templates collection
$TemplateFileCollection.Add(&quot;_catalogs/lt/$($TemplateFile.Name)&quot;, $TemplateFile.OpenRead(), $true)
Write-Host &quot;Done!Template has been uploaded!!&quot;
$web.Dispose()

}

Get-ChildItem $SiteTemplatesLocation -Filter *.stp |
Foreach-Object {
Write-Host $_.FullName
#Upload the list temaplte to the list templates gallery
UploadListTemplate $SPSite $_.FullName

}

This script will create the lists based on the list templates NOTICE that this does not differentiate between existing list templates not uploaded with the script above.

 param (
 [string]$SPSiteFilter = &quot;http://portal3.dev.com/sites/sc&quot;,
 [string]$ListTempalteIDPostFix = &quot;SU&quot;,
 [string]$destination = &quot;C:\\temp&quot;
 )

 $site = Get-SPSite $SPSiteFilter
 $web = Get-SPWeb $SPSiteFilter

 # Create lists based on the list templates
$site.GetCustomListTemplates($web) |
Foreach-Object {
if($web.Lists.TryGetList($_.Name.Replace($ListTempalteIDPostFix,&quot;&quot;)) -eq $null)
{
 $web.Lists.Add($_.Name.Replace($ListTempalteIDPostFix,&quot;&quot;), $_.Description, $_)
 }
}

 $web.Dispose()
 $site.Dispose()
 

If your list has content that is too large to save as a template try to run this script and remember to change to the default value which I think should be: 52428800


$docSize = 500000000
$webservice = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$webservice.MaxTemplateDocumentSize = $docSize
$webservice.Update()

Prerequisites for custom list templates

SharePoint List must meet the following criteria to move a list by using a list template (source):

  • The list must contain less than 10 megabytes (MB) of list data.
  • You must be a member of a site group with the Manage Lists right on the source site and on the destination site. By default, the Manage Lists right is included in the Web Designer and Administrator site groups.
  • The source site and the destination site must be based on the same site template.

How to use Microsoft Graph to get office groups listed in a native (Console) application

To get groups from using Microsoft Graph you have to do the following things:

  • Register an application using Azure AD and give required privileges to the application
  • Request a token for your application using the client ID and client secret key
  • Make the API call to using REST by specifying that your realm where to get the groups from

Register your application through Azure AD

Go to https://portal.azure.com/ or https://manage.windowsazure.com

Next from the Azure navigation go to your active directory. Next you should see different options in the top area of the your AAD, such as:

Users, Groups, Applications, Domain and so on.

Select the Applications section.

aad1

Next you should get a listing of applications configured in your AAD.

Next from the AAD UI select ADD to add a new application.

aad2

Select what type of an application it is. You can use both option. I used the configurations of an MVC application which allowed me to work just fine. What matters is the client ID, client secret key and the privileges. The redirect URL is not necessary for a Native Application, you can type in anything as long as it is a URL.

aad4aad5

 

After your application is created go to the configure section.

aad6

Here find the client ID and copy store it somewhere to be used later.

Then go to the keys section and add a new key(client secret)

aad7

Then scroll down and go the applications section and add the Microsoft Graph application and select the needed privileges. In this case, you would like at least to be able to read groups.

aad8aad9

That is it, next is some code.

Request a token for your application

This is the piece of code that will get the token from your application. The constants and parameters will be explained soon.

public static string GetTokenForApplication(String realm, String clientId, String clientSecret)
 {
 AuthenticationContext authenticationContext = new AuthenticationContext(Constants.UnifiedApiConnect.AzureADAuthority + realm, false);
 // Config for OAuth client credentials 
 ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

 AuthenticationResult authenticationResult = authenticationContext.AcquireToken(Constants.UnifiedApiConnect.O365UnifiedAPIResource,
 clientCred);
 string token = authenticationResult.AccessToken;
 return token;
 }

Make the API Call to get the groups

This is the code that will get the token and request data from the Graph API


TokenHelper.Token = Program.GetTokenForApplication(realm, clientId, clientSecret);
 List&amp;lt;Group&amp;gt; groups = new List&amp;lt;Group&amp;gt;();
 string APIURL = Constants.UnifiedApiConnect.O365UnifiedAPIResource + "v1.0/" + realm + "/groups?$filter=groupTypes/any(c:c+eq+'Unified')";
 try
 {
 groups = GroupsHttpHelper.GetGroups(APIURL);
 foreach (var group in groups)
 {
 groupsSite.Add(new SiteDirectoryEntity() { Title = group.displayName, URL = String.Format(Program.O365OutlookMailGroupURL, realm, realmLCID, group.mail) });
 }
 }
 catch (Exception ex)
 {
 Logger.Error("Error in processing O365 groups through MS Graph: " + ex.Message + "\n" + ex.StackTrace);
 }

This is the code that will do the request to the Graph API, notice that the data is deserialized into objects.

 


public class GroupsHttpHelper
 {
 public static List&amp;lt;Group&amp;gt; GetGroups(string apiUrl)
 {
 if (String.IsNullOrEmpty(apiUrl)) { throw new ArgumentNullException("apiUrl"); }

 List&amp;lt;Group&amp;gt; groups = new List&amp;lt;Group&amp;gt;();

 string responseContent = GroupsHttpHelper.GetHttpResource(apiUrl);
 var responseObject = JsonConvert.DeserializeObject&amp;lt;GraphResponse&amp;lt;Group&amp;gt;&amp;gt;(responseContent);
 foreach (var item in responseObject.value)
 {
 groups.Add(item);
 }

 return groups;

 }

 public static string GetHttpResource(string url)
 {
 string responseContent = String.Empty;

 string token = TokenHelper.Token;

 var request = (HttpWebRequest)HttpWebRequest.Create(url);

 request.Method = "GET";
 request.Accept = "application/json";
 request.Headers.Add("Authorization", "Bearer " + token);

 var response = request.GetResponse();
 using (var reader = new StreamReader(response.GetResponseStream()))
 {
 responseContent = reader.ReadToEnd();
 }

 return responseContent;
 }
 }

public class Group
 {
 public string accessType { get; set; }

 public bool? allowExternalSenders { get; set; }

 public bool? autoSubscribeNewMembers { get; set; }
 public string description { get; set; }
 public string displayName { get; set; }
 public string[] groupTypes { get; set; }
 public string id { get; set; } // identifier

 public bool isSubscribedByMail { get; set; }
 public string mail { get; set; }

 public bool? mailEnabled { get; set; }
 public string mailNickname { get; set; }
 public string onPremisesLastSyncDateTime { get; set; } //timestamp
 public string onPremisesSecurityIdentifier { get; set; }

 public bool? onPremisesSyncEnabled { get; set; }
 public string[] proxyAddresses { get; set; }

 public bool? securityEnabled { get; set; }
 public int unseenCount { get; set; }
 public string visibility { get; set; }
 }

Namespaces needed in the code:

using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;

NuGet Packages needed:

Active Directory Authentication Library – Id: Microsoft.IdentityModel.Clients.ActiveDirectory
Json.NET – Id: Newtonsoft.Json

WebConfig Values and parameters in the code

 

<add key=”MSGraphGourps_Realm” value=”yourrealm.com” />

<add key=”ClientId” value=”your client ID in the Azure AD application” />
<add key=”ClientSecret” value=”your client secret key in the Azure AD application” />

The URL format for the authentication context request is something like this: https://login.microsoftonline.com/yourrealm.com

To acquire the token: https://graph.microsoft.com/

To get the groups the URL is: https://graph.microsoft.com/1.0/yourrealm.com/groups

If you are not sure where to get your realm from there are two ways:

  1. Get it from the URL in your browser bar when you are viewing an O365 outlook mail box or group: https://outlook.office.com/owa/?realm=yourrealm.com
  2. The other option is to use the Azure Management UI and again in the url your should find it: https://manage.windowsazure.com/yourrealm.com

 

Getting other information from Groups

One Drive:

https://graph.microsoft.com/v1.0/your realm name/groups/{your group guid}/drive/root

Owners:

https://graph.microsoft.com/v1.0/your realm name/groups/{your group guid}/owners

Group Logo: