SharePoint Crawls and Security Updates

Keeping an eye on my SharePoint crawls, I noticed some crawls were taking a long time.
The crawls were picking up a few items, but then I noticed the number of security updates.

Thanks to my friend Google, I found this posting on the subject.

A clip from the posting:

Question:

Why do security only crawls take so long?

Answer:

The time difference in crawl can be attributed to expansion of the SharePoint Group and also that the group is at the site collection level and affects items beyond the list. If a Sharepoint group has several thousand users at site collection level, you can see how this can be very expensive. Also, a large number of items within that site collection can add to the delay because new ACL changes will be pushed down to every item affected by the security change.

Question:

How can I work around this and prevent security only crawls from affecting incremental crawl times?

Answer:

Instead of users explicitly added to SharePoint groups, add AD groups instead. Managing adding/removing users from Active Directory security groups will not cause ACL changes within SharePoint. Because of this, no security only crawls will occur.

*Update*

Read this:

http://blogs.msdn.com/b/kaevans/archive/2013/05/06/clarifying-guidance-on-sharepoint-security-groups-versus-active-directory-domain-services-groups.aspx

Modify Search Topology Stuck on Processing

More than once I’ve had this happen. For one reason or another, a change to the SharePoint Search Topology needed to be made.

Go in, add a new crawler or partition index, click save, and the page gets stuck on

Processing….
Please wait while your changes are processed for SharePoint Server Search.

sharepoint-search-stuck-processing

Okay, one thing I’ve found to help avoid this issue. Make sure the SharePoint Admin service is running on each box in the farm BEFORE making any updates to the search topo.

Fix:

Navigate to timer job definitions.
http://YourCentralAdminSite/_admin/ServiceJobDefinitions.aspx

Change the View to Service
then change
Service: SharePoint Server Search

Run the Configuring the existing search service application SharePoint Server Search job.

Go back and check the modify topology page.

Remember, make sure the Admin Service is running!

*NOTE*
In the comments, user SM pointed out that the Configuring the existing search…. job may not appear unless it needs to be executed.

SharePoint Not Crawling List or Library

SharePoint search results were not correct or would be missing some data. After hours of digging around, I noticed that one Search Scope was empty. To try and fix this, I went as far as reseting the search index, yes, clearing out all the search data. No fun!

Here is what I found to work.

List Settings
Allow items from this list to appear in search results?
Change this to NO
Run a crawl on the Content Source.
Go back to List Settings.
Allow items from this list to appear in search results?
Change this to YES
Run a crawl on the Content Source.

My Search Scope filled up.
Search was working again!

EDIT –
I first wrote this post back in 2013, and Microsoft has made a change in how this works.

Reindex a sit

  1. On the site, select Settings Settings icon., and then select Site settings. If you don’t see Site settings, select Site information, and then select View all site settings.
  2. Under Search, select Search and offline availability.
  3. In the Reindex site section, select Reindex site.
  4. A warning appears, check the box before Please check this box to acknowledge and agree to the statement above. Select Reindex site again to confirm. The content is reindexed during the next scheduled crawl.

Reindex a document library or a list

  1. On the site, go to the list or library that you want to reindex.
  2. In the upper right corner, selet Settings, and then choose Library Settings or List Settings.
  3. On the Settings page, under General Settings, choose Advanced settings. If you don’t see the Settings page, you may need to choose More library settings or More List settings.
  4. Scroll down to Reindex Document Library or Reindex List, and select the button. A warning appears. Select the button again to confirm. The content is reindexed during the next scheduled crawl.

https://learn.microsoft.com/en-us/sharepoint/crawl-site-content

Cannot Undeclare Record in SharePoint

Using SharePoint Records Management, I declared a document as a record.  Then I tried to undeclare the document as a record.  For some reason SharePoint wouldn’t not undeclare the document.

Using PowerShell, you can force the undeclare action.

#Load the sharepoint snapin
$SPWeb = Get-SPWeb "http://sharepointed.com/sites/taco" 
  
$SPList = $SPWeb.Lists["Taco Recipes"]   
$SPItem = $SPList.GetItemById("75")     

#new code to remove hold first    
$SPItem.Properties.Remove("ecm_ItemLockHolders")
$SPItem.File.Properties.Remove("ecm_ItemLockHolders")   
$SPItem.SystemUpdate()    

#undeclare the record
[Microsoft.Office.RecordsManagement.RecordsRepository.Records]::UndeclareItemAsRecord($SPItem)

 

Doing this will remove the lock from the document.

Use PowerShell to Update Item Permssions in SharePoint

What if you want to update the item permissions on every item in a list or library, BUT you don’t want to trigger an associated workflow?

Why?

Request came in to add a new SharePoint group to all the items in a library.  Options were to update EVERY item in the library and let the workflow update the permissions, update the items ONE AT A TIME…

OR

Use PowerShell to update item permissions and not stress the server(s).


# add powershell snapin
$web = Get-SPWeb -Identity "http://sharepointed.com"
$list = $web.Lists.TryGetList("Taco Time")
$group = "Taco Makers"
$PermissionLevel = "Read"

#get site group and setup permission/role
$group = $web.Groups[$group]
$roleAssignment = new-object Microsoft.SharePoint.SPRoleAssignment($group)
$roleDefinition = $web.RoleDefinitions[$PermissionLevel];
$roleAssignment.RoleDefinitionBindings.Add($roleDefinition);

if ($list -ne $null)
{
	foreach ($item in $list.Items)
	{
		if ($item.HasUniqueRoleAssignments -eq $False)
		{
			$item.BreakRoleInheritance($True)
		}
	       
                if ($web.SiteGroups[$group] -ne $null)
		{
			$item.RoleAssignments.Add($roleAssignment)
		}
		else
		{
			Write-Host "Group is not valid."
		}		
	}
}
$web.Dispose()

Update People Picker Using PowerShell

Recently had a new domain added to our forest. After this happened, users would see duplicate values in the SharePoint people picker. The values would both look like John Doe and John Doe, but their underlying domains were different. This caused all sorts of fun when people started emailing “john doe can’t access my site.”

To fix this, the people picker property for each web application in the farm needed to be updated.

There are a lot of properties and options that you can update. I’m only updating my people picker to show one domain.

More on the people picker:
http://msdn.microsoft.com/en-us/subscriptions/cc263012(v=office.12).aspx


#add the powershell snapin

$contentWebAppServices = (Get-SPFarm).services |
 ? {$_.typename -eq "Microsoft SharePoint Foundation Web Application"}

foreach($webApp in $contentWebAppServices.WebApplications)
{
 Set-SPSite $webApp.Url -UserAccountDirectoryPath "DC=YourDomain,DC=Com"
}

What I’m doing is getting all the web applications in the SharePoint farm.  Looping through the applications and updating the people picker.

InfoPath Dynamic Hyperlink Field C# and Code Behind

In InfoPath, dynamically update a hyperlink field using code.
Sounded simple, but it took me a few minutes to get it straightened out.

I’ve attached the InfoPath form and the code behind files here: http://www.sharepointed.com/wp-content/uploads/2012/12/Dynamic_URL1.zip

Create a new Blank InfoPath form.

Add a Hyperlink control to the form.

In this step, I’ve set the field to Read-Only. Why? I didn’t want the user to be able to modify the field.

Change the field names. The first field (field1) is the field that will hold the URL path. The second field (field2) will hold the text that you want to display in place of the URL.

I’ve updated my fields as follows:
field1 changed to URLpath
field2 changed to URLdisplay

To quickly test this post, click on the Developer tab, then click Loading Event.

        public void FormEvents_Loading(object sender, LoadingEventArgs e)
        {
            XPathNavigator ipFormNav = MainDataSource.CreateNavigator();
            XPathNavigator assnAttachURL = ipFormNav.SelectSingleNode("/my:myFields/my:URLpath", NamespaceManager);
            XPathNavigator assnAttachDisplay = ipFormNav.SelectSingleNode("/my:myFields/my:URLpath/@my:URLdisplay", NamespaceManager);

            //Update the URL path to a document on your site.
            assnAttachURL.SetValue("http://sharepointed.com/library/taco.xlsx");
            assnAttachDisplay.SetValue("taco");
        }

To get the correct XPath values, see the screenshot below.

To see this work, in the code editor, click on Build, then Start Debugging.

Use PowerShell to Check SharePoint Library Version History

Randomly ran across a library that a user had jacked versioning up to 99 versions.

So, how do you audit every list and library in a web app / site collection / site.

In the script below, I set the write-host to only be triggered if major or minor versions is greater than 20.

$siteURL = "http://webapp1.sharepointed.com/"
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication

foreach($site in $spWebApp.Sites)
{
	foreach($s in $site.AllWebs)
	{
		foreach($l in $s.lists)
		{
			$maj = $l.MajorVersionLimit
			$majMinor = $l.MajorWithMinorVersionsLimit
			
			if(($maj -gt 20) -or ($majMinor -gt 20))
			{
				Write-Host $s.Url
				Write-Host $l.Title
				Write-Host "Major: " $maj
				Write-Host "Minor: " $majMinor
			}
		}
	$s.Dispose()
	}
}

JQuery Total Calculated Column in SharPoint 2010

Working off Paul Grenier’s post JQuery for Everyone: Total Calculated Columns and some hair loss, I got this working in SharePoint 2010.

Need to sum / total a calculated column in SharePoint 2010, here is the answer.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script> 
<script type="text/javascript">
function addCommas(nStr) {//formats number
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}
$(function() {//sums money in specific list column
	var col = 2; //which column to sum
	var m = "$"; //change to "" for non-money format
	var headers = $("table.ms-listviewtable:first> tbody> tr:first th").get();
 	var arrayList = $("table.ms-listviewtable:first> tbody> tr:gt(1)").find(">td:eq("+col+")").get();
	var x = 0;
	var p1 = "";
	var p2 = "";
	$.each(arrayList, function(){
		x += Number($(this).text().replace(/\$|,|\)/g, "").replace(/\(/g,"-"));
	});
	if (x < 0) {//format for negative numbers
		p1 = "(";
		p2 = ")";
		x = Math.abs(x);
	}
	
	$(".ms-listviewtable:first> tbody> tr:eq(1)").find(">td:eq("+col+")")
		.css("text-align","middle")
		.html("<b>Total = "+p1+m+addCommas(x.toFixed(2))+p2+"</b>");
});
</script>