User automatically removed from SharePoint Group

During my current project we received an access request from a user. We did what we normally do, we checked the request and added the user in the appropriate SharePoint Group and notified the user.

After 15 minutes the user told us that it wasn’t working. We looked at the User Group and found out that the user was not in the group. So we added the user again because we thought that we forgot this step. After some time we received another mail from the user telling us that it still wasn’t working.

We requested the account details from the user and tried it our self, we found out that the user was missing again and added the account again. We logged in with the user opened a document with Office Web Applications and took another look at the members of the specific SharePoint group. WTF the user was gone!

After digging into the ULS files and looking in the Event log we did not found a clue of what was happening. After a small conversation with the user she told us that everything worked fine before and that she had several problems since see re-joined the company.

What happened was the following the user was removed from the active directory and when she got back a new account was created with the same login name.

When the user re-joined the account had the same login name but did not have the same SID. SharePoint saves information about an account by using the login name and the SID (Security Identifier) of a user. Because of the mismatch SharePoint was removing the applied security rights.

This issue can be fixed by using different commands:

The commands look as followed:

$user = Get-SPUser -Web [SiteUrl] -Identity [Login Name]
Move-SPUser -Identity $user -NewAlias [Login Name] -IgnoreSID

For the PowerShell commando you will first need to retrieve the specific user.When retrieving the user and setting the new alias you should always use the claim login name: “i:0#.w|Domain\user”.

stsadm -o migrateuser -oldlogin [Login Name] -newlogin [Login Name] -ignoresidhistory

The STSADM command looks almost the same as the PowerShell command if you also look at the parameters they both have something to Ignore the SID history. The parameter is included because if you do not include the parameter it will check the SID references and as we all know they do not match.

Possible Problem: When performing one of these options you can receive a “Object reference not set to an instance of an object”. The solution to this problem is pretty simple, When it happens your user does not have enough rights. Try it with another account or give your current user rights to the User Profile Service Application.”

Share Button

Warm Up Form Based Web Application

Normal warm up scripts for SharePoint open a site object or web object and make a request to that specific site. When you use form based authentication and do not allow anonymous access, you would only warm up the login page.

In order to warm up a application form based SharePoint site you would have to apply your credentials. All off this can be done by using PowerShell and specific COM objects. This script can then be scheduled with “Task Scheduler” that is included in windows.

function Warm-FBASite{
    [CmdletBinding()]
    param (
        [string] $RootUrl = $(Read-Host -prompt "Root Url"),
        [string] $LoginUrl = $(Read-Host -prompt "Login Url"),
        [string] $SiteUrl = $(Read-Host -prompt "Site Url"),
        [string] $UserName = $(Read-Host -prompt "Username"),
        [string] $Password = $(Read-Host -prompt "Password"),
        [bool] $loggedIn = $(Read-Host -prompt "Already logged in")
    )
    $ieMain=New-Object -ComObject "InternetExplorer.Application";
    if($loggedIn -ne $true){
        Login-FBA -RootUrl $RootUrl -LoginUrl $LoginUrl -UserName $UserName -Password $Password -Browser $ieMain;
    }
    Navigate-Site -RootUrl $RootUrl -SiteUrl $SiteUrl;
    $ieMain.Quit();

}

The Warm-FBASite function is the main function that calls other functions. This function needs the following parameters:

  • RootUrl: The root URL of the application you would like to warm up.
  • LoginUrl: The relative URL to the login page.
  • SiteUrl: The relative URL to the site you would like to warm up.
  • UserName: The username off the forms user.
  • Password: The password off the forms user.
  • LogginIn: Boolean value whether the user has already been logged in.

In this function we open a Com object of internet explorer and provide it as a parameter to the function “Login-FBA”.

function Login-FBA{
    [CmdletBinding()]
    param (
        [string] $RootUrl = $(Read-Host -prompt "Root Url"),
        [string] $LoginUrl = $(Read-Host -prompt "Login Url"),
        [string] $UserName = $(Read-Host -prompt "Username"),
        [string] $Password = $(Read-Host -prompt "Password"),
        $Browser = $(Read-Host -prompt "Browser")
    )

    $url = $RootUrl + $LoginUrl;

    Write-Host "Trying to login the user:" $UserName " on the Url: " $url -ForegroundColor Green
    $Browser.navigate($url);
    $Browser.visible=$false;

    if ((Wait-Browser $Browser -Url $url ) -eq $false){
        Write-Host "Something went wrong with requesting the page";
        return
    }else{
        $doc=$Browser.Document
    }

    $txtUsername=$doc.getElementByID("ctl00_PlaceHolderMain_signInControl_UserName"); #Replace by your own ID
    $txtPassword=$doc.getElementByID("ctl00_PlaceHolderMain_signInControl_password"); #Replace by your own ID
    $btnSubmit=$doc.getElementByID("ctl00_PlaceHolderMain_signInControl_login"); #Replace by your own ID
    
    $txtUsername.value=$UserName;
    $txtPassword.value=$Password;
    $btnSubmit.click();
    if ((Wait-Browser $Browser -Url $url ) -eq $false){
        return;
    }
}

This function tries to open the login page in the com object you send in the parameters. When this page is loaded it inserts the username and password in the login controls by finding these controls by there id.

In this function you will have to insert your own Id’s of the username textbox, password textbox and submit button. In this function you also see a reference to the “Wait-Browser” function. This function is created to make sure the site you are requesting in the COM object is fully loaded.

function Wait-Browser{
    [CmdletBinding()]
    param (
            $Browser = $(Read-Host -prompt "Browser"),
            $Url = $(Read-Host -prompt "Url")
    )

    $maxRetries=50;
    $retry = 2;
    $retryCount = 0;

    while ($Browser.Busy -eq $true){  
        Write-Host "Waiting for browser: " $URl  -ForeGroundColor Yellow;
        
        if ($retryCount -gt $maxRetries){
            return $false;
        }
        
        $retryCount++;
        start-sleep $retry ;
    } 

    return $true;
}

When the login request succeeds it is time to open the site and let that document load within the COM object. When the site is loaded it will write the page title to the PowerShell window.

function Navigate-Site{
    [CmdletBinding()]
    param (
        [string] $RootUrl = $(Read-Host -prompt "Root Url"),
        [string] $SiteUrl = $(Read-Host -prompt "Site Url")
    )

    $url = $RootUrl + $SiteUrl;

    $iePage=New-Object -ComObject "InternetExplorer.Application";
    $iePage.navigate($url);
    $iePage.visible=$false;
    $retryCounter=0
    
     if ((Wait-Browser $iePage -Url $url ) -eq $false){
        Write-Host "Something went wrong with requesting the page" -ForegroundColor Red;
        return
    }else{
        $doc=$iePage.Document
        Write-Host "Site Loaded: " $doc.title -ForegroundColor Green;
    }

    $iePage.Quit();    
}

To make use of these functions you only have to add these functions in PowerShell and call the “Warm-FBASite” function just like below.

Warm-FBASite -RootUrl "https://sharepointsite.com"  -LoginUrl "/_layouts/15/login.aspx" -SiteUrl "/client/35" -UserName "[form account name]" -Password "[password]" -LoggedIn $false;
Share Button

Limitations of a Public Facing Website in Office 365

When you buy an Office 365 tenant you get the option to build a Public website within the SharePoint administration panel.

Creating a website will give you the following URL by default:

  • http://[tenant]-public.sharepoint.com.

Within SharePoint 2013 they have extended the options to build massive websites where you had to do a lot of customizations in SharePoint 2010. There are already many site available for example (http://www.motion10.nl ) but most off these websites are build on SharePoint 2013 on premise. This is all because building a public website within Office 365 has a lot of limitations. In this blog post I will try to list the limitations I know. If you find any other limitations or they have changed something on the Office 365 platform to make it work and I haven’t alter the blog post please add a comment or send me a email.

Site Settings

Multiple site settings screens are missing from the administration menu. Some of these pages can be accessed by the Url and some of them don’t even exist.

Site Setting Public Website Office 365

  1. Manage Site Collection Features: The link and the page are missing for a public website.
  2. Manage Site Features: The link and the page are missing for a public website.
  3. Site Content Types: The link and the page are missing for a public website.
  4. Site Columns: The links is missing for a public website you can access the page by using the following URL: [URL]/_layouts/15/mngfield.aspx.
  5. Solution Gallery: The links is missing for a public website you can access the page by using the following URL: [URL]/_catalogs/solutions/Forms/AllItems.aspx.
  6. Web Part Gallery: The links is missing for a public website you can access the page by using the following URL: [URL]/_catalogs/wp/Forms/AllItems.aspx.
  7. List Template Gallery: The links is missing for a public website you can access the page by using the following URL: [URL]/_catalogs/lt/Forms/AllItems.aspx.
  8. Term store management: The link and the page are missing for a public website.

If you would like to activate or see which features are activated on the SharePoint Public site take a look at this blog post:

Variations

Many website on the internet are created in multiple languages. Looking at SharePoint you would then maybe would like to use Variations. In Office 365 variations cannot be used.

Managed Metadata

As you can see on point 8 within the site settings section you are not able to access the Term Store Management. This also makes it that one off the amazing new features off SharePoint 2013 taxonomy-based navigation cannot be used on a Office 365 public website.

Besides that more taxonomy based features do not work as for example the product catalog functionality.

Sub Sites

From the UI you cannot create a sub site.  You will have to use SharePoint Designer in order to create a sub site. But even then you are not able to use every site template. In my situation I tried to create a Publishing Site and it got immediately deleted from my tenant.

The only templates that can be used on the online version are:

  • Team Site
  • Basic Search Site
  •  

    Content Search Web Part

    One of the web parts you had to develop for previous version of SharePoint (At least I did) now came to SharePoint 2013 and that is the “Content Search Web Part”. This web part is not available on the public web site of Office 365.

    Online you can find great tips to deal with the limitations of the Public website:

    Share Button

    Data Deduplication in Windows Server 2012 R2

    After reading a lot of information about Windows Server 2012 R2 I found out that it has a really nice feature if you are into virtualization as much as me. When using virtualization you may have a lot of virtual disks that contain a lot of the same data. For example you have four machines that have an installation of Windows Server 2012.

    All together this will take up a lot off disk space. I this situation you could also create a base image and use this base image for every virtual machine. But you will then still have the updates and you will have to maintain the base image.

    In Windows Server 2012 you already had the feature off Data Deduplication for File and Storage Servers. What it does is the following: It finds and removes duplication within data on a volume while ensuring that the data remains correct and complete. This makes it possible to store more file data in less space on the volume.

    A nice image created by Guido van Brakel in the following blog post: Data Deduplication in Windows Server 2012 really explains it:

    Data Deduplication

    Data Deduplication

    In Windows Server 2012 R2 they have added a new functionality called:

    • Data deduplication for remote storage of Virtual Desktop Infrastructure (VDI) workloads

    This means you can use the Data Deduplication for your virtual machines when you are running Windows Server 2012 R2 meaning that when you have four virtual machines running the same operating system you will not have to take up all that amount off disk space.

    Take a look at the following articles if you want to get started with Data Deduplication:

    Share Button

    My daughter Fiene Vlinder van der Gaag

    The last couple of days I haven’t been blogging as much as I would like. I also think in the upcoming month I will not have much time to blog.

    This is all because my amazing girlfriend gave birth to a really beautifull daughter on 24-02-2014, Fiene Vlinder. As soon as I have some more time I will pick up blogging again and will be posting some interesting Microsoft stuff.

    Fiene Vlinder

    Fiene Vlinder

    Share Button

    Unable to start User Profile Synchronization Service

    A few days ago I wrote a post about loading modules in PowerShell by default: “Load modules by default when opening PowerShell”. Today we had to setup a new SharePoint Farm and to perform some default operations we created the PowerShell profile described in that post.

    The complete configuration of the server went well until we wanted to start the “User Profile Synchronization Service”. The Service moves to starting and the timer job that configures the service also starts but after 5 seconds it already stops.

    Looking at the ULS log we found this error message:

    “UserProfileApplication.SynchronizeMIIS: Failed to configure MIIS post database, will attempt during next rerun. Exception: System.Runtime.InteropServices.SEHException (0×80004005): External component has thrown an exception.
    at Microsoft.Office.Server.UserProfiles.Synchronization.ILMPostSetupConfiguration.ConfigureMiisStage2()
    at Microsoft.Office.Server.Administration.UserProfileApplication.SetupSynchronizationService(ProfileSynchronizationServiceInstance profileSyncInstance).”

    This message did not gave us a clue at all. At the same time we were working on the PowerShell Profiles and had temporary removed our custom profile from the service.

    Provisioning the “User Profile Synchronization Service” without the custom profile resulted in success. So remember when you want to provision the “User Profile Synchronization Service” make sure you are not using a custom PowerShell profile.

    Share Button

    Load modules by default when opening PowerShell

    At the moment we are working a lot with PowerShell in combination with SharePoint. Over time we created a lot of usable functions that were not availible within the default SharePoint Module.

    With these functions we created our own PowerShell Module in order to easily load the function within our PowerShell instance. When you would like to know more on how to create a PowerShell Module you can read this TechNet article:

    When you have written a module it is relatively easy to load it in the PowerShell instance by using the import-module comment.

    import-module [Path To Your Module]\Module.psm1 -WarningAction Ignore

    As you can see in the above script we have added the “–WarningAction ignore” because loading a module mostly generate a warning for unapproved Verbs:

    “WARNING: The names of some imported commands from the module ‘Module’ include unapproved verbs that might make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of approved verbs, type Get-Verb.”

    If you want to stick with the approved Verbs you can take a look at the approved verb list on TechNet:

    Now the question still is how do we load it in every PowerShell instance by default. You can accomplish this by creating a “profile.ps1” file. This file needs to be added in the following directory:

    C:\Windows\System32\WindowsPowerShell\v1.0\

    In the directory “C:\Windows\System32\WindowsPowerShell\v1.0\Example” there is a example profile.ps1 file. This file is empty. For our module we had created the following profile.ps1 file:

    #  Copyright (c) Microsoft Corporation.  All rights reserved.
    #  
    # THIS SAMPLE CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
    # WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
    # WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
    # IF THIS CODE AND INFORMATION IS MODIFIED, THE ENTIRE RISK OF USE OR RESULTS IN
    # CONNECTION WITH THE USE OF THIS CODE AND INFORMATION REMAINS WITH THE USER.
    
    if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
        Write-Host "Loading Microsoft SharePoint PowerShell" -ForegroundColor Green
        Add-PSSnapin "Microsoft.SharePoint.PowerShell"
    }
    
    Write-Host "Loading Custom SharePoint PowerShell Module" -ForeGroundColor Green
    import-module D:\SCRIPTMODULE\Module.psm1 -WarningAction Ignore

    Using the profile.ps1 file make sure that the profile is loaden in every powershell window. You could also use this filename: “Microsoft.PowerShellISE_profile.ps1″ to only load within the PowerShell ISE window.

    Important: When using custom profiles on your SharePoint servers in combination the the Userprofile Synchronization Service and use the profile.ps1 approach you could be getting in a situation that your Forefront Identity Manager Service and ForeFron Identity Manager Synchronization Service do not start any more after a reboot. This is because of the profile.ps1 file. Remove the profile and it will start again.

    Share Button

    Filtering SharePoint Search Results by Content Source

    Working for one my projects we were looking for a solution to only retrieve search results for a specific Content Source. In our scenario we had a External Content Type that was linked to a “FilteredEMail” view of a CRM database.

    We connected CRM to SharePoint in this scenario because searching in CRM for a specific email was a big problem and slowed down the complete CRM system.

    What there was implemented on CRM was a small button to open a window  / frame to a SharePoint Search page. On this SharePoint search page you could search for the specific Mail and then the result would link you back to CRM.

    Creating the External Content Type wasn’t that hard. The main thing here If you would also like to search trough your external content type is to define a field as a Timestamp field in order to enable incremental search.

    Timestamp field

    For us this was very important because we were dealing with more than a million items. After we had the external content type in place and created the profile pages we crawled the complete set of emails.

    We than needed to create a result source in order to retrieve only the information from the external content type. On the Search Service Application page we clicked on the ‘Result Sources’ menu option and created a new Search Result Source.

    New Result Source

    After setting these properties we opened the Query Builder. Within the query builder you do not have a default option of some sort to start filtering the results by a specific content source.

    When I took a closer look at the property filter drop down after selecting “— Show All Managed properties —“ you have a property called “ContentSource”. We selected this and filled in the value of our content source.

    Query Builder

    After that we used the default options for the rest of the properties and saved the result source. Following this hunch resulted in a result source that only returns items of a specific content source.

    New Result Source 2

    After that we created a “Display Template” to refer back to CRM if you are curious on how we accomplished that please let me know.

    Share Button

    PowerShell Scripts

    During my current project we are using a lot of PowerShell scripts to administrate the environment and make development easier for us.

    In this post that I will try to update frequently, I will share some of our useful PowerShell scripts.

    Unregister a Custom Claim Provider for a specific zone in a web application

    There are situations were for you will develop custom claim providers. These claim providers can be installed globally on the farm but can also be installed for a specific zone in a web application. The following script will allow you to unregister a custom claim provider for a zone.

    function Unregister-CustomClaimProvider{
    	param(
    		  [string] $DisplayName = $(Read-Host -prompt "Claim Provider Display Name"),
    		  [string] $Url = $(Read-Host -prompt "Web Application Identity"),
    		  [string] $InternalName = $(Read-Host -prompt "Claim Provider Internal Name"),
    		  [string] $Zone = $(Read-Host -prompt "Zone")
    	)
    
    	
    	$WebApplication = Get-SPWebApplication $Url 
    	if ($WebApplication.IisSettings.ContainsKey($Zone)){
    		$settings = $WebApplication.GetIisSettingsWithFallback($zone)
    		$providers = $settings.ClaimsProviders;
    		if($providers.Contains($InternalName)) {
    			Write-Host "Claim Provider is registerd in this zone trying to remove..." -ForegroundColor Green
    			$providers.Remove($InternalName);
    			Set-SPWebApplication -Identity $WebApplication -Zone $Zone -AdditionalClaimProvider $providers
    		}else{
    			Write-Host "$DisplayName is not registered on $($WebApplication.Url) in zone $Zone" -ForegroundColor Yellow
    		}
    	}
    }
    

    Disable Browser Based Editing for Sites under a Specific Url

    In certain situations you would like to disable all browser based editing for specific sites within SharePoint. With the below PowerShell script you can disable browser based editing.

    Get-SPSite -WebApplication [Web Application] -Limit ALL | where {$_.Url.StartsWith("[Url start With]") } | Foreach-Object { 
        Write-Host "Activating Feature Client Based Editing for site" $_.Url
        Enable-SPFeature –identity 8a4b8de2-6fd8-41e9-923c-c7c3c00f8295 -URL $_.Url
    }
    

    Warm Up SharePoint 2013 Site Collections

    When you maintain SharePoint environments you would like to warm up the environments for example once a day. The first load on SharePoint still takes a lot of time. For this situation I have developed a warm up script that also take in account your extended Host Named Site Collections.

    function WarmUp-Url([string]$url){
        Write-Host "Warming up " $url -ForegroundColor DarkYellow;
        Invoke-WebRequest $url -UseDefaultCredentials -UseBasicParsing; 
    }
    
    foreach ($WebApp in (Get-SPWebApplication -IncludeCentralAdministration)){
        $sites = $WebApp | Get-SPSite -Limit All | Get-SPWeb -Limit All
            foreach($site in $sites){
                $html= WarmUp-Url -url $site.Url 
            
                if($site.IsRootWeb){
                    $extendedurls = Get-SPSiteURL $site.Url  -ErrorAction SilentlyContinue;
    
                    foreach($url in $extendedurls){
                        if($url.Url -ne $site.Url){                        
                            $html = WarmUp-Url -url $url.Url;
                        }
                    }
                }
            $site.Dispose();
        }   
    }
    

    Publish Content Types for Specific group

    When you start working with the Content Type Hub in SharePoint you will get in situations were you would like to publish multiple content types at once. In these situations you could use the below function to publish all the content types in a specific group.

    Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
    function Publish-ContentTypesForGroup {
        param
        (
            [parameter(mandatory=$true)][string]$hubUrl,
            [parameter(mandatory=$true)][string]$group
        ) 
    
        $site = Get-SPSite $hubUrl
    
        if(!($site -eq $null))
        {
            $contentTypePublisher = New-Object Microsoft.SharePoint.Taxonomy.ContentTypeSync.ContentTypePublisher ($site)
            $site.RootWeb.ContentTypes | ? {$_.Group -match $group} | % {
    
                if($_.ReadOnly){
                    Write-Host "Content Type" $_Name " is Read Only" -ForegroundColor Yellow;
                    $_.ReadOnly = $false;
                    $_.Update();
                }
                $contentTypePublisher.Publish($_)
                write-host "Content type" $_.Name "has been republished" -foregroundcolor Green
            }
        }
    }

    Starting the Content Type Subscriber Job

    When you work a lot with the Content Type Hub in SharePoint you would also like to start the Content Type Subscriber job by using PowerShell. The below script does the job the web application you specify.

    Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
    function Run-SPContentTypeHubJob([string]$url) 
    { 
        $job = Get-SPTimerJob -WebApplication $url | ?{ $_.Name -like "MetadataSubscriberTimerJob"} 
    
        if ($job -ne $null)  
        {   
            Write-host "The timerjob will be started....." -ForeGroundColor Green
            $job | Start-SPTimerJob 
    
            Write-host  "Run the admin job..." -ForeGroundColor Green
            Start-SPAdminJob -ErrorAction SilentlyContinue              
        }
        else{
    	Write-Host "The Job could not be found" -ForeGroundColor Red
        }
    }

    Delete all items in a List

    During many projects I had situations were I had to remove all items in a list. In this situation you can choose for removing the complete list en recreating it or you could delete every single item. With the below function you can delete every item in the list.

    Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
    function Clear-SPList {
        param
        (
            [parameter(mandatory=$false)][string]$siteUrl,
            [parameter(mandatory=$false)][string]$listname
        )
    
        $site = Get-SPSite $siteUrl;
        $web = $site.OpenWeb();
        $list = $web.Lists[$listname];
    
        write-host "Clearing SharePoint list: " $list.Title -ForeGroundColor Green
    
        $collListItems = $list.Items;
        $count = $collListItems.Count - 1;
        for($intIndex = $count; $intIndex -gt -1; $intIndex--)
        {
                $collListItems.Delete($intIndex);
        } 
    }

    Finding content types that use a specific field

    It ofton occurs that you would like to delete a site column but can’t because it is used by a specific content type. It really takes a long time then to find the right content type. Using the below PowerShell function it is easy and fast to find your content type.

    Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
    function Find-ContenttypesByField {
        param
        (
            [parameter(mandatory=$false)][string]$siteUrl,
            [parameter(mandatory=$false)][string]$fieldname
        )
    
      $site = Get-SPSite $siteUrl
      $web = $site.RootWeb;
      $fields = $web.Fields;
    
      $guid = $fields[$fieldname].id;
    
      $ct = $web.AvailableContentTypes 
      for ($i=0; $i -lt $ct.count; $i++) 
      {
        for ($j=0; $j -lt $ct[$i].fields.count; $j++) 
        {
          if ($ct[$i].fields[$j].id -eq $guid)
          {
            Write-host $ct[$i].Name " has column";
          }
        }
      }
    }

    Setting up Ping and SharePoint Trust Federation

    For a environment we wanted to setup a SSO environment with for example K2. The most know situation is using ADFS. But at our client we were required to use Ping. The configuration an the SharePoint site looks very much the same as ADFS. For a reference I have included the PowerShell script in this post.

    Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
    
    $certpath  = "[Ping Certification Path]"
    $stsname   = "Auth-iLink"
    $stsdesc   = "PingFederate Claims Provider SharePoint"
    $stsrealm  = "sharepoint:ping:con"  #realm configured on Ping
    $signinurl = "[URL Ping]/idp/prp.wsf"
    
    Write-host "Importing Certification on SharePoint Server (Trust relation)." -ForegroundColor Green
    New-SPTrustedRootAuthority -Name "PingFederate IP-STS Sharepoint" -Certificate $certpath
    
    Write-Host "Getting the Certification Object." -ForegroundColor Green
    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certpath)
    
    Write-Host "Setting up Claim Mapping for SharePoint Authentication" -ForegroundColor Green
    $mappingRole = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/claims/Group" -IncomingClaimTypeDisplayName "Role" -LocalClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
    $mappingName = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/claims/CommonName" -IncomingClaimTypeDisplayName "GivenName" -LocalClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
    
    Write-Host "Setting Up Token Issuer"
    New-SPTrustedIdentityTokenIssuer -Name $stsname -Description $stsdesc -Realm $stsrealm -ImportTrustCertificate $cert -ClaimsMappings $mappingRole,$mappingName -SignInUrl $signinurl -IdentifierClaim $m2.InputClaimType
    
    Write-Host "Trusted Identity Token Issuer is set up."

    Delete empty sub folders

    For a migration we had a large set of folder with also empty folders in it. During the migration we iterated trough the folders also going trough the empty folders took a lot of time for the migration process. That way we wanted a PowerShell script to delete the empty sub folders. (Remove the –whatif to actually perform the script).

    Get-ChildItem -recurse | Where {$_.PSIsContainer -and `
    @(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} |
    Remove-Item -recurse -whatif

     

    Delete site that start with a specific URL.

    When you are using host named site collections within your environment and also build some kind provisioning mechanism (how this can be done with host named site collections can be read here). You will get in situations that you would like to remove a huge number of site collections that start with a specific URL. By using this script you can:

    Get-SPSite -Limit ALL | where {$_.Url.StartsWith("http://spdev.com/sites") } | Foreach-Object { Remove-SPSite $_.Url –Confirm:$False
    }

    Flushing the blob cache

    Because we are using the blob cache within our environment, we also need a easy option to clear the blob cache when we have update our style sheets or maybe JavaScript files.

    Using this function you can easily clear the blob cache for a specific web application.

    function Flush-SPBlobCache{
            param(
              [string] $Url = $(Read-Host -prompt "Web Application Identity")
            )        
            $webApp = Get-SPWebApplication $Url
            [Microsoft.SharePoint.Publishing.PublishingCache]::FlushBlobCache($webApp)
            Write-Host "Flushed the BLOB cache for:" $webApp
    }

     

    Feature upgrading

    For upgrades on our solutions we use the standard upgrading framework of SharePoint. You can read about it here this is an article on the upgrading framework for SharePoint 2010 but it is also something for SharePoint 2013.

    Using the following function you are able to upgrade a specific feature within a web application.

    function Upgrade-SpecificFeatures{
            param(
              [string] $Url = $(Read-Host -prompt "Web Application Identity"),
              [Guid] $ID = $(Read-Host -prompt "Feature ID")
            )
    
            $SPWebApp = Get-SPWebApplication $Url;
    
            foreach ($site in $SPWebApp.Sites){
                if ($site -ne $null){
    
                    Write-Host "Upgrading site features for site:" $site -ForegroundColor Green;
                    $count = 0;
                    $features = $site.QueryFeatures($ID, $true);
                    Foreach($feature in $features) {
                            $oldVersion = $feature.Version;
                            Write-Host "Upgrading feature:" $feature.Definition.DisplayName;
                            Write-Host "  Current version:" $oldVersion;
                            $feature.Upgrade($true);
                            $newVersion = $feature.Version;
                            Write-Host "      New version:" $newVersion;
                            if ($oldVersion -eq $newVersion) {
                                Write-Host "  Something went wrong upgrading this feature!" -ForegroundColor Red;
                            } else {
                                Write-Host "  Upgrade successful." -ForegroundColor Green;
                                $count++;
                            }
                    }
    
                if ($count -eq 0) {
                    Write-Host "No features found that needed upgrading for site:" $site -ForegroundColor Yellow;
                } else {
                    Write-Host "Done upgrading" $count "feature(s). for site:" $site -ForegroundColor Green;
                }
            }
       }
    }
    Share Button

    SharePoint License Versions versus Versions

    As a SharePoint developer you do not often get the question what SharePoint version do we need to install. In many situations we see that the Enterprise license is installed.

    For a project I’m currently working on I got the question to stick to the SharePoint 2013 Standard license. Having this requirement we were looking for a list of features we could use within a Standard license.

    Searching on the internet supplied as a lot of resources but all these resources were all very different.

    Finally we found a link that pointed us to a TechNet article:

    This article contains a lot of information regarding the following things:

    • Differences in features across Office 365 plans.
    • Subscription options.
    • SharePoint Online boundaries and limits.
    • Differences in features across standalone plans.
    • Differences in features across on-premise solutions (Differences between: SharePoint Foundation, Standard and Enterprise).
    Share Button