Category Archives: Sharepoint 2007

Change MOSS 2007 server to another Windows 2003 Domain

 

Last week I found that some emails weren't sent by sharepoint. When I created an alert I received an email saying that the alert was just created but after some change in the list no email was sent.

The same problems happened with approval workflows. The email saying the the workflow just started was sent to the document owner but the other emails for the approvers never arrived.

After digging a while in sharepoint admin I found that in the timer job definitions haven't run for some days. Even those jobs with a frequency of minutes.

I also found that the last day that they ran successfully was the day that the IT team decided to change the moss server from one domain to another 🙂

I've followed these instructions How to change service accounts and service account passwords in SharePoint Server 2007 and in Windows SharePoint Services 3.0 and every thing seems fine now. I'll wait for now…

@echo off
rem other app pools
echo *** Updating app pool passwords
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o updateaccountpassword
-userlogin %1 -password %2 -noadmin
rem central admin
echo *** Updating Central Admin password
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o updatefarmcredentials
-userlogin %1 -password %2
rem ssp - new
echo *** Updating ssp password for new installs
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o editssp
-title "SharedServices1" -ssplogin %1 -ssppassword %2
rem ssp - upgrade
echo *** Updating ssp password for upgraded installs
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o editssp
-title "Default Web Site" -ssplogin %1 -ssppassword %2
rem osearch
echo *** Updating osearch password
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o osearch
-farmserviceaccount %1 -farmservicepassword %2
echo *** MANUAL UPDATE NEEDED. To update the password, visit the SSP Web application page,
click Search Settings, and then click Default Content Access Account.
rem spsearch
echo *** Updating spsearch password
"%commonprogramfiles%\Microsoft Shared\Web server extensions\12\BIN\Stsadm.exe" -o spsearch
-farmserviceaccount %1 -farmservicepassword %2
echo *** Updating spsearch content access account
"%commonprogramfiles%\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o spsearch
–farmcontentaccessaccount %1 -farmcontentaccesspassword %2
rem restarting IIS
echo *** Doing soft restart of IIS
iisreset /noforce
echo on

Approval status, MOSS and Sharepoint Designer

I was creating a SPD workflow that checks the approval status field. When you add this condition in SPD, the designer automatically gives you a combo box with all the possible values for the approval status field: 1;#Rejected, …

This works fine if you have your site in English. In my case, I have my site in Portuguese, so the designer gives me the options in Portuguese: 1,#Rejeitado

But, when the workflow is running the actual value for the approval status that is used to check the IF condition is the English value

if 1;#Rejected equals 1;#Rejeitado then

This always returns false. The first argument is given by moss and the other is from the workflow rules built with the SPD.

To solve this bug I found a workaround. I’ve created a workflow string variable that whaen the workflow starts receives the approval status value.

Next, instead of comparing the approval status field, I compare the workflow variable with "1;Rejected". This is possible because in this case I have a text box to fill the value instead of the combo box.

Custom Action for Sharepoint Designer

I'm going to create a custom action for Sharepoint Designer that creates a discussion thread in a discussion list based on the current list item.

I'm going to use the code found here and put it into a SPD custom action.

First create a Workflow Activity Library project in Visual Studio 2005.

 

Rename the Activity1 to MyCustomActivity and add a Code activity.

 

Add the Microsoft.Sharepint.dll and Microsoft.Sharepoint.WorkflowActions.dll assembly reference

Now we're going to create the input properties from where we're going to receive input data from the workflow.

public static DependencyProperty ListIdProperty = DependencyProperty.Register

("ListId", typeof(string), typeof(MyCustomActivity));

 

The ListIdProperty is going to receive the list ID of the list item that we're going to copy to the discussion list (a string representation of the Guid)..

public static DependencyProperty ToListIdProperty = DependencyProperty.Register

("ToListId", typeof(string), typeof(MyCustomActivity));

 

The ToListIdProperty is going to receive the discussion's list ID (a string representation of the Guid).

public static DependencyProperty ListItemProperty = DependencyProperty.Register

("ListItem", typeof(Int32), typeof(MyCustomActivity));

 

This is the list item ID

public static DependencyProperty __ContextProperty = DependencyProperty.Register

("__Context", typeof(WorkflowContext), typeof(MyCustomActivity));

 

And this is a special property that is going to have the workflow context to have access to the current SPWeb.

Then add the public properties

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public string ListId

{

get {return ((string) (base.GetValue(MyCustomActivity.ListIdProperty)));}

set {base.SetValue(MyCustomActivity.ListIdProperty, value);}

}

 

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public string ToListId

{

get {return ((string) (base.GetValue(MyCustomActivity.ToListIdProperty)));}

set {base.SetValue(MyCustomActivity.ToListIdProperty, value);}

}

 

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public Int32 ListItem

{

get {return ((Int32) (base.GetValue(MyCustomActivity.ListItemProperty)));}

set {base.SetValue(MyCustomActivity.ListItemProperty, value);}

}

 

[Description("My description which can be any text I want.")]

[Category("My category which could be anything.")]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

public WorkflowContext __Context

{

get {return ((WorkflowContext)(base.GetValue(MyCustomActivity.__ContextProperty)));}

set {base.SetValue(MyCustomActivity.__ContextProperty, value);}

}

 

Now just add the following code to the Code activity handler

private void _mainCodeActivity_ExecuteCode(object sender, EventArgs e)

{

// get the list

SPList sourceList = __Context.Web.Lists[new Guid(ListId)];

 

// get list item

SPListItem item = __Context.GetListItem(sourceList, ListItem);

 

// get the discussion list

SPList targetList = __Context.Web.Lists[new Guid(ToListId)];

 

// create the discussion item

SPListItem discussionItem = SPUtility.CreateNewDiscussion(targetList.Items, item.Title);

discussionItem.Update();

}

 

Sign the project with a key, compile and put the assembly in GAC.

 

Now you have to define the new action in the WSS.ACTIONS file found in \12\TEMPLATE\1033\Workflow

<Action Name="My Custom Action"

ClassName="SPDCustomActions.MyCustomActivity"

Assembly="SPDCustomActions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a980f97a0f622f27"

AppliesTo="all"

Category="List Actions">

<RuleDesigner Sentence="Create discussion item in %1 to %2.">

<FieldBind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseListItem" />

<FieldBind Field="ToListId" Text="this list" Id="2" DesignerType="ListNames" />

</RuleDesigner>

<Parameters>

<Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />

<Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />

<Parameter Name="ToListId" Type="System.String, mscorlib" Direction="In" />

<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" />

</Parameters>

</Action>

 

Then add the following line to the web.config file of your site collection

<authorizedType Assembly=" SPDCustomActions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a980f97a0f622f27" Namespace=" SPDCustomActions" TypeName="*" Authorized="True" />

 

That's it! Test the action in Sharepoint Designer:

 

How to upload a list template

public static SPFile UploadListTemplate(string siteUrl, string templatePath)

{

using (SPSite site = new SPSite(siteUrl))

{

SPDocumentLibrary templates = (SPDocumentLibrary)site.GetCatalog(SPListTemplateType.
ListTemplateCatalog);

 

System.IO.FileInfo fileInfo = new System.IO.FileInfo(templatePath);

byte[] bytes = System.IO.File.ReadAllBytes(fileInfo.FullName);

 

return templates.RootFolder.Files.Add(fileInfo.Name, bytes);

}

}

How to upload a site template

public static SPFile UploadWebTemplate(string siteUrl, string templatePath)

{

using (SPSite site = new SPSite(siteUrl))

{

SPDocumentLibrary templates = (SPDocumentLibrary)site.GetCatalog(SPListTemplateType.WebTemplateCatalog);

 

System.IO.FileInfo fileInfo = new System.IO.FileInfo(templatePath);

byte[] bytes = System.IO.File.ReadAllBytes(fileInfo.FullName);

 

return templates.RootFolder.Files.Add(fileInfo.Name, bytes);

}

}

How to create an item in a discussion list

Creating a discussion in discussion list is different from creating a simple list item. The code for creating a discussion item is:

using (SPSite site = new SPSite(“SITE URL”))

{

using (SPWeb web = site.OpenWeb())

{

SPList list =web.Lists[“LIST TITLE”];

result = SPUtility.CreateNewDiscussion(list.Items, “SUBJECT”);

result[SPBuiltInFieldId.Body] = “BODY”;

result.Update();

}

}

ItemUpdating, AfterProperties and field names

I was checking for a field value change in a WSS V3 list with the help of event handlers with no success.

In the ItemUpdating event, the list item has the current values of the item and the AfterProperties has the values that the item will have after the update

The problem was that I was using the display name of the field rather than the internal name. In the SPListItem you can use the display name but also the internal name, but with the AfterProperties you can't use the display name. You must use the internal name of the field.

Problems with ItemAdded and ItemUpdated in MOSS

Just followed the steps described by Ted Pattison at Creating and Using Event Handlers in Windows SharePoint Services 3.0 in my MOSS virtual machine to set up event handlers for the ItemAdded and ItemUpdated of a Sharepoint Custom List.

The problem is that I can’t put the event handlers to work. I’ve just removed all the code inside the event handlers and replaced it by some logging just to see if something happens. But nothing happens.

Here is the code:

class RequestIdentificationHandler : SPItemEventReceiver

    {

        public override void  ItemUpdated(SPItemEventProperties properties)

        {

            Log(properties);

        }

        public override void ItemAdded(SPItemEventProperties properties)

        {

            Log(properties);

        }

        private void Log(SPItemEventProperties properties)

        {

            // Some logging code lines

        }

    }

I’ve placed the assembly in the GAC and registered the events:

SPSite site = new SPSite("http://server");

                SPWeb web = site.OpenWeb();

                SPList list = web.Lists["CustomList"];

                string asmName = "Assembly Name";

                string clsName = "Class Name";

                list.EventReceivers.Add(SPEventReceiverType.ItemUpdated, asmName, clsName);

                list.EventReceivers.Add(SPEventReceiverType.ItemAdded, asmName, clsName);

              

I even used Patrick Tisseghem's Free Tool: Register Event Handlers Programmatically (WSS 2007) to register the events but the events don’t work.

But if I replace the events for the synchronous event versions, ItemAdding and ItemUpdating, everything works fine. The problem is that I can’t use these events, I have to use the ItemAdded and ItemUpdated.

I’ve looked into the Services console but everything seems working, and there aren’t no relevant services stopped.

Finally, I remembered that I had a clean Windows Server 2003 virtual machine, so I installed WSS V3 instead of MOSS. After WSS was installed, with the default configurations, I placed the assembly in the GAC, and registered the events and… the events worked!!!

The same code in my WSS V3 virtual machine works and in the MOSS virtual machine doesn’t work. I’ll continue to search for the solution but for now I just have to find a way to replace the events.

Hope to post here soon the solution for the problem…