SharePoint: How to enumerate shared services
Continuing the previous article – How to get Shared Service name, I’m going to show how to enumerate all available Shared Services (or Shared Resource Providers, to be more precise). Here is the code (with Reflection, of course 🙂 ) :
public static void EnumerateSharedServices(SPSite spSite, Action<object> action) { ServerContext serverContext = ServerContext.GetContext(spSite); object serverFarm = serverContext.GetType().GetField("m_ServerFarm", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(serverContext); var sspCollectionProp = serverFarm.GetType().GetProperty("SharedResourceProviders"); var sspCollection = sspCollectionProp.GetValue(serverFarm, null) as IEnumerable; foreach (SPPersistedObject sharedServiceProvider in sspCollection) action(sharedServiceProvider); }
You have to use Reflection to get a property value of a Shared Service Provider; the general use of it is something similar to this:
EnumerateSharedServices(SPContext.Current.Site, delegate(object sharedResourceProvider) { string sspName = sharedResourceProvider.GetType().GetProperty("Name").GetValue(sharedResourceProvider, null).ToString(); string sspUserName = sharedResourceProvider.GetType().GetProperty("UserName").GetValue(sharedResourceProvider, null).ToString(); string sspPassword = sharedResourceProvider.GetType().GetProperty("Password").GetValue(sharedResourceProvider, null).ToString(); Console.WriteLine(string.Format("{0} [UserName: {1}, Passw: {2}]", sspName, sspUserName, sspPassword)); // enumerate web applications that are served by the shared service var appCollection = sharedResourceProvider.GetType().GetProperty("WebApplications").GetValue(sharedResourceProvider, null) as System.Collections.IEnumerable; foreach (Microsoft.SharePoint.Administration.SPWebApplication app in appCollection) Console.WriteLine(string.Format("Web app: {0}", app.Name)); });
Let’s take a deeper look at EnumerateSharedServices. Its key object is serverFarm, which is an object of the internal ServerFarm class (the Microsoft.Office.Server.Administration namespace in the Microsoft.Office.Server DLL) containing a collection of Shared Resource Providers (collection of SharedResourceProvider objects). Navigating through this collection an user action is called for each provider.
To make this code more readable, I’d recommend using an object-wrapper for Shared Resource Provider. For example:
public class SharedServiceInfo { protected readonly object _rawSharedResourceProvider; public string Name { get { return GetPropertyValue("Name").ToString(); } } public string UserName { get { return GetPropertyValue("UserName").ToString(); } } public string Password { get { return GetPropertyValue("Password").ToString(); } } public List<SPWebApplication> WebApplications { get { IEnumerable iEnumerable = (IEnumerable)GetPropertyValue("WebApplications"); return new List<SPWebApplication>(iEnumerable.Cast<SPWebApplication>()); } } public SharedServiceInfo(object rawSharedResourceProvider) { _rawSharedResourceProvider = rawSharedResourceProvider; } protected object GetPropertyValue(string propName) { return _rawSharedResourceProvider.GetType().GetProperty(propName).GetValue(_rawSharedResourceProvider, null); } } public static void EnumerateSharedServices(SPSite spSite, Action<SharedServiceInfo> action) { ServerContext serverContext = ServerContext.GetContext(spSite); object serverFarm = serverContext.GetType().GetField("m_ServerFarm", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(serverContext); var sspCollectionProp = serverFarm.GetType().GetProperty("SharedResourceProviders"); var sspCollection = sspCollectionProp.GetValue(serverFarm, null) as IEnumerable; foreach (SPPersistedObject sharedServiceProvider in sspCollection) action(new SharedServiceInfo(sharedServiceProvider)); }
You can extend SharedServiceInfo with the properties you need.
Sample of usage:
EnumerateSharedServices(SPContext.Current.Site, delegate(SharedServiceInfo sharedServiceInfo) { Console.WriteLine(string.Format("{0} [UserName: {1}, Passw: {2}]", sharedServiceInfo.Name, sharedServiceInfo.UserName, sharedServiceInfo.Password)); // enumerate web applications that are served by the shared service foreach (Microsoft.SharePoint.Administration.SPWebApplication app in sharedServiceInfo.WebApplications) Console.WriteLine(string.Format("Web app: {0}", app.Name)); });