Wednesday, April 21, 2010

Sharepint 5 - Use SPJobDefinition to schedule a Job

Build a Console Application, reference Microsoft.Sharepoint.dll

Ex 1. If we want to get all the scheduled jobs in a site:

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

class Program
{
static void Main(string[] args)
{

SPSite mySite = new SPSite("http://mysite:port");

foreach (SPJobDefinition job in
mySite.WebApplication.JobDefinitions)
{
Console.WriteLine("JobName: {0} , Last Run time: {1}, Type: {2}",job .Title,job.LastRunTime.ToLongTimeString(),job.Schedule.GetType().ToString()));
}
}
}

Ex 2. If we want to delete a scheduled job.

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

class Program
{
static void Main(string[] args)
{

SPSite mySite = new SPSite("http://mysite:port");

foreach (SPJobDefinition job in
mySite.WebApplication.JobDefinitions)
{
if(job.Title=="My Job")
{job.Delete();}
}
}
}

Ex 3. Now let's talk about Create a Job, and Register and Schedule it.

Create a Console Application, reference Microsoft.Sharepoint.dll, Add a new item class, call this Class MyJob.

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

public class MyJob:SPJobDefinition
{
public MyJob() { }

//Below we can override the constructor
public MyJob(string myJobName, SPWebApplication myWebApplication) : base(myJobName, myWebApplication, null, SPJobLockType.Job) { }


//Notice the key point is to override the Execute Method and
//place our job code inside it.
public override void Execute(Guid ConetentDataBaseID)
{

SPSite mySite = new SPSite("http://mysite:port");
SPWeb myWeb = mySite.OpenWeb();
SPList myList = myWeb.Lists["{***}"];


SPListItem newitem = myList.Items.Add();
newitem["Title"] = "Insert An item Every Day"
newitem.Update();

}
}

This is just a sample job to insert to Lists["{***}"] an item every day, now we in Main entry to register this job and schedule the job using SPDailySchedule.

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

static void Main(string[] args)
{
SPServer myServer = SPServer.Local;
SPSite mySite = new SPSite("http://site:port");
SPWebApplication myApplication = mySite.WebApplication;
SPJobDefinitionCollection myJobsColl = myApplication.JobDefinitions;


MyJob myJob = new MyJob("myJob", myApplication);
myJob.Title = "This is A Test Job";

SPDailySchedule myDailySchedule = new SPDailySchedule();
myDailySchedule.BeginHour = 12;
myDailySchedule.BeginMinute = 59;
myDailySchedule.BeginSecond = 0;
myDailySchedule.EndHour = 12;
myDailySchedule.EndMinute = 59;
myDailySchedule.EndSecond = 0;

myJob.Schedule = myDailySchedule;

myJobsColl.Add(myJob);
myApplication.Update();

}

In this case we build a job and register and scheduled it, it runs 12:59:00 every day.

Notice that you need to specify both the Begin and End Times. Setting the BeginHour, BeginMinute, and BeginSecond without specifying the EndHour, EndMinute, and EndSecond values will prevent the timer job from running. No error is thrown, just no execution.

You can also use FromString method of SPSchedule when let the job run at a specific time:

SPSchedule schedule = SPSchedule.FromString("daily at 12:59:00");

You can also Schedule the job every one minute, every one hour, every week, something like:

SPMinuteSchedule myMinuteSchedule = new SPMinuteSchedule();
myMinuteSchedule.BeginSecond = 0;
myMinuteSchedule.EndSecond = 59;
myMinuteSchedule.Interval = 1;
myJob.Schedule = myMinuteSchedule;

Sharepoint 4 - Use Web User Control to build WebPart

Step 1.

New a Web application, add a web user control(there will have ascx file and ascx.cs file). Strong named Signing. Install the Web application dll to GAC (C:\Windows\Assembly).

Step 2.

Place the ascx file and ascx.cs file to the path:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS

Step 3.
Copy the Web application dll to C:\Inetpub\wwwroot\wss\VirtualDirectories\port\bin
Modify the file:C:\Inetpub\wwwroot\wss\VirtualDirectories\port\web.config
Between < SafeControls> < /SafeControls> node, add:
< SafeControl Assembly="MyWebApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=******" Namespace="MyWebApplication" TypeName="Class" Safe="True" />


Step 4.
Create a sharepoint webpart project

New a Control, and load the control from our ascx file, the code is pretty much like:

[Guid("**********")]
public class ThisisADemodWebpart : System.Web.UI.WebControls.WebParts.WebPart
{

Control _myControl;
string err;


public ThisisADemodWebpart()
{

this.ExportMode = WebPartExportMode.All;
}

protected override void Render(HtmlTextWriter writer)
{
try
{
_myControl.RenderControl(writer);
}
catch (Exception e)
{
writer.Write(e.Message + ":" + err);
}
}

protected override void CreateChildControls()
{
base.CreateChildControls();
try
{
this.Controls.Clear();
_myControl = this.Page.LoadControl("\\_layouts\\myWebUserControl.ascx");
this.Controls.Add(_myControl);
}
catch (Exception e)
{
err = e.Message;
}
}
}

One thing to notice, that in the web user control, if there is Sql Database access, we may meet the security access/permission exception below:
" at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) at System.Security.PermissionSet.Demand() at System.Data.Common.DbConnectionOptions.DemandPermission() at System.Data.SqlClient.SqlConnection.PermissionDemand() at ...."
We need to modify the file:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\wss_minimaltrust.config
Add:
< SecurityClass Name="SqlClientPermission"
Description="System.Data.SqlClient.SqlClientPermission, System.Data,
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
/>
to the SecurityClasses section and
< class="highlight1">IPermission class="SqlClientPermission" version="1"
Unrestricted="true" />


Notice: this post is for sharepoint2007 or earlier version. The reason using this way is that sharepoint webpart solution template is not able to add web user control. This post is the same as add use an ascx control from another web site. In sharepoint 2010, there is visual webpart project and we don't need to bother to do like this post any more.

Monday, April 12, 2010

Sharepoint 3 -Event Reciever Handler

There are many resources explained about Event Receiver Handler in Sharepoint. Let's take the SPItemEventReciever as an example: (I was planning to synchronize two list in sharepoint using Workflow, but for item deleting/deleted, the item cannot trigger an WF, in this case I wrote code of event reciever)

Here I wrote what I did in my project.

Step 1. Write the class inherited from SPItemEventReciever.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace DeleteReference
{
public class DeleteItem: SPItemEventReceiver
{
public override void ItemDeleted(SPItemEventProperties properties)
{
SPSite site= new SPSite("http://myserver:3000/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.GetList("/Jerry/Lists/Task2");
SPListItem item = list.Items.Add();
item["Title"] = "A";
//item["Title"] = properties.ListItem["Title"];
item.Update();
}
}

public override void ItemDeleting(SPItemEventProperties properties)
{

using (SPWeb web = properties.OpenWeb().ParentWeb)
{
SPList list = web.GetList("/Jerry/Lists/Task2");
SPListItem item = list.Items.Add();
item["Title"] =properties.ListItem["Title"];
//item["Title"] = properties.ListItem["Title"];
item.Update();
}
}
public override void ItemAdded(SPItemEventProperties properties)
{

SPListItem item = properties.ListItem;
this.DisableEventFiring();
item["Release"] = "AB";
item.Update();
this.EnableEventFiring();
/*SPSite site = new SPSite("http://myserver:3000/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.GetList("/Jerry/Lists/Release1");
SPListItem item = list.Items.Add();
item["Title"] = "C";
//item["Title"] = properties.ListItem["Title"];
item.Update();
}*/
}

}
}

Step 2.

Use the strong named signing and register it in GAC.

Step 3.
Write the feature.xml and Element.xml file in the folder(Create DeleteReference folder under the FEATURES folder)

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\DeleteReference

feature.xml:
< Feature Scope="Web"
Title="Deleting Event Handler"
Id="8CDFAE41-98F9-4139-9546-A7C0B7D3C1FE"
xmlns="http://schemas.microsoft.com/sharepoint/">
< ElementManifests>
< ElementManifest Location="Element.xml"/>
< /ElementManifests>
< /Feature>

Element.xml

< Elements xmlns="http://schemas.microsoft.com/sharepoint/">
< Receivers ListTemplateId="107">
< Receiver>
< Name>DeleteReference< /Name>
< Type>ItemAdded< /Type>
< SequenceNumber>10000< /SequenceNumber>
< Assembly>DeleteReference, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ef537f21ff0cf29f< /Assembly>
< Class>DeleteReference.DeleteItem< /Class>
< Data>< /Data>
< Filter>< /Filter>
< /Receiver>
< /Receivers>

< Receivers ListTemplateId="107">
< Receiver>
< Name>DeleteReference< /Name>
< Type>ItemDeleted< /Type>
< SequenceNumber>10000< /SequenceNumber>
< Assembly>DeleteReference, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ef537f21ff0cf29f< /Assembly>
< Class>DeleteReference.DeleteItem< /Class>
< Data>< /Data>
< Filter>< /Filter>
< /Receiver>
< /Receivers>

< Receivers ListTemplateId="107">
< Receiver>
< Name>DeleteReference< /Name>
< Type>ItemDeleting< /Type>
< SequenceNumber>10000< /SequenceNumber>
< Assembly>DeleteReference, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ef537f21ff0cf29f< /Assembly>
< Class>DeleteReference.DeleteItem< /Class>
< Data>< /Data>
< Filter>< /Filter>
< /Receiver>
< /Receivers>

< /Elements>

Notice the ListTemplateID is also easy to be found in internet resources, for example:
GenericList 100
DocumentLibrary 101
Survey 102
Links 103
Announcements 104
Contacts 105
Events 106
Tasks 107
DiscussionBoard 108
PictureLibrary 109

For us we want our feature register to a task list, so we use 107.


Step 4.

Install the features to the subsite where the list is:

pushd %programfiles%\common files\microsoft shared\web server extensions\12\bin

::stsadm -o deactivatefeature -filename DeleteReference\feature.xml -url http://myserver:3000/Jerry/List/Task1
::stsadm -o uninstallfeature -filename DeleteReference\feature.xml


stsadm -o installfeature -filename DeleteReference\feature.xml

stsadm -o activatefeature -filename DeleteReference\feature.xml -url http://myserver:3000/Jerry/List/Task1

iisreset