Adding A Custom Claim to a Web App Policy via PowerShell in SharePoint 2010

I found this process to be much more difficult than anticipated, and then much easier than expected once done so I figured I would do a quick post on it.  The task at hand was to add a custom claim to a web app policy via PowerShell.  It all works simple enough via the central admin UI.  Once you get into PowerShell though I was initially taking the approach of creating a New-SPClaimsPrincipal to add to the policies for the zone.  Just for your at-Steve’s-expense-amusement, here’s a variety of different approaches that I tried (and far from all of the different permutations I looked at):

#$tp = Get-SPTrustedIdentityTokenIssuer -Identity “ADFS with Roles”
#$cp = Get-SPClaimProvider -Identity “BasketballTeamProvider”

#$account = New-SPClaimsPrincipal -ClaimValue “DVK Jovenut” -ClaimType “Role” -TrustedIdentityTokenIssuer $tp
#$account = New-SPClaimsPrincipal -Identity “DVK Jovenut” -TrustedIdentityTokenIssuer $tp
#$account = New-SPClaimsPrincipal -Identity “c:0ǹ.c|basketballteamprovider|dvk jovenut” -IdentityType EncodedClaim
#$account = New-SPClaimsPrincipal -ClaimValue “DVK Jovenut” -ClaimType “http://schema.steve.local/teams” -ClaimProvider $cp.ClaimProvider
#$account = New-SPClaimsPrincipal -EncodedClaim “c:0ǹ.c|basketballteamprovider|dvk jovenut”

Many of them added the claim successfully, but it was clearly not the correct identifier because the policy was not implemented (i.e. I grant Full Control but users with that claim could not log in).  This was the “more difficult than anticipated” phase.  To get it to work it turned out that I really didn’t need a New-SPClaimsPrincipal object at all.  Instead, here’s the PowerShell that got the claim correctly added and working:

$WebAppName = “https://fc1

$wa = get-SPWebApplication $WebAppName

$account = “c:0ǹ.c|basketballteamprovider|dvk jovenut”

$zp = $wa.ZonePolicies(“Default”)
$p = $zp.Add($account,”Claims Role”)
$fc=$wa.PolicyRoles.GetSpecialRole(“FullControl”)
$p.PolicyRoleBindings.Add($fc)
$wa.Update()

So at the end of the day, just adding the custom claim as a simple string is what worked.  Note that to get that $account value, I just added the policy via central admin at first and copied the claim value it displayed when done.  Hopefully this will save you all some time should you need to do this in the future.

Advertisements

Using PowerShell for SharePoint 2010 in C#

A buddy of mine at Microsoft was good enough to point me to this video on channel 9 that talks about using PowerShell from your C# code without doing the dreaded process and spawn routine we’ve probably all used before.  To begin with, watch the 4 minute video at http://channel9.msdn.com/posts/bruceky/How-to-Embedding-PowerShell-Within-a-C-Application/.  Once you get the basic steps there for adding the appropriate references to your code and using statements to your class, there are a few other useful things to know as it relates to SharePoint 2010 and PowerShell:

  • Start with the standard process to create your PowerShell process:  PowerShell ps = PowerShell.Create();
  • Add the SharePoint snap-in like this:  ps.AddScript(“Add-PsSnapin Microsoft.SharePoint.PowerShell”);
  • Now you can create your SharePoint PowerShell commands as strings and run them.  Here’s an example of adding a new data connection library to the list of trusted data connection libraries in Excel Services.  This is a good example of something that can only be done in PowerShell because there aren’t any adminstrative APIs for it, so it made a good test case for this methodology.  So here’s what it looks like to create the command: 

     

     

    string pCmd = “New-SPExcelDataConnectionLibrary “ + “-address ‘http://farm2/sites/sporeports/dcl’ “ + “-ExcelServiceApplication ‘Excel Services Application’ “;

  • And now add it to the list of cmdlets to run: ps.AddScript(pCmd);

  • Finally, to execute your PowerShell script:  ps.Invoke<string>();

Overall this is a pretty nice way to tackle scenarios when you have managed code but need to fallback to PowerShell for getting a task done.  When you get into it there are some other interesting ways you can tackle using cmdlets, using the CmdletInfo, CommandMetadata and ProxyCommand classes.  Unfortunately they still break down when you are working with non-public APIs but the basic approach I described above continues to work well in those cases too.

Creating Service Applications and Service Application Proxies for SharePoint 2010 in PowerShell

This is kind of a silly little thing really, but I just stumbled upon it because it’s one of those things that when you are trying to do it, you end up pulling your hair out trying to remember how.  Just wanted to show a rather inventive and simple method for creating a service application and proxy in basically one fell swoop.  Here you go, maybe bookmark this page for those times when you’re trying to recall how to do it so simply:

$appPool = Get-SPServiceApplicationPool -Name “SharePoint Web Services Default”
New-SPWordViewingServiceApplication -Name “WdView” -ApplicationPool $appPool | New-SPWordViewingServiceApplicationProxy -Name “WdProxy”
New-SPPowerPointServiceApplication -Name “PPT” -ApplicationPool $appPool | New-SPPowerPointServiceApplicationProxy -Name “PPTProxy”
New-SPExcelServiceApplication -Name “Excel” -ApplicationPool $appPool

Anyways, thought this was kind of cool so figured I’d share.

Reflecting on PowerShell in SharePoint 2010

As we all know, sometimes we just get stuck trying to figure out how to get from point A to point B when working through some SharePoint coding scenario.  One of the things that comes up more frequently in this regardin in SharePoint 2010 has to do with the PowerShell cmdlets that are used so prevalently throughout the product.  Many of you know how to use Lutz’s Reflector tool to look at code in the SharePoint DLLs to understand better what’s going on or how to do something.  But wouldn’t it be nice to do the same thing with those PowerShell cmdlets?  Well it turns out you can.  I’m going to show you how to do that, along with another useful trick once you get it loaded up.

The key thing to remember here is that the PowerShell cmdlets are just implemented in DLLs like any other managed code.  The main PowerShell assembly for SharePoint is called microsoft.sharepoint.powershell.dll.  If you do a little snooping around on your hard drive though you will have a hard time finding it.  That’s because at install time the assembly is only placed in the global assembly cache.  So in order to use it with Reflector, here’s what I do:

  1. Open a command prompt.
  2. Change to the root of your system drive (we’ll assume the C:\ drive for simplicty here)
  3. Do a deep directly search for the file – i.e., “dir microsoft.sharepoint.powershell.dll /s”
  4. You will eventually see the temporary directory the GAC has created and stored the dll.  Copy the dll to a fixed folder location; I just copy it back to c:\.

Now you that have the SharePoint PowerShell dll, you can load it up in Reflector and see what those PowerShell cmdlets are doing under the cover.  This can be VERY helpful when trying to figure out the who/what/where of how to target your OM code.  Now here’s tip #2 – you have the assembly loaded in Reflector.  You run some PowerShell command and want to look at it, but you can’t find it in the listing of methods for microsoft.sharepoint.powershell.dll.  Maybe it isn’t in there, or maybe you just don’t know what the name of the method is that it’s calling.  This is actually a pretty common occurrence.  It happens because not every PowerShell cmdlet is included in that one assembly.  So with all of the assemblies that ship with SharePoint, how do you find the one that has the cmdlet you’re looking for?  That’s tip #2 – what you do is execute the command but supply an invalid value for one of the parameters.  Most cmdlets take an “Identity” parameter, so I usually just run the command with an -Identity “asdfasdf” parameter.  What generally happens is that it tells you the parameter is invalid…along with the name of the method it tried to execute and the assembly it lives in.  For example, when I run Get-SPTrustedIdentityTokenIssuer -Identity “fasdfas”, it tells me that the method it’s calling is SPCmdletGetSPIdentityProvider, and it’s in the Microsoft.SharePoint.PowerShell assembly.  When I run Get-SPEnterpriseSearchServiceApplication -Identity “fasdf”, it tells me that it is calling the GetSearchServiceApplication in the Microsoft.Office.Server.Search assembly.  So then it’s easy enough to find that assembly on disk, load it in Reflector, and find the method I’m looking for.

These are kind of hacky, but useful tricks to get you through your development day.

Manually Adding Query Suggestions in SharePoint 2010

One of the great new features around Search in SharePoint 2010 is the concept of query suggestions.  There are pre-query and post-query suggestions.  A pre-query suggestion is a type-ahead feature that appears in the search box on the search page.  As you start typing in your query, SharePoint will go find other queries that have been executed with results and populate the type ahead drop down for you.  We only use queries that return results so we don’t suggest something that will bring back zero matches.  A post-query suggestion is similar, only it appears after you have executed a query.  It finds similar queries that have been executed and return results, and it displays them by default in the top right corner of the search results page.  Clicking on a post-query suggestion will execute that query for you.

One of the important things to remember about query suggestions though is that since they are built based on user’s performing searches and clicking through results, when you start out with your SharePoint farm you will not see any suggestions.  I’m going to show you how to seed the suggestions manually to get things going.  The suggestions you add in this manner show up as both pre-query and post-query suggestions.  Adding them manually is useful for getting this started or just seeing how the feature works; you may also have some set of query suggestions that you ALWAYS want to show up no matter what query is executed.  Also note that these steps were tested and work on the SharePoint escrow build (you TAP and RDP customers know which one this is) but I don’t think they work on the public beta bits.  This will be good info though for everyone once you have RTM bits. One final note – this process *should* work for both SharePoint Search and FAST Search for SharePoint. So here are the steps:

  1. Get a reference to your search service application.  If you type Get-SPEnterpriseSearchServiceApplication it will give you a list of them.  In this example I’m going to use the default name created with the SharePoint farm wizard:
    1. $ss = Get-SPEnterpriseSearchServiceapplication -Identity “Search Service Application”
  2. Create a new suggestion:
    1. New-SPEnterpriseSearchLanguageResourcePhrase -SearchApplication $ss -Language En-Us -Type QuerySuggestionAlwaysSuggest -Name “SharePoint Server 2010”

Now the next thing you want to do is run a timer job.  The timer job is called Prepare query suggestions and it is scheduled to run once a day.  Run it now to get it to process your suggestion.

One way you can verify if your suggestion was added successfully is to use this PowerShell command:

Get-SPEnterpriseSearchQuerySuggestionCandidates -SearchApplication $ss

That will show you the Always Suggest words; of course, you can and should go try it out in the browser as well.  Finally, you may add one and decided that you want to remove it; we can do that too.  Here’s the PowerShell command for that:

Remove-SPEnterpriseSearchLanguageResourcePhrase -SearchApplication $ss -Language En-Us -Type QuerySuggestionAlwaysSuggest -Identity “SharePoint Server 2010”

Note the main difference is the last parameter name.  When you are adding a suggestion, the last parameter is called “Name”; when you are removing it the parameter is named “Identity”.  Also, don’t forget to run the timer job after you remove an entry.  It may take a few minutes after running the timer job to see the updated results.

 

Multi Tenancy in SharePoint 2010 Part 3

I’ve done a couple of blogs now about some of the multi-tenant features in SharePoint 2010 (http://blogs.technet.com/speschka/archive/2009/11/30/enabling-multi-tenant-support-in-sharepoint-2010.aspx and http://blogs.technet.com/speschka/archive/2009/12/30/multi-tenancy-in-sharepoint-2010-part-2.aspx).  In this post I’m going to talk about something called feature packs (A.K.A. feature sets in previous builds and blogs).  A feature pack is a way to take a set of site- and/or web-scoped features and group them together.  Once grouped together in that pack, they can be associated with a subscription.  At that point, all the site collections in that subscription can use only the site- and web-scoped features that are part of that pack.  As you can imagine, it gives you the opportunity to do things like create different service levels and charge higher rates for more features, lock down features for different subscriptions, etc.

So let’s get started – how do you create a feature pack?  You can use the PowerShell cmdlet New-SPSiteSubscriptionFeaturePack.  To back up a little though, as described in part 2 of the multi tenant blog series, we’re going to get a reference to a site subscription.  So I’ll start with that – here I’m getting a reference to one of my subscriptions:

$sub = Get-SPSiteSubscription -identity 7bc0cb76-a355-485d-ac7e-8332d40147f2

Now I’m going to create a new feature pack:

$pack = New-SPSiteSubscriptionFeaturePack

Pretty easy, right?  Just like site subscriptions, feature packs are devoid of frilly goo, like say a name.  J  So now if I just type $pack in PowerShell and hit Enter it will give me all the info it has about it:

FeatureDefinitions

Id

——————

{}

b329f3b0-58ec-408b-86c9-bd13661acd45

 

Creating the feature pack using the object model is similarly straightforward:

SPSiteSubscriptionSettingsManager mgr = SPSiteSubscriptionSettingsManager.Local;

SPSiteSubscriptionFeaturePack fs = mgr.CreateFeaturePack();

fs.Update();    

Note that you must call the Update method or your feature pack will not be persisted.  Now that we have a feature pack we want to start adding features to it.  To add new features to a pack you can use the Add-SPSiteSubscriptionFeaturePackMember PowerShell cmdlet.  To do that we’ll need to pass in two variables:  the ID of our feature pack and the ID of a feature.  While I don’t want to stray too far from our objective here, remember that you can only add a site- or web-scoped feature to a subscription; it will automatically use farm- and web application-scoped features.  Using PowerShell we have three options to get a list of the features that might work for a feature pack then:

get-spfeature –site http://urlToSite   (returns all the enabled features on the site – both full trusted and partially trusted code)

get-spfeature –site http://urlToSite –sandboxed (returns all installed partially trusted code feature definitions on the site)

get-spfeature –web http://urlToWeb  (returns all the enabled features in the web)

So pick your poison and get the ID to a feature that you want to add to the feature pack.  In this example I’m going to add the Search Web Parts feature to my feature pack.  So my PowerShell command looks like this:

Add-SPSiteSubscriptionFeaturePackMember -identity $pack -FeatureDefinition eaf6a128-0482-4f71-9a2f-b1c650680e77

There you go – feature added.  Now if I type in $pack in PowerShell and press Enter it looks like this (only without the word wrap):

FeatureDefinitions

Id

——————

{FeatureDefinition/eaf6a128-0482-4f71-9a2f-b1c65068…

b329f3b0-58ec-408b-86c9-bd13661acd45

 

The object model follows a similar pattern – here is that code:

//get the site subscriptions manager

SPSiteSubscriptionSettingsManager mgr =

SPSiteSubscriptionSettingsManager.Local;

 

//get all the feature packs

SPSiteSubscriptionFeaturePackCollection fSec = mgr.GetAllFeaturePacks();

               

//retrieve the pack we want to work with

SPSiteSubscriptionFeaturePack fs = fSec[new Guid(yourFeaturePackGUID)];

 

//define a new feature definition

SPFeatureDefinition fd = null;

 

//get the collection of feature definitions

SPFeatureDefinitionCollection fDefs = SPFarm.Local.FeatureDefinitions;

 

//get the feature definition we want to add to the feature pack

fd = fDefs[new Guid(yourFeatureGUID)];

 

//add to the feature pack

fs.Add(fd);

 

Okay, we’re making good progress now.  We’ve created a feature pack.  We know how to add features to it.  Because I am occasionally sadistically anal I will briefly cover how to remove a feature from a feature pack.  In PowerShell use the Remove-SPSiteSubscriptionFeaturePackMember cmdlet.  Like the cmdlet to add a feature to a pack, you must again provide as parameters the feature pack and feature ID that should be removed from it.  If you’re using the object model you would just use the Remove method on the SPSiteSubscriptionFeaturePack instance and then call the Update method.

 

The last step of course is now to associate our feature pack with a site subscription.  Going back to the beginning of this post, I used the $sub variable to get a reference to my subscription.  Now I going to use that to make that association between subscription and feature pack.  In PowerShell I need to get a reference to the local subscription settings manager, then associate my feature pack with my subscription.  Here’s what that looks like:

 

$mgr = [Microsoft.SharePoint.SPSiteSubscriptionSettingsManager]::Local

$mgr.AssignFeaturePackToSiteSubscription($pack, $sub)

 

The object model basically uses the same exact code as PowerShell; you can use the code shown previously in this blog to get your reference to the site subscription and feature pack.  Then you just get an instance of Microsoft.SharePoint.SPSiteSubscriptionSettingsManager.Local and call the AssignFeaturePackToSiteSubscription method.

 

For completeness, if you want to disassociate a feature pack with a subscription, you would assign $Null as the feature pack reference in the AssignFeaturePackToSiteSubscription method.  Also, if you wanted to delete a feature pack you would use the Remove-SPSiteSubscriptionFeaturePack cmdlet; in the object model you get a reference to the SPSiteSubscriptionFeaturePack instance and call the Delete method.

 

This the last of the features and configuration that I’ll probably cover for multitenant.  I have an idea of another related topic to this, but you’ll just have to stay tuned to see if I can pull that together.  Hope everyone is enjoying their new year.