惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
J
Java Code Geeks
H
Help Net Security
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
Microsoft Security Blog
Microsoft Security Blog
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
U
Unit 42
博客园 - 三生石上(FineUI控件)
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
小众软件
小众软件
博客园 - 叶小钗
D
Docker
量子位
P
Proofpoint News Feed
博客园_首页
T
Tailwind CSS Blog
F
Fortinet All Blogs

博客园 - Burnett

【招聘.NET开发人员】待遇从优 【剖析MOSS系列之一】万能的AllUserData MOSS 2007 SP1的一些补丁说明 Form认证的AD升级之道 谁动了我的Infopath附件?-Infopath上传文件产生“文件损坏” InfoPath的上传附件控件在MOSS中失效的解决办法 WorkFlow中引入自定义类对象在类级生命周期里引发工作流异常 我本将心向明月,奈何明月照沟渠。安装VS2008出错 - Burnett - 博客园 简单的IE浏览器代理切换软件-ezProxySwitch 关于写注册表的时候出现UnauthorizedAccessException异常的问题 今天发现MOSS2007的一个非常奇怪的地方 使用Web部件连接接口实现可以设置条件的过滤器 HRESULT 80070842 错误解决办法 Sharepoint 2007中可在列表中添加的内容类型 关于“无任何网络提供程序接受指定的网络路径错误” 没事放上来一个我做的第一个webpart组件可以显示农历,包含源代码 SharePoint站点迁移解决方案 【翻译 WSS3.0 SDK系列之二】内容类型导读 【翻译 WSS3.0 SDK系列之一】用户,组和认证
来自MOSS2007的Sex Bomb:自定义计时器
Burnett · 2007-03-26 · via 博客园 - Burnett

  前一段时间为了满足公司的要求,需要使用Timer的特性来进行开发。当时碰到这个需求的时候,首先想到的,就是写一个控制台程序放在服务器上跟着MOSS2007一起跑算了,可是后来想了一下,似乎在管理中心见过计时器的特性。随即打开了“计时器作业定义”,研究了半天也没有头绪,接着一头栽进SDK里搜寻了半天,发现了这个SPJobDefinition类似乎有点意思,不过需要使用SPFeatureReceiver这个类来进行部署,也就是说,制作一个可以部署的计时器,需要分成两个部分来设计:
   首先,编写计时器程序,也就是继承于SPJobDefinition的类,我写的叫做EventCheckTimer。
   其次,编写部署这个计时器所需要的安装器,也就是继承SPFeatureReceiver的类,我这里叫做EventCheckTimerInstaller
   然后就很清楚了,使用这个Installer将EventCheckTimer部署到服务器上,部署的方式,是将feature.xml、mainifest.xml、强命名密钥、以及这两个类生成的dll文件打包成wsp格式的文件(其实就是cab文件),你也许会用到这个wsp部署的模板:wsp模板
  好的,我们引入程序:
这一个类是Timer Job的主类,系统主要是调用里边的Execute方法,这个方法的参数targetInstanceId(内容数据库ID)并不需要你来传递,而是系统在合适的时间在调用的时候自动传递的,你可以把它看作几乎被我们写烂的Main函数:)

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;namespace MyCompany.Management.Employees
{
    
/// <summary>
    
/// 这一个类是计时器的主工作类,系统会按照在Installer中
    
/// 设定的schedule定期调用此类中的Execute方法
    
/// </summary>
    public class EventCheckTimer : SPJobDefinition
    {
        
public EventCheckTimer() : base() { }/// <summary>
        
/// 初始化EventCheckTimer
        
/// 更多的构造函数请参看SDK
        
/// </summary>
        
/// <param name="_timername">计时器的名称</param>
        
/// <param name="_wp">Web应用程序名称</param>
        public EventCheckTimer(string _timername, SPWebApplication _wp)
            : 
base(_timername, _wp, null, SPJobLockType.ContentDatabase)
        {
            
this.Title = "合同到期提醒器0.04";
        }
/// <summary>
        
/// 此方法由系统调用,contentDbId也由系统传递
        
/// </summary>
        
/// <param name="_contentdbid">内容数据库的id</param>
        public override void Execute(Guid targetInstanceId)
        {
            SPWebApplication webApplication 
= this.Parent as SPWebApplication;
            SPContentDatabase contentDb 
= webApplication.ContentDatabases[targetInstanceId];
            DateTime dt;
//遍历当前员工库中的员工,审查所有可能的提醒事件
            foreach (SPListItem li in contentDb.Sites[0].AllWebs["Employees"].Lists["员工库"].Items)
            {
                
if (li["合同止时间"!= null)
                {
                    dt 
= Convert.ToDateTime(li["合同止时间"]);
                    TimeSpan ts 
= (dt.Date - DateTime.Today.Date);
                    
//如果合同止时间小于当前时间,这种情况一般只发生在服务崩溃的时候
                    if (dt.Date < DateTime.Now.Date)
                    {
                        SPListItem si 
= contentDb.Sites[0].AllWebs["Employees"].Lists["任务"].Items.Add();
                        si[
"标题"= String.Format("{0}的合同已经到期!", li["员工姓名"]);
                        si[
"截止日期"= DateTime.Now.AddDays(7);
                        si.Update();
                    }
                    
else
                        
if (ts.Days <= 30)//如果距离现在有30天的时间,那么发出提醒
                        {
                            SPListItem si 
= contentDb.Sites[0].AllWebs["Employees"].Lists["任务"].Items.Add();
                            si[
"截止日期"= DateTime.Now.AddDays(7);
                            si[
"标题"= String.Format("{0}的合同将于{1}天后到期,日期:{2}", li["员工姓名"], (dt.Date - DateTime.Now.Date), li["合同止时间"]);
                            si.Update();
                        }
                }
            }
        }
    }
}

在设定完TimerJob的时候,就可以编写安装器了,下边是代码:其实可以照抄的,不过要注意在FeatureActivated中改成你要部署的计时器的对象,还有就是计时器的计时周期,需要改成你自己需要的。这里的BeginSecond和EndSecond指的是计时器满足触发条件的时候,在一分钟内的那一段时间内执行,比如我这就是可以在0~59秒内执行。其他计时周期类似。

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;namespace MyCompany.Management.Employees
{
    
/// <summary>
    
/// 这一个类的作用主要是安装某一个功能到站点上
    
/// 被安装的对象的类必须是从SPJobDefinition继承
    
/// 过来的
    
/// </summary>
    class EventCheckTimerInstaller : SPFeatureReceiver
    {
        
const string MY_TASK = "EventCheckTimer";/// <summary>
        
/// 在功能被安装以后被调用
        
/// </summary>
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }
/// <summary>
        
/// 在功能被卸载的时候被调用
        
/// </summary>
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }
/// <summary>
        
/// 在功能被激活的时候被调用
        
/// </summary>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            
// 取得当前站点的作用域
            SPSite site = properties.Feature.Parent as SPSite;// 确保在安装此功能之前系统不被调用
            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
            {
                
if (job.Name == MY_TASK)
                    job.Delete();
            }
// 安装TimerJob
            EventCheckTimer timer = new EventCheckTimer(MY_TASK, site.WebApplication);
            
//设置记时器的工作计划表,在这里是每日启动一次,运行时间00:00-05:00,更多的Timer请参看SDK,最小是只执行一次,最长是一天
            
//SPDailySchedule schedule = new SPDailySchedule();
            
//schedule.BeginHour = 0;
            
//schedule.EndHour = 5;
            SPMinuteSchedule schedule = new SPMinuteSchedule();
            schedule.BeginSecond 
= 0;
            schedule.EndSecond 
= 59;
            schedule.Interval 
= 1;
            timer.Schedule 
= schedule;
            
            timer.Update();
        }
/// <summary>
        
/// 在功能被冻结的时候被调用
        
/// </summary>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site 
= properties.Feature.Parent as SPSite;// 删除这个功能
            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
            {
                
if (job.Name == MY_TASK)
                    job.Delete();
            }
        }
    }
}

如果你用了wsp安装包,那么部署激活的顺序是这样的
stsadm -o addsolution -filename yourwspfile.wsp
stsadm -o deploysolution -name yourwspfile.wsp -immediate -allowgacdeployment -force
stsadm.exe -o execadmsvcjobs '这一段是立即执行部署操作
net stop "Windows SharePoint Services Timer" '重启计时器服务,
net start "Windows SharePoint Services Timer"
resetiis
在解决方案管理里部署你的解决方案
在网站集功能里打开这个功能,就OK了。
如果你要卸载Timer,就比较麻烦~~~
首先需要在网站集功能里关闭功能,然后执行
stsadm -o deletesolution -name ZTEsoft.Management.Employees.EventCheckTimer.wsp -override
千万记着最后要重启Windows SharePoint Services Timer刷新服务,否则网站集还是会继续执行Timer服务的。
这点也许对于调试不是很爽,其实因为你写的程序是周期性的执行,所以你可以先模拟TimerJob的执行环境在控制台程序里执行一下,确保万事OK了,再放在Execute函数里,用Installer包装一下安装就可以了。
如果你只是测试,那么测试完成后一定要记得关掉网站集功能,否则也许在将来的某天,你的数据库会被同样的信息塞满的:)