Thursday, January 21, 2016

Resource Saturation in SharePoint Search

So we saw this in the /15 hive logs recently. 

SearchServiceApplicationProxy::Execute--Error occured: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: Tried IMS endpoints for operation Execute: Operation sent to IMS failed: Resource saturation, try again later.

We would see it when a search crawl was executing while users were trying to search various items.  We have three crawl and query servers in the environment, so we didn't think resources could be the cause. 

Well....we thought wrong.  It turns out two of our three search servers had the IIS Admin Service disabled, which was causing all sorts of havoc with the Security Token Service on the farm.

Starting the IIS Admin Service on the two affected search servers resolved the problem.  We were able to pretty easily identify the cause of the issue because the SharePoint Health Analyzer in Central Admin was telling us.

So, uh, don't ignore that red bar in Central Admin.  It gave us a really fast fix.

Delete Sites, Clear the Recycle Bin, EVERYTHING MUST GO!!!

The following set of scripts will really help you if you ever need to get something Actually Deleted in SharePoint.

They are:

1.  A script that will delete a web inside a Site Collection.  So if you have a site in a Collection with a ton of sub sites, you won't have to go site-by-site and delete the subs, then the parents, up the tree.

2.  A script that empties all user-level recycle bins in a Site Collection.

3.  A script that clears the contents of a Site Collection Recycle Bin.

add-pssnapin Microsoft.SharePoint.Powershell
# This script completely deletes the specified Web (including all subsites). 

function RemoveSPWebRecursively(
    [Microsoft.SharePoint.SPWeb] $web)
{
    Write-Debug "Removing site ($($web.Url))..."
   
    $subwebs = $web.GetSubwebsForCurrentUser()
   
    foreach($subweb in $subwebs)
    {
        RemoveSPWebRecursively($subweb)
        $subweb.Dispose()
    }
   
    $DebugPreference = "SilentlyContinue"
    Remove-SPWeb $web -Confirm:$false
    $DebugPreference = "Continue"
}

$DebugPreference = "SilentlyContinue"
$web = Get-SPWeb "http://some.sharepointsite.com/sites/main/SubsiteToBeDeleted"
$DebugPreference = "Continue"

If ($web -ne $null)
{
    RemoveSPWebRecursively $web
    $web.Dispose()
}

*****


Add-PSSnapin Microsoft.SharePoint.Powershell

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint");

#This script will empty all Recycle Bins for all sites and subsites in a Site Collection. 

$url = "http://some.sharepointsite.com/sites/main/"
$site = new-object microsoft.sharepoint.spsite($url)

for ($i=0;$i -lt $site.allwebs.count;$i++)
{
  write-host $site.allwebs[$i].url "...deleting" $site.allwebs[$i].recyclebin.count "item(s)."
  $site.allwebs[$i].recyclebin.deleteall()
}

write-host $site.url "...deleting" $site.recyclebin.count "item(s)."

$site.recyclebin.deleteall()
$site.dispose()



*****

Add-PSSnapin Microsoft.SharePoint.Powershell

#This script will delete the contents of the Site Collection Recycle Bin for a given Collection.

$sitecollectionUrl = “http://some.sharepointsite.com/sites/main/”

$siteCollection = New-Object Microsoft.SharePoint.SPSite($sitecollectionUrl)


write-host(“Items to be deleted : ” +$siteCollection.RecycleBin.Count.toString())

$now = Get-Date


write-host(“Deleting started at ” +$now.toString())

$siteCollection.RecycleBin.DeleteAll();


$now = Get-Date

write-host(“Deleting completed at ” +$now.toString())


$siteCollection.Dispose()


InfoPath 2013 and SharePoint Designer 2013 on SharePoint 2016

Going to lead with the source here.  The Release Candidate for SharePoint 2016 is live.

https://blogs.office.com/2016/01/20/sharepoint-server-2016-and-project-server-2016-release-candidate-available/

Here's the important bit: 

Q. When SharePoint 2013 RC was released, there were new versions of InfoPath and SharePoint Designer at the same time. Will SharePoint Server 2016 RC include new versions of those products as well?

A. For the past decade, InfoPath and SharePoint Designer have been at the forefront of Microsoft solutions for professional developers and information workers building lightweight business applications for the enterprise. SharePoint Server 2016 extends our commitment to lightweight business applications.

As we continue to evolve, we recognize the need for a long runway as we augment existing business app offerings with new tools and capabilities. As a result, we’re updating the support timelines in conjunction with SharePoint Server 2016, specifically:
  • SharePoint Server 2016 will include an ongoing capability to host InfoPath Forms Services. InfoPath Forms Services on SharePoint 2016 will be supported for the duration of SharePoint 2016’s support lifecycle.
  • InfoPath Forms Services on Office 365 will continue to be supported.
  • InfoPath 2013 and SharePoint Designer 2013 will be the last versions of those products. SharePoint Designer is not being re-released with SharePoint Server 2016, although we will continue to support custom workflows built with SharePoint Designer and hosted on SharePoint Server 2016 and Office 365. Support for InfoPath 2013 and SharePoint Designer 2013 will match the support lifecycle for SharePoint Server 2016, running until 2026.
So if you're looking at long-term strategy, I think the message is InfoPath and SP Designer are toast for whatever follows SP 2016. 

Tuesday, January 19, 2016

SharePoint 2013 - Search Status = Paused for:External Request

So you go to your Search Service Application in SharePoint 2013 and see "Paused for:External request" in the Administrative Status.

I've seen this issue when a Search Service is either explicitly paused for administrative reasons, or is not properly taken offline during a system restart. 

Fortunately, there's a simple way to fix it. 

First, you need to clear the timer cache.  You can use the Powershell script from my post here.

After that script has finished, and the cache has been reset and the Timer service has restarted on all servers, run this:

Add-PSSnapin Microsoft.SharePoint.PowerShell
$ssa = Get-SPEnterpriseSearchServiceApplication Identity "Search Service Application"
$ssa | Resume-SPEnterpriseSearchServiceApplication

Be sure the "Search Service Application" matches the name of your Search Service app.

I've found that script will take a few minutes to run, while it unpauses the service app.


Friday, January 15, 2016

January server updates will break SharePoint 2013

Just going to link directly to Todd Klindt, who posted about this yesterday. 

Go read.  And don't have your SharePoint servers set to automatically apply updates!  Ever!

http://www.toddklindt.com/blog/Lists/Posts/Post.aspx?ID=616

Powershell to add Site Collection Admins

Adding Site Collection admins should be a part of every Site Collection creation Powershell script.  As you might know, you can't add Active Directory groups as Site Collection admins in Central Administration.  It only takes two names, and they have to be people.

This, among other reasons, is why creating Site Collections via Powershell is so much easier.  The script below will allow you to add as many alternate Site Collection admins as you want.  I typically just run this script after the Site Collection has been created.  However, you could incorporate it into an overall Site Collection creation script.  Basically I'm lazy, and this works.  Maybe one day I'll put it in the main creation script. 

This script, like most of the ones I use, is a combination of a few scripts I've found on the internet.  I think it's important to note on most of the scripts I use that I usually change them, sometimes improve them, but rarely write the entire thing from scratch.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$logfile = "Powershelloutput.log"


# $AccountList is an array of Windows Identities in the format of $AccountList = @("DOMAIN\USERID" , "DOMAIN\USERID2")

$AccountList = @("AD\someuser", "AD\someotheruser", "AD\sharepointadministrators")

# $iisSiteList is an array of top level IIS site URLs

$iisSiteList = @("http://some.sharepointsite.com")



# this is from an earlier version of the script

# That scrip looks at all SP sites on the farm, I've left the old code here for reference

# this gets an array of objects representing the sites at the IIS level:

## $IISSites = Get-SPWebApplication

Foreach($oneIISSite in $IISSiteList)

{

 foreach ($SharepointSiteCollection in (Get-SPWebApplication $oneIISSite).Sites)

{

 $msg = $SharepointSiteCollection.url

 write-host -ForegroundColor Cyan $msg

 Add-Content $logfile $msg



 $spweb = Get-SPWeb $SharepointSiteCollection.url



 #now we have the website, so lets look at each account in our array

 foreach ($Account in $AccountList)

{

 #lets see if the user already exists

 $msg = "Looking to see if User " + $account + " is a member on " + $SharepointSiteCollection.url

 Write-host -foregroundColor Blue $msg

 Add-Content $logfile $msg



 $user = Get-SPUSER -identity $Account -web $SharepointSiteCollection.url -ErrorAction SilentlyContinue #This will throw an error if the user does not exist

 if ($user -eq $null)

 { #if the user did NOT exist, then we will add them here.

 $SPWeb.ALLUsers.ADD($Account, "", "", "Added by AdminScript")

 $user = Get-SPUSER -identity $Account -web $SharepointSiteCollection.url

 $msg = "Added user $Account to URL $SPWeb.URL"

 Write-host -Foregroundcolor Magenta $msg

 Add-Content $logfile $msg

}

 else

{

 $msg = "user $Account was already in URL " + $SPWeb.URL

 Write-host -ForegroundColor DarkGreen $msg

 Add-Content $logfile $msg

}



 if ($user.IsSiteAdmin -ne $true)

{

 $user.IsSiteAdmin = $true

 $user.Update()

 $msg = "$account has been made an admin on $SPWeb.URL"

 Write-host -Foregroundcolor Magenta $msg

 Add-Content $logfile $msg

}

 else

{

 $msg = "$account was already an admin on $SPWeb.URL"

 Write-host -ForegroundColor DarkGreen $msg

 Add-Content $logfile $msg



}

}



 $SharepointSiteCollection.Dispose()

}

}

$msg = "=============== ALL DONE ================"

Write-host -ForegroundColor DarkGreen $msg

Add-Content $logfile $

Clone a SharePoint List or Library via Powershell

This Powershell script automates the process of cloning a List. 

Consider the following situation:

- You want to save a list as a template, with the data in the list included.
- You want to then create a new list somewhere else, using that template, after it's been saved.
- You want to delete the List Template after the new list has been created.

This script does all that. 

Add-PSSnapin Microsoft.SharePoint.Powershell
 
        #Get the source and destination sites (SPWeb objects)            
        $site = New-Object Microsoft.SharePoint.SPSite("http://some.sharepointsite.com/sites/somesitecollection")
        $web =  $site.OpenWeb()
        $destinationSite = New-Object Microsoft.SharePoint.SPSite("http://some.sharepointsite.com/sites/someothersitecollection");
        $destinationWeb = $destinationSite.OpenWeb()
 
        #Define the source and destination list names            
        $SourceListName = "The Name of Your Source List";
        $DestinationListName = "My New Destination List";
 
        #Connect to the source list            
        $sourceList = $web.Lists[$SourceListName];
 
        #Create a unique name to use when saving the list as a template.            
        $id = [Guid]::NewGuid()
        $templateName = [String]::Format("{0}-{1}",$sourceList.Title,$id.ToString());
        $templateFileName = $templateName;
 
        #Save the list as a list template. The fourth parameter of the SaveAsTemplate method takes a boolean value indicating whether to save list data with the list.       
     
        $sourceList.SaveAsTemplate($templateFileName, $templateName, $sourceList.Description, $true)
 
        #Get the list template that was just saved            
        $listTemplate = $site.GetCustomListTemplates($web)[$templateName]
 
        #Create a new list at the destination web using the list template created from the source list         
        $destinationWeb.Lists.Add($destinationListName, $sourceList.Description, $listTemplate);
        $destinationWeb.Update()
 
        #Clean Up            
        #Delete the list the list template for, the List Template Fallery            
        $listTemplates = $site.RootWeb.Lists["List Template Gallery"]
        $lt = $listTemplates.Items | ?{$_.Title -eq $templateName}
        if($lt -ne $null){$lt.Delete();}
 
        #Dispose of the SPWeb and SPSite objects            
        $web.Dispose();
        $site.Dispose();
        $destinationWeb.Dispose();
        $destinationSite.Dispose();​

Set all Site Collections to Read-Only via Powershell

This is a great script that helps with a migration.  We've found that setting sites to Read Only as you migrate from one environment to another allows users to see the old farm while being forced to use the new farm. 

Add-PSSnapin Microsoft.SharePoint.Powershell

# Define whether ReadOnly will be set to true or false
[bool]$readOnly = $true

# Set excluded paths as comma-delimited strings.  Any sites listed below will NOT be changed. 
# Note: Web applications must end in a trailing slash, where site collections do not
[array]$excludedPaths = "http://apps.insidegulfstream.com/",
                        "http://some.sharepointsite.com/",
                        "http://another.sharepointsite.com/somesitecollection",
                        “http://athird.sharepointsite.com/”

# Get all Web applications (except Central Admin)
Get-SPWebApplication | ForEach-Object {
 
    if ($excludedPaths -notcontains $_.Url)
    {
        # Enumerate all content databases in each Web application
        if ($_.ContentDatabases -ne $null) {
            $_.ContentDatabases | ForEach-Object {
         
                # Enumerate all site collections in each content database
                if ($_.Sites -ne $null) {
                    $_.Sites | ForEach-Object {
                     
                        # Check if there are sites where the property should not be changed
                        if ($excludedPaths -notcontains $_.Url)
                        {
                            Write-Host "Changing ReadOnly property for site" $_.Url
                         
                            # Set ReadOnly property
                            $_.ReadOnly = $readOnly
                            Write-Host "ReadOnly property for site" $_.Url "set to" $_.ReadOnly
                         
                            # Dispose site collection object
                            $_.Dispose()
                        }
                        else
                        {
                            # Confirm if no changes made on excluded sites
                            Write-Host "No changes made for site" $_.Url
                        }
                    }
                }
            }
        }
    }
    else
    {
        # Confirm if no changes made on excluded web applications
        Write-Host "No changes made for web application" $_.Url
    }
}

# Get all Web applications (except Central Admin)
Get-SPWebApplication | ForEach-Object {
    # Enumerate all content databases in each Web application
    if ($_.ContentDatabases -ne $null) {
        $_.ContentDatabases | ForEach-Object {
            # Enumerate all site collections in each content database
            if ($_.Sites -ne $null) {
                $_.Sites | ForEach-Object {
                    Write-Host "ReadOnly property for site" $_.Url "set to" $_.ReadOnly
                    # Dispose site collection object
                    $_.Dispose()
                }
            }
        }
    }
}

Wednesday, January 13, 2016

Project Server 2013 - _canBeAssignedIsEnabled error when adding a new resource

So consider the following scenario:

- You've recently applied a cumulative update to Project Server 2013 & SharePoint

OR

- You've imported an instance of Project Server from a farm that was at an earlier cumulative update version of Project Server, and it's showing that the upgrade part of the migration process was successful.

Then you go to add a new user to that Project Server instance (in Project Server mode, not SharePoint user mode).  When you add the user, you get an error that says _canBeAssignedIsEnabled does not exist.

The typical reason for this is you've applied the patch to your farm, but you've not actually upgraded the instance.  You can check the Project Server instance status by running the following Powershell:

Get-SPProjectWebInstance -Url http://server/pwa

If NeedsUpgrade = True, then you can run the following Powershell to upgrade the instance:

Upgrade-SPProjectWebInstance -Identity "http://servername/pwa"

We found that after running this, the NeedsUpgrade flag was changed to False, but we were still seeing the error.  It turned out that even in spite of running the upgrade command for the individual instance (which upgraded the content database), we still needed to run the Configuration Wizard for the farm as a whole.

After running the config wizard, we were able to add users in Project again.  

Powershell to export a solution file....or all solution files from SharePoint 2013

These two are cousins.  The first will export a single solution (wsp) file.  The second script will hoover them all up.  I use these basically every day.

Add-PSSnapin Microsoft.SharePoint.Powershell
$farm = Get-SPFarm
$file = $farm.Solutions.Item("some.solution.wsp").SolutionFile
$file.SaveAs("c:\bk\some.solution.wsp")

***

Add-PSSnapin Microsoft.SharePoint.Powershell

    ## setup our output directory
    $dirName = "f:\installations\solutions"

    Write-Host Exporting solutions to $dirName
    foreach ($solution in Get-SPSolution)
    {
        $id = $Solution.SolutionID
        $title = $Solution.Name
        $filename = $Solution.SolutionFile.Name

        Write-Host "Exporting ‘$title’ to …\$filename" -nonewline
        try {
            $solution.SolutionFile.SaveAs("$dirName\$filename")
            Write-Host " – done" -foreground green
        }
        catch
        {
            Write-Host " – error : $_" -foreground red
        }
    }


Tuesday, January 12, 2016

Clear Config and Timer Cache SharePoint 2013

This script is one I use probably too often.  It will reach every server in your SharePoint farm, stop the Timer Service, clear the configuration cache, then start the Timer Service again. 

# Clear the SharePoint Timer Cache

# Output program information

Write-Host -foregroundcolor White ""

Write-Host -foregroundcolor White "Clear SharePoint Timer Cache"

#**************************************************************************************

# Constants

#**************************************************************************************

Set-Variable timerServiceName -option Constant -value "SPTimerV4"

Set-Variable timerServiceInstanceName -option Constant -value "Microsoft SharePoint Foundation Timer"

#**************************************************************************************

# Functions

#**************************************************************************************

#<summary>

# Loads the SharePoint Powershell Snapin.

#</summary>

Function Load-SharePoint-Powershell

{

       If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)

       {

              Write-Host -ForegroundColor White " - Loading SharePoint Powershell Snapin"

              Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction Stop

       }

}

#<summary>

# Stops the SharePoint Timer Service on each server in the SharePoint Farm.

#</summary>

#<param name="$farm">The SharePoint farm object.</param>

function StopSharePointTimerServicesInFarm($farm)

{

Write-Host ""

# Iterate through each server in the farm, and each service in each server

foreach($server in $farm)

{

foreach($instance in $server.ServiceInstances)

{

# If the server has the timer service then stop the service

if($instance.TypeName -eq $timerServiceInstanceName)

{

[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Stop '$timerServiceName' service on server: "

Write-Host -foregroundcolor Gray $serverName

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$timerServiceName'"

sc.exe \\$serverName stop $timerServiceName > $null

# Wait until this service has actually stopped

WaitForServiceState $serverName $timerServiceName "Stopped"

break;

}

}

}

Write-Host ""

}

#<summary>

# Waits for the service on the server to reach the required service state.

# This can be used to wait for the "SharePoint 2010 Timer" service to stop or to start

#</summary>

#<param name="$serverName">The name of the server with the service to monitor.</param>

#<param name="$serviceName">The name of the service to monitor.</param>

#<param name="$serviceState">The service state to wait for, e.g. Stopped, or Running.</param>

function WaitForServiceState([string]$serverName, [string]$serviceName, [string]$serviceState)

{

Write-Host -foregroundcolor DarkGray -NoNewLine "Waiting for service '$serviceName' to change state to $serviceState on server $serverName"

do

{

Start-Sleep 1

Write-Host -foregroundcolor DarkGray -NoNewLine "."

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$serviceName'"

}

while ($service.State -ne $serviceState)

Write-Host -foregroundcolor DarkGray -NoNewLine " Service is "

Write-Host -foregroundcolor Gray $serviceState

}

#<summary>

# Starts the SharePoint Timer Service on each server in the SharePoint Farm.

#</summary>

#<param name="$farm">The SharePoint farm object.</param>

function StartSharePointTimerServicesInFarm($farm)

{

Write-Host ""

# Iterate through each server in the farm, and each service in each server

foreach($server in $farm)

{

foreach($instance in $server.ServiceInstances)

{

# If the server has the timer service then start the service

if($instance.TypeName -eq $timerServiceInstanceName)

{

[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Start '$timerServiceName' service on server: "

Write-Host -foregroundcolor Gray $serverName

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$timerServiceName'"

sc.exe \\$serverName start $timerServiceName > $null

WaitForServiceState $serverName $timerServiceName "Running"

break;

}

}

}

Write-Host ""

}

#<summary>

# Removes all xml files recursive on an UNC path

#</summary>

#<param name="$farm">The SharePoint farm object.</param>

function DeleteXmlFilesFromConfigCache($farm)

{

Write-Host ""

Write-Host -foregroundcolor DarkGray "Delete xml files"

[string] $path = ""

# Iterate through each server in the farm, and each service in each server

foreach($server in $farm)

{

foreach($instance in $server.ServiceInstances)

{

# If the server has the timer service delete the XML files from the config cache

if($instance.TypeName -eq $timerServiceInstanceName)

{

[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Deleting xml files from config cache on server: "

Write-Host -foregroundcolor Gray $serverName

# Remove all xml files recursive on an UNC path

$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\*.xml"

Remove-Item -path $path -Force

break

}

}

}

Write-Host ""

}

#<summary>

# Clears the SharePoint cache on an UNC path

#</summary>

#<param name="$farm">The SharePoint farm object.</param>

function ClearTimerCache($farm)

{

Write-Host ""

Write-Host -foregroundcolor DarkGray "Clear the cache"

[string] $path = ""

# Iterate through each server in the farm, and each service in each server

foreach($server in $farm)

{

foreach($instance in $server.ServiceInstances)

{

# If the server has the timer service then force the cache settings to be refreshed

if($instance.TypeName -eq $timerServiceInstanceName)

{

[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Clearing timer cache on server: "

Write-Host -foregroundcolor Gray $serverName

# Clear the cache on an UNC path

# 1 = refresh all cache settings

$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\cache.ini"

Set-Content -path $path -Value "1"

break

}

}

}

Write-Host ""

}

#**************************************************************************************

# Main script block

#**************************************************************************************

# Load SharePoint Powershell Snapin

Load-SharePoint-Powershell

# Get the local farm instance

$farm = Get-SPServer | where {$_.Role -match "Application"}

# Stop the SharePoint Timer Service on each server in the farm

StopSharePointTimerServicesInFarm $farm

# Delete all xml files from cache config folder on each server in the farm

DeleteXmlFilesFromConfigCache $farm

# Clear the timer cache on each server in the farm

ClearTimerCache $farm

# Start the SharePoint Timer Service on each server in the farm

StartSharePointTimerServicesInFarm $farm

PowerPivot in SharePoint 2013 - The schedule has been altered outside of PowerPivot. Use the Manage Data Refresh page to update and re-save the schedule

Ouch. This one sucked.  It sucks because the error you see in the PowerPivot refresh history doesn't tell you much.  Here's what we were seeing in the refresh history:

The schedule has been altered outside of PowerPivot. Use the Manage Data Refresh page to update and re-save the schedule.

We'd see this error any time we'd try to kick off a manual refresh.  Even more strangely, we'd see that the Excel file in question required a check-out before we could modify the refresh schedule.

Hmmmmmm....

So it turns out you need to disable the requirement for checking out a file for any Document Library in SharePoint 2013 where PowerPivot scheduled refreshes are enabled.  Don't believe me, check the TechNet article:

http://blogs.technet.com/b/excel_services__powerpivot_for_sharepoint_support_blog/archive/2014/09/15/powerpivot-scheduled-data-refresh-quot-the-workbook-must-be-checked-out-before-it-can-be-replaced-you-can-save-this-file-with-another-name-quot.aspx

Also - that's one of the shortest, most succinct TechNet articles I've ever read. 

At any rate, we were seeing the following in our ULS logs as well.  It was actually the ULS error that pointed me to the TechNet article.

EXCEPTION: System.InvalidOperationException: Call to Excel Services returned an error. ---> Microsoft.AnalysisServices.SPClient.Interfaces.ExcelServicesException: The workbook must be checked out before it can be replaced.  You can save this file with another name.

So the fix, in case you didn't go directly to the TechNet article, is to remove the requirement for check-out in the Document Library. 

I'm posting this one because when I searched on the initial error, I found one TechNet thread that didn't have the resolution I needed.  Hopefully this will help someone out.

Friday, January 8, 2016

Force check-in of all items in a SharePoint 2013 Site Collection


if ((Get-PSSnapin | ? { $_.Name -eq "Microsoft.SharePoint.PowerShell" }) -eq $null) {

    Add-PSSnapin "Microsoft.SharePoint.PowerShell"

}



$RootWeb = Get-SPWeb http://dev.sharepoint.com/sites/somesite

#$webfilter = "http://dev.sharepoint.com/sites/somesite"

$webfilter = ""



$noiselists = @(

    "appdata";

    "wfpub";

    "Cache Profiles";

    "Composed Looks";

    "Content and Structure Reports";

    "Content type publishing error log";

    "Device Channels";

    "Form Templates";

    "List Template Gallery";

    "Long Running Operation Status";

    "Quick Deploy Items";

    "Notification List";

    "Master Page Gallery";

    "Style Library";

    "Relationships List";

    "Solution Gallery";

    "Suggested Content Browser Locations";

    "TaxonomyHiddenList";

    "Theme Gallery";

    "Translation Packages";

    "Translation Status";

    "User Information List";

    "Variation Labels";

    "Web Part Gallery";

    "Converted Forms";

    "Reusable Content";

    "Site Collection Documents";

    "Site Collection Images";

    "Suggested Content Browser Locations";

    "Access Requests";

)



function BrowseItems($list) {

    $listPrinted = $false

    foreach ($item in $list.Items) {

        $itemFile = $item.File



        if ($itemFile.CheckOutStatus -ne "None") {

            if ($listPrinted -ne $true) {

                $listPrinted = $true

                $currentURL = $list.parentweb.Url

                Write-Host "Checking URL $currentURL" -f yellow

                Write-Host "List " -f green -NoNewline

                Write-Host $list -f cyan -NoNewline

                Write-Host " has items checked out" -f green

            }

            $fileName = $itemFile.Name

            $userName = $itemFile.CheckedOutByUser.Name;

            Write-Host "Document $fileName is checked out by $userName" -f Magenta



            Write-Host "Doing automatic CheckIn on the item" -f green -NoNewline

            $itemFile.CheckIn("Automatic CheckIn. (Administrator)")

            Write-Host " Done!" -f Yellow

        }

    }

}



function BrowseLists($lists) {

    foreach($list in $lists) {

    #Write-Host "lists"

        if ($list.title -notin $noiselists) {

            if($list.EnableVersioning -eq $true) {

                BrowseItems $list

            }

        }

    }

}



function BrowseSubsites($webs) {

    foreach($web in $webs) {

    #Write-Host "subsites"

        if ($web.Url -like $webfilter + "*") {

            BrowseLists $web.lists

            BrowseSubsites $web.Webs

        }

    }

}



function ForceCheckIn() {

    $web = $RootWeb

    BrowseLists $web.lists

    BrowseSubsites $web.Webs

}





ForceCheckIn​

Use Powershell to create a Site Collection in its own Content Database in SharePoint 2013

This script is one I use often.  It creates a Site Collection in SharePoint 2013 in its own database, and then sets that database to only allow one Site Collection in it.  It's good for deployments that will have very large content databases.Add-PSSnapin Microsoft.SharePoint.Powershell

#Set variables
$sitename = "SOME SITE NAME"
$managedpathname = "MANAGED PATH NAME"
$contentdb = "Some_Content_Database"
$dbserver = "databaseserver_sql"
$webapp = "
http://dev.sharepoint.com"
$siteurl = "
http://dev.sharepoint.com/managedpath/sitename"
$feature = Get-SPFeature PublishingSite
$Template = STS#0
$Owner = "domain\username"

#Create the content database the new collection will live in
New-spcontentdatabase -name $contentdb -databaseserver $dbserver -webapplication $webapp

#Create the Managed Path, if needed.  Often this line will be commented out, as is below
#new-spmanagedpath $managedpathname -webapplication
http://dev.sharepoint.com

#Create the site collection in that content database
new-spsite -name $sitename -contentdatabase $contentdb -url $siteurl -owneralias $Owner -template $Template

#Set the content database to only allow that site collection to be built there
get-spcontentdatabase -site $siteurl | set-spcontentdatabase -maxsitecount 1 -warningsitecount 0