Saturday, August 18, 2012

Deploying WSP Files with PowerShell - Part 1

When I started with SharePoint 2010 development, WSP (Web Solution Package) deployments on dev box was thought to be a trivial job; like selecting "Deploy Solution" from the Build menu in Visual Studio, as simple as that.


But later on, the question that started bugging me was; how do I get my WSP files to SharePoint instances running on QA and Production servers? The thought that crossed my mind was to point the Visual Studio 2010 to the remote SharePoint server and get it done, but later only I came to realize the fact that Visual Studio 2010 won't allow you to deploy SharePoint solutions to any remote servers expect your local machine. The Good news is, starting with VS.NET 2012 this restriction is not longer there, and you can deploy solutions to SharePoint 2013 running on a remote box.


After some search, I zeroed in on the definite solution what I was looking for, which was nothing but PowerShell. With SharePoint 2010, Microsoft had deployed this new scripting platform as an alternative to STSADM (a command-line administration tool for Office SharePoint Server 2007 servers and sites). With PowerShell, Microsoft had come up with a unified scripting platform covering the entire spectrum of Microsoft Server products, there by allowing devs, admins and IT Pros to leverage a common scripting platform for automating the day to day tasks. 

The hearsay is that, Microsoft is planning to bump off STSADM from future releases of SharePoint; but at that time of writing, STSADM is still available with SharePoint 2013 Preview, don't know whether Microsoft might drop off it in RTM release, well wait and see.

Solution:

So lets get started and deploy the WSP file using PowerShell; before we start off, make sure the all the points mentioned in the pre-requisites are in place before move on.

Prerequisites:
1. The commands are to be executed on the machine where SharePoint is installed.
2. You must be a member of the Administrators group on the machine which you are to execute the Windows PowerShell scripts.
3. Must be a member of SharePoint Farm Administrators group account
4. db_owner of Content DB that of Central Admin WebApp
5. db_owner of Config DB
6. db_owner of Content DB that of WebApp you wish deploy the solutions against
7. Copy the WSP files to be deployed, on to SharePoint server
8. The following widows services should be up and running

    - SharePoint 2010 Administration
    - SharePoint 2010 Timer



Failing to start the SharePoint Administration service will cause to throw an error while Installing solution, with the error text "Admin SVC must be running in order to create deployment timer job".

Lets begin with how to deploy a feature, scoped to Site Collection containing assemblies to be deployed to GAC. The process involves three steps.

Step 1: Add solution
Step 2: Install\Deploy solution
Step 3: Activate features


1. To perform the above steps, open SharePoint PowerShell Console on SharePoint Server. Make sure you are running PowerShell under a user having Farm Admin privileges, else you will encounter an error stating that

"The local farm is not accessible. Cmdlets with FeatureDependencyId are not registered"







2. First of all we are going to Add the solution; for that key in the following script and press enter, which will add the WSP solution to SharePoint farm.

Add-SPSolution -LiteralPath "<ENTER ABSOLUTE PATH TO WSP FILE>"


if everything goes well, you should see the deployed column with "False" status. 

Internals: In this step, an entry is made to the SharePoint farm ConfigDB. This particular step can also be achieved using the Object model, however the same isn't possible through Central Admin UI.


3. Next we need to Install the solution, for that key in the following script and press enter.


Install-SPSolution -Identity "<NAME OF WSP FILE>" -WebApplication <URL TO WEB APP> -GACDeployment



Note: The -GACDeployment switch is required only if the WSP file contains .NET assemblies (.dll) which needs to be deployed to GAC, else this can be omitted.


Internals: In this step, the WSP file is unpacked and copied to the respective locations. This particular step is executed by Timer Job.

4. Next we need to see whether the solution is deployed or not. For that key in the following script and press enter.


Get-SPSolution "<NAME OF WSP FILE>"


you should see the "Deployed" status as True, which means the solution was successfully deployed by the Timer Job; if yes, proceed to step 5. 

If not the possible cause could be, either of the following.

- The "SharePoint 2010 Timer Job" windows service isn't running
- Timer job might be busy with some long running tasks.

If you wish to see whether a timer job has been scheduled for this particular solution, key in the following script


$solution = Get-SPSolution -Identity:"<NAME OF WSP FILE>"
Write-Host $solution.JobExists

If you see True, then the job is in queue and just need to wait for the timer to take up your request. If False, either it could be because of the timer had already completed the job or could be some other reasons.

5. Next is to activate the feature, before that we need to get the name or GUID for this feature; for that key in the following script and press enter



Get-SPFeature | Where-Object {$_.DisplayName -like "*<FILE NAME>*" }



Copy the value listed under the ID field. In the scope field, you could see that this feature is scoped to Site Collection, that why the value "Site" is displayed.

6. Finally we are at the final stage of deployment, that is feature activation. For this key in the following script and press enter.


Enable-SPFeature -Identity "<PASTE GUID VALUE>" -URL <PASTE SITE URL>



If everything went well, you are done with deploying the WSP to SharePoint site using PowerShell.

Closing Note:

On the contrary, developers tends to shy away from these kind of arcane stuff because of the fact that, its difficult to get hold of the syntax and beyond that its a time consuming and tedious job. So a lazy programmer like me always wants to gets things done in a jiffy by leveraging scripts\tools available on the Internet. To get a hold off on, how SharePoint deployments work under the hood, I thought of getting my hands dirty by writing the PowerShell scripts by hand.


My thought went in a different direction, what if a project had hundreds of WSP files? am I going to do this one at a time like this? if so, definitely its going to be an overkill, so there should be some way to make the life of dev\admin better, right! I came to stumble upon this cool PowerShell script by Allan Merolla, which takes up all the WSP files contained in a folder and processes them one by one, cool isnt it? but the down side with this script is, it wont do any logging or feature activation stuff, which needs to be handled manually.


Happy WSP Deployment !!!




Sunday, June 17, 2012

SharePointKochi User Group Meet v1

The maiden session of KochiSharePoint User Group met at Hexis Labs on Saturday, 16th June 2012. The User Group (UG) is formed with an objective to keep up with the burgeoning developments in Enterprise Collaboration space, there by providing a platform to share and learn the technologies and products associated with it; the UG also gives special emphasis on SharePoint, the flagship product from Microsoft on enterprise collaboration vertical. 


The session started off with stimulating talk by Praseed Pai, the far-famed Software Consultant and Solutions Architect, he is also an avid blogger and speaker at many tech forums including K-MUG. He started off the session by talking about the changing landscape of custom software development which is giving out in favour of packaged software solutions in the enterprise space. He highlighted the some of key features required by every enterprise software and showed how Microsoft SharePoint features aligns with those. He concluded the talk by  mentioning how .NET developers could take their career to the next level with SharePoint, by leveraging their existing ASP.NET skills and added how enterprises could save themselves from the phenomena of "Reinventing the Wheel" by adopting SharePoint as their Collaboration platform thereby cutting down risk associated with custom development.

The next session was by Abraham Peter, a senior SharePoint developer working for Ernst & Young. His session titled "Why & How SharePoint", covered SharePoint from business standpoint equating the six pillars of SharePoint with real life business scenarios and pointed how business could seamlessly streamline their operations using SharePoint. Next he covered how  different variants of Document Management features of SharePoint how they stack up each other. In the last slides he covered how to start off with SharePoint development and various offerings by Microsoft and other third party providers to set up SharePoint development box. Later he demoed the cloud version of SharePoint development services from CloudShare.com

The final session was by Shalvin PD a renowned independent consultant and trainer in .Net and SharePoint technologies with years of experience. You can find him speaking at prominent tech events like Kerala Microsoft User Group, Community Tech Days and others. He started off with a straight dive into SharePoint by demoing how to provision some of the key features covered in the six pillars of SharePoint including Sites, Content and Communities. He covered a good ground on developing SharePoint solutions with Visual Webparts, Sandbox Webparts and covered Central Administration module there by giving the audience a feel of SharePoint development and its features.

We had a adhoc session by Ms.Nimisha, a SharePoint developer from Orion, she briefly covered what all to watch out for especially for developers coming to SharePoint from ASP.NET background. Her session covered topics including the changes that SharePoint makes when installing it to a machine, the SharePoint site hierarchy, sandbox solution and its relevance and many more. Her initiative to share her experiences was well appreciated by the UG.

The adhoc session was followed by the QA session, which was then followed by a self introduction of each and every member in the audience. It was exciting to see people attending the UG not just from development background but also from IT infrastructure services and academia too. 

The SharePointKochi UG hosts would like to specifically thank each and everyone of you who turned up for the meet and made this UG initiative a success and thanks to those who wished to attend but couldn't turn up because of personal reasons. A special word of thanks to Hexis Labs for arranging the Infrastructure without which the event would have been made possible. 


Thanks to God almighty.




Tuesday, January 10, 2012

Descriptive Text for Enums

While working on an windows application, I came to across an interesting problem, which is of trivial in nature. I had a drop-down (combo box) control which was populated with field names from an Enum, which is acting as a container for designation values. The problem with Enums were, the field names can't contains spaces, where as the actual designations did contain spaces. This made the end users feel a bit odd, the way which values were listed in the drop-down control. So putting some thoughts on this, I came up with a solution, which did hit the bulls eye. So here's how I did it.


First I need a container to hold this descriptive text, for this an attribute class called "EnumDescription" was defined to hold the string
[AttributeUsage(AttributeTargets.Field)]
public class EnumDescription : Attribute
{
    public EnumDescription(string Value)
    {
        if (!string.IsNullOrEmpty(Value))
            Description = Value;
        else
            throw new NullReferenceException("EnumDescription not provided");
    }

    public string Description { get; set; }
}

Next I started decorating the enum fields with the previously created attribute class "EnumDescription"; this allowed me to pass descriptive text to the enum fields, which helped me get past the .NET enum field naming contsraint.
enum Designations
{
 [EnumDescription("General Manager")]
 GeneralManager = 1,

 [EnumDescription("Project Manager")]
 ProjectManager,

 [EnumDescription("Technical Manager")]
 TechnicalManager,

 [EnumDescription("Group Project Manager")]
 GroupProjectManager,

 [EnumDescription("QA Manager")]
 QAManager,

 [EnumDescription("Accounts Manager")]
 AccountsManager,

 Designer
}
Next step of the puzzle is to read the string contained in the custom attributes. For this a simple custom attributes reader was implemented, but when I ran a unit test against the code snippet, it failed. The reason being, some enum fields doesn't require custom attributes as the designation names they represent didn't contain spaces. The code snippet I had written, now need to deal with enum fields with and without custom attributes, i.e; the catch here is to return the value contained in the EnumDescription, if the attribute is defined, else the field name itself should be returned.

public static string GetText(Enum e)
{
 string ReturnVal = string.Empty;
 EnumDescription oEnumDescription = null;

 if (e != null)
 {
  FieldInfo oFieldInfo = null;
  oFieldInfo = e.GetType().GetField(e.ToString());

  if (oFieldInfo != null)
  {
   object[] CustomAttribs = oFieldInfo.GetCustomAttributes(typeof(EnumDescription), false);

   if (CustomAttribs != null && CustomAttribs.Length >= 1)
   {
    oEnumDescription = (EnumDescription)CustomAttribs[0];
   }
  }

  if (oEnumDescription != null)
   ReturnVal = oEnumDescription.Description;
  else
   ReturnVal = e.ToString();
 }

 return ReturnVal;
}


Now the problem of getting descriptive text is sorted out. The next piece of the puzzle is how to set enum value based on the custom attribute text value? for this a SetText method was written, which will accept the value to be set, either based on the description or on the field name.

public static T SetText<T>(string Value) where T : struct
{
 T ReturnVal = default(T);
 EnumDescription oEnumDescription = null;
 bool DescriptionFound = false;

 if (!string.IsNullOrEmpty(Value))
 {
  //iterate through all the enum fields and check for the given Value in the EnumDescription
  foreach (FieldInfo fld in typeof(T).GetFields())
  {
   object[] CustomAttribs = fld.GetCustomAttributes(typeof(EnumDescription), false);

   if (CustomAttribs != null && CustomAttribs.Length >= 1)
   {
    oEnumDescription = (EnumDescription)CustomAttribs[0];

    if (oEnumDescription != null &&
     oEnumDescription.Description.ToLower() == Value.ToLower())
    {
     DescriptionFound = true;
     ReturnVal = (T)Enum.Parse(typeof(T), fld.Name);
     break; //we found the matching field so exit the foreach loop
    }
   }
  }

  //If no attribute with the given text was found, look for field names
  if (!DescriptionFound)
  {
   foreach (FieldInfo fld in typeof(T).GetFields())
   {
    if (fld != null &&
     fld.Name.ToLower() == Value.ToLower())
    {
     DescriptionFound = true;
     ReturnVal = (T)Enum.Parse(typeof(T), fld.Name);
     break; //we found the matching field so exit the foreach loop
    }
   }
  }
    
 }

 if (!DescriptionFound)
  throw new ApplicationException("Invalid description or field name: " + Value);

 return ReturnVal;
}

with these two methods in place I can now access and assign Enum descriptive text to Enums.
Here's a the code snippet which I used to test my two methods.
class Program
{
 static void Main(string[] args)
 {
  Designations SelectedDesig;
  string Value;

  SelectedDesig = Designations.GeneralManager;
  Value = EnumStringReader.GetText(SelectedDesig);
  Console.WriteLine("GetDescription: " + Value);

  SelectedDesig = EnumStringReader.SetText<Designations>("Designer");
  Console.WriteLine("SetEnum from Description: " + SelectedDesig);
 }
}
You can download the sample C# project from this link.