Showing posts with label SharePoint. Show all posts
Showing posts with label SharePoint. Show all posts

2016-10-07

SharePoint 2016 Application Pools and Other Processes Stop Immediately After Starting

At one point of developing SharePoint 2016 Farm solution on my dev machine SharePoint application pools, namely web application pool and CA application pool, started to crash on start. I restarted the server and then all of a sudden no SharePoint services (SharePoint Timer Service, SharePoint Tracing Service) could be started.

All google results pointed to faulty application pool account. I double checked that account was not locked and had appropriate perms. No luck there.

System Event log was full of events 5002, 5009 and 5011.

After inspecting a situation with Process Monitor we pin pointed an error to missing HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\16.0\Location value in the registry. After adding C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ data to Location value all services went back online after server restart.

Only change in server configuration that day was installment of Microsoft Office Professional Plus 2016. I don't have time to investigate what caused deletion of aforementioned value in registry but I am eager to find out.

Hopefully, I will edit this post if I find out more details.

2016-05-02

OpenQuery Failed with status ID: 0x800007d0

ULS on my clients' farm was polluted by messages "OpenQuery Failed with status ID: 0x800007d0" every few seconds.

Turns out I had to add user which is running mssearch.exe process (SP_Search in my case) to local group called Performance Monitor Users. After adding the user I rebooted the machine and the problem went away.

2014-08-20

Implementation of ribbon button availability by calling asynchronous methods

It is known that SharePoint ribbon can be extended by implementing CustomAction Ribbon.Library.Actions.AddAButton. SharePoint allows you to dynamically control whether this ribbon button should be enabled. This is done by implementing Javascript logic in CommandUIHandler's EnabledScript attribute.

The problem is if you want to include asynchronous call in aforementioned attribute because this Javascript block must return boolean value. So, when SharePoint calls asynchronous method it will not get the result immediately. Instead, it will get the result of async call in callback function but it's too late, Javascript block has already returned.

The solution to this problem was very well described by Andrew Connell on his blog post. Since no code snippets were included in this post I decided to provide it here because there is one caveat that is not so obvious from first look at the Andrew's post.

This is the implementation of ribbon button in Elements.xml:

    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition
          Location="Ribbon.Library.Share.Controls._children">
          <Button Id="Ribbon.Library.Share.NewRibbonButton"
                  Command="NewRibbonButtonCommand"
                  Image16by16="/_layouts/15/Style/buttonIcon16.png"
                  Image32by32="/_layouts/15/Style/buttonIcon32.png"
                  LabelText="New case"
                  ToolTipTitle="Get new case."
                  ToolTipDescription="Assigns new case to you."
                  TemplateAlias="o2" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
          Command="NewRibbonButtonCommand"
          EnabledScript="javascript:IsCurrentUserMemberOfGroup('puk ref');       
       "/>
      </CommandUIHandlers>
    </CommandUIExtension>

Since our project doesn't include customized forms nor master pages we had to include external Javascript file to Elements.xml:

  <CustomAction
   ScriptSrc="/_layouts/15/Scripts/SPRibbonHelperScript.js"
   Location="ScriptLink"
   Sequence="1001">
  </CustomAction>

This makes it easier to debug the solution if Javascript code is included in external file. Prerequisite for this step is to add new Javascript file to layouts mapped folder.

Next piece of code is the actual implementation of enabling/disabling the button based on current user's group membership in SPRibbonHelperScript.js:

var isMemberOfGroup = false;

function IsCurrentUserMemberOfGroup(groupName) {
    var currentContext = new SP.ClientContext.get_current();
    var currentWeb = currentContext.get_web();
    var currentUser = currentContext.get_web().get_currentUser();
    currentContext.load(currentUser);

    var allGroups = currentWeb.get_siteGroups();
    currentContext.load(allGroups);

    var group = allGroups.getByName(groupName);
    currentContext.load(group);

    var groupUsers = group.get_users();
    currentContext.load(groupUsers);
    currentContext.executeQueryAsync(OnSuccess, OnFailure);

    function OnSuccess(sender, args) {
        var userInGroup = false;
        var groupUserEnumerator = groupUsers.getEnumerator();
        while (groupUserEnumerator.moveNext()) {
            var groupUser = groupUserEnumerator.get_current();
            if (groupUser.get_id() == currentUser.get_id()) {
                userInGroup = true;
                break;
            }
        }

        if (isMemberOfGroup == false || isMemberOfGroup == 'undefined') {
            if (userInGroup == true) {
                isMemberOfGroup = userInGroup;
                RefreshCommandUI();
            }
        }
    }

    function OnFailure(sender, args) {
    }

    return isMemberOfGroup;
}