怎么样把大象塞进冰箱里?
分3步:打开冰箱门、把大象塞进去、关上冰箱门。
怎么样让 SharePoint 2010 定时做件事情呢?
Something 函数
这次不关心是具体做什么事情,因为我可以把这件事情看成是:void Something(string content); 只要让 SharePoint 2010 给我一个机会,定时的调用这个 Something 函数就可以了,剩下的这个函数会处理。
Time Job
Time Job 可以在服务器后台定期执行 Something 并且可以无视登录 SharePoint 的用户身份来以最大权限执行任务。(没有用户登录 SharePoint 也不影响 Time Job 的运行,它就在那里自己跑着。)同时,如你所担心的,代价就是 Time Job 的开发需要服务器场部署。
- 创建一个空白的服务器场解决方案
- 添加一个继承 SPJobDefinition 的类,用做调度任务的主程序(Something 函数)
- 添加一个继承 SPPersistedObject 的类,用于保存调度任务主程序的设置信息
- 在 Feature 的激活事件里面创建 SPJobDefinition 派生类的实例、SP%Schedule 类(% 可以是 Hourly、Daily、Weekly 等等定时间隔)、设置信息的派生类
- 部署、测试
具体的代码可以参考:Creating Timer Jobs in SharePoint 2010 that Target Specific Services
这里有个问题:SP%Schedule 类只有分钟、小时、天、周、月、年的间隔,如果我希望每个工作日的上午 9 点 25 分执行一个操作,怎么办? 如果不考虑与其它技术方案配合,只用 Time Job,那么可能需要这样:
- 利用 SPDailySchedule 类在 Feature 的激活事件里面设置按天调用
- SPDailySchedule 设置 BeginHour, BeginMinute 为 9 和 20 (提前一点),EndHour, EndMinute 为 9 和 30(给 Time Job Service 一点儿时间)
- 在 SPJobDefinition 子类(干活的那个)里先判断当前系统日期,看看是否是工作日(但是,如果考虑春节、中秋这种假日,你就不能只用 Time Job 了),是的话,调用 Something
Time Job 的调用时有延迟的。不是你说让它 9 点 25 分开始,它就能够开始的。它会尽力,但事实上,那个 Time Job Service 相当的忙,哪怕你的 SharePoint 环境是刚刚安装好的,什么都没做,它也已经在后台开始“疯狂”的运行了。
依靠 Time Job 的其它定时调度程序(如 User Profile 同步、工作流)也都会有延迟。而且,服务器场的解决方案部署,是要重启 IIS 的,调试的时候颇为痛苦。
然而,很多时候,当提到要打开冰箱门把大象放进去,一般脑海里面首先还是会闪过 Time Job 的影子。“调度任务扔进去就可以不管”、“拥有各种权限”就是它的优势。
工作流
这本质上还是在用 Time Job。不过,部署更加灵活,不必一定要用服务器场部署。
SharePoint Designer 工作流
利用 SharePoint Designer 设置工作流等待一段特定的时间后执行某个操作,比如下面这个每周四下午 3 点多执行的工作流:
里面的 Pause until 日期也可以写在列表项的一个日期字段里面,用户可以指定暂停的时间。
这样需要执行多少次就写多少个 “Pause”的做法,只适用于少量的定时调用,量大的时候,肯定是 Hold 不住的。而且,大量这种 long running 的工作流(实例)拖死服务器那是相当容易的事情。
而且,调度间隔不可能太短(通常建议 5 分钟),因为 Time Job 那里,给 Workflow 的事件做处理的间隔默认也是 5 分钟:
有没有办法让工作流自己重新开始执行自己,实现不限次数的定时呢?
答案是:没有。
那是否可能让工作流在创建列表项时自动启动,然后在工作流里面定时再新建一个列表项,从而实现循环触发呢?
答案是:不行。SharePoint 里面列表自己通过工作流创建在自己内部的列表项根本不触发工作流。
那我两个列表互相触发还不行?
答案是:不行。第一波触发可以完成,第二波就会“失败”,工作流根本就触发。微软知道你想干什么,它 say no 了。
那用工作流能定时做什么?!
答案:它可以和列表项、信息策略配合使用。
为什么要这么麻烦?!
答案:因为在生产环境,你很可能根本碰不到 SharePoint 服务器,别提 Farm Admin 了,可能 Site Collection Admin 都没有。必须利用手头能用的资源。
信息策略
通过配置 Retention 策略,可以让指定的工作流定期执行,比如每隔 5 天调用一次我们的工作流:
此时,我们把工作流当作 Something 函数用。(知道为什么一开始我就没写 Something 函数代码了吧,因为,它可能根本就不是一段代码)
不过,要注意一点:信息策略后台仍然是 Time Job 在跑,所以,Time Job 的执行周期要特别留意(因为默认是每周,这样,你每 5 天最后也还是变成每周):
列表项
或者说,“定时列表”项。
前面几种方法,有个问题。比如这种应用:每个月的第一周、第三周的周二下午3点开部门会议。前面几种做法就没戏了。不是每个月都有4周的,这个会开不了几次,定时就偏了。
此时,回到我们的工作流 Pause until 上面来。
我们不是说,可以在列表项里面加入日期字段作为工作流等待的到期日期么?那么,呵呵,刚才的部门会议应用,你就可以先建好 1 年(24 次)的列表项,然后每个列表项的“会议日期”字段值设置为当期的准确日期,配合工作流即可实现定时。非常准确,完全不受闰年、5周的月份的影响 :)
Alert 通知
如果这个 Something 恰好是汇总某个列表的内容改动,发邮件给经理。那么用 Alert 功能就最合适不过了:
写代理程序
用 Visual Studio 拖一个 Form 程序(WPS 也可以)、挂一个 Timer 控件,调 SharePoint Client Object Model 模型,直接 do Something。
想怎么写就怎么写,什么节假日、公司假日、工厂 Shutdown 的假日、每月第几周周一的大会,风雨无阻,全部都可以考虑进去。而且,还不用 Time Job,特别节省资源。
只要跑在一台不关机的电脑上就可以,挂在那里跑就行。(管理员还是要定期去看看的,不如代理自己挂了就不好了)
只有一个问题:用户身份验证。毕竟是 Client Object Model,万一运气不好(很有可能),SharePoint 搞了 SAML 玩 Federation,你得折腾一番了。
用手
你上好闹钟,坐在电脑旁边。
每次时间到了,就打开 SharePoint Site,然后进去点击几个按钮执行任务。
我可以 100% 的确认:这次绝对可以把大象装进冰箱里面。