Category: SharePoint 2013

Resetting Office 365 Cloud Search Index

From time to time we need to remove all the items out of the Office 365 search index. There are 3 options:

1. Re-index everything on premises and after the indexing completes delete the content sources to trigger a delete crawl to run. Of course re-indexing everything is not efficient, it takes time and if items have been deleted from the on premises content you still run the risk of missing orphans in the Office 365 search index.

2.  Call Microsoft Office 365 support and raise a ticket to ask for an index purge, something that takes time and again is inefficient for the task at hand.

3. Use DeleteAllCloudHybridSearchContent method of PushTenantManager.

More information on DeleteAllCloudHybridSearchContent method can be found here and here.

That was another page in the Chronicles of SharePoint Bits, happy scripting!

Error: PowerShell ISE stopped working

PowerShell Integrated Scripting Environment is a very powerful and useful tool to create and debug PowerShell scripts. After installing some security patching and IRM component it stopped working and would crash:

The issue is related to the corrupt GlobalUserInterface.CompositeFont file. This causes PowerShell ISE. It also effects other WPF applications to fail as well. See this article: https://github.com/dotnet/announcements/issues/53.

We used the Solution 3:

Replace GlobalUserInterface.CompositeFont Manually

Manually replace corrupted font file with correct version.

  1. Download GlobalUserInterface.CompositeFont (default download for Windows 7 is %USERPROFILE%\Downloads).
  2. Launch cmd as Administrator and navigate to %windir%\Microsoft.NET\Framework\v4.0.30319\WPF\Fonts and run:
    xcopy /y %USERPROFILE%\Downloads\GlobalUserInterface.CompositeFont .
    (or copy and paste the GlobalUserInterface.Composite file through Windows Explorer to %windir%\Microsoft.NET\Framework\v4.0.30319\WPF\Fonts)
  3. Launch cmd as Administrator and navigate to %windir%\Microsoft.NET\Framework64\v4.0.30319\WPF\Fonts and run:
    xcopy /y %USERPROFILE%\Downloads\GlobalUserInterface.CompositeFont .
    (or copy and paste the GlobalUserInterface.Composite file through Windows Explorer to %windir%\Microsoft.NET\Framework64\v4.0.30319\WPF\Fonts).
  4. Re-launch the application.
  5. Reboot machine and re-launch application if you still have trouble.
##
##
xcopy /y GlobalUserInterface.CompositeFont %windir%\Microsoft.NET\Framework\v4.0.30319\WPF\Fonts
xcopy /y GlobalUserInterface.CompositeFont %windir%\Microsoft.NET\Framework64\v4.0.30319\WPF\Fonts
##
##

 

That was another page in the Chronicles of SharePoint Bits, happy scripting!

Howto: Check all the sites in the particular Content DB

From time to time, there is a need to check the SharePoint sites is a particular content database are accessible. There is a simple script for it:  enumerate all the sites in the DB and Invoke a Web Request for the site URL. The returned Web request code will indicate if site is accessible or not:

####################################################################################################
#
# Author.......: David Shvartsman
# Date.........: 07/05/2018
# Description..: Check all the sites in the particular Content DB
#
####################################################################################################
#Load SharePoint PowerShell Snapin
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$db = "Content_DBName"
$Sites = Get-SPSite -ContentDatabase $db -Limit All
foreach ($site in $sites) {
    $SiteStatus = Invoke-WebRequest -Uri $site.url -UseDefaultCredentials | Select-Object StatusCode

    If ($siteStatus.StatusCode -eq 200) {
        Write-host "$($site.url) is OK." -ForegroundColor Green
    }
    Else {
        Write-Host "Failed check for $($site.url)" -ForegroundColor Red
    }
}

####################################################################################################

That was another page in the Chronicles of SharePoint Bits, happy scripting!

Troubleshooting: Collecting Verbose ULS logs

Working with Microsoft on the one of the issues we were asked to provide verbose ULS logs. Having the ULS logs in verbose mode might take a lot of disk space. Here is a simple solution: enable the verbose logging only for the period of time to reproduce the issue and switch it back to default level when done. PowerShell to the rescue: the following script will change the ULS log level to verbose and pause while you can reproduce the issues that is being troubleshooted. Just press the enter button after that and it will switch the log level to default (Information). If your default log level is different from Information modify the script accordingly. The script will generate Merged ULS log for the period between the start of the script and the time you pressed the Enter button to continue.

####################################################################################################
#
#  Author.......: David Shvartsman
#  Date.........: 06/27/2018
#  Description..: Troubleshooting: Collecting Verbose ULS logs
#
####################################################################################################
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
CLS
$startDate = (Get-Date -format "MM/dd/yyyy HH:mm:ss")
set-sploglevel -traceSeverity verbose
pause

$endDate = (Get-Date -format "MM/dd/yyyy HH:mm:ss")
Clear-SPLogLevel
$logfile = "d:\temp\ULSLogFileName.log"
if (test-path $logfile) {
          Remove-Item $logfile
}

Merge-SPLogFile –Path $logfile –StartTime $startDate –EndTime $endDate

####################################################################################################

That was another page in the Chronicles of SharePoint Bits, happy scripting!

PowerShell: working with JSON files

With introduction of Office 365 and SharePoint online, Microsoft increasingly using JSON file format to transfer data to and from the new platform. For example, Bulk UPA Custom Profile Properties Update API for SharePoint Online. For SharePoint administrator is natural to fall back to PowerShell to perform those tasks and automate the integration between the on-Premises environment and SharePoint Online.  Windows PowerShell 3.0 higher includes couple of commandlets (ConvertFrom-Json and ConvertTo-Json) to convert PowerShell objects to JSON format and back. One of the used cases is a fast and easy way to interact with web services.

####################################################################################################
#
#  Author.......: David Shvartsman
#  Date.........: 05/21/2018
#  Description..: Using PowerShell with JSON
#
#################################################################################################### 
#Save PowerShell object to the file in JSON format
$users | Where {$_name -like 'test'} | Select-Object $selectObject -skip 10 | 
            Select-Object -First 5 | ConvertTo-Json > C:\temp\users.json


#Read File in JSON format into PowerShell object
$users = Get-Content 'C:\temp\users.json' | Out-String | 
            ConvertFrom-Json | SELECT -expand Value | SELECT UserPrincipalName 

#Read Web Request response:
$WebRequestURL = "http://www.nactem.ac.uk/software/acromine/dictionary.py?sf=BMI"
Invoke-WebRequest $WebRequestURL | ConvertFrom-Json  | select *


#################################################################################################### 

That was another page in the Chronicles of SharePoint Bits, happy scripting!

Audience Compilation Status is ‘Compiling’ for a long time

Looking at Central Administration console under Manage Profile Service we have noticed that Audience Compilation Status shows ‘Compiling’ for a long time. There is no errors in the event logs. Attempts to stop compilation or compile an individual audience did not produce any results.

There is AudienceJob.exe executable that you can use to manipulate audiences:

AudienceJob.exe <Application Id> [Crawl Type] [Audience Name]
Application Id: Guid corresponding to UserProfile application
Command: 1 = Start, 0 = Stop
Crawl Type: 1 = Full, 0 = Incremental (default = 1)
Audience Name: Specific audience to compile (default = all)

####################################################################################################
#
#  Author.......: David Shvartsman
#  Date.........: 05/18/2018
#  Description..: Restart Audience Compilation
#
#################################################################################################### 
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$ServiceType = "User Profile Service Application"
$spService = Get-SPServiceApplication  | where {$_.TypeName -like $ServiceType }
$id = $spService.id
Audiencejob.exe $id 0 
Audiencejob.exe $id 1

You can use AudienceJob.exe to compile a specific audience.

It works in SharePoint 2010, SharePoint 2013 and SharePoint 2016.

That was another page in the Chronicles of SharePoint Bits, happy scripting!

Application error when access /_layouts/15/EditProperty.aspx, Error=AccessKey too long

After installing March 2018 update for SharePoint 2013 you may get the following error when trying to configure sync in User Profile Service Application:

Application error when access /_layouts/15/EditProperty.aspx, Error=AccessKey too long, cannot be more than one character. Parameter name: value
at System.Web.UI.WebControls.WebControl.set_AccessKey(String value)
at Microsoft.SharePoint.Portal.WebControls.InputFormCheckBox.set_AccessKeyLocId(LocStringId value)
at ASP._layouts_15_editproperty_aspx.__BuildControlchkboxIsVisibleOnViewer()
at ASP._layouts_15_editproperty_aspx.__BuildControlInputFormSectionFieldArea4()
at ASP._layouts_15_editproperty_aspx.__BuildControlSection4()
at ASP._layouts_15_editproperty_aspx.__BuildControlInputForm1()
at ASP._layouts_15_editproperty_aspx.__BuildControl__control7(Control __ctrl)
at System.Web.UI.MasterPage.InstantiateInContentPlaceHolder(Control contentPlaceHolder, ITemplate template)
at ASP._admin_admin_master.__BuildControlPlaceHolderMain()
at ASP._admin_admin_master.__BuildControlDeltaPlaceHolderMain()
at ASP._admin_admin_master.__BuildControl__control27()
at ASP._admin_admin_master.__BuildControlSPHtmlTag()
at ASP._admin_admin_master.__BuildControlTree(_admin_admin_master __ctrl)
at System.Web.UI.MasterPage.CreateMaster(TemplateControl owner, HttpContext context, VirtualPath masterPageFile, IDictionary contentTemplateCollection)
at System.Web.UI.Page.get_Master()
at System.Web.UI.Page.ApplyMasterPage()
at System.Web.UI.Page.PerformPreInit()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

You also might have experienced the slight disfigurement of UI Search/Content Source configuration screen:
The Ok and Cancel button label changed.

The problem is related to ASP.net temporary files. The workaround is to delete ASP.net temporary files on CA server and let .NET framework rebuild the executable. To fix the issue follow the steps below:
1. Stop IIS: iisreset /stop
2. Delete the content of the following folder:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files
3.Start IIS: iisreset /start

Stopping SharePoint Service Instance on the Server

SharePoint Central Administration Portal provides a way to start/stop Services Instance on a particular server. It is accessible under Application Management/Service Applications/Manage Services on Server option. It is all good in the small environment but controlling the Service Instances in the big environment becomes cumbersome. PowerShell to the rescue. Bellow is a code to stop SharePoint Service Instance on the particular server:

####################################################################################################
#
#  Author.......: David Shvartsman
#  Date.........: 11/24/2017
#  Description..: Stopping SharePoint Service Instance on the Server
#
#################################################################################################### 
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$ServerName = "Server Name"
$ServiceType = "Services Application Name" 
$spService = Get-SPServiceInstance | where {$_.TypeName -eq $ServiceType -and $_.Server.name -eq $ServerName } 
$i = 0
if ($spService.Status -eq "Online") {
    Write-Host "Stopping $($ServiceType) on $($ServerName) Server..." -NoNewline
    ##$spService.Unprovision()
    $spService = Stop-SPServiceInstance $spservice.Id -Confirm:$false
    DO {
        write-host -NoNewline "."
        sleep 30
        $spService = Get-SPServiceInstance $spService.Id
        $i++
    } While (($spservice.Status -ne "Disabled") -and ($i -lt 10))
    if ($spservice.Status -eq "Disabled") {
        Write-Host " Success!" -ForegroundColor Green
    } else {
        Write-Host " Failed!" -ForegroundColor Red
    }
}

Services Application Names:

Access Database Service 2010
Access Services
App Management Service
Business Data Connectivity Service
Central Administration
Claims to Windows Token Service
Distributed Cache
Document Conversions Launcher Service
Document Conversions Load Balancer Service
Excel Calculation Services
Lotus Notes Connector
Machine Translation Service
Managed Metadata Web Service
Microsoft SharePoint Foundation Incoming E-Mail
Microsoft SharePoint Foundation Sandboxed Code Service
Microsoft SharePoint Foundation Subscription Settings Service
Microsoft SharePoint Foundation Web Application
Microsoft SharePoint Foundation Workflow Timer Service
PerformancePoint Service
PowerPoint Conversion Service
Request Management
Search Host Controller Service
Search Query and Site Settings Service
Secure Store Service
SharePoint Server Search
SQL Server PowerPivot System Service
SQL Server Reporting Services Service
User Profile Service
User Profile Synchronization Service
Visio Graphics Service
Word Automation Services

 

Service Application Instance Status:

Online
Unprovisioning
Disabled
Provisioning

 

That was another page in the Chronicles of SharePoint Bits, happy scripting!

Event ID 3351: SQL database login for ” on instance ” failed.

In certain environments you will see ‘Event ID 3355: SQL database login for ” on instance ” failed.’ in the event logs.
The errors are related to MOM/SCOM Agent trying to access some information from the SharePoint Configuration database under ‘Local System’ account and gets access denied.

Resolution:
To resolve the issue we need to grant SPShellAdmin access to Local System account to Configuration DB for each server in the farm:

####################################################################################################
#
#  Author.......: David Shvartsman
#  Date.........: 11/01/2017
#  Description..: Fixing Event ID 3355: SQL database login for '<Config DB Name>' on instance '<SQL Instance Name>' failed. 
#
#################################################################################################### 
if ((Get-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin Microsoft.SharePoint.PowerShell
}
Add-PSSnapin Microsoft.SharePoint.Powershell

$domainName = ((gwmi Win32_ComputerSystem).Domain).Split(".")[0]

$Servers = get-spserver | ? { (($_.Role -eq "Application") -or ($_.Role -eq "SingleServer")) }
foreach($Server in $Servers) 
{
    $serverName = $Server.Name
    Get-SPDatabase | where {$_.name -match "config"} | Add-SPShellAdmin -username "$domainName\$serverName$"
}



That was another page in the Chronicles of SharePoint Bits, happy scripting!

SharePoint 2013: The case on orphan database

Issue:
Trying to create new site collection generates the following error:
New-SPSite : Object reference not set to an instance of an object.
At line:1 char:
+ New-SPSite -Url “http://company/sites/NewSiteName&#8221; -OwnerAlias “UserID”
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Microsoft.Share…SPCmdletNewSite:SPCmdletNewSite) [New-SPSite], NullReferenceException
+ FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletNewSite

You still can create a new site collection if you explicitly specify the Content DB name in the New-SPSite command

Also, subsequently if you run SharePoint Product Configuration Wizard fails on step 9 with the following error:
09/14/2017 16:43:43.45 OWSTIMER (0x23E4) 0x178C SharePoint Foundation Upgrade SPHierarchyManager ajyw5 ERROR Attempt to register null pointer at:    at Microsoft.SharePoint.Upgrade.SPHierarchyManager.AddNextLevelObjects(Object current, IEnumerable nextObjects)     at Microsoft.SharePoint.Upgrade.SPHierarchyManager.Grow(SPTree`1 root, Boolean bRecursing, SPDelegateManager delegateManager)     at Microsoft.SharePoint.Upgrade.SPHierarchyManager.Grow(SPTree`1 root, SPDelegateManager delegateManager)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.NeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.ReflexiveNeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.NeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.ReflexiveNeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.NeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.ReflexiveNeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.NeedsUpgrade(Object o, Boolean bRecurse)     at Microsoft.SharePoint.Administration.SPServerProductInfo.DetectLocalUpgradeStatus()     at Microsoft.SharePoint.Administration.SPServerProductInfo.DetectLocalProductVersions(SPProductVersions prodVer)     at Microsoft.SharePoint.Administration.SPServerProductInfo.UpdateProductInfoInDatabase(Guid serverGuid)     at Microsoft.SharePoint.Administration.SPUpgradeJobDefinition.Execute(Guid targetInstanceId)     at Microsoft.SharePoint.Administration.SPAdministrationServiceJobDefinition.ExecuteAdminJob(Guid targetInstanceId)     at Microsoft.SharePoint.Administration.SPTimerJobInvokeInternal.Invoke(SPJobDefinition jd, Guid targetInstanceId, Boolean isTimerService, Int32& result)     at Microsoft.SharePoint.Administration.SPTimerJobInvoke.Invoke(TimerJobExecuteData& data, Int32& result)  . 9c44199e-c716-7014-4bcb-6f3921ecc9f6

Identifying the issue:

Getting content databases shows the $null value as one of the content DBs. Yes, is a case of an orphan DB.

 
Get-SPWebApplication | SELECT ContentDatabases

ContentDatabases
—————-
{$null, Content_DB1, Content_DB2…}

All we need is to get a GUID of the DB and delete it from the configuration, but PowerShell does not show any  $null content db:

$webapp = Get-SPWebApplication http://company
$webapp.ContentDatabases | Select Id, Name
Id Name
—-
7ed114d7-6b90-4fae-8f1a-81ea0fc744a9 Content_DB1
f638999c-9075-4726-aeaa-c4ea6dd6d8f4 Content_DB2
fea346c5-1f47-485f-8959-47ebe3996469 Content_DB3

 

Solution:
To get the GUID of the null database we need to go dipper into the belly of the beast called SharePoint and get that information.
1.  we need to get the GUID of the Web Application with the orphaned database:

 
$webapp = Get-SPWebApplication http://company
$webapp.Id 

2. we need to get the Web Application configuration in XML format directly from SQL Server by running the following query against the Configuration DB:

 
SELECT TOP [Id],[ClassId],[ParentId],[Name],[Status],[Version],cast([Properties] as XML) FROM [SharePoint_Config].[dbo].[Objects] (nolock) where Id = ‘GUID of the Web Application found in Step 1’ 

3. Search for null value in SPContentDatabaseCollection type. The GUID of it is the GUID of an orphaned DB.

4. Back to PowerShell. Delete the Database with the GUID found in step 3 in configuration:

 
$webapp = Get-SPWebApplication -identity http://company
$webapp.ContentDatabases.Delete("GUID found in step 3")

Problem solved.

That was another page in the Chronicles of SharePoint Bits, happy scripting!