Changing Domain and Changing SharePoint Distributed Cache Host Name

Today, I’m asked to change my SharePoint Servers to another domain. (jaw dropped). And I’m gonna share the important steps that help you to rename your existing distributed cache host name to a new host name.

I will be using the following naming for better illustration

SharePointWeb01.olddomain.com  -> SharePointWeb01.newdomain.com

As usual, you would domain disjoint, restart server, join to the new domain (using enterprise admin of the new domain). Once the server is joint to the new domain. You can instantly see many error log generated in your event viewer. This post I’m gonna cover only how to swing Distributed Cache and make it goes Live again and with assumption that you have changed the SharePoint Farm Account to a new account. (cause this is domain change activity! big task)

 

First thing first

Make sure the OLD distrbuted host name is pingable and it is still connecting back to the same server. How to do that?

Fire NOTEPAD and edit C:\windows\system32\drivers\etc\hosts

Add in your server IP with the old host name. You will then remove the old host name AFTER successfully getting the distributed cache cluster up.

 

Secondly, change the distributed cache service from the old orphan service account to a new one in the new domain.

Run the following to change the service account


$farm = Get-SPFarm
$cacheService = $farm.Services | where {$_.Name -eq "AppFabricCachingService"}
$accnt = Get-SPManagedAccount -Identity "NEWDOMAIN\NewFarmAdmin"
$cacheService.ProcessIdentity.CurrentIdentityType = "SpecificUser"
$cacheService.ProcessIdentity.ManagedAccount = $accnt
$cacheService.ProcessIdentity.Update()
$cacheService.ProcessIdentity.Deploy()

Restart-CacheCluster

## At this step you will see error but please ignore.

Get-CacheHost

## And you should see your old cache host is UP.

## Register your new Host Name

## Note the DataSource=XXX it may be different from your environment. Change it accordingly to yours.

Register-CacheHost -Provider "SPDistributedCacheClusterProvider"
-ConnectionString "Data Source=SQL;Initial Catalog=SharePoint_Config;Integrated Security=True;Enlist=False"
-Account "<NEW DOMAIN>\<NEW FARM ACCOUNT>"
-CachePort 22233 -ClusterPort 22234 -ArbitrationPort 22235 -ReplicationPort 22236
-HostName <HOST NAME of the server, SharePointWeb01>

After executing the Register-CacheHost

Kindly perform a Export-CacheClusterConfig -Path c:\cache.xml to double check cache.xml if the new FQDN of your server is showing under datacache > hosts

Should look something like that


<hosts>
 <host replicationPort="22236" arbitrationPort="22235" clusterPort="22234"
 hostId="54695588" size="781"
 leadHost="true" account="<new service account>"
 cacheHostName="AppFabricCachingService"
 name="<new and Correct FQDN e.g. SharePointWeb01.newdolmain.com>"
 cachePort="22233" />

 <!-- Together with another host that stating your OLD FQDN e.g. SharePointWeb01.olddomain.com -->
</hosts>

new host’s name should be a FQDN that you can ping and resolve right away without the need of editing HOSTS file.

Once this is done, run the final command in SharePoint Powershell console

Unregister-CacheHost -Provider "SPDistributedCacheClusterProvider" 
-ConnectionString "Data Source=SQL;Initial Catalog=SharePoint_Config;Integrated Security=True;Enlist=False" 
-HostName <the old host name e.g. SharePointWeb01.olddomain.com>

Go back to your HOSTS file and remove the old ip mapping to SharePointWeb01.olddomain.com.

 

Target Audience in Web Part Property is missing.

Or rather how to prevent Target Audience feature in Web Part from missing.

I bumped into this problem where I wanted to set a web part to show only to a certain group of users.

Checking the Web Part properties does not show the Target Audience column. The behavior of this Target Audience web part property is that it will be shown (which we thought it was supposed to be shown by default), only when there is User Profile Service Application associated to your web application. (which usually will be provisioned automatically if you configure the farm via wizard).

user profile service application association

One reason for not associating this is for to prevent user from accessing My Site when they hit “About Me” site action menu.

about me

For some reason, this will also turn off the Target Audience in the Web Part. So. In order to turn on back the target audience feature. Here are the steps.

Resolution:

  1. Go to SharePoint Central Admin
  2. Go to Application Management and hit “Configure service application associations”
  3. In your web application row, hit the application proxy group to show the associations.
  4. Tick “User Profile Service Application” and hit OK.
  5. Your web part should immediately show Target Audience property

web part property target audience sharepoint

 

WAMP SERVER is in Amber Color and cannot be started

Happened to bump into this hiccup and I thought it would be helpful to document it down.

Someone of you may have faced this error where your newly installed WAMP  cannot be started and there is no MYSQL/PHP/APACHE error log generated.

One place that I always like to check if the Event Viewer (eventvwr.msc). If you navigate to your Application Logs and happen to see this error

The Apache service named reported the following error:
>>> (OS 10048)Only one usage of each socket address (protocol/network address/port) is normally permitted. : AH00072: make_sock: could not bind to address 0.0.0.0:80 .

The Apache service named reported the following error:
>>> AH00451: no listening sockets available, shutting down .

The Apache service named reported the following error:
>>> AH00015: Unable to open logs .

Congratz! I may have a solution for you!

The above error simply means that the port 80 of your current machine is in used by another Running program…  Wait a minute.. I did not run any Web Server in my local machine.. Why would it be in used??

Step below show you how to check which program/service is using your ports

  1. Open CMD (Command Prompt) with Administrator rights
  2. Run “netstat -anob | more“. Use ” | more” in case the output is long and you need to see them page by page (hit Space to see next page of output, just so you know)
  3. Look for Local Address that contains “:80” port 80. (which is what the WAMP stack requires)
  4. You should see the executable that is using the port now. (In my Case, it was SKYPE.EXE… OKAY!! thanks for not telling me during my installation!)

 

Side Note, You can still use Skype for Business while hosting your WAMP Server. Go to Skype Option > Advanced > Connection. Uncheck the use port 80 443 for additional incoming connection.

 

SharePoint Custom Solution Branding and Tips – Part 1

Today, I want to talk about some of the good practices when it comes to SharePoint custom code development. More often than not, you would learn that SharePoint custom solution requires you to create Feature (and usually it’s automatically created when you pick any of the default SharePoint Project template e.g. Visual Web Part) to deploy your web part, style sheet, JavaScript files, or master pages.

I can understand that the Microsoft VS team is trying to help SharePoint Developers setting up a working solution as easy and as best as they could. What we need to really take note or at least be aware of is those default values assigned to the template. Below are some of the items in which I personally think that it should not be left unchanged or not thought thoroughly in order to develop a quality solution.

Namespace

Before even creating a new SharePoint 2010/2013 project, please think through the namespace that you want to use. Changing of namespace after you have tons of web parts, feature or pages will kill you. And I kid you not, using VS rename feature does not 100% guarantee you that the code will not break. I have experienced it, and it really takes you a lot of time to just renaming a namespace. (if you are new to SharePoint Development of course)

What I always like to use for namespace naming convention is as per below format

[Company Name].[Type/Name of the solution].[Sub type]

e.g. Microsoft.Branding, Microsoft.Branding.UserControls, Microsoft.Branding.DelegateControls

I would say it is not advisable to have more than 3 levels as it would introduce a very lengthy code referencing.

And I would also suggest using sub type like “UserControls”, “WebParts” or “WebPages” to organize your codes accordingly. It makes the next developer who is taking over your code easier to understand.

Feature Name

Sorry to say that this is one of the item that I dislike most when you found out that your developers did not use it correctly or not even care about changing the name of the feature!

You may not see the impact for now but once you have your code deployed to your customer’s SharePoint environment, it would really look bad and unprofessional to have this appearing in their Site Collection Feature or Manage Site Feature page.

sharepoint feature name bad practice

If you care enough, you will notice that only your custom feature’s name is ending with the numeric “1”. As if there is feature 2 and so on? LOL hell no!

Well, as a new beginner, you will likely to use the SharePoint – Visual Web Part template for a quick start.

sharepoint visual web part

What this template provides by default in the solution is the feature, package and a visual web part. Refer pic below

shareopint default feature name

Please please, remove the “1” and use a proper name.

Note that if you have already deployed your solution to production. After changing the name, you have to retract existing solution by running “Uninstall-SPSolution”, “Remove-SPSolution” and subsequently “Add-SPSolution” and “Install-SPSolution”. You should not use “Update-SPSolution” or else you will hit error deploying it.

Please also use a meaningful description. =)

Feature Image

The next thing I want to talk about is the icon of SharePoint feature. SharePoint by default assign an icon GenericFeature for your feature. As the image name suggested, it is a Generic Feature gif and in order to out stand or brand your feature, I would always like to use a custom image for my feature.

One simple reason is that it makes life easier when there is a lot of features within your SharePoint Site and you need to scroll through the entire list in order to activate or deactivate your feature.

sharepoint long list of feature

How to not miss the “EASY” icon if the color is outstanding enough. You know what I’m trying to say. Outstanding!

The following paragraph describes how you can actually add feature icon into your SharePoint Feature.

First of all, create a good icon for your feature, and put it into your SharePoint Solution.

sharepoint add images mapped folderSimply right click the project, hover to Add and click “SharePoint Images Mapped Folder” (if you already mapped, this option will be grey out)

Once you have it mapped, you can just dump your  images into the mapped image folder and it will automatically be included into your package. The relative URL of your images folder is always starting from “/_layouts/15/IMAGES/”

How to know if it is really going into that URL? You can check by looking into the Property of the Images mapped folder – Deployment Location where it stated “{SharePointRoot}\Template\Images”. This actually goes to your SharePoint 15 hives (SP2013) of your deployed server and if you look into IIS Manager for your SharePoint Web application. This folder is actually mapped as a Virtual Directory with path

sharepoint virtual directory image

Once you have your image prepared in the solution, next step is to tell your Feature to use the image. Easy. Go to your feature element files as shown below.

Simply place your cursor right before the end of the “>” tag and you should see the intellisence starting to show up. At this stage, the attribute that you would need to pick is quite self-explanatory.

sharepoint feature auto suggestion

Insert the ImageUrl. Just remember to make sure the url is correctly populated. Sample as shown below.

sharepoint feature image url example

Once you have it specified correctly, deploy it and you should see that your feature is now with your custom icon. Sample below shows not really a good example, but please use a size that you find fits.

sharepoint feature image output

 

Custom Action Group and Action

Another item that worth mentioning when doing SharePoint development is the Custom Action and Group. Since SharePoint 2010 (not sure about SharePoint 2007). It introduces a new feature where you can inject Stuff (could be links, could be Ribbon action or event Site Action) into certain area of your SharePoint pages.

Basically, the idea is that there is list of area (which it is called Location) in SharePoint where you can add/remove Stuff and within each area, there is another sub-area (which is called Group ID) if you need to further scoping down into a more specific area.

You can refer to MSDN https://msdn.microsoft.com/en-us/library/office/bb802730.aspx for Location and GroupID that you can make use of.

Things can be made easier if you need to display some custom site action or site settings link for your user to access certain page (be it your custom application page or SharePoint OOTB pages where it may not be displayed by default e.g. /_layouts/groups.aspx (Groups Page)).

I’m going to share how to go about doing it.

First of all, go to MSDN link above and identify the Location that you want to use. For the simplicity, let use Microsoft.SharePoint.SiteSettings as a example.

So let assume you want to insert a hyperlink into Site Setting page.

Go to your VS Project, Right click and add new item. Select Empty Element as shown

sharepoint empty element

Pick a nice name and hit Add. Note that once it is added, you can find a file called “Elements.xml” being added. Open it and,

Insert the following code.

sharepoint feature site setting example

 

Things that you need to note here is the GroupId and Location used. I added a Custom Action Group with a custom id, but using a valid Location. Subsequently, create another CustomAction and use the custom GroupId and the same valid Location (You still need to specify the same value as the CustomActionGroup or else it won’t work).

The Sequence in the Custom Action Group tells how earlier you want your group to be rendered in the Location. In the example above, 1 is being the first to render.

sharepoint site setting link

 

Hence it will be at the top of all existing group.

Things get a little bit complicated here if, let say other feature have used the same Sequence number as you did. In this case, the later registered ones will be displayed first.

Like example below. Group A being registered later and hence it is displayed first before the Group B.

sharepoint feature sequence does matters

 

Note that you need not to order the Custom Action xml to below Custom Action Group. SharePoint can still recognize them.

 

I have much more to share but that’s it for today! I hope above info and tips can help giving you some ideas and to be able to build a good SharePoint solution!

 

Read part 2 here

How to clear SharePoint People Picker suggestion cache

If you have been SharePoint Site owner long enough, you would have definitely bumped into task like assigning document permission using SharePoint People Picker.
One of the out of the box SharePoint People Picker features is that it auto caches all previous user entry entered/selected by you.

 

This cached people picker entity is meant to help you to quickly find the user and assign the permission.people picker cache issue
It would introduce invalid entry if there is cease of identity provider (for whatsoever reason that the decision made from the IT management needs us to swing the SharePoint identity provider to other platform).

Things could get messier for those who frequently accessing people picker, to be seeing the old cached user.

Another situation that introduce inconsistency is when there is change of user name/job title etc for which is cached and not reflecting the correct info to the end user.

 

SharePoint People Picker uses LocalStorage to cache the people picker entity. In order to flush the cache, you would need to run a JavaScript to clear the cache. What’s worst is that there is no expiration set.
If you fire up your browser development tool and type in “localStorage” (case sensitive) in the console. You would see the cache key/value for ClientPeoplePickerMRU.

hit F12: For Chrome, IE and Firefox (Note:You must be firing up the developer tool at the SharePoint Page)ie people picker localstorage

 

Chrome – Resource tab

chrome people picker localstorage

 

So what can we do?

If you are developer and techie, you can easily fire up the developer console of your browser and run the below JavaScript


localStorage.clear();

If you are helping your end user to flush the cache, one possible way is to provide them a quick custom web part using javascript above to flush their cache. Alternatively, creating a custom JS with leveraging Cookie as expiration check, put it into your home page. Whenever user accessing to your home page, this JS will check from Cookies to see if it is time to Refresh (or clear) the local storage.
The other possible way is to get them clear the Local Storage from their Browser. I couldn’t find where the IE local storage is. If you know, I will be more than happy if you can tell me.

For IE Users who wish to clear the people picker. Here are the steps you may follow
1. Go to page with people picker
2. F12 Developer Tools
a. Console
b. localStorage.clear();
3. Close F12
4. Then refresh the web page to test it.

[Credit goes to Chris for the steps above]

How to check my CPU Temperature using PowerShell Remotely

Thought it would be helpful to share how to remotely check your Computer temperature especially when you have a computer at home and you want to track if it is HOT. Just in case you don’t want to burn your computer etc etc, for whatsoever reason.

Well. Steps below show you how to do that! Make sure your client machine (the one that you are using) has PowerShell version 2.0 and above (well most of the Windows nowadays has it already). Just do a Search in your program menu and you should see it

  1. First of all, ensure your target computer (the one sitting at home that you want to check) has Firewall Turn off (not recommended). Alternatively, set Exception rules for WMI rules.
    Very briefly, go to “wf.msc” – Windows Firewall of the target computer and enable Inbound Rules for “Windows Management Instrumentation (WMI-In)” – Profile: Domain.
    remotely check cpu temperature - 1
    See detail steps here 
  2. Once firewall is cleared, make sure you have local administrator rights account that can query the CPU temperature in the target computer. (this one is simple) Fire “lusrmgr.msc” in the Run command.
    Check the “Administrators” group and make sure your account is the member.
  3. In order for you to be able to remotely check your computer temperature, you must have connectivity to your target computer. I believe there could have many way you can have connectivity to your target computer. Of what I know, the below three should be enough to fulfill the task
    1. One that I always like to use is Teamviewer. With this, you can easily establish VPN or remotely login to run the script mention in Step 4. (without specifying the -Computer and -Credential).
      Make sure when you install the Teamviewer, you have the VPN Driver installation option ticked.
    2. Allowing RDP to your target computer from public IP. In this option, you need to configure your Home Router to allow port 3389 to hit your target computer. Please go to your router admin page (usually ends of 192.168.0.1 or  192.168.1.1 depending on which is your subnet) and configure port forwarding to your private IP.
      In this way, you will be doing the same steps as option 1 where the only difference is you remotely accessing your home computer and run the script directly onto the target computer. Again, without specifying the -Computer and -Credential parameter in step 4)
    3. Option 3 is kinda most complete one and if you want to learn a little bit deeper for WMI. In this option, you will be granting DCOM port (135) and a fixed port (24158) port forwarding to your remote compute (which is accessible via public IP like what you’ve done in option 2). Refer here for how to fix WMI port.Screen shot example on how I configured the WMI to fixed port. (please pardon the typo)
      configure WMI to fixed port
      At the end of the day, your target computer but be accessible via DCOM port and WMI port from public IP.
  4. Open PowerShell via Administrator rights and run the following PS command

    Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace “root/wmi” -ComputerName “<IP of your target computer>” -Credential (Get-Credential)

    You will be prompted to specify the credential, use the account that you have administrator rights mentioned in step 2 above.
  5. You should be expecting response like screen below
    remotely check cpu temperature - 3
  6. Look for “CurrentTemperature” and the value is in Celsius

How to enable Remote Desktop for your Computer/Server

To most of the IT guys out there, I believe this is quite a common thing that you may have bumped into this and believe me, sometimes you thought you have done it right and still did not able to get it working.

Let me note that all the steps that you need to do in order to allow RDP to your Server (from some machine within the same Network).

Most people already know the step 1 and 2. What’s lacking here that you may not know is the step 3 (Fire Wall!)

FIRE~~~~ Wall FIRE~~~~ Wall

Photo credits to www.clker.com

Step 1: Allow remote connections to this computer and grant login for RDP

  1. Open RUN and enter “sysdm.cpl” and click “Remote” tabs.
    Alternatively, go to Explorer (Windows + E), right click anywhere, select Properties and click “Remote Settings” on the left panel.
  2. You should see System properties panel as shown below.
    remote desktop allow remote connections
  3. Check “Allow remote connections to this computer“.  Refer to here for option “Allow connections only from computers running Remote Desktop with Network Level Authentication (recommended)”
  4. Click “Select Users” and add in any users that you want to allow remote connection. If it is for your own usage, you may just leave this empty. In scenario where you need to allow multiple users to access your computer using different account, you need to create local user and add them here. In a even more common scenario where your computer/server is joined to a domain, you can add in the domain users account here for remote access.

Step 2: Security Policy

  1. At times, your server may need to join to a domain. Some domain policy may have configure the security policy to harden all domain servers. In this case, please check your local security policy and see if the Allow log on through Remote Desktop Services has included the login that you are gonna use. For simplicity, unless otherwise, use Administrator group of users which by default, granted permission to RDP.
  2. To check, open RUN and fire “secpol.msc
  3. Navigate the left panel to “Security Settings” > “Local Policies” > “User Rights Assignment”
  4. Look for “Allow log on through Remote Desktop Services” and see if your remote login is in this value. If not, “Please contact your server administrator” lol!

 

Step 3: Firewall!

  1. Open RUN and enter “wf.msc” (shortcut to Windows Firewall).
  2. Click “Inbound Rules” from the left panel
  3. Look for “Remote Desktop – User Mode (TCP-In)” and “Remote Desktop – User Mode (UDP-In)” and make sure they are both enabled. If not, please right click and hit “Enable Rule”

 

Once the steps above are done, open Remote Desktop Connection program (or “mstsc” in RUN), specify the computer/server IP and start RDP!

 

How to bulk insert multiple users into SharePoint People Picker

Sometimes, you will need to add permission or assign multiple users using People Picker field. This post tells you how you can insert multiple user entities using COPY (CTRL + C) and PASTE (CTRL + V).

First of you, make sure your user logins are in claims format. The reason why you need it to be in this format is that the SharePoint People Picker cannot identify of which provider the login if it is not in the full format…

Refer to link here for all the format required.

Append “;” at the back of each login

e.g.

i:0e.t|identity provider|someone@somewhere.com;i:0#.w|domainA\domainuser1;

 

Additonal Note: SharePoint People Picker allows you to quick Check Name by hitting Ctrl + K

SharePoint Permission Back Up and Restore in PowerShell

Hi SharePoint Admins! I’ve recently worked on a module to enhance SharePoint Backup experience. If you haven’t known SharePoint Native Backup enough, please read this.  SharePoint Native backup supports Backup-SPFarm, Backup-SPSite, Backup-SPFarm, Export-SPWeb.

All these approaches backup the actual content of the file and at times requires the entire Site or List to be restored entirely. If you are using Version History feature, recovering file can be made easier by restoring only the mis-updated files. In additional, the introduction of Recycle Bin since SharePoint 2010 has helped many SharePoint Admins (at least for myself) to recover accidentally deleted files without burning much of your time.

However, there is no Version History for Permission. Whatever permission changes that you have made onto a document, library or site do not keep a backup copy for you to restore in the later time. You can tap on third party product to help you on this, downside is, you have to pay for the service. Some 3rd party products that you can find in the markets are like Lightning Tools and AvePoint . (Personally never tried that but I’m more of a Self Fulfilling kind, where everything can be done by my left hand and my right hand. But please don’t get me wrong, paying more for premier service sometimes can be good as it comes with support and service level assurance)

So much for the introduction, now let’s go into the script!

I uploaded my script to CodePlex – PowerShell to backup/restore SharePoint Webs, Libraries, Folders and Files and inside the source code, you can find two powershell script, namely BackupPermission.ps1 and RestorePermission.ps1.

You would first run the BackupPermission.ps1. This backuppermission.ps1 generates a Permission.xml file that you gonna need it for the RestorePermission.ps1 later.

What this Backuppermission.ps1 does is to loop through your entire SharePoint Farm for Site Collections. Subsequently, for each of the site collection, it back up its Root Web permissions and Sub Web permissions. After backing up the web level permission, it goes to back up all document libraries permission, folder permission within each library and optionally (turn on by default) files permission.

Why do I need to care about backing up the permission? Well, there may have many reasons for that but below are just some for myself…

  1. You screw up the permission and can’t afford to restore the SharePoint Site Collection (cause only Backup-SPFarm was running DAILY)
  2. You do not want to inform the user for backup recovery cause the user will scream at you if the data that you going to restore has been modified by the user.
  3. You do have full confidence to run SharePoint Native Restore-SPSite as you all know, some times it doesn’t Work. Some how.. (MS, no offense on this, well, it does work most of the time but reason 1 superseded this)
  4. You accidentally RESET or Hit the “Delete Unique Permission” button when trying to change a WEB permission. Refer to my previous post on why this will kill your document permission.

 

Here I’m gonna talk about the Permissions.xml that is generated by my BackupPermission.ps1. You can always change the XML to suit your backup needs. Things like Restoring only partial of your Site Collection, restoring only a document library and even up to only a folder or file. By default, if a entity does not contains <RoleAssignments> node, the RestorePermission.ps1 script will bypass updating the permission and it will remains as its current stage (could be Inherting its parent permission or already broken permission. no changes will be done).


<?xml version="1.0" encoding="UTF-8"?>
<SharePoint>
 <Sites>
  <Site>
   <Url>https://mysharepoint.com</Url>
   <RootWeb>
    <Title>SharePoint Portal</Title>
    <Url>https://mysharepoint.com</Url>
    <RoleAssignments>
     <RoleAssignment User="i:0#.w|contoso\appadmin">
      <RoleDefinitionBindings>
       <RoleDefinition Name="Full Control"/>
      </RoleDefinitionBindings>
     </RoleAssignment>
     <RoleAssignment Group="SharePoint Portal Owners">
      <RoleDefinitionBindings>
       <RoleDefinition Name="Full Control"/>
      </RoleDefinitionBindings>
     </RoleAssignment>
     <RoleAssignment Group="SharePoint Portal Visitors">
      <RoleDefinitionBindings>
       <RoleDefinition Name="Read"/>
      </RoleDefinitionBindings>
     </RoleAssignment>
    </RoleAssignments>
    <Lists>
     <List>
      <Title>Documents</Title>
      <RootFolder>
       <Name>Documents</Name>
       <Url>Documents</Url>
       <SubFolders>
        <Folder>
         <Name>Folder A</Name>
         <Url>Documents/Folder A</Url>
         <RoleAssignments>
          <RoleAssignment Group="SharePoint Portal Owners">
           <RoleDefinitionBindings>
            <RoleDefinition Name="Full Control"/>
           </RoleDefinitionBindings>
          </RoleAssignment>
          <RoleAssignment Group="SharePoint Portal Visitors">
           <RoleDefinitionBindings>
            <RoleDefinition Name="Read"/>
           </RoleDefinitionBindings>
          </RoleAssignment>
          <RoleAssignment Group="SharePoint Portal Members">
           <RoleDefinitionBindings>
            <RoleDefinition Name="Contribute"/>
           </RoleDefinitionBindings>
          </RoleAssignment>
         </RoleAssignments>
        </Folder>
        <Folder>
         <Name>Folder B</Name>
         <Url>Documents/Folder A - Copy (8)</Url>
        </Folder>
       </SubFolders>
       <Files>
       </Files>
      </RootFolder>
     </List>
    </Lists>
    <Webs>
    </Webs>
   </RootWeb>
  </Site>
 </Sites>
</SharePoint>

What you are seeing above basically showing a backup xml that if you restore using this, only 1 site “https://mysharepoint.com” will be processed.  The permission of this site will have the following permission

  • appadmin (SPUser) – Full Control
  • SharePoint Portal Owners (SPGroup) – Full Control
  • SharePoint Portal Visitors (SPGroup) – Read

Subsequently, the script will continue to loop and restore List (in my backup script, this node stores only document libraries.) with Title “Documents” which is inheriting parent permission.

Folder “Folder A” within this document library will have unique permission while “Folder B” will inherit library permission which follows the Web permissions.

 

Well if you don’t really care at all, simply running BackupPermission.ps1 and RestorePermission.ps1 should be able to help you recovering you web permission.

To complete the entire process, set a Task Scheduler job to backup your farm permission regularly!

SharePoint Limited Access Permission – Careful when using BreakInheritance

This post is for SharePoint Developer or Admin who deals with SharePoint APIs (PowerShell or C#)

I have recently discovered a killing command from SharePoint that could kill your SharePoint Day. At times, you will need to configure a Unique permission to document/file for Content Sharing purposes. Typical feature which your end user will ask is to Share a certain document or folder to only certain group of people. Although it is recommend to Share using SharePoint Group which more manageable when it comes to a big Content management system, sometime you prefer to make a easier way out by just assigning to the Individual Users. (Less group to manage and you CAN Afford to loss the permission when things go wrong… and yes, this post will tell you why and how it goes wrong)

With much user friendly SharePoint “Share With” feature, you could break inheritance, grant new user permission so on and so forth. You can’t stop user from doing it, cause it is so apparent nowadays in SharePoint 2013

break and grant permission

Or you can run PowerShell script to Get the ListItem (or to be precise, SPSecurableObject Base Type object), subsequently execute  $object.BreakInheritance($false) and start adding SPRoleAssignment object.

If you have noticed this API

void ISecurableObject.BreakRoleInheritance(bool copyRoleAssignments)

 

This command allows you to quickly remove all existing RoleAssignment (from inheriting parent object permission) and so you can start adding Custom permission that you desired.

Important! This is Extremely Dangerous. Why? Because if you carefully loop into the $object.RoleAssignments (SPRoleAssignmentCollection) property, you will discover that some role definition bindings are named “Limited Access”. In SharePoint 2010, you can easily notice this definition through the permission setting page whereas in SharePoint 2013, it is hidden by default (which is more scarier cause you didn’t even know its existence).

Why is this Limited Access permission? There are many articles out there telling you why and why. I’m not gonna cover that here.

But if you really intend to so-called Cleanse the messy permission list that you have already added, the advice is Don’t.

Let me give you an example of how this BreakInheritance way of breaking parent permission can cause you problem.

By executing BreakInheritance(False), you are technically removing ALL Role Assignments from this object, which include the Limited Access permission granted automatically by SharePoint. You will usually see a lot of limited access for Document library and Web, cause the children within it are likely to be requested (by user) to have unique custom permission.

reset and break with false

 

For Example

  • Web 1 
    • Document Library A
      • Folder a (Break inheritance)
        • File
      • Folder b 

Assuming you have a “Folder a” with broken inheritance permission for UniqueUserA. Upon granting this unique permission, SharePoint automatically creates a Role Assignment for UniqueUserA with “Limited Access” permission to Web1 because Document Library A is inheriting permission from Web1 and hence it is added into Web1 instead.

Somehow or other, you need to change/script to change the permission for Web 1 object up there (the one with Limited Access), by purging the limited access granted to UniqueUserA. the permission that you granted previously to “Folder a” will be DELETED automatically! Yes, Automatically, seamlessly, without-your-knowingly.

And what is going to happen after that? Your lovely user UniqueUserA will send email you, telling you that he has no permission to access files or folder a. Not to mention if you have many Unique permission granted for sub folders within that document library.

Now, the Task you need to ask yourself is – How to still be able to remove existing permission while preserving the Unique configured child permission.

I came out with a simple PowerShell script that allows me to clear the permission. I think it can be easily translated into C# for code behind implementation.


#############################################################################
# Clearing Permission while keeping Limited Access user - Important #
#############################################################################
function ClearPermission
{
 Param([Microsoft.SharePoint.SPSecurableObject]$obj)

 $roleAssignments = $obj.RoleAssignments;
 $count = $roleAssignments.Count;
 for($i = 0; $i -lt $count ; $i++)
 {
  $roleAssignment = $roleAssignments[$i];
  $bindingCount = $roleAssignment.RoleDefinitionBindings.Count
  $clearCounter = 0;
  for($j = 0; $j -lt $bindingCount ; $j++)
  {
   $roleBinding = $roleAssignment.RoleDefinitionBindings[$clearCounter];
   if($roleBinding.Name -ne "Limited Access")
   {
    $roleAssignment.RoleDefinitionBindings.Remove($clearCounter);
   }
   else
   {
    $clearCounter++;
   }
  }
 }
 $obj.Update();
}

What it simply does is to loop through the Role Assignment Collection and delete only Binding with definition of Limited Access. Note that I do not loop via ForEach loop as when you looping the collection, you cannot delete the object within the collection. You can try and you will end up seeing error.

How to use:


Add-PSSnapin Microsoft.SharePoint.PowerShell

$w = Get-SPWeb https://yoursite

ClearPermission $w;

#add your unique permission here.

#additional code to add role assignement (permission)

$user = $w.EnsureUser("domainX\LoginNameY");

$roleAssignment = New-Object Microsoft.SharePoint.SPRoleAssignment($user);

$roleDefinition = $w.RoleDefinitions["Full Control"]

$roleAssignment.RoleDefinitionBindings.Add($roleDefinition)

$w.Update();

Hope it helps