Second Life of a Hungarian SharePoint Geek

May 31, 2014

How to get the SharePoint application Pool accounts from code

Filed under: PowerShell, Reflection, SharePoint — Tags: , , — Peter Holpar @ 09:01

In the past months I had a lot of trouble because of the incorrectly specified accounts on various SharePoint web and service applications, most frequently due to their missing permissions on other resources.

If you need to determine the user account configured for a web application, it is not very complicated to find out via the user interface, as described here.

You can check the account used for service application similarly using the Service Account page in the Central Administration as illustrated below.

image

Assume, you need the same information from code (C# or PowerShell) to be able to automate the verification, or simply make things to be performed faster. I’ll show you how to achieve that. It is not complicated as the UI-version at all, once you know the right path in the object model structure to dig down into the requested piece of information.

Let’s see the application pool account of a SharePoint web application first.

In the first case I assume that the code runs in the SharePoint context (like a web part):

string userName = SPContext.Current.Site.WebApplication.ApplicationPool.Username;

If you don’t have access to the context, you have to find another way to the web application:

string userName = SPWebApplication.Lookup(new Uri(http://YourSharePoint)).ApplicationPool.Username;

The PowerShell script is very simple and straightforward:

$wa = Get-SPWebApplication http://YourSharePoint
$userName = $wa.ApplicationPool.Username

Next I show, how to get the identity of a service application. If the .NET type of the service application, like the type BdcService (defined in namespace Microsoft.SharePoint.BusinessData.SharedService) for the business data connectivity service, this task is not very tricky:

BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>();
SPIisWebServiceApplication bdcApp = bdcService.Applications.FirstOrDefault() as SPIisWebServiceApplication;
// if you have multiple instances of the same type of service application, you can filter for example based on their name
// SPIisWebServiceApplication bdcApp = bdcService.Applications.FirstOrDefault(a => a.Name == "Business Data Connectivity Service") as SPIisWebServiceApplication;
string serviceAccountName = bdcApp.ApplicationPool.ProcessAccount.LookupName();

Things get a little bit more complicated, if the .NET type of the service application is defined as internal, as in the case of UserProfileService. The task can be completed using Reflection, see a similar problem and solution in my former post. Some extra lines (like checking for null values) were removed in sake of readability, but it should not affect the functionality in the standard case.

  1. // hack to get the Microsoft.Office.Server.UserProfiles assembly
  2. Assembly userProfilesAssembly = typeof(UserProfile).Assembly;
  3. // UserProfileService is an internal classes,
  4. // so you cannot get them directly from Visual Studio
  5. // like I do with the SPServiceCollection type
  6. Type userProfileServiceType = userProfilesAssembly.GetType("Microsoft.Office.Server.Administration.UserProfileService");
  7. Type spServiceCollectionType = typeof(SPServiceCollection);
  8.  
  9. // first we call
  10. // SPFarm.Local.Services.GetValue<UserProfileService>()
  11. MethodInfo mi_GetValue = spServiceCollectionType.GetMethod("GetValue",
  12.         BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null
  13.         );
  14. // get the generic version of GetValue method
  15. MethodInfo mi_GetValueGeneric = mi_GetValue.MakeGenericMethod(userProfileServiceType);
  16. Object userProfileService = mi_GetValueGeneric.Invoke(SPFarm.Local.Services, null);
  17.  
  18. System.Reflection.PropertyInfo pi_Applications = userProfileServiceType.GetProperty("Applications", BindingFlags.NonPublic | BindingFlags.Instance);
  19. // userProfileApplicationCollection is of type Microsoft.Office.Server.Administration.UserProfileApplicationCollection
  20. IEnumerable<SPIisWebServiceApplication> userProfileApplicationCollection = pi_Applications.GetValue(userProfileService, null) as IEnumerable<SPIisWebServiceApplication>;
  21. SPIisWebServiceApplication userProfileApplication = userProfileApplicationCollection.FirstOrDefault();
  22. // if you have multiple instances of the same type of service application, you can filter for example based on their name
  23. //SPIisWebServiceApplication userProfileApplication = userProfileApplicationCollection.FirstOrDefault(a => a.Name == "User Profile Service Application");
  24. string serviceAccountName = userProfileApplication.ApplicationPool.ProcessAccount.LookupName();

PowerShell provides a simple solution, independently of the external visibility of the service class type. It is due to the fact that the microsoft.sharepoint.powershell assembly is defined as a friend assembly in the microsoft.sharepoint assembly, so the former one has access to the internal members of the latter one.

$ups = Get-SPServiceApplication | ? { $_.TypeName -eq "User Profile Service Application" }
$serviceAccountName  = $ups.ApplicationPool.ProcessAccount.Name

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: