I've been asked a number of times about installation order of SharePoint Portal Server 2003 and Exchange 2003 on a domain controller. “Why on earth would a person want to do that?”, you ask? Well, both SharePoint and Exchange development introduce some rather tricky development scenarios, and rather than butt heads with your local network admin, folks lean to developing within a “sandboxed” environment, like that provided by a virtual machine running in either VMware or Virtual PC , where they could potentially be “mobile“ and not be joined at the hip to servers or their friendly neighborhood admin.
So, with that being said, in order to have both products coexist on the single machine, Exchange must be installed first, then SharePoint Portal Server. The full installation order I typically use is as follows (for simplicity, let's say we're creating a dev environment in a Virtual PC virtual machine):
Done. These are some basic steps that I follow (with a few more additions not listed). Some folks may have different approaches, but this has yielded a 100% success rate for any initial install I've done on my local development machine VMs
Ran across this informative Microsoft Knowledge Base article that gives step-by-step instructions on how to rename a computer that's already running SharePoint Portal Server 2003. I can't count how many times I've been asked that question (even recently). I thought about writing a post that describes the steps, however, this article was right on time
Article URL: http://support.microsoft.com/default.aspx?scid=kb;en-us;830970
This sample code demonstrates how to programmatically add users in SharePoint Portal Server 2003 or Windows SharePoint Services v2.0 (exception handling omitted)
In C#
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
public class MyUserAdminClass
{
public void AddUser(string username, string emailAddress, string fullName, string comments)
{
// get a reference to the current SharePoint site
SPWeb PortalWeb = SPControl.GetContextWeb(Context);
// get a reference to the role that you want to add the user to
SPRole UserRole = PortalWeb.Roles(“Administrator“);
// add the user to the role
UserRole.AddUser(username, emailAddress, fullName, comments);
}
}
In VB.NET
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.WebControls
Public Class MyUserAdminClass
Public Sub AddUser(ByVal username As String, _
ByVal emailAddress As String, _
ByVal fullName As String, ByVal comments As String)
' get a reference to the current SharePoint site
Dim PortalWeb As SPWeb = SPControl.GetContextWeb(Context)
' get a reference to the role that you want to add the user to
Dim UserRole As SPRole = PortalWeb.Roles(“Administrator“)
' add the user to the role
UserRole.AddUser(username, emailAddress, fullName, comments)
End Sub
End Class
Notes:
In my Part 1 of my post on extending SharePoint workflow with event sinks, I talked briefly about essentially creating event sinks to handle events triggered by user interaction with a SharePoint portal and providing custom implementation to handle those events above and beyond that supplied out-of-the-box by SPS 2003. I showed some high level code prototypes on how event sinks are implemented in the context of handling events triggered when posting content to SharePoint doc libraries. In this post, I'll talk a little about how to register your new event sink with SharePoint and associating it to a document library so that your custom code can begin handling events raised by SharePoint.
In order to have SPS recognize your event sink and begin handing event objects to it (the SPListEvent class is spoke about in my last post), you must first enable events for SharePoint document libraries as events are disabled by default. This can usually be accomplished by using the SharePoint admin tools, which are installed when you install SharePoint, to enable document library events. Once you've done this, there are a few housekeeping details that you must complete for the actual event sink code. First, ensure that your event sink classes are defined in a class library project template, as you must deploy your sink as a DLL assembly in the Global Assembly Cache (GAC). Once you've created your class library, you'll need to assign it a GUID and give the assembly a strong name. To generate a GUID, you can use the Create GUID utility located in the Tools menu of Visual Studio.NET (really nifty tool by the way) Be sure that the GUID you create is in Registry Format (option #4 on the Create GUID utility). Copy the newly created GUID to your assembly's <Assembly: GUID> field in the project's AssemblyInfo file (AssemblyInfo.vb for VB.NET users and AssemblyInfo.cs for C#). Also make sure that you define a version number for your assembly in the Assembly Info file and don't accept the default auto numbering scheme VS.NET uses as a prerequisite for insertion into the GAC is a concrete assembly version. For example, your assembly version defined in AssemblyInfo should look something like this:
<Assembly: AssemblyVersion(“1.0.0.0“)>
Compile the project to create a DLL. Once compiled, you'll need to create a strong name for your compiled assembly. To do this, you can make use of the strong name utility, sn.exe, that ships as a part of the .NET Framework SDK. Once you've ran the utility and created an assembly key file, add a reference to this newly created file to your assembly's AssemblyInfo file. For example:
<Assembly: AssemblyKeyFile(”C:\\Temp\\MyAssemblyKeyFile.snk”)>
Recompile the project and copy the compiled assembly to the GAC of the server where SharePoint Portal Server is running.
That's it! Now your new event sink is ready to be used by SPS. To associate your event sink with a document library in your SharePoint solution, go into the portal and view the advanced settings on a given document library web part. You should see an Event Handler section where you can enter the name of your assembly containing your custom event sink code. The assembly name must be in the following format:
NameOfAssemblyWithoutExtension, Version=”VersionNumberGoesHere”, Culture=CultureHere, PublicKeyToken=TokenValueCanBeRetrievedFromGAC.
In the “Class Name” field, simply enter the name of the class in your assembly that implements your custom event sink (for example CustomEvents.MyCustomEventSink).
Done. So basically it's a matter of of (1) creating strong name for a compiled assembly; (2) registering it in the GAC; and (3) Going into SharePoint and associating the new event sink with a document library. Although this post is a little on the verbose side, it's really a 5 minute or less process!! Note, this process works for Windows SharePoint Services as well.
It’s of no surprise that the workflow capabilities within SharePoint Portal Server 2003 leaves a lot to be desired. SharePoint does have decent, but limited, content approval workflow capabilities, however, for large enterprise customers with complex business processes, the limitations of SharePoint’s “out-of-the-box“ content approval flow far outweigh its usefulness. However, what SharePoint lacks in its out-of-the-box feature set, it makes up with a robust and extensible API.
There are many out there who say that in order to achieve the ultimate in SharePoint’s workflow capabilities, you should integrate BizTalk Server into the solution. While I agree with this claim 100%, this shouldn’t discount the tools and capabilities provided by SharePoint to build custom workflow.
One of the key product extensibility features in SPS 2003 that allows developers to provide more robust workflow capabilities is SharePoint’s Event Sink API. Event Sinks allow you to hook into the SharePoint event model and provide custom handlers for the various events that fire as a result of some user action. Now mind you, event sinks in SPS 2003 sport a far better implementation than what was implemented in SPS 2001. And the fact that SPS 2003 is built on top of the .NET framework makes it even more inviting for developers looking to extend their portal solutions. Creating an event sink is as easy as creating a custom .NET class the implements the IListEventSink interface and provide implementation for the single method defined by this interface, OnEvent. The OnEvent method accepts a single argument, an SPListEvent object, that contains all relevant information about the event that was fired. The OnEvent method is call by SharePoint and is passed an instance of the SPListEvent class. The code examples below shows a simple prototype of a custom event sink class implementation for a SharePoint document library.
In C#
using Microsoft.SharePoint;
public class MyCustomEventSink : IListEventSink
{
public void OnEvent(SPListEvent theEvent)
{
// now, do something special based on the type of event fired
switch (theEvent.Type)
{
case SPListEventType.CheckIn:
// do something for document check-in events
break;
case SPListEventType.Update:
// do something when an item on a SharePoint list is updated
break;
}
}
}
In VB.NET
Imports Microsoft.SharePoint
Public Class MyCustomEventSink
Implements IListEventSink
Public Sub OnEvent(ByVal theEvent As SPListEvent)
Implements IListEventSink.OnEvent
' now, do something special based on the type of event
' fired
Select Case theEvent.Type
Case SPListEventType.CheckIn
' do something for document check-in events
Case SPListEventType.Update
' do something when an item on a SharePoint list is
' updated
End Select
End Sub
End Class
Event Sinks provide the ability to create some compelling workflow scenarios using SharePoint Portal Server 2003.