Tag Archives: SharePoint 2013
FIXED – AzurePlugin was not able to get Tenant Info from configuration server (CSSA)
While enabling the CSSA (Cloud Search Service Application) I came across this error during first full crawl after successfully completing the on-boarding steps outlined at https://blogs.msdn.microsoft.com/spses/2015/09/15/cloud-hybrid-search-service-application/ with PowerShell scripts. The Azure plugin was unable to crawl on-premise content. Root cause was proxy server configuration, which needs to be consistent across three places. Hope this helps!
Central Admin
An unexpected error occurred in the Azure plugin. This item will be retried in the next incremental crawl. ( AzureException AzurePlugin was not able to get Tenant Info from configuration server; SearchID = B056F137-1C77-4792-B402-256B615DBE82 )
Verbose ULS
Get-SPLogLevel |? {$_.Area -like "SharePoint Server Search"} | Set-SPLogLevel -TraceSeverity VerboseEx
New-SPLogFileULS Log
By running PowerShell commands “Set-SPLogLevel” and “New-SPLogFile” I was able to get verbose URL for the CSSA crawl process. Here are the entries showing inability to communicate over the proxy server to the Internet.
12/08/2016 15:36:31.55 mssearch.exe (0x195C) 0x0B18 SharePoint Server Search Crawler:Azure Plugin amn0f High AzureServiceProxy::GetCerts caught AggregateException: The ServicePointManager does not support proxies with the myproxy scheme.
12/08/2016 15:36:31.55 mssearch.exe (0x195C) 0x0B18 SharePoint Server Search Crawler:Azure Plugin amn0g High AzureServiceProxy::GetCerts: Failed to get encryption certificates from cert server https://tenant.sharepoint.com for realm 67d7b889-884d-4c2a-a8d8-3ff81f37b497, documents will be send unencrypted (if unecrypted submit is allowed)
12/08/2016 15:36:31.55 mssearch.exe (0x195C) 0x0B18 SharePoint Server Search Crawler:Azure Plugin amn0h High AzureServiceProxy::GetAzureTenantInfo caught AggregateException: The ServicePointManager does not support proxies with the myproxy scheme., unable to get EndpointAddress, submit is blocked
12/08/2016 15:36:31.55 mssearch.exe (0x195C) 0x0B18 SharePoint Server Search Crawler:Azure Plugin amn0i High AzureServiceProxy caught Exception: *** Microsoft.Office.Server.Search.AzureSearchService.AzureException: AzurePlugin was not able to get Tenant Info from configuration server at Microsoft.Office.Server.Search.AzureSearchService.AzureServiceProxy.GetAzureTenantInfo(String portalURL, String realm, String& returnPropertyValue, String propertyName) at Microsoft.Office.Server.Search.AzureSearchService.AzureServiceProxy.SubmitDocuments(String azureServiceLocation, String authRealm, String SPOServiceTenantID, String SearchContentService_ContentFarmId, String portalURL, String testId, String encryptionCert, Boolean allowUnencryptedSubmit, sSubmitDocument[] documents, sDocumentResult[]& results, sAzureRequestInfo& RequestInfo) ***
Resolution
Proxy server settings need to be confirmed in three places. The crawler was attempting to use “myproxy:8080” DNS names when it actually needs URL format “http://myproxy:8080”
1) Internet Explorer
Tools > Options > Connections > LAN Settings
Provide either PAC URL (proxy auto config) or proxy server DNS name.
2) Command Line
NETSH WINHTTP SHOW PROXY
NETSH WINHTTP SET PROXY PROXY-SERVER=”myproxy:8080” BYPASS-LIST=”*.company.com;<local>”
3) Dot Net Global [machine.config]
Run notepad
Open “C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config”
Add following XML code
<system.net>
<defaultProxy>
<proxy usesystemdefault=”false” proxyaddress=”http://myproxy:8080” bypassonlocal=”true” />
</defaultProxy>
</system.net>
Notes
- Completed the “Hybrid Onedrive” click once application to create “ACS” and “SPO” service application proxies before Hybrid Search CSSA onboarding. https://configure.office.com/
References
- https://support.office.com/en-us/article/SharePoint-hybrid-sites-and-search-5ff7e56a-7af2-4511-adec-1e043afe244e
- https://blogs.msdn.microsoft.com/spses/2015/09/15/cloud-hybrid-search-service-application
- https://blogs.msdn.microsoft.com/spses/2015/05/20/the-all-new-cloud-search-service-application-coming-to-sharepoint-2013-and-sharepoint-2016/
- https://github.com/spjeff/office365/tree/master/office365-hybrid-search-cssa
- https://thesharepointfarm.com/2016/12/cloud-search-service-application-crawl-performance
I Wanna Patch FAST
Want to patch your SharePoint farms faster? Try running https://github.com/spjeff/sppatchify
The latest version (0.42) includes new PowerShell code for parallel execution of “Upgrade-SPContentDatabase.” This was implemented with “Get-Job” and PowerShell job management to remote sessions.
The more user content databases you have, the greater the time savings. Below are summary statistics from patching a 9 server SharePoint 2013 farm with 200 SQL content databases in just 4 hours. Each of the 9 servers will spawn 4 PowerShell remoting runspaces for “Upgrade-SPContentDatabase.” With 36 concurrent worker threads, the queue of 200 content databases now becomes only 6 deep.
Instead of waiting 200 units of time to process content databases serially, we now only wait 6 units of time for the upgrade database phase.
Larger farms with more user content (and databases) will see significant overall time savings considering how a majority of the traditional patching timeline is processing all content databases. The binary EXE phase runs with all content databases removed (Dismount-SPContentDatabase ) so PSCONFIG can complete sooner. After that is done, content is introduced again (Mount-SPContentDatabase) and upgraded (Upgrade-SPContentDatabase).
Amazing speed!!! Cheers 
Charts

SPPatchify

SPPatchify – CU patch entire farm from one script
Patching can be tedious and time consuming. Why not automate that? Who wants to be awake all night clicking “Next” and watching SP config wizard? So I coded a single PowerShell script to manage the full end-to-end patching process.
The script will …
- Enable PowerShell client remoting. Connects to farm peer machines.
- Autodetect current user password from IIS pools
- Download Microsoft Cumulative Update (CU) media (EXE +CAB) and copy to all servers. Optionally, you can download to the \media\ sub folder manually.
- Stop Distributed Cache (DC)
- Stop SharePoint services
- Run EXE binary in paralle
- Wait for EXE to complete and reboot
- Dismount-SPContentDatabase
- Start SharePoint services
- Run SharePoint Config Wizard serially
- Mount-SPContentDatabase
- Remove Microsoft Cumulative Update (CU) media from peer servers
- Ensure IIS started
- Launch Central Admin with IE
- Reboot current PC
Duration from start to end is incredibly fast. I tested a 4 server SharePoint 2013 farm and ran the entire process in just 45 minutes. Stopping services and dismounting content databases speeds up patching significantly. Automating serial (one-at-time) Configuration Wizard ensures minimal “think time” between steps. Removing manual human process gives higher consistency while mitigating risk of error.
The script uses Get-SPServer to auto detect farm members. That enables CU media copy sideways to peers and the stop/start of SharePoint services. Get-SPContentDatabase is exported to a local CSV file to “snapshot” before patching and later Mount-SPContentDatabase step to present databases again. The big goal isn’t zero downtime, but rather minimal downtime.
The entire farm patching process can be managed from one PowerShell window. Enjoy!
Please leave a comment if you found this helpful.
Get Started
- https://github.com/spjeff/sppatchify
- Extract to “C:\SPPatchify” on any server in the farm
- RDP with farm account and run “C:\SPPatchify\SPPatchify.ps1”
Flow Diagram
Screenshots




References
How to detect if MS16-004 hotfix is installed
While managing a number of farms I needed to search and find out if the hotfix for MS16-004 bug was installed. Stefan posted a helpful solution for the Jan 2016 CU ListView issue at https://blogs.technet.microsoft.com/stefan_gossner/2016/01/15/solution-for-the-list-view-issue-with-ms16-004-january-2016-pu-for-sharepoint-2013/ and some farms have “wssloc2013-kb3114508-fullfile-x64-glb.exe” installed but not all.
This PowerShell can be run local or remote to indicate if a given farm has the hotfix. Below is a remote sample across 40 servers with https://github.com/spjeff/splaunch. Enjoy! ![]()
Code
$p1=$false;
$p=Get-SPProduct;
$p.PatchableUnitDisplayNames |% {
$n=$_;
if (($p.GetPatchableUnitInfoByDisplayName($n).patches |? {$_.patchname -like '*3114508*'}).count -gt 0) {
$p1=$true;
}
};
$obj = New-Object -TypeName PSObject -Prop (@{'wssloc2013-kb3114508-fullfile-x64-glb'=$p1;});
$obj;
Screenshot
Enable Business Intelligence on any Team Site
Have you worked on a standard SP2013 Team Site then recognized a need to activate BI features. The BI Center template comes with a lot preloaded. I used that baseline to compare Activated Features and got the list below.
Running this PowerShell will enable the same features so you can apply BI work to any other base template (Team Site, Community, etc.) Cheers! ![]()
PowerShell
# target
$url = "http://portal/sites/team"
# scope
$webfeat = "PPSMonDatasourceCtype,PPSRibbon,PPSSiteCollectionMaster,PPSWebParts,PPSWorkspaceCtype".Split(",")
$sitefeat = "BICenterDashboardsLib,BICenterDataConnections,BICenterDataconnectionsLib,BICenterDataConnectionsListInstance,BICenterPPSContentPages,BICenterPPSNavigationLink,BICenterPPSWorkspaceListInstance,BICenterSampleData,PPSSiteMaster,PPSWorkspaceList".Split(",")
# activate
foreach ($f in $webfeat) {
Write-Host "Activating Web - $f"
Enable-SPFeature -Identity $f -Url $url
}
foreach ($f in $sitefeat) {
Write-Host "Activating Site - $f"
Enable-SPFeature -Identity $f -Url $url
}
Write-Host "DONE"Site Features
PPSMonDatasourceCtype
PPSRibbon
PPSSiteCollectionMaster
PPSWebParts
PPSWorkspaceCtype
Web Features
BICenterDashboardsLib
BICenterDataConnections
BICenterDataconnectionsLib
BICenterDataConnectionsListInstance
BICenterPPSContentPages
BICenterPPSNavigationLink
BICenterPPSWorkspaceListInstance
BICenterSampleData
PPSSiteMaster
PPSWorkspaceList
Untitled ASPX – light CEWP framing
If you need to host a JavaScript SPA in SharePoint and display on external systems with <IFRAME>. The below empty ASPX page can host a single Content Editor Web Part to effectively run JavaScript with light framing. The page loads crazy fast too.
I created it with SP Designer 2010 (https://www.spjeff.com/2014/05/08/get-design-view-back-on-sharepoint-2013-woohoo/) and WYSIWYG to embed a Web Part Zone and Content Editor above the blank ASPX default page. ![]()
Screenshot
Code
<%@ Page Language="C#" inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register tagprefix="WebPartPages" namespace="Microsoft.SharePoint.WebPartPages" assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Microsoft wants to hear YOU! UserVoice
The below links are a great way to provide feedback for the Microsoft future roadmap, research & development, and cloud first releases. Please give feedback and help the community steer in the right direction. Cheers! ![]()


http://aspnet.uservoice.com
http://bingads.uservoice.com
http://microsoftvisio.uservoice.com
http://msaccess.uservoice.com
http://office365.uservoice.com
http://office365video.uservoice.com
http://officeforms.uservoice.com
http://officemix.uservoice.com
http://officespdev.uservoice.com
http://onedrive.uservoice.com
http://onenote.uservoice.com
http://owa.uservoice.com
http://powerpoint.uservoice.com
http://sharepoint.uservoice.com
http://sway.uservoice.com
http://visualstudio.uservoice.com
http://xbox.uservoice.com
http://binglistens.uservoice.com
http://excel.uservoice.com
http://systemcentervmm.uservoice.com
http://word.uservoice.com
Post to Newsfeed on behalf of another user (Server Object Model)
The below code will post to Newsfeed for any user account you specify. Activity appears the same as if the user manually posted. This could be helpful for populating Newsfeed from external activity, custom event receivers, workflow, and other developer sources. Enjoy! ![]()
Screenshot
Code
using Microsoft.Office.Server.Social;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.SharePoint;
using System;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Config
string siteUrl = "http://mysite";
string login = "i:0#.w|domain\\user";
using (SPSite site = new SPSite(siteUrl))
{
// Context
SPUser user = site.RootWeb.SiteUsers[login];
SPUserToken token = user.UserToken;
SPServiceContext ctx = SPServiceContext.GetContext(site);
using (new SPServiceContextScope(ctx))
{
// Init
UserProfileManager upm = new UserProfileManager(ctx);
UserProfile prof = upm.GetUserProfile(user.LoginName);
SPSocialFeedManager mgr = new SPSocialFeedManager(prof, ctx, token);
SPSocialPostCreationData post = new SPSocialPostCreationData();
// Text
post.ContentText = "hello world, look at {0}!";
post.UpdateStatusText = true;
// Link
SPSocialDataItem [] link = new SPSocialDataItem [1];
link[0] = new SPSocialDataItem();
link[0].ItemType = SPSocialDataItemType.Link;
link[0].Text = "My Cool Link";
link[0].Uri = new Uri("http://www.google.com");
post.ContentItems = link;
// Save
SPSocialThread thread = mgr.CreatePost(null, post);
}
}
}
}
}
References
Custom Security Roles
Contributor is often too generic to match business needs. Below are 4 custom security roles with more granular purpose. Running the below PowerShell will create the roles (if missing) for a given web URL.
- NoDelete = Contribute without delete
- AddOnly = Contribute without delete or edit
- EditOnly = Contribute without add or delete
- NoEdit = Contribute without edit
# #############################################################################
# NAME: AddCustomRoles.ps1
#
# COMMENT: This script creates two Custom Access levels for
# a given SharePoint URL.
#
# * NoDelete = Contribute without delete
# * AddOnly = Contribute without delete or edit
# * EditOnly = Contribute without add or delete
# * NoEdit = Contribute without edit
#
# REQUIRE: Permission to unlock account
# USAGE: .\AddCustomRoles.ps1 http://sharepoint/sites/team
#
# #############################################################################
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$url
)
Write-Host "Opening $url ... "
$web = Get-SPWeb $url
Write-Host "OK" -ForegroundColor Green
#### CREATE NODELETE
$nd = $web.RoleDefinitions |? {$_.Name -eq "NoDelete"}
if ($nd) {
Write-Host "Found NoDelete" -ForegroundColor Green
} else {
Write-Host "Missing NoDelete"
Write-Host "Adding NoDelete ..."
$noDeleteRole = New-Object "Microsoft.SharePoint.SPRoleDefinition"
$noDeleteRole.Name = "NoDelete"
$noDeleteRole.Description = "Can view, add, and update list items and documents."
$noDeleteRole.BasePermissions = "AddAndCustomizePages,AddDelPrivateWebParts,AddListItems,BrowseDirectories,BrowseUserInfo,CreateAlerts,EditListItems,EditMyUserInfo,ManagePersonalViews,Open,OpenItems,UpdatePersonalWebParts,UseClientIntegration,UseRemoteAPIs,ViewFormPages,ViewListItems,ViewPages,ViewVersions"
$web.RoleDefinitions.Add($noDeleteRole)
Write-Host "OK" -ForegroundColor Green
}
#### CREATE ADDONLY
$ao = $web.RoleDefinitions |? {$_.Name -eq "AddOnly"}
if ($ao) {
Write-Host "Found AddOnly" -ForegroundColor Green
} else {
Write-Host "Missing AddOnly"
Write-Host "Adding AddOnly ..."
$addOnlyRole = New-Object "Microsoft.SharePoint.SPRoleDefinition"
$addOnlyRole.Name = "AddOnly"
$addOnlyRole.Description = "Can view and add items and documents."
$addOnlyRole.BasePermissions = "AddAndCustomizePages,AddDelPrivateWebParts,AddListItems,BrowseDirectories,BrowseUserInfo,CreateAlerts,EditMyUserInfo,ManagePersonalViews,Open,OpenItems,UpdatePersonalWebParts,UseClientIntegration,UseRemoteAPIs,ViewFormPages,ViewListItems,ViewPages,ViewVersions"
$web.RoleDefinitions.Add($addOnlyRole)
Write-Host "OK" -ForegroundColor Green
}
#### CREATE EDITONLY
$eo = $web.RoleDefinitions |? {$_.Name -eq "EditOnly"}
if ($eo) {
Write-Host "Found EditOnly" -ForegroundColor Green
} else {
Write-Host "Missing EditOnly"
Write-Host "Adding EditOnly ..."
$EditOnlyRole = New-Object "Microsoft.SharePoint.SPRoleDefinition"
$EditOnlyRole.Name = "EditOnly"
$EditOnlyRole.Description = "Can view, and update list items and documents."
$EditOnlyRole.BasePermissions = "AddAndCustomizePages,AddDelPrivateWebParts,BrowseDirectories,BrowseUserInfo,CreateAlerts,EditMyUserInfo,ManagePersonalViews,Open,OpenItems,UpdatePersonalWebParts,UseClientIntegration,UseRemoteAPIs,ViewFormPages,ViewListItems,ViewPages,ViewVersions"
$web.RoleDefinitions.Add($EditOnlyRole)
Write-Host "OK" -ForegroundColor Green
}
#### CREATE NOEDIT
$ne = $web.RoleDefinitions |? {$_.Name -eq "NoEdit"}
if ($ne) {
Write-Host "Found NoEdit" -ForegroundColor Green
} else {
Write-Host "Missing NoEdit"
Write-Host "Adding NoEdit ..."
$NoEditRole = New-Object "Microsoft.SharePoint.SPRoleDefinition"
$NoEditRole.Name = "NoEdit"
$NoEditRole.Description = "Can add, view and delete list items and documents."
$NoEditRole.BasePermissions = "AddAndCustomizePages,AddDelPrivateWebParts,AddListItems,BrowseDirectories,BrowseUserInfo,CreateAlerts,DeleteListItems,DeleteVersions,EditMyUserInfo,ManagePersonalViews,Open,OpenItems,UpdatePersonalWebParts,UseClientIntegration,UseRemoteAPIs,ViewFormPages,ViewListItems,ViewPages,ViewVersions"
$web.RoleDefinitions.Add($NoEditRole)
Write-Host "OK" -ForegroundColor Green
}AngularJS – $http default JSON headers
The below JavaScript will change $http default headers to be JSON ready for SharePoint REST APIs. This is handy when sending GET/POST to SharePoint 2013 so we don’t need to repeat headers on each individual call. Enjoy! ![]()
//namespace
var namespace = namespace || {};
//NG-controller
namespace.myCtl = function ($scope, $mySvc) {
//viewmodel
var vm = $scope;
};
//NG-service
namespace.mySvc = function ($q, $http) {
$http.defaults.headers.common['Accept'] = 'application/json;odata=verbose';
//User Profile - me
this.getMe = function () {
return $http.get('/_api/SP.UserProfiles.PeopleManager/GetMyProperties');
};
//User Profile - users
this.getUser = function (login) {
var url = '/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=@v)?@v=\'domain\\' + login + '\'';
return $http.get(url);
};
};
//NG-module
angular.module('myApp', [])
.controller('myCtl', namespace.myCtl)
.service('$mySvc', namespace.mySvc)
.run(function () {
//prepare GUI
});
