SharePoint 2010 Service Applications and PowerShell

by Martin Buus Østergaard 16. august 2010 15:11

I've been doing some configuring of my SP2010 test-bench. This involves configuring service applications with PowerShell scripting.
I found a superb reference in http://www.todd-carter.com/post/2010/04/26/The-Wizard-Likes-His-GUIDs.aspx to script creating applications!

One error I stumbled upon while running the script was:
"The term 'New-SPExcelServiceApplication' is not recognized as the name of a cmdlet" (a similar arror occured with Access services... figures...)

Hmmm, I thought my Enterprise CAL was enough... IT IS! But: somehow my installation was mixed up with confusion. It said in SCA that the Enterprise CAL was used. After a lot of digging, I found out that I had to go into "Upgrade and Migration" --> "Enable Features on Existing Sites":

In the "Enable Features..." page you have to check the "Enable all site in..." option and press OK

Wait for the upgrade to finish, and violá: the term 'New-SPExcelServiceApplication' is now available!

Tags: ,

Exporting existing wsp packages from SharePoint

by Martin Buus Østergaard 5. juli 2010 13:01

I'm currently working on a project with migrating from one SharePoint installation to another newer installation. For this project, the client has a couple of installed wsp's in the farm. But they do not have the wsp's to reinstall them... So I somehow had to write up some code that could export a given wsp from the farm. I ended up writing an extension for STSADM (yeah, I know, I should use PowerShell, but I'm an oldie for a little longer :-)). I thought, I'd share the end result with those who wanted to give it a go. (Use the supplied wsp at your own risk)

The source code goes here:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.StsAdmin;
using System.Collections.Specialized;
using Microsoft.SharePoint.Administration;

namespace ExportWSP
{
	public class ExportWSP : ISPStsadmCommand
	{
		public string GetHelpMessage(string command)
		{
			return "-wsp ";
		}

		public int Run(string command, StringDictionary keyValues, out string output)
		{
			if (!keyValues.ContainsKey("wsp") && !keyValues.ContainsKey("all"))
			{
				throw new InvalidOperationException(string.Format("USAGE: -eit-exportwsp -wsp  [-all]. You supplied wsp: {0}, all: {1}", keyValues["wsp"], keyValues["all"]));
			}

			try
			{
				this.ExportWSPPackage(keyValues);
			}
			catch (Exception ex)
			{
				output = ex.Message;
				return 1;
			}

			output = "Success";
			return 0;
		}

		private void ExportWSPPackage(StringDictionary keys)
		{
			if (keys.ContainsKey("all"))
			{
				foreach (SPSolution sol in SPFarm.Local.Solutions)
				{
					this.ExportWSPPackage(sol.Name);
				}
			}
			else
			{
				this.ExportWSPPackage(keys["wsp"]);
			}
		}

		private void ExportWSPPackage(string wspName)
		{
			//Get reference to solution
			SPSolution sol = SPFarm.Local.Solutions[wspName];

			if (sol != null)
			{
				//Save file (assuming it does so to the execution path
				sol.SolutionFile.SaveAs(wspName);
			}
			else
			{
				throw new InvalidOperationException("Solution does not seem to exist");
			}
		}
	}
}

Below is a link to the wsp-file. The project has been built with STSDev a tool I absolutely love when developing SharePoint solutions!

To use the extension, simply use one of the following commands:

stsadm -o eit-exportwsp -all , or
stsadm -o eit-exportwsp -wsp <NAME OF WSP TO EXPORT>

The first line exports all the wsp's in the farm to the folder the command is executed from. The second export the given wsp to the folder the command is executed from.

Parameters explained:
-all: Exports ALL WSP's in the farm
-wsp <NAME OF WSP TO EXPORT>: exports a single wsp from the farm.

To install the solution, simply use:

stsadm -o addsolution -f exportwsp.wsp
stsadm -o deploysolution -n ExportWSP.wsp -imm -allowgac
stsadm -o execadmsvcjobs

 

ExportWSP.wsp (8,21 kb)

Tags: , , , ,

.NET | MOSS

SharePoint 2010 Search Service

by Martin Buus Østergaard 24. marts 2010 12:46

I've now moved on to the testing state of SharePoint 2010. This requires, between many other things, to configure your Search Service Application. But what good does this do you, when you cannot create an Search Service Application?? I got an error when trying to create the Search Service Application:

Errors were encountered during the configuration of the Search Service Application. Requested registry access is not allowed.
[More gibberish in form of stacktrace, but the stacktrace didn't help at ALL, it didn't tell me which key in the registry that were inaccessible]

So I got the input to use the Process Monitor from Microsoft (formerly RegMon by SysInternals). Using this, I was able to pinpoint the key in error: "HKLM\SOFTWARE\Microsoft\Shared Tools\Web server extensions\14.0\Secure\FarmAdmin" and the user that didn't have access (my App Pool identity, strange...). Using regedit to navigate to the key in question, I could now add the permissions to the user (app pool identity).
After doing this it worked :) :

Hope this can help someone out there.

As the used environment is only for testing purposes, I don't care about the real impact of just adding permissions directly on a registry key. In the real world you might consider other ways around (in short: do it right from the start ;) )

Tags: , ,

SharePoint SearchBoxEx and OSSSearchResults.aspx

by Martin Buus Østergaard 12. marts 2010 14:09

I've been working on a solution for a client, where I where to add a searchbox to the masterpage. This wasn't hard: just add a SearchBoxEx web control to the page, give it the runat="server", add the ScopeDisplayGroupName="[Name-of-scope-goes-here]" and go! This seemed somehow to do the job. Search results seem to be presented... But even though I had set the Search Center setting in the Site Settings to /Search/Pages, the results where always displayed on the /_layouts/OSSSearchResults.aspx page. Some of the scopes had a cusotm results page, but SharePoint didn't seem to honor this setting.
Enter the UseSiteDefaults-property of the SearchBoxEx control: this is per default set to false :( This has to be set to true, if you want to use the custom settings in the site and scopes! Resulting markup for SearchBoxEx:

<SPSWC:SearchBoxEx runat="server" TextBeforeDropDown="" ScopeDisplayGroupName="DisplayGroupName" UseSiteDefaults="true" />

This caused the searchbox to use the correct search settings (e.g.: peopleresults.aspx and results.aspx in the search center)

Easy as pie in the end, but hard to find out Yell

Tags: , ,

.NET | MOSS

Sharepoint: This page has been modified

by Martin Buus Østergaard 18. august 2009 12:40

I've implemented a solution for a customer, where we created a site definition template. In the onet.xml-file we defined some modules for default pages. Fairly easy. We created an aspx-page that resembled the layout page in the feature for the web-project. This means: we actually cerated the same markup twice, we even inherited from the same class! This seemed to work fine. It's noteworthy that the installation is running SP2. The problems started to occur a little later up the development cyclus, when our tester would perform normal content editing tests. When he edited a default page (only the one created by the module in the site def, not if you changed the default page to another) it would say that the page has been modified since it had been checked out. Weird was, that it didn't seem to be consistent when it did it or not. Sometimes editing and saving/publishing the page worked like a charm Yell I didn't take the time to look into the problem, so I just said it was a setup issue, and it would be a problem in the production environment later on. But it became a big problem!!

I read a lot of places, the your pages had to inherit from the TemplateRedirectionPage-class. Our class inherited from the PublishingPage-class so I tried to change the inheritance to the TemplateRedirectionPage. This did NOT do the trick! It blew up the page with more strange ASP.NET errors. Eventually I found out, it was only the aspx in the site def template dir (placed in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\SiteTemplates) had to inherit from this class. but it didn't seem to help either; it still gave strange errors. At last I figured out, I had to remove ALL the markup from the aspx in the site def template dir! Then it would use my page layout in the web-feature instead! Just as defined in the onet.xml-module!

Example from onet.xml:

		<Module Name="DefaultCustomerPage" Url="$Resources:cmscore,List_Pages_UrlName;" Path="">
			<File Url="Default.aspx" Type="GhostableInLibrary" Path="CustomerSectionPage.aspx">
				<Property Name="Title" Value="$Resources:cmscore,IPPT_HomeWelcomePage_Title;" />
				<Property Name="MasterPageUrl" Value="~SiteCollection/_catalogs/masterpage/Customer.master" />
				<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/CustomerSectionPage.aspx, Customer section page" />
				<Property Name="ContentType" Value="Customer section page" />
				<Property Name="PublishingAssociatedContentType"
Value=";#Customer section page;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390095C37FB9ADBD44F59D2F0889858A3913;#" />
			</File>
		</Module>

Example from aspx:

<%@ Page Inherits="Microsoft.SharePoint.Publishing.TemplateRedirectionPage,Microsoft.SharePoint.Publishing,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %> <%@ Reference VirtualPath="~TemplatePageUrl" %> <%@ Reference VirtualPath="~masterurl/custom.master" %>

The example of the aspx has to be in ONE single line, two lines didn't work for me!

Tags: ,

.NET | MOSS

SharePoint Logs: Preserving template record with size XXXX

by Martin Buus Østergaard 9. juli 2009 10:20

Frankly I'm not quite sure what this error means, but my SharePoint Logs has been bombarded with these entries ("Preserving template record with size"). I would get around a 100 entries almost every second!!! Too much info! And too big log-files! The server filled up with 1gb of log-files within ½ a day :(

The solution, which worked for me, was to apply kb968850 to the server. Go get it boys and girls!

Tags: ,

MOSS

Following up on edit, display and new form

by Martin Buus Østergaard 8. juli 2009 10:49

Following up on Customizing DispForm, EditForm and NewForm

I've found out how to not override the RenderTemplates. "All" you have to do is:

  1. Create classes (in .cs-files) which overrides the classes, you want to customize
  2. Make sure to register both the assembly and the namespace in the ascx
  3. assign new ID's to the rendertemplates in your ascx

This is what I did in the ascx:

<%@ Control Language="C#" AutoEventWireup="false" %>
<%@Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@Assembly Name="Customer.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXX" %>
<%@Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.WebControls"%>
<%@Register TagPrefix="SPHttpUtility" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Utilities"%>
<%@ Register TagPrefix="wssuc" TagName="ToolBar" src="/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" src="/_controltemplates/ToolBarButton.ascx" %>
<%@ Register TagPrefix="Customer" Assembly="Customer.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXX" Namespace="Customer.Controls.CustomControls" %>

<SharePoint:RenderingTemplate ID="MyListForm" runat="server">
 <Template>
 <div id="text">
  <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator=" " runat="server">
    <Template_RightButtons>
     <SharePoint:NextPageButton runat="server"/>
     <SharePoint:SaveButton runat="server"/>
     <SharePoint:GoBackButton runat="server"/>
    </Template_RightButtons>
  </wssuc:ToolBar>
  <SharePoint:FormToolBar runat="server"/>
  <Customer:EmployeeFieldIterator runat="server"/>
 </div>
 </Template>
</SharePoint:RenderingTemplate>

<SharePoint:RenderingTemplate ID="EmployeeDisplayCompositeField" runat="server">
 <Template>
  <h3><SharePoint:FieldLabel runat="server"/></h3>
  <p><SharePoint:FormField runat="server" /></p>
  <SharePoint:AppendOnlyHistory runat="server"/>
 </Template>
</SharePoint:RenderingTemplate>

<SharePoint:RenderingTemplate ID="EmployeeFormIterator" runat="server">
 <Template>
  <Customer:EmployeeCompositeField runat="server"/>
 </Template>
</SharePoint:RenderingTemplate>

<SharePoint:RenderingTemplate ID="EmployeeCompositeField" runat="server">
 <Template>
  <h3><SharePoint:FieldLabel runat="server"/></h3>
  <p><SharePoint:FormField runat="server"/></p>
  <p><SharePoint:FieldDescription runat="server"/></p>
  <SharePoint:AppendOnlyHistory runat="server"/>
 </Template>
</SharePoint:RenderingTemplate>

I've made the overriden classes in one .cs (not very best-practice, but it does the job!):

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI.HtmlControls;

namespace Customer.Controls.CustomControls
{
 public class EmployeeFieldIterator : ListFieldIterator
 {
  protected override string DefaultTemplateName
  {
   get
   {
    return "EmployeeFormIterator";
   }
  }
 }

 public class EmployeeDisplayCompositeField : CompositeField
 {
  protected override string DefaultTemplateName
  {
   get
   {
    if (SPContext.Current.FormContext.FormMode == SPControlMode.Edit || SPContext.Current.FormContext.FormMode == SPControlMode.New)
     return "EmployeeCompositeField";
    else
     return "EmployeeDisplayCompositeField";
   }
  }
 }

 public class EmployeeCompositeField : CompositeField
 {
  protected override string DefaultTemplateName
  {
   get
   {
    if (SPContext.Current.FormContext.FormMode == SPControlMode.Edit || SPContext.Current.FormContext.FormMode == SPControlMode.New)
     return "EmployeeCompositeField";
    else
     return "EmployeeDisplayCompositeField";
   }
  }
 }
}

Notice the only thing I do is to ovevrride the DefaultTemplateName-property and return the ID of the RenderTemplate in the ASCX. Fairly easy.

If you expirience problems with the above, try searching through your latest SharePoint Logs in the 12-hive. That helped me!

Happy SharePointing!

Tags: , , , , ,

MOSS

Customizing DispForm, EditForm and NewForm

by Martin Buus Østergaard 8. juli 2009 08:30

EDIT UPDATE: This post is followed up in Following up on edit, display and new form

I am doing a project for a client who wants a listitem details page to be customized (DispForm, EditForm and NewForm that is). At first this seemed like a trivial task, but I found out it would involve lots of research and editing.

First of all, to customize DispForm, EditForm and NewForm you have to make up your mind on one of two approaches (there might be more):

  1. Do you want the customization to be bound to a specific content type?
  2. Or do you want it to be tied to a specific list template?

I choose the first option. I tried the second but I couldn't make it work... The following is what I had to customize to achive my goal in this matter.

  1. Customize the ContentType-element in my feature
  2. Create an ascx to hold my customization
  3. Create new RenderTemplates
  4. Override existing RenderTemplates
  5. Deploy customization

First off, you have to make an XmlDocuments-element as a child element to your ContentType-element in your feature:


In the above CAML I've bound the customization to the content type by adding the XmlDocument child-element to the ContentType-element. In this example I've used the MyListForm-template for all the scenarios: display, edit and new. This means, it uses the same rendering for the three scenarios (don't worry, kids, it will render textboxes and the like when in new- or edit-mode, I'll get back to that).

Next off, I've created an ascx-control which is deployed to 12/TEMPLATES/CONTROLTEMPLATES. The name of the ascx doesn't matter, what matters is what is inside the ascx! In the ascx you have your rendering-templates. This is basically how you want your view to be rendered. This is what's inside the ascx:

<%@ Control Language="C#" AutoEventWireup="false" %>
<%@Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.WebControls"%>
<%@Register TagPrefix="SPHttpUtility" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Utilities"%>
<%@ Register TagPrefix="wssuc" TagName="ToolBar" src="/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" src="/_controltemplates/ToolBarButton.ascx" %>

<SharePoint:RenderingTemplate ID="MyListForm" runat="server">
 <Template>
 <div id="text">
  <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop"
 RightButtonSeparator=" " runat="server">
    <Template_RightButtons>
     <SharePoint:NextPageButton runat="server"/>
     <SharePoint:SaveButton runat="server"/>
     <SharePoint:GoBackButton runat="server"/>
    </Template_RightButtons>
  </wssuc:ToolBar>
  <SharePoint:FormToolBar runat="server"/>
  <SharePoint:ListFieldIterator runat="server"/>
 </div>
 </Template>
</SharePoint:RenderingTemplate>

<SharePoint:RenderingTemplate ID="DisplayCompositeField" runat="server">
 <Template>
  <h3><SharePoint:FieldLabel runat="server"/></h3>
  <p><SharePoint:FormField runat="server" /></p>
  <SharePoint:AppendOnlyHistory runat="server"/>
 </Template>
</SharePoint:RenderingTemplate>

<SharePoint:RenderingTemplate ID="ListFieldIterator" runat="server">
 <Template>
  <SharePoint:CompositeField runat="server"/>
 </Template>
</SharePoint:RenderingTemplate>

<SharePoint:RenderingTemplate ID="CompositeField" runat="server">
 <Template>
  <h3><SharePoint:FieldLabel runat="server"/></h3>
  <p><SharePoint:FormField runat="server"/></p>
  <p><SharePoint:FieldDescription runat="server"/></p>
  <SharePoint:AppendOnlyHistory runat="server"/>
 </Template>
</SharePoint:RenderingTemplate>

Above code explained: Part of it has been taken from the DefaultTemplates.ascx in the 12/TEMPLATES/CONTROLTEMPLATES-dir. The SharePoint:RenderTemplate with the ID="MyListForm" is my own and the ID is correpsonding to ID in the ContentType's Display-, Edit- and New-elements. The MyListForm is a "copy" of the ID="ListForm"-template in DefaultTemplates.ascx, just customized. As I said, you can assign different rendering-templates to the three scenatios, I choose the same for all of them.
To accomplish a custom rendering to my liking, I had to override the DisplayCompositeField (which is the template used for the display-mode), the ListFieldIterator-template, which iterates fields (regardless of the display/new/edit-mode) and the CompositeField-template which renders the inputs when in edit mode.
(As of writing I've found out that the overridden templates also has effect on the rendering of all other listitems, and not just the rendering of the contenttype in question (Employee Item) :( I'll have to fix this later, if you find a way to do this, please let me know)

When deploying, make sure your ascx goes to the 12/TEMPLATES/CONTROLTEMPLATES-dir. Do an IISRESET because SharePoint is caching the contents of the renderingtemplates. IISRESET is done if you perform a real deploysolution or upgradesolution with stsadm, but not if you just manually copy the ascx to the 12/TEMPLATES/CONTROLTEMPLATES-dir.

EDIT UPDATE: This post is followed up in Following up on edit, display and new form

Tags: , , , , ,

MOSS

Sharepoint timer jobs, GAC and development

by Martin Buus Østergaard 27. maj 2009 11:16

I've been developing a feature that contains a list, a webpart (a customized CQWP) to display the contents of the list and a timerjob. For the last part (the timerjob) I create an assembly, which deploys to the GAC. This is all swell untill the point where I'm no longer satisfied with functionality of the dll and change the code. Redeploying to GAC, upgrading solution, nothing helps... :( Even resetting the IIS!! The dll still stays in the GAC cache. It appears to be removed from the GAC when reinstalling, but the functionality is still that of the old code...

What to do is, that you have to use gacutil. One simple command: "gacutil.exe -cdl".
After this I recommend you you delete your temporary ASP.NET files. For me, running a Windows 2k8 64-bit this is done by running this command: 'rmdir "C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files" /s /q'.
This might be troublesome if your apppool still has handles in the GAC, so you might need to recycle your apppools before issuing the last command, or, sometimes even better yet, run an IISRESET.

My co-worker Ulrich pointed me to an interesting post which led to above solution: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/4bdd28d0-af2b-4ddf-bf9c-efaeee023139

EDIT 090722: If the above still doesn't seem to do the trick, try to restart the "Windows SharePoint Services Timer" in Services. Then you might be good to go

Tags: , , , ,

MOSS

Long time no writing - new project coming up

by Martin Buus Østergaard 6. maj 2009 16:05

It's been a while since the last time I wrote a blog-post. I've been hung up on work, and I've been to United Bluff :)

I'm now done with the publishing site I've referred to earlier and I'm now going to undertake a smaller project (still as technical project manager) on a collaboration portal. Of course still MOSS :)
In my toolbox for this project, I'll definitely be using these tools:

I HIGHLY recommend having these in your toolbox!

UPDATE 090709:

I've run into other tools which speeded up the development process, and learned me even more about MOSS:

 

Tags: , ,

.NET | MOSS

Powered by BlogEngine.NET 1.6.1.0
Theme by Extensive SEO

Om mig / About

(English follows)
Martin Buus Østergaard er født i november 1980. Bosiddende i Fredensborg, ude i Asminderød. Her bor min hustru Christina og jeg i et dejligt rækkehus. Her er god plads, højt til loftet og udsigt over Knurrenborgvang Skov. Skønt, skulle jeg hilse og sige!
Jeg arbejder hos epista IT som senior konsulent, nærmere betegnet med rådgivning, integration, udvikling og arkitektur på SharePoint-platformen.
Jeg har en profil på LinkedIn, og en på Facebook

English:

Welcome!
I am Martin Buus Østergaard, born november 1980.
I work at epista IT as a technical project manager and senior developer, mostly with SharePoint and integration in .NET C#.
Take a look at my LinkedIn-profile

Recent comments

Comment RSS