Generate WSP and coy to another location on post build event in Visual Studio 2010

April 19, 2012

When working on all SharePoint 2010 projects deployments are generally done via PowerShell scripts. I usually have a set PowerShell script which I copy and alter updating items such as the site URL, solution name and feature ID and I save this in a deployment folder under where the solution file is located. I then create a solution folder in Visual Studio called ‘Deployment files’ and add my PowerShell scripts to this. This way the deployment files are part of the solution and should be added into our code repository as well.

In my PowerShell scripts I don’t hard coded the WSP location I find the current directory from which the script is getting executed and then append the WSP name, see below. This means the WSP has to be in the same folder as the scripts which isn’t generally an issue but it means I have to package the project in Visual Studio and then copy the WSP from the build folder to my scripts folder. While this only takes a few minutes you need to do it each time which can get a bit repetitive.

Find Solution Location
  1. $scriptpath = $MyInvocation.MyCommand.Path
  2. $dir = Split-Path $scriptpath
  3. $solutionName=”WSPNAME.wsp”
  4. $solutionPath = $dir + “\” + $solutionName

 

I decided to look into using post build commands to see if I could generate the WSP then copy it to the folder where my scripts are located. Since I have done it several times I first looked at copying the WSP file to another location. This can be done by

  1. Right click on the project and select properties

ProjectPropertiesWindow

  1. Next select the Build Events option on the RHS
  2. In the post-build event command line window enter the script below

copy $(TargetDir)$(TargetName).wsp $(SolutionDir)DeploymentFiles

    1. The TargetDir should be the full path to the build folder where the WSP will be created
    2. The TargetName should be the same name as the project so in my case if the project name was TestProject I would be looking for a file called TestProject.wsp
    3. The SolutionDir should be the full path to the folder where the solution file is located.
    4. \DeploymentFiles is simply the name of the folder located under the main solution folder where I keep my PowerShell scripts

3. Save the file and build the project

If it has worked you should get a message in the Output screen indicating the file has been copied.

This was fine except this simply copies the WSP from the bin folder to my deployment scripts folder but what I need is to ensure I am getting the latest version of the WSP so I need to generate the WSP before copying the file. As this was not something I had done before I done some research and it seems the only way to do this is to edit the project file.

I opened my project file in Notepad++, might be worth taking a backup of this first, and found the section at the end, see below, and added the suggested XML, see below.

Section After which I need to add my addition XML
<Import Project=”$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\SharePointTools\Microsoft.VisualStudio.SharePoint.targets” />

Required XML
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn);CreatePackage</BuildDependsOn>
</PropertyGroup>”

What I found was as I had already added my post build event to copy the WSP there was already a section in the project file called “PropertyGroup”, see below.

PostBuildCopyProjectXML

At this point I wasn’t sure if I was supposed to add a new PropertyGroup element or add my BuildDependsOn section to the existing property group. I looked around on Google but there wasn’t much details on this so added the section to generate the WSP as another PropertyGroup element but I added this before my copy build event in case the order was important. When I opened Visual Studio, or if you already had it opened you will need to reload the project, and build it I found it did copy the file and it did build the WSP it did them in the wrong order. It first copied the WSP then it built a new version of the WSP.

Obviously this isn’t much use as I would always end up with an old version of the WSP. I tried adding the post build code which moves the file into the same property group, see below, but I still ended up with the same outcome where the file was moved first then a new version created.

XML with generate new WSP and move file in one property group in project file
PostBuildAndGenerateWSPProjectXML

I spent some time researching this issue on Google and found an article on how to generate a WSP in post build command and noticed that I had “<BuildDependsOn>” in my version but in the article above it was “<PostBuildEventDependsOn>”. As soon as I changed this, see new project XML below, things executed in the correct order and it first built my WSP then copied it.

Final version of project file XML

<PropertyGroup>  <PostBuildEventDependsOn>$(PostBuildEventDependsOn);CreatePackage</PostBuildEventDependsOn>
<PostBuildEvent>copy “$(TargetDir)$(TargetName).wsp” “$(SolutionDir)DeploymentFiles”</PostBuildEvent>
</PropertyGroup>

I hope this will help others as it took me a while to get this right. As always please be careful with making changes to the project file as this can cause issues.

Advertisements

JQuery to see if the user is on either the display, edit or new list item form

April 18, 2012

There have been a few situations where I have wanted to run some JQuery on either a display, edit or new item form to change the layout of the pages or hide certain fields. Typically I done this by checking the URL to see if I’m on the list in question, see example below, and then running my JQuery.

  1. if (window.location.href.indexOf('/Lists/TestListName/') != -1) {
  2.         alert('Am in list');
  3.         }

 

This works fine but it results in the above condition generally being true when you are interacting with the list i.e. looking at a particular view. I decided to take a look around to see if there was anything out there which would allow me to see if I was on one of the list forms but I didn’t find anything.

I spent some time looking at the HTML of the list forms to see if there was any way I could accurately check which page I was on. In the end I decided I would use the ribbon as part of the way I would target the type of form along with the breadcrumb. When checking the HTML I noticed the display form had an element for the ribbon which had an ID of ‘Ribbon.ListForm.Display’. From my previous experience of working with the ribbon I knew this was a relatively safe way of checking as the element wouldn’t appear on any other pages as it was particularly targeted at List Forms ribbon options, see function below.

Check if display form
  1. function IsDisplayForm()
  2. {
  3.     var isDisplayForm = false;
  4.  
  5.     var ribbonLiElement = document.getElementById("Ribbon.ListForm.Display");    
  6.     if ($(ribbonLiElement).length > 0) {
  7.         isDisplayForm = true;
  8.     }            
  9.  
  10.     return isDisplayForm;
  11. }

 

While this worked for display forms the solution for the edit and the new forms was slightly more complex as while both of these have a ribbon element they are both ‘Ribbon.ListForm.Edit’. This meant I needed another way to be able to distinguish between a new and an edit form. After comparing the HTML I decided to use the current breadcrumb node as the text for the two types of forms is slightly different. For the new forms it is ‘New Item’ and for the edit form it is ‘Edit Item’, see code below.

Check if edit form
  1. function IsEditForm() {
  2.     var isEditForm = false;
  3.  
  4.     var ribbonLiElement = document.getElementById("Ribbon.ListForm.Edit");
  5.     var currentBreadcrumbElement = $("span.s4-breadcrumbCurrentNode");    
  6.     if (currentBreadcrumbElement.length > 0 && currentBreadcrumbElement.text().toLowerCase() == "edit item"
  7.     && $(ribbonLiElement).length > 0) {
  8.         isEditForm = true;
  9.     }
  10.  
  11.     return isEditForm;
  12. }

 

Check if new form
  1. function IsNewForm() {
  2.     var isNewForm = false;
  3.  
  4.     var ribbonLiElement = document.getElementById("Ribbon.ListForm.Edit");
  5.     var currentBreadcrumbElement = $("span.s4-breadcrumbCurrentNode");        
  6.     if (currentBreadcrumbElement.length > 0 && currentBreadcrumbElement.text().toLowerCase() == "new item"
  7.     && $(ribbonLiElement).length > 0) {
  8.         isNewForm = true;
  9.     }
  10.  
  11.     return isNewForm;
  12. }

Conclusion

The easy option for this may have been to simply check the URL for NewForm.aspx, DispForm.aspx  or EditForm.aspx but I decided it would be better not to use this approach as it is possible to create custom versions of these forms which would have different names.

The one area I have tested where this will not work is if you create a custom InfoPath form using the option in the list ribbon so this is worth keeping in mind.

The other limitation is I have hardcoded the text I’m testing against so this will only work in English but it could be change for other languages.

As always please check this works on a development environment and is tested thoroughly before using. Fingers crossed this will help some people.


%d bloggers like this: