Wednesday, November 12, 2008

SharePoint Performance Analysis Tool

This is a re-post from the Microsoft SharePoint Team Blog.  They’re releasing a tool in the next couple of weeks that allows you to do a very quick analysis of your SharePoint code’s performance. It focuses around disposing of SharePoint objects properly in your code, and “using (SPWeb web) …” coding techniques to ensure objects are released from memory when a code block exits. 

As soon as it drops I’ll make sure I post about it again and provide a download link.  In the meantime, this blog post directs us to a few best practices articles about how to properly manage memory for high-performance SharePoint code: 

 

The SPSite and SPWeb Dispose() methods are an important thing for developers who work with Microsoft SharePoint Products and Technologies to master. Many SharePoint API's allocate COM based memory that is not released by CLR garbage collection and must be released by calling the Dispose() methods. Microsoft Guidance for when to call SPSite and SPWeb Dispose() methods have been published in this MSDN whitepaper by Mike Ammerlaan and Scott Harris. In addition, Roger Lamb has provided additional detail and discussion on his MSDN SharePoint Developer blog. This guidance applies only to customers building custom software that they compiled to .NET assemblies that make use of SharePoint API calls.  Also, an update to the MSDN whitepaper is being planned to reflect key guidance from the blogs.

Microsoft wants to help developers build better quality code that manages available memory better. We are now building a console tool that will help to evaluate customer code against the guidance that is provided. The tool, calledSPDisposeCheck, will open your custom compiled assemblies recursively and validate them against the Microsoft published guidance. The output from the tool will contain messages that may indicate the SPSite and SPWeb Dispose() methods guidance is are not being followed in the customers source code. While these messages need expert evaluation in order to determine if the software is not performing properly, in some cases just running the tool on your custom code can lead you to simple fixes that improve the quality and performance of custom code on SharePoint. This tool is planned for release during the coming North American Winter.  Customers who are currently experiencing difficulties with memory management in their custom applications should review the guidance listed above.  Customers who are currently experiencing difficulties with Microsoft Office SharePoint Server 2007 should contact their regular Microsoft Customer Support Services contact, or refer to http://support.microsoft.com.

References:

Best Practices: Using Disposable Windows SharePoint Services Objects

Best Practices: Common Coding Issues When Using the SharePoint Object Model

SharePoint Tools for Visual Studio 2010

This is admittedly getting a bit ahead, but I ran across some information about tool support for SharePoint developers in the upcoming VS2010.  From what I had heard, there wasn’t much discussion at PDC.  At a more recent conference though they shed some light on what sounds like a great toolset for SharePoint developers in the upcoming release of Visual Studio: 

  • Server Explorer for SharePoint viewing Lists and other artifacts in SharePoint directly inside of Visual Studio

  • Windows SharePoint Services Project (WSP file) Import to create a new solution

  • Added a new web part project item and showed the Visual web part designer which loads a user control as a web part for SharePoint

  • Showed adding an event receiver for SharePoint and using the wizard to choose the event receiver and to just create a source file with that event receiver.

  • Added an ASPX workflow initiation form to a workflow project and showed how this workflow initiation form has designer capability

  • Showed the packaging explorer and the packaging editor which lets you structure the SharePoint features and WSP file that is created

More on http://channel9.msdn.com/tags/Visual+Studio+2010/

Monday, October 20, 2008

SharePoint Timer Jobs (in a little more depth)

I’ve posted before on an issue I ran into with a timer job related to using an “SPDailySchedule.”  That post didn’t show an example of creating and deploying a timer job end-to-end, so this post will. 

This walk-through assumes you’re using STSDEV (which I strongly recommend – saves a bunch of time).  In STSDEV, choose a “Simple Feature Solution (C# assembly):

1

 
Also choose “Site” for the feature scope and remember to include a feature receiver:

2


STSDEV will give you the folder structure and FeatureReceiver.cs class you need to get started.  For the timer job, we just need to create a class that inherits from “SPJobDefinition” and overrides a few events and constructors.  (You’ll need to add “using” statements for “Microsoft.SharePoint” and “Microsoft.SharePoint.Administration.”) 

All four of these constructors must be overridden.  Here’s what my class looks like with just the overridden constructors:


using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace ORNL.EnterpriseApplications.PublicationTracking.PtsRoleImport
{
    public class RoleImportTimerJob : SPJobDefinition
    {
        public RoleImportTimerJob() : base() { }

        public RoleImportTimerJob(string jobName, SPService service, SPServer server, SPJobLockType targetType)
            : base(jobName, service, server, targetType)
        {

        }

        public RoleImportTimerJob(string jobName, SPWebApplication webApplication)
            : base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
        {
            this.Title = "PTS Role Import Timer Job";
        }

        public RoleImportTimerJob(SPWebApplication webApp)
            : base("PTS Role Import Timer Job", webApp, null, SPJobLockType.ContentDatabase)
        {
            this.Title = "PTS Role Import Timer Job";
        }

    }
}


Override the Execute() Method

The Execute() method is where the real work happens when your timer job fires.  The method signature looks like this:

public override void Execute(Guid targetInstanceId) {  }


Add the logic required to make your Execute() method do what’s required from your timer job, then you’re about 90% done. 


The last thing to do is use your FeatureReceiver.cs class to handle the installation and un-installation of your timer job.


FeatureReceiver Class

The FeatureReceiver.cs class that STSDEV provides should give you the skeleton you need for your feature receiver (it’s also automatically wired up the necessary entries in your feature.xml, which is handy). 

We just need to tell our feature receiver class how to install and uninstall the timer job. 

Here’s my overridden “FeatureActivated” method:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPSite site = properties.Feature.Parent as SPSite;

    // Make sure the timer job isn't already registered
    foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
    {
        if (job.Name == "PTS Role Import Timer Job" || job.Title == "PTS Role Import Timer Job")
        {
            job.Delete();
        }
    }

    // Install the job
    RoleImportTimerJob timerJob = new RoleImportTimerJob(site.WebApplication);

    // Set the schedule - nightly at 1:15 am
    SPSchedule customSchedule = SPSchedule.FromString("daily at 01:15");

    timerJob.Schedule = customSchedule;
    timerJob.Update();

}

 

And here’s my “FeatureDeactivating” method:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    SPSite site = properties.Feature.Parent as SPSite;

    // Make sure the timer job isn't already registered
    foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
    {
        if (job.Name == "PTS Role Import Timer Job" || job.Title == "PTS Role Import Timer Job")
        {
            job.Delete();
        }
    }
}

Tuesday, October 14, 2008

Custom Build Properties in Central Team Build

I’m wrapping up the configuration of my Team Build in Team Foundation Server for a project, and ran into a problem with an MSBuild command.  My application writes to the SharePoint Unified Logging System (ULS) logs, and the class required to do that uses “unsafe” code.  Unsafe code causes the regular compiler (csc.exe) to throw an error while building in Visual Studio.  Overcoming that can be done in the IDE – simply open the “Properties” window for your project and check off “Allow unsafe code blocks” on the “Build” tab for all different configurations you plan to use (for example, “Debug” and “Release”). 

It’s less straight-forward when your build is happening on another box, namely the Team Server.  To do this (assuming you’ve taken the steps from Rob’s posts to set up central build to begin with), you simply need to add this property in your TFSBuild.proj file: 

  <CustomPropertiesForBuild>AllowUnsafeBlocks=true</CustomPropertiesForBuild>


As we become more standardized on using the ULS logs as our primary mechanism for diagnostics in SharePoint web parts and other artifacts, you might run into this.  If you do, hope this helps!

Silverlight 2 Released


The final-release version of Silverlight 2.0 was just released.  This includes the Silverlight runtime, Visual Studio SDK and tools, and some other tools like Microsoft Expression Blend 2 and DeepZoom Composer.  I’m uncertain if DeepZoom is actually an updated version or if Microsoft is just drawing attention to it with this release, but if you’re interested in the tool might as well grab the latest copy. 

Here’s the best link I’ve found that has links to download all the components, as well as tutorials and video walk-throughs: 

http://silverlight.net/GetStarted/


Enjoy!

Wednesday, October 8, 2008

Programmatically Upload Documents to a SP Doc Library


I’m rather late getting around to posting this, but for anyone who has to program against a SharePoint document library (or the SPListItems that those documents correspond to), I hope this can be a quick jump-start. 

While migrating a large enterprise application to SharePoint, we had to make sure that the EIGHTEEN GIGABYTES of documents came along with the rest of the application.  (For anyone who’s curious about the performance considerations involved in such an effort, I’d be glad to discuss). 

But as far as the actual uploading of the documents to the SharePoint document library, then subsequently setting a few properties on the newly-uploaded documents, I think once you check out the source code you’ll agree it’s actually rather straight forward. 

So I’ll let the source do the talking …

// Open the site and web
SPSite site = new SPSite(txtSite.Text);
SPWeb web = site.OpenWeb();
SPFolder docLibFolder = web.GetFolder(txtDocumentLibrary.Text);

// Read the file on disk into a FileStream
FileStream fs;
Byte[] docContents;
fs = File.OpenRead(fileName);
docContents = new byte[Convert.ToInt32(fs.Length)];
fs.Read(docContents, 0, Convert.ToInt32(fs.Length));

// Perform the actual upload to the SP doc library
SPFile uploadedFile;
uploadedFile = docLibFolder.Files.Add(documentTitle, docContents);

// The “.Add()” method return to us a reference to the document’s
// corresponding SPListItem object. Here we can set properies as needed.
SPListItem listItem;
listItem = uploadedFile.Item;

listItem["Title"] = documentTitle;
listItem["Name"] = documentTitle;

listItem.Update();

// Close our FileStream object to release the resources
fs.Close();

Custom SharePoint Timer Jobs


This post certainly doesn’t walk you through the steps of authoring a custom SharePoint timer job.  It does highlight one issue I ran into though while I was building one recently that seems to be a plain old bug.  After struggling with it for some time, I thought I’d drop a quick post with the hopes it will save someone else the headache! 

The structure of a customer timer job is actually pretty simple – you need a class that inherits from “SPJobDefinition,” that overrides a few constructors as well as the Execute() method.  The Execute() method defines what actually happens when your timer job elapses and gets fired. 

To install your timer job and register in Central Admin, you need a FeatureReceiver.cs class.  It’s not in the scope of this brief post to go through the details of the FeatureReceiver class (but of course email me if you’re stuck!).  The FeatureReceiver for my timer job overrides the “FeatureActivated” and “FeatureDeactivating” events.  The area that was giving me trouble was in the “FeatureActivated” event.  I wanted my timer job to run once per day at 1:45 am.  The code looked something like this:

// Install the job
AggregatorTimerJob aggregatorTimerJob = new AggregatorTimerJob(site.WebApplication);

// Set the schedule - run once daily
SPDailySchedule dailySchedule = new SPDailySchedule();
dailySchedule.BeginHour = 1;
dailySchedule.BeginMinute = 45;
dailySchedule.BeginSecond = 0;

aggregatorTimerJob.Schedule = dailySchedule;
aggregatorTimerJob.Update();


Seems simple enough!  However after hours of experimenting with the SPDailySchedule, and searching for answers, I simply could NOT get this thing to run on a daily schedule.  Most frustrating was that using an “SPMinuteSchedule” or “SPHourlySchedule” worked beautifully!

After much searching I finally concluded that using the “SPDailySchedule” approach seems to universally fail – that seemed to be the consensus amongst the community. 

So … the Workaround

I think this is an easier, more straight-forward approach anyway, so I hesitate to call it a “work-around” at all!  I ended up using the “SPCustomSchedule” class and defining its run schedule as a free-form string parameter as follows.  Works like a charm – on my environment, all the way through production without any issues!

SPSchedule customSchedule = SPSchedule.FromString("daily at 01:45");

aggregatorTimerJob.Schedule = customSchedule;
aggregatorTimerJob.Update();

Podcasting Kit for SharePoint (Sept. 2008)


I had been keeping my eye on this project on CodePlex for sometime, and the team recently dropped their September release.  The Podcasting Kit s really quite cool, and could provide and additional avenue for communication for within our Apps team, and possibly throughout the enterprise.  I could come up with dozens of uses for it, but I’ll spare you and simply cite the team’s description of its capabilities. 

It’s located on CodePlex here: 
http://www.codeplex.com/pks

 

What Can You Do With Podcasting Kit for SharePoint (PKS)?:
  • Listen and watch audio/video podcasts, anywhere on your PC or mobile device (Zune, SmartPhone, or any podcasting device)
  • Share content by producing your own audio/video podcasts and publish them on PKS on your own.
  • Connect and engage with podcasters via your integrated instant messaging program
  • Find the most relevant content using the five star rating system, tag cloud, search engine and provide your feedback via comments.
  • Get automatic podcast updates by subscribing to RSS feeds fully compatible with Zune and other podcasting devices
    • Simple RSS feed based on a defined podcast series
    • Simple RSS feed based on a person
    • Dynamic RSS feed based on search results (will be implemented later in 2009)
  • Play podcasts in real-time using Microsoft® Silverlight™ and progressive playback
  • Retrieve instant ROI and metrics with the ability to track the number of podcasts downloaded and/or viewed, instant feedback via rating system and comments, and subscribers via the RSS feed
  • Access the richness of SharePoint to extend the solution: workflows, community sub-sites, access rights, editorial and more
  • Customize your own PKS User Experience

Enable the “Delete” Button in Timer Job Definitions


This is a trick I picked up from Brett when we were deploying a custom SharePoint timer job last week.  Quite a handy trick that allows you to delete a timer job definition directly from Central Administration without the needed for the STSADM.EXE commands. 

From Central Administration > Operations > Timer Job Definitions, when you click on a job definition you see a screen similar to this:

TimerJobDeleteButton1


To enable the “Delete” button from this same screen, we simply have to modify an ASPX file under the “12” hive.  Under “\12\TEMPLATE\ADMIN”, find the file named “JobEdit.aspx” and open it with Notepad.  Find the line of markup containing:

OnClick="BtnDeleteJob_Click"

That control has its “visible” property set to “false.”  Simply change that to “true” and save the file.  Then refresh the page, and sure enough – we have a Delete button!

TimerJobDeleteButton2

Free Upgrade for VMWare Fusion Users


For anyone running their SharePoint virtual environment on a Mac with VMWare Fusion, VMWare announced a free upgrade for users who purchased version 1.x of the product to upgrade to 2.0. 

I’ve only played around with it briefly, but at a glance it’s a very worthwhile upgrade.  VMWare’s synopsis of the enhancements and additional features are below. And the download link is here: 

http://www.vmware.com/download/fusion/

 

Multiple Snapshots and AutoProtect

  • Save your virtual machine in any number of states, and return to those states at any time
  • New Snapshot UI to help you manage all the snapshots you have saved
  • Automatically take snapshots at regular intervals with AutoProtect

Shared Folders Improvement and Mirrored Folders

  • Shared Folders are easier to discover. New Shared Folders option in Status bar and Virtual Machine menu. Can open all Shared Folders or just a specific Shared Folder in the virtual machine
  • Greatly improved reliability of shared folders—now compatible with Microsoft Office, Visual Studio, and QuickBooks
  • Improved compatibility running Java applications from a Shared Folder
  • Map key folders in Windows Vista and Windows XP (Desktop, My Documents, My Music, My Pictures) to their corresponding Mac folders (Desktop, Documents, Music, and Pictures)

URL Handling

  • Click on a URL in a virtual machine and open it in your favorite Mac browser, or configure your Mac to open its links in a virtual machine
  • VMware Fusion supports opening URLs of the following types: Web pages (http, https), Remote Sessions (telnet, ssh), Mail (mailto), Newsgroups (news), File transfers (ftp, sftp), and RSS feeds (feed)

Application Sharing

  • Allow your Mac to open applications in the virtual machine—Finder can now open your Mac's files directly in Windows applications like Microsoft Word and Windows Media Player
  • Allow the virtual machine to open applications on your Mac—VMware Fusion can configure virtual machines to open their files in Mac applications like Preview and iTunes
  • VMware Fusion can directly open Windows programs (.exe) and installers (.msi) in a virtual machine just by double-clicking on them in Finder

True Multiple Display Support

  • VMware Fusion automatically detects multiple displays by default
  • Your virtual machines will recognize each display you connect to your Mac as a separate virtual display
  • Handles changes to resolution and display orientation automatically
  • Option to use one or all screens in Full Screen mode
  • Unity windows can be dragged between displays, and will maximize correctly to just the display they're on
  • Correctly handles plugging and unplugging displays
  • 3D supported on primary display when using multiple displays

Friday, October 3, 2008

Manually Getting to the “Web Parts Maintenance Page”


Certainly every SharePoint developer has dropped a custom web part onto a page that killed the whole page.  Sometimes SharePoint will prompt you with a link to reach the Web Parts Maintenance Page, sometimes it won’t.  On some occasions (when I’ve really broken something) SharePoint will provide me a hyperlink to the maintenance page, but clicking the link simply throws another irrecoverable error. 

Here are a few screenshots of this rather infuriating error:

1

Clicking the “Web Parts Maintenance Page” hyperlink results in something even less helpful:

2


The Fix / Workaround


So it’s helpful to be able to get to that “web parts maintenance page” for any page, at any time we want.  This might be common knowledge, but I’ll throw this little trick out there in case it can be of any help. 

For any web part page in your SharePoint environment, you can append the query string “?contents=1” after the “.aspx” link and get directly to the web parts maintenance page.  Works every time! 

For example, if your problem page is “http://localhost/sites/MyBrokenSite/default.aspx”, the URL to the maintenance page (where you can easily close or delete the problem web parts) would be “http://localhost/sites/MyBrokenSite/default.aspx?contents=1.” 

3

 

Hope that helps … enjoy!

-- Jon

Sunday, September 21, 2008

“Dryad” by Microsoft Research

Dryad is a Microsoft Research project – they refer to it as its own “infrastructure” actually – that allows programmers to target hugely-clustered platforms without having to change anything about the way in which they author their software.  In their introductory article explaining the project, they cite advantages such as executing code on thousands of machines across and enterprise or even entire datacenter. 

Here’s their summary of the project’s objectives:

Dryad is an infrastructure which allows a programmer to use the resources of a computer cluster or a data center for running data-parallel programs. A Dryad programmer can use thousands of machines, each of them with multiple processors or cores, without knowing anything about concurrent programming.

I would imagine the supercomputers downstairs are probably off limits to us on the Apps team.  But even in much smaller (by comparison) environments, a cluster of n number of computers could be leveraged to run code across a clustered environment, and that clustering and parallelism would be transparent to us as developers. 

In the article, I found it particularly interesting that they mention Dryad being used with familiar technologies such as SSIS (SQL Server Integration Services), and LINQ. 

You can check out the full article here:

http://research.microsoft.com/research/sv/Dryad/

Enabling Remote Errors in SQL Reporting Services

Recently working with reporting services, I ran into this error:

“For more information about this error, navigate to the report server on the local server machine, or enable remote errors.”

The scenario is that reporting services lives on a different box than the SharePoint installation.  The fix is to simply set a flag in a configuration table in the Reporting Services database on the report server.  Pull up a new query in SQL Server Management Studio and run the following UPDATE statement and you should be good to go! 

USE ReportServer
GO

update configurationinfo
set value = 'True'
where name = 'EnableRemoteErrors'
GO

Performance Update Roll-Up for WSS 3.0

Microsoft dropped an Infrastructure Update today (7/15/2008) that addresses some key performance-related aspects of WSS 3.0.

According to the post:

Overview

The Infrastructure Update for Windows SharePoint Services 3.0 (KB951695) includes the latest performance updates and fixes for Microsoft Windows SharePoint Services 3.0.
Key updates for Windows SharePoint Services 3.0 include:

  • Platform performance improvements and fixes.
  • Several backup and restore fixes.
  • Several core Workflow fixes.

It is strongly recommended that you install this update.


I have installed it on my DEV environment with no issue.  To be safe, it wouldn’t hurt to shut down your VPC, make a backup, then apply the update.  The link is here:

http://www.microsoft.com/downloads/details.aspx?FamilyID=256ce3c3-6a42-4953-8e1b-e0bf27fd465b&DisplayLang=en

Tuesday, September 9, 2008

Determine if Your Web Part is in Design Mode

Credit for this goes to David Bond and Rick Phillips, I’m just posting because David mentioned it and I think it’s a helpful tip.  This is being used in PTS web part projects as well as the new RHACS solution.  I think David made a great point in the meeting Tuesday by stating if you’re in design mode, there’s probably no reason you need to be pinging a database or web service, etc.

Here’s the code:

WebPartManager wpm = WebPartManager.GetCurrentWebPartManager(this.Page);
webPartIsInDesignMode = wpm.DisplayMode.AllowPageDesign;