Add-PSSnapin Microsoft.SharePoint.Powershell
###########################
# "Enter the site URL here"
$SITEURL = "http://somesite.com"
# "Name of Site group from which users have to be removed"
$SITEGROUP = "Members"
###########################
$site = new-object Microsoft.SharePoint.SPSite ( $SITEURL )
$web = $site.OpenWeb()
"Web is : " + $web.Title
$oSiteGroup = $web.SiteGroups[$SITEGROUP];
"Site Group is :" + $oSiteGroup.Name
$oUsers = $oSiteGroup.Users
foreach ($oUser in $oUsers)
{
"Removing user : " + $oUser.Name
$oSiteGroup.RemoveUser($oUser)
}
Day to day Powershell, SharePoint, and Project Server experiences. Any scripts here are provided as-is, and you're encouraged to test them before you run them on production. Most are scripts I've altered to suit my needs, and come from places like Stack Overflow or TechNet.
Wednesday, March 16, 2016
Sunday, February 28, 2016
Warm up SharePoint - Vickers Style
There are about a million of these scripts on the Internet, but this one is mine. Put it on a server, run it regularly in Task Scheduler, and forget about it.
The nice thing about this one is you don't have to change anything about it to run it on your farm. It will query SharePoint to get the relevant web applications, search centers, mysites, etc.
Add-PSSnapin Microsoft.SharePoint.PowerShell
try
{
# Set Variables
$MultiThreadSites = @()
$SingleThreadSites = @()
$WebServers = @()
$SearchServers = @()
$Servers = Get-SPServer | where {$_.Role -ne "Invalid"}
# Get Web Applications
$WebApps = Get-SPWebApplication
# Get Global Search Center Url
$SearchSvc = Get-SPEnterpriseSearchServiceApplication | Where {$_.Name -eq "Search Service Application"}
$SrcCenterUrl = $SearchSvc.SearchCenterUrl -Replace "/default.aspx", ""
# If search center is set
if($SrcCenterUrl)
{
# Set Various Search Urls
$SrcUrls = @("$($SrcCenterUrl)/default.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/results.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/peopleresults.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/conversationresults.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/results.aspx?k=test")
}
# Get Central Admin Url
$CentralAdmin = [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]::Local
$CentralAdminUrl = $CentralAdmin.Url
$HealthReportUrl = "$($CentralAdminUrl)/Lists/HealthReports"
$CAServer = $CentralAdmin.Url.split('//')[2].split('`:')[0]
# Loop through all the servers in farm
foreach($Server in $Servers)
{
# Create a variable of Server Name
$ServerName = $Server.Name
# Determine the farm Web Servers
If ($ServerName -notlike "SRPAPPPW003") {
$WebServiceIns = Get-SPServiceInstance -Server $ServerName | where {$_.TypeName -eq "Microsoft SharePoint Foundation Web Application"}
if($WebServiceIns.Status -eq "Online")
{
$WebServers += ,@($ServerName)
} }
# Determine the farm Search Servers
$SearchServiceIns = Get-SPServiceInstance -Server $ServerName | where {$_.TypeName -eq "SharePoint Server Search"}
if($SearchServiceIns.Status -eq "Online")
{
$SearchServers += ,@($ServerName)
}
}
# Loop through all the Web Applications
foreach($WebApp in $WebApps)
{
# Get the first site collection Url
$SiteCols = Get-SPSite -WebApplication $WebApp -Limit 5
# If there are Site Collections in this Web Application
if($SiteCols)
{
# Loop through all the Site Collections
foreach($SiteCol in $SiteCols)
{
$MultiThreadSites += $SiteCol.Url | Where {$_ -notlike "*$CAServer*"}
}
}
}
# Add Central Admin and Helath Check to the Site Array
#$SingleThreadSites += ,@($CentralAdminUrl)
#$SingleThreadSites += ,@($HealthReportUrl)
# Loop through all the Search Urls
foreach($SrcUrl in $SrcUrls)
{
# Add Url to the Site Array
$SingleThreadSites += ,@($SrcUrl)
}
# Loop through all Search Servers
foreach($SearchServer in $SearchServers)
{
# Add Url to the Site Array
$TopologyUrl = "http://$($SearchServer.ToLower()):32843/Topology/topology.svc"
$SingleThreadSites += ,@($TopologyUrl)
}
# Loop through all urls
foreach($Site in $SingleThreadSites)
{
Write-host "Loading $($Site)..." -NoNewline
$Url = "$($Site)"
$Request = [System.Net.WebRequest]::Create($Url)
$Request.UseDefaultCredentials = $true
try
{
$Response = $Request.GetResponse()
}
catch [System.Net.WebException]
{
$Response = $_.Exception.Response
}
$Status = [int]$Response.StatusCode
if($Status -eq 200)
{
$WebClient = New-Object Net.WebClient
$WebClient.UseDefaultCredentials = $true
$PageContents = $WebClient.DownloadString($Url)
$WebClient.Dispose()
Write-host "200 OK" -ForegroundColor Green
}
else
{
Write-host "Error: $Status" -ForegroundColor Red
}
}
# Loop through all site collections
foreach($Site in $MultiThreadSites)
{
# Loop through all web servers
foreach($WebServer in $WebServers)
{
Write-host "Loading $($Site) on server $($WebServer)..." -NoNewline
$Url = $($Site)
$BypassLocal = $false
$ProxyUri = "http://" + $WebServer
$Proxy = New-Object System.Net.WebProxy($ProxyUri, $BypassLocal)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.UseDefaultCredentials = $true
$Request.Proxy = $Proxy
try
{
$Response = $Request.GetResponse()
}
catch [System.Net.WebException]
{
$Response = $_.Exception.Response
}
$Status = [int]$Response.StatusCode
if($Status -eq 200)
{
$WebClient = New-Object Net.WebClient
$WebClient.UseDefaultCredentials = $true
$WebClient.Proxy = $Proxy
$PageContents = $WebClient.DownloadString($Url)
$WebClient.Dispose()
Write-host "200 OK" -ForegroundColor Green
}
else
{
Write-host "Error: $Status" -ForegroundColor Red
}
}
}
Write-host "Loading Central Admin on server $($CAServer)..." -NoNewline
$Url = $($CentralAdminUrl)
$BypassLocal = $false
$ProxyUri = $CentralAdminUrl
$Proxy = New-Object System.Net.WebProxy($ProxyUri, $BypassLocal)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.UseDefaultCredentials = $true
$Request.Proxy = $Proxy
try
{
$Response = $Request.GetResponse()
}
catch [System.Net.WebException]
{
$Response = $_.Exception.Response
}
$Status = [int]$Response.StatusCode
if($Status -eq 200)
{
$WebClient = New-Object Net.WebClient
$WebClient.UseDefaultCredentials = $true
$WebClient.Proxy = $Proxy
$PageContents = $WebClient.DownloadString($Url)
$WebClient.Dispose()
Write-host "200 OK" -ForegroundColor Green
}
else
{
Write-host "Error: $Status" -ForegroundColor Red
}
}
catch
{
Write-host "Error" -ForegroundColor Red
Write-host "Error at line $($_.InvocationInfo.ScriptLineNumber): $_" -ForegroundColor DarkGray
}
# Remove created variables
#Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
The nice thing about this one is you don't have to change anything about it to run it on your farm. It will query SharePoint to get the relevant web applications, search centers, mysites, etc.
Add-PSSnapin Microsoft.SharePoint.PowerShell
try
{
# Set Variables
$MultiThreadSites = @()
$SingleThreadSites = @()
$WebServers = @()
$SearchServers = @()
$Servers = Get-SPServer | where {$_.Role -ne "Invalid"}
# Get Web Applications
$WebApps = Get-SPWebApplication
# Get Global Search Center Url
$SearchSvc = Get-SPEnterpriseSearchServiceApplication | Where {$_.Name -eq "Search Service Application"}
$SrcCenterUrl = $SearchSvc.SearchCenterUrl -Replace "/default.aspx", ""
# If search center is set
if($SrcCenterUrl)
{
# Set Various Search Urls
$SrcUrls = @("$($SrcCenterUrl)/default.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/results.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/peopleresults.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/conversationresults.aspx")
$SrcUrls += ,@("$($SrcCenterUrl)/results.aspx?k=test")
}
# Get Central Admin Url
$CentralAdmin = [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]::Local
$CentralAdminUrl = $CentralAdmin.Url
$HealthReportUrl = "$($CentralAdminUrl)/Lists/HealthReports"
$CAServer = $CentralAdmin.Url.split('//')[2].split('`:')[0]
# Loop through all the servers in farm
foreach($Server in $Servers)
{
# Create a variable of Server Name
$ServerName = $Server.Name
# Determine the farm Web Servers
If ($ServerName -notlike "SRPAPPPW003") {
$WebServiceIns = Get-SPServiceInstance -Server $ServerName | where {$_.TypeName -eq "Microsoft SharePoint Foundation Web Application"}
if($WebServiceIns.Status -eq "Online")
{
$WebServers += ,@($ServerName)
} }
# Determine the farm Search Servers
$SearchServiceIns = Get-SPServiceInstance -Server $ServerName | where {$_.TypeName -eq "SharePoint Server Search"}
if($SearchServiceIns.Status -eq "Online")
{
$SearchServers += ,@($ServerName)
}
}
# Loop through all the Web Applications
foreach($WebApp in $WebApps)
{
# Get the first site collection Url
$SiteCols = Get-SPSite -WebApplication $WebApp -Limit 5
# If there are Site Collections in this Web Application
if($SiteCols)
{
# Loop through all the Site Collections
foreach($SiteCol in $SiteCols)
{
$MultiThreadSites += $SiteCol.Url | Where {$_ -notlike "*$CAServer*"}
}
}
}
# Add Central Admin and Helath Check to the Site Array
#$SingleThreadSites += ,@($CentralAdminUrl)
#$SingleThreadSites += ,@($HealthReportUrl)
# Loop through all the Search Urls
foreach($SrcUrl in $SrcUrls)
{
# Add Url to the Site Array
$SingleThreadSites += ,@($SrcUrl)
}
# Loop through all Search Servers
foreach($SearchServer in $SearchServers)
{
# Add Url to the Site Array
$TopologyUrl = "http://$($SearchServer.ToLower()):32843/Topology/topology.svc"
$SingleThreadSites += ,@($TopologyUrl)
}
# Loop through all urls
foreach($Site in $SingleThreadSites)
{
Write-host "Loading $($Site)..." -NoNewline
$Url = "$($Site)"
$Request = [System.Net.WebRequest]::Create($Url)
$Request.UseDefaultCredentials = $true
try
{
$Response = $Request.GetResponse()
}
catch [System.Net.WebException]
{
$Response = $_.Exception.Response
}
$Status = [int]$Response.StatusCode
if($Status -eq 200)
{
$WebClient = New-Object Net.WebClient
$WebClient.UseDefaultCredentials = $true
$PageContents = $WebClient.DownloadString($Url)
$WebClient.Dispose()
Write-host "200 OK" -ForegroundColor Green
}
else
{
Write-host "Error: $Status" -ForegroundColor Red
}
}
# Loop through all site collections
foreach($Site in $MultiThreadSites)
{
# Loop through all web servers
foreach($WebServer in $WebServers)
{
Write-host "Loading $($Site) on server $($WebServer)..." -NoNewline
$Url = $($Site)
$BypassLocal = $false
$ProxyUri = "http://" + $WebServer
$Proxy = New-Object System.Net.WebProxy($ProxyUri, $BypassLocal)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.UseDefaultCredentials = $true
$Request.Proxy = $Proxy
try
{
$Response = $Request.GetResponse()
}
catch [System.Net.WebException]
{
$Response = $_.Exception.Response
}
$Status = [int]$Response.StatusCode
if($Status -eq 200)
{
$WebClient = New-Object Net.WebClient
$WebClient.UseDefaultCredentials = $true
$WebClient.Proxy = $Proxy
$PageContents = $WebClient.DownloadString($Url)
$WebClient.Dispose()
Write-host "200 OK" -ForegroundColor Green
}
else
{
Write-host "Error: $Status" -ForegroundColor Red
}
}
}
Write-host "Loading Central Admin on server $($CAServer)..." -NoNewline
$Url = $($CentralAdminUrl)
$BypassLocal = $false
$ProxyUri = $CentralAdminUrl
$Proxy = New-Object System.Net.WebProxy($ProxyUri, $BypassLocal)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.UseDefaultCredentials = $true
$Request.Proxy = $Proxy
try
{
$Response = $Request.GetResponse()
}
catch [System.Net.WebException]
{
$Response = $_.Exception.Response
}
$Status = [int]$Response.StatusCode
if($Status -eq 200)
{
$WebClient = New-Object Net.WebClient
$WebClient.UseDefaultCredentials = $true
$WebClient.Proxy = $Proxy
$PageContents = $WebClient.DownloadString($Url)
$WebClient.Dispose()
Write-host "200 OK" -ForegroundColor Green
}
else
{
Write-host "Error: $Status" -ForegroundColor Red
}
}
catch
{
Write-host "Error" -ForegroundColor Red
Write-host "Error at line $($_.InvocationInfo.ScriptLineNumber): $_" -ForegroundColor DarkGray
}
# Remove created variables
#Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
Thursday, February 25, 2016
Here's something you don't really want to see....ever
We ran into a unique error in Project Server 2013 a couple days ago. In short, what we found was if you are running a Bulk Update of all Project sites, there's a possibility of putting locks on your database if you are running an instance of Project Server that is highly customized.
The error we were seeing in the SharePoint logs was this: PWA:{PWA Url}, ServiceApp:Project Services Application, User:PROJECTSERVER\system, PSI: User {User Account} could not be authenticated because logon permission has not been granted.
In our case, the stored procedure for pub.MSP_AUTH_AuthenticateUserByAccount could not fire, not because of an access or authentication issue, but because a lock had been placed on the tempdb's log file.
In searching for the error, I saw something I've never seen before on Google.
Behold
You know you're having a bad day when even Google only has one idea.
The error we were seeing in the SharePoint logs was this: PWA:{PWA Url}, ServiceApp:Project Services Application, User:PROJECTSERVER\system, PSI: User {User Account} could not be authenticated because logon permission has not been granted.
In our case, the stored procedure for pub.MSP_AUTH_AuthenticateUserByAccount could not fire, not because of an access or authentication issue, but because a lock had been placed on the tempdb's log file.
In searching for the error, I saw something I've never seen before on Google.
Behold
You know you're having a bad day when even Google only has one idea.
Monday, February 22, 2016
Enable that Cross-Domain People Picker, yo!
I'm writing this one definitely not as the first source on this subject, but mainly out of frustration. Way too many Bing and Google searches looking for the right syntax, and way too many posts with the wrong string.
The following STSADM command will allow the People Picker to search for users in a situation where you have a one-way trust between domains. This is especially useful if you're load testing your QA domain.
This command is all in one string. Run this after you create a credential key. Do that by entering this:
stsadm.exe -o setproperty -pn peoplepicker-searchadforests -pv "" -url http://qa.somecompany.com
Hope this helps someone.
The following STSADM command will allow the People Picker to search for users in a situation where you have a one-way trust between domains. This is especially useful if you're load testing your QA domain.
This command is all in one string. Run this after you create a credential key. Do that by entering this:
stsadm -o setapppassword -password <password>
STSADM.exe -o
setproperty -pn
peoplepicker-searchadforests -pv "forest:QAFOREST.somecompany.com,AD\service-somesvcacct,thataccountpw;
domain:ADFOREST.somecompany.com,AD\service-somesvcacct,thataccountpw" -url http://qa.somecompany.com
Explanations:
The service account used is the service account from the primary domain. So in a one-way scenario, QA will trust it.
Once you run it, you can run the following to verify the setting was applied:
stsadm.exe -o getproperty -pn peoplepicker-searchadforests -url http://qa.somecompany.com
If you need to clear the property, you can run this:
stsadm.exe -o setproperty -pn peoplepicker-searchadforests -pv "" -url http://qa.somecompany.com
Hope this helps someone.
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.
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()
}
*****
#This script will empty all Recycle Bins for all sites and subsites in a Site Collection.
*****
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()
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:
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.
Subscribe to:
Posts (Atom)
