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.
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.
- // hack to get the Microsoft.Office.Server.UserProfiles assembly
- Assembly userProfilesAssembly = typeof(UserProfile).Assembly;
- // UserProfileService is an internal classes,
- // so you cannot get them directly from Visual Studio
- // like I do with the SPServiceCollection type
- Type userProfileServiceType = userProfilesAssembly.GetType("Microsoft.Office.Server.Administration.UserProfileService");
- Type spServiceCollectionType = typeof(SPServiceCollection);
- // first we call
- // SPFarm.Local.Services.GetValue<UserProfileService>()
- MethodInfo mi_GetValue = spServiceCollectionType.GetMethod("GetValue",
- BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null
- );
- // get the generic version of GetValue method
- MethodInfo mi_GetValueGeneric = mi_GetValue.MakeGenericMethod(userProfileServiceType);
- Object userProfileService = mi_GetValueGeneric.Invoke(SPFarm.Local.Services, null);
- System.Reflection.PropertyInfo pi_Applications = userProfileServiceType.GetProperty("Applications", BindingFlags.NonPublic | BindingFlags.Instance);
- // userProfileApplicationCollection is of type Microsoft.Office.Server.Administration.UserProfileApplicationCollection
- IEnumerable<SPIisWebServiceApplication> userProfileApplicationCollection = pi_Applications.GetValue(userProfileService, null) as IEnumerable<SPIisWebServiceApplication>;
- SPIisWebServiceApplication userProfileApplication = userProfileApplicationCollection.FirstOrDefault();
- // if you have multiple instances of the same type of service application, you can filter for example based on their name
- //SPIisWebServiceApplication userProfileApplication = userProfileApplicationCollection.FirstOrDefault(a => a.Name == "User Profile Service Application");
- 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
