Friday, December 07, 2018

SharePoint 2013 - Search Index partition error - a yellow triangle

If something goes wrong with SP 2013 or your Search you will see Search Index partition error. This error some times comes when we restore Search Databases too. This means there is something wrong with the index partition on that particular search server.


I have seen many post and resolution on resolving the SharePoint Search Index partition error - a yellow triangle. I would recommend following solution before you can try to reset Index or even try to re-create the Search Service application from scratch. Definitely when it comes to Production both the solution stated above will be time consuming and lengthy downtime if you have millions of items to be crawled.

Try following:
  1. Log on to the Search Server where partition has error.
  2. Clear the SharePoint Server Cache. 
    1. Stop SharePoint Timer Service.
    2. Browse to %SystemDrive%\ProgramData\Microsoft\SharePoint\Config
      Note: ProgramData folder is a hidden folder.
    3. Select the Guid folder which was recently modified.
    4. Select and delete all the XML files except the Cache.ini file.
    5. Open and Edit the Cache.ini file and set it to 1.
    6. Start SharePoint Timer Service.
    7. Verify the XML files start populating again. wait for few minutes
      Note: You can compare the number of files from another healthy server in your farm else wait for few minutes till all files are recreated.
  3. Restart the "SharePoint Server Search 15" service in Services.msc
  4. Wait for few more minutes and you wont see a yellow triangle - a partition error.
    Note : You should see the Search Index folder growing in its size.
If Indices are not corrupted then after clearing cache and restarting the service, your Topology should show up just fine with all green tick marks under all the components.



Thursday, October 25, 2018

SharePoint 2013 - Exception while trying to migrate account 'xxxxxxxx\ksxxx' to 'xxxxxxxxx\ksxxx'

After successful configuration of User Profile Synchronization Service. I encountered another problem in the event viewer as below.

 "System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AggregateException: One or more errors occurred. ---> Microsoft.Office.Server.UserProfiles.UserProfileException: Exception while trying to migrate account 'xxxanie\kstpe' to 'xxxANIES\kstpe'. ---> Microsoft.SharePoint.SPException: The user does not exist or is not unique. ---> System.Runtime.InteropServices.COMException: The user does not exist or is not unique.0x81020054

I checked with my IT team and yes DomainNetBIOS name was different then FQDN Domain. Some suggested to recreate the User Profile service. I really didn't want to recreate the User Profile service.

NetBiosDomainNamesEnabled is a property that is set on every User Profile Application. By default, this value is set to false which means that you must set it to true in the scenario where the domain netbios\FQDN names are different.

I tried setting this NetBiosDomainNamesEnabled property to true and tried to re-sync the profiles but it did not resolved the above error. To use the domain NetBIOS name, a new synchronization connection must be created and used. This means that you can’t use the existing synchronization connection.

Please follow below steps to resolve the above issue.
  1. Delete existing Synchronization Connections
    Central Admin > Application Management > Manage Service Applications > User Profile Service Application > Configure Synchronization Connections

    Delete the appropriate existing connection.
  2. Run the Following PS1 command to enable NetBiosDomainNamesEnabled 

    Get-SPServiceApplication
    # (lists the Service Applications and their GUIDs)
    $UPA = Get-SPServiceApplication –Id
    $UPA.NetBIOSDomainNamesEnabled=1
    $UPA.Update()
  3. Recreate the Connection 
  4. Restart IIS 
  5. Run Full Profile Syncronize
    Central Admin > Application Management > Manage Service Applications > User Profile Service Application > Start Profile Syncronisation

    Select "Start Full Synchronization" option and click ok.
  6. All user profiles will be corrected.
  7. You can see the progress by running miisclient.exe
    Location: C:\Program Files\Microsoft Office Servers\15.0\Synchronization Service\UIShell

    Note: Make sure you see following things in sequence in miisclient.exe



Thursday, September 13, 2018

ShaREPoint 2013 : Profile photo not showing in mysites and search results

Many times when we rebuilt the User Profile service or Restart the User profile service, We loose the functionality of showing the user profile photo in search results or in mysites.

Errors:




Few things need to be checked here:

  • Metadata Property 
    1. Make sure Metadata Property Mappings for the PictureURL property in Search Service Application is default to "ows_PictureURL(Text), People:PictureURL(Text)".
    2. if not then add it and run the Search full crawl.
  • Import Photos or update Thumbnails in Photo Store (mostly comes after upgrade)

    Run the Update-SPProfilePhotoStore cmdlet to ensure that the SharePoint profile photo store is compatible with SharePoint Server. whenever this cmdlet used, three thumbnail versions with predictable sizes and names are created from the original photo, the new photos are placed into the My Site Host's User Photos library, and the property value in the profile database is updated

    Update-SPProfilePhotoStore -MySiteHostLocation

    OR

    Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1 -MySiteHostLocation

    This will resolve your first issue of phot being not displayed in mysites.
  • Enabled Cross-Domain feature

    The Search result page uses "proxy" page userphoto.aspx to load pictures which takes a couple of parameters; URL of the picture, the account name (or e-mail) as well as the picture size (S, M or L). This page will return a JPEG stream of the user profile picture on the client side.

    SharePoint team has added a new feature to SharePoint that allows us to show profile pictures cross-domain in search results. This option is by default disabled , you need to do is to set the CrossDomainPhotosEnabled property on the SPWebApplication object to true.

    1
    2
    3
    4
    asnp Microsoft.SharePoint.PowerShell
    $wa = Get-SPWebApplication http://intranet.xxxx.com
    $wa.CrossDomainPhotosEnabled = $true
    $wa.Update()
    This will resolve your second error on search result page.

Wednesday, August 08, 2018

SharePoint 2013 - PWA AD Synchronization error - GeneralQueueJobFailed (26000) - AdSyncERP.AdSyncERPMessage

After Installation of new Patch for SharePoint 2013, few days after i suddenly started receiving Project Web Application - Ad Syncronization error.
This started occurring for all new projects being created as well as on any attempt to synchronize the site permissions from Server Settings – Project Sites.

Due to this error users could not access any of the affected sites. There was no errors connecting the AD since my User Profile Service Application was running fine and getting sync everyday.








Error Message
  • GeneralQueueJobFailed (26000) - AdSyncERP.AdSyncERPMessage. Details: id='26000' name='GeneralQueueJobFailed' uid='1a562258-c32d-e911-80ed-005056827509' JobUID='b5288351-xxxx-xxxx-80ed-005056827509' ComputerName='XXXXXXXX-411c-45a4-98c8-c87005e63efe' GroupType='AdSyncERP' MessageType='AdSyncERPMessage' MessageId='1' Stage='' CorrelationUID='7dd5be9e-510e-XXXX-XXXX-e8492f101fa4'. For more details, check the ULS logs on machine XXXXXXXX-411c-45a4-98c8-c87005e63efe for entries with JobUID b5288351-xxxx-xxxx-80ed-005056827509.

And in the ULS log we see some more details:

Microsoft.Office.Project.Server (0x0770) 0x2E80 Project Server                Queue                          ad3fy Critical Standard Information:PSI Entry Point:   Project User:   Correlation Id:   PWA Site URL:   SA Name:   PSError: A queue job has failed. This is a general error logged by the Project Server Queue everytime a job fails - for effective troubleshooting use this error message with other more specific error messages (if any), the Operations guide (which documents more details about queued jobs) and the trace log (which could provide more detailed context). More information about the failed job follows. GUID of the failed job: 84b1d856-xxxx-xxxx-8115-005056891468. Name of the computer that processed this job: xxxxxxxx-e8d6-482c-b869-521681f05f8f (to debug further, you need to look at the trace log from this computer). Failed job type: AdSyncERP. Failed ... d305be9e-4196-xxxx-xxxx-d245e095323c

Microsoft.Office.Project.Server (0x0770) 0x2E80 Project Server                Queue                          ad3fy Critical ...sub-job type: AdSyncERPMessage. Failed sub-job ID: 1. Stage where sub-job failed:  (this is useful when one sub-job has more than one logical processing stages). d305be9e-4196-xxxx-xxxx-d245e095323c


After searching net I found people are getting similar log messages but with the some user name mentioned it. The resolution was simple just remove those user displayed in log messages. but If you see i highlighted some part of message "".  Most of the times the "" part has user name for which the job was failing. but in my case it wasn't showing up any users. 

I had word with AD team and raise a ticket to remove all disabled users. Removing the users from AD Group immediately corrected the issue! Phew. 

Tuesday, July 10, 2018

Replace SharePoint attachment icons with hyperlink names in list view webpart

Many times we allow users to upload attachment to the list items.

However if you add the "Attachments" column to your list views, you get a column that only shows a icon (see below) if there are any attachments.

fig 1.1

Clicking that paperclip also won’t open any attachment or the list item to open the document in new window. It’s strictly an image. Here’s a way to replace that icon on each row with the actual name of your attachment linked to the actual attachment. If there are more than 1 document attached then it displays all documents links with name and link to open it.

Download this below code, or copy and paste it into a new file in your Site Assest folder as ShowAttachments.js:

(function () {

    // Create object that have the context information about the field that we want to change it output render  

    var attachmentsFiledContext = {};

    attachmentsFiledContext.Templates = {};

    attachmentsFiledContext.Templates.Fields = {
         
        "Attachments": { "View": AttachmentsFiledTemplate }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(attachmentsFiledContext);

})();


// This function provides the rendering logic for list view 
function AttachmentsFiledTemplate(ctx) {
    var itemId = ctx.CurrentItem.ID;
    var listName = ctx.ListTitle;       
    return getAttachments(listName, itemId);
}

//get attachments field properties
function getAttachments(listName,itemId) {
  
    var url = _spPageContextInfo.webAbsoluteUrl;
    var requestUri = url + "/_api/web/lists/getbytitle('" + listName + "')/items(" + itemId + ")/AttachmentFiles";
    var str = "";
    // execute AJAX request
    $.ajax({
        url: requestUri,
        type: "GET",
        headers: { "ACCEPT": "application/json;odata=verbose" },
        async: false,
        success: function (data) {
            for (var i = 0; i < data.d.results.length; i++) {
                str += "" + data.d.results[i].FileName + "";
                if (i != data.d.results.length - 1) {
                    str += "
";
                }                
            }          
        },
        error: function (err) {
            //alert(err);
        }
    });
    return str;
}

Edit the List view page on which you want to add above functionality.

Edit the list view webpart > miscellaneous > Js Link

If you have already refer "jquery-1.11.1.min.js" in your master page then just refer ShowAttachments.js else Add following URL into the JS Link text box.

~site/SiteAssets/jquery-1.11.1.min.js|~site/SiteAssets/showAttachments.js
Final result will be this:



Thursday, June 07, 2018

SharePoint 2013 - Column Default Value setting page throws an error after creating new list using existing list template

Column default value settings - Throwing "Sorry Something went wrong" error.

I've tried to adjust 'Column default value settings ' and upon clicking the link in Document Library Settings the familiar error dialog box appears 'Sorry Something went wrong'

I checked the Log and found below error.

System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string.  Parameter name: startIndex    at System.String.Substring(Int32 startIndex, Int32 length)     at Microsoft.Office.DocumentManagement.MetadataNavigation.PerLocationViewManager.HumanReadablePath(SPList list, Guid fieldId, String uniqueNodeId, String pathDelimiter)     at Microsoft.Office.Server.WebControls.MetaDataNavTree.TreeViewDataBound(Object sender, EventArgs e)     at System.Web.UI.WebControls.BaseDataBoundControl.OnDataBound(EventArgs e)     at Microsoft.Office.DocumentManagement.MetadataNavigation.MetadataNavigationContext.OnTreeViewLoad(SPTreeView spTreeView)     at Microsoft.Office.Server.WebControls.MetaDataNavTree.PerLocationPageLoad()     at Microsoft.Office.DocumentManagement.Pages.ColumnDefa... 1959bd9e-813e-a0e8-05f8-fd58ef93f9c2


...ultsPage.OnLoad(EventArgs e)     at System.Web.UI.Control.LoadRecursive()     at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) 1959bd9e-813e-a0e8-05f8-fd58ef93f9c2

Other libraries in the site collection/ web was working fine. I thought of creating them again manually and dropped the plan since it was having 15000 items in it. I wanted to have a quick solution as it was production.

This seems to happen when you have a library where you have set values for "Column default value settings".  When you then save this library as a template and create a new document library from it, you get the error when you go to"Column default value settings" in the new library. I was doing the same creating new library using existing library which had column default value set. I rechecked the original list and found out that it has Column default setting set. was there any problem when i created new list using template.

To fix, follow below steps:

  1. Open the site in SharePoint Designer 
  2. Go to "All Files".  
  3. Browse to the document library with the error.
  4. Open up the Forms folder.  
  5. In there you will see a file called client_LocationBasedDefaults.html.  
  6. Edit the you will see this file appears to contain the settings for the Column Default Settings, but you will see the url is still pointing to the old doc lib url and so hence why it now errors. just change the URL to new library. (Note: you can delete this file and it will allow to re-create the column default setting, but i recommend to edit the url otherwise you will loose the column default setting)  

Thursday, May 10, 2018

SharePoint 2013 - Files and Folders to be excluded from Antivirus Scanning when you use file-level antivirus software in SharePoint

Most of organization scans their servers with System Center Endpoint Protection. In an effort to improve our security and reduce our risk of an infection on various servers in organization. SCCM, the tool that manages the Anti-malware environment, is set up to search for servers with SharePoint Server installed

Mostly quick scans will scheduled daily and should complete within approximately 15 minutes.  This will help ensure the scan is completed before working hours. The Quick scan only scans resident memory and critical OS files. Also, All incoming files will be scanned automatically to protect systems after the full scan is completed and to compliment the Quick scans.

To minimize performance impacts mostly Microsoft and vendors recommends some file and folder exception. As SharePoint Administrator, IT team might ask you to provide certain folders that may have to be excluded from antivirus scanning when you use file-level antivirus software in SharePoint.

More information can be found at below link for SharePoint Servers. Refer below article and prepare the List of folders for each farm admin account and Search Index folder on Search Servers.

https://support.microsoft.com/en-us/help/952167/certain-folders-may-have-to-be-excluded-from-antivirus-scanning-when-y


Wednesday, March 21, 2018

SharePoint 2013 - Execute Search Query using Powershell for large number of results

I recently came across the need to provide a report of specific Content Types documents using SharePoint 2013 Search. Content Search Web Parts does this, however, there is no out-of-the-box method to export your search results to a spreadsheet. you can definitely copy from page to .CSV file but this will not help if there are more items (in thousand's). If your search yields anything above just a couple of pages you’re looking at a lengthy, time consuming, and very boring, task.

Of course there is way, PowerShell to the rescue!. PowerShell saves my lot of time. I will rather spent some time to create powershell so that it will be useful in other senarios too. However, with my latest engagement being primarily focused on the administration side of things, I had finally sat down and really dug into PowerShell, something I’ve been meaning to do for quite some time. PowerShell makes short work of tasks such as the one demonstrated here.

Remember you wil get most of the example on the internet which has powershell to export the search results into csv file. but believe me guys these examples always assumes that your results are less than 10-20 rows. what if you have thousands of rows which need to be exported? the answer is still powershell but there is smart way to use it.

After doing some research I came up with the following reusable script:

Step 1 : Scripts Parameter

#input parameters
param
(
[string] $siteUrl = "https://sharepointdev.company.com", # Web Application URL
[string] $outputPath = ".", # Log File
[string] $queryText = 'ContentTypeId:0x0101009E3C6E67A2CF4261807753FA8CF19B5F*'

Step 2 : Add Snapin

if ((Get-PSSnapin -Name "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null )
{  
    Add-PsSnapin "Microsoft.SharePoint.PowerShell"
}

Step 3 : Set File Path

$csvFilePathTo = "$outputPath\Documents.csv"
$logFilePathTo = "$outputPath\Documents_Log.txt"

set-variable -option constant -name filename -value $csvFilePathTo
set-variable -option constant -name outputFile -value $logFilePathTo # Log File

Step 4 : Set keywordquery object

# new keywordquery object
$site = New-Object Microsoft.SharePoint.SPSite $siteUrl
$query = New-Object Microsoft.office.Server.Search.Query.KeywordQuery $site

# set ResultTypes
$query.ResultTypes = [Microsoft.Office.Server.Search.Query.ResultType]::RelevantResults

# set number of items to return
$currentIndex = 1

#$query.StartRow = $currentIndex
$query.RowLimit = 500
$query.TrimDuplicates = $true;
$query.Timeout = 600000; #10 Minutes

write-host 'Timeout: ' $query.Timeout

# actual string you are searching for

$query.QueryText = $queryText

Step 5 : Set the Properties you want to retrieve

# get all the extended properties for query
$selectProperties = $query.SelectProperties;

$selectProperties.Add(“SiteName”)
$selectProperties.Add(“Path”)
$selectProperties.Add(“ListName”)
$selectProperties.Add(“Title”)
$selectProperties.Add(“Author”)
$selectProperties.Add(“AuthorOWSUser”)
$selectProperties.Add(“DisplayAuthor”)
$selectProperties.Add(“PostAuthor”)
$selectProperties.Add(“Created”)
$selectProperties.Add(“CreatedOWSDate”)
$selectProperties.Add(“ModifiedBy”)
$selectProperties.Add(“LastModifiedTime”)
$selectProperties.Add(“ModifiedOWSDate”)

$selectProperties.Add(“ContentTypeId”)

Step 6 : Get results first time in temporary table

# execute the query
try
{
    $resultTableColl = $query.Execute()
}
catch
{
    # update log files
      "timeout Error Occured `r`n" | Out-File $outputFile -Append
    $resultTableColl = $query.Execute()
}

# get the results back
$resultTable = $resultTableColl.Item([Microsoft.Office.Server.Search.Query.ResultType]::RelevantResults)
write-host $resultTable.TotalRowsIncludingDuplicates
# make a DataTable from the results

$resDataTable = $resultTable.Table 

Step 7 : Loop through the results till all results traversed

###########################################################################
# Loop through the results and append all results into $resDataTable
###########################################################################
do
{
    #write-host $resultTable.TotalRows
    $currentIndex += $resultTable.Table.Rows.Count
    write-host $currentIndex
    $query.StartRow = $currentIndex
    # execute the query
    $resultTableColl = $query.Execute()
    # get the results back
    $resultTable = $resultTableColl.Item([Microsoft.Office.Server.Search.Query.ResultType]::RelevantResults)
   
    if($resultTable.Table.Rows.Count -le 0)
    {
        break;
    }
    else
    {
        # make a DataTable from the results
        $resDataTable.Merge($resultTable.Table)
    }   

    # use below block is for testing purpose only
    # if results are more than 500 then this loop will run only one time 
    if($resDataTable.Rows.Count -gt 500)
    {
        
         # Un-comment the next line to get only <=1000 results
         #break;
    }

}while($resultTable.TotalRowsIncludingDuplicates -gt $resDataTable.Rows.Count)

write-host "Total Rows Found" $resDataTable.Rows.Count

Step 8 : Traverse the table object to creates rows for csv to export

# since we have data lets format as per o/p we needed.
$RArray = New-Object System.Collections.ArrayList
$urlArray = $null
foreach($row in $resDataTable.Rows)
{   
    $urlArray = $row["Path"] -split '/'
    $DocURL = $row["Path"]
    $listTitle = $row["ListName"]
    $website = $row["SiteName"]
    $itemName = $row["Title"]
    $varcreatedBy = $row["AuthorOWSUser"].tostring().Split("|");   
     
    # Add our data to $CTDBObject as attributes using the add-member commandlet
    # Create a new custom object to hold our result.                   
    $CTDBObject = new-object PSObject -Property @{           
                                        DocumentId       = [int]($row["DocId"].tostring() )              
                                        SiteUrl          = $website
                                        Site             = $siteName             
                                        DocumentUrl      = $DocURL
                                        ListName         = $listTitle                                                                           
                                        DocumentName     = $itemName                                        
                                    }  
   
      $RecordNumber = $RArray.Add($CTDBObject
     
    $CTDBObject = $null
}

Step 9 : Export the data to CSV file


#############################################################################
# Export data in excel
$RArray | Select DocumentId, SiteUrl, Site, DocumentUrl, ListName, DocumentName | Export-csv $filename  -NoTypeInformation


Save step 1 to 9 in one file name as "SearchDocuments.ps1". you can either execute ps1 file and specifiy parameter on the fly or else create  a batch file and specify the parameter in that file.

e.g.
Batchfile name: SearchDocuments.bat
Batchfile contents:

SET ThisScriptsDirectory=%~dp0
SET SiteURL=https://sharepointdev.company.com
SET Enivironment=Prod
SET outputDirectory=\\sharepointdev.company.com\reports


PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%ThisScriptsDirectory%SearchDocuments.ps1' '%SiteURL%' '%outputDirectory%' 'ContentTypeId:0x0101009E3C6E67A2CF4261807753FA8CF19B5F*' "