SharePoint2013TimerJob计时器发送邮件 眼下正好有一个SP项目需要用到计时器功能,本人平常忘性大,所以学一点记录一点,其中参考了不少网络上的好文章,因为怕麻烦,我就不引用看过的博客的链接了,忘各路大神莫怪。 sharepoint 计时器类似于Windows 任务计划一样,可以按分,时,天,周,月去自动执行你布置的任务,你可以到sharepoint 管理中心去查看及更改你的计时规则,值得注意的是,每当你部署一个计时器的时候,你需要到服务器中的“服务”中,有一个叫“SharePoint Timer Service”的服务,你需要重启一下,更新后的计时器才会显效,其余的话不说了,下面就跟我一起去学习此功能吧。 1 添加新项目,打开vs2013‘文件’->‘新建’->‘项目’,我建了一个“OneTimeJob”的空项目 |
3 创建一个计时器任务类“OneTimeJob.cs” |
4 继承SPJobDefinition ,需要引用Microsoft.SharePoint.Administration; 如下图 |
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
namespace OneTimeJob
{
class OneTimeJob : SPJobDefinition
{
/// <summary>
/// 构造函数
/// </summary>
public OneTimeJob() : base() { }
/// <summary>
/// 带有参数1的构造函数,适合其他的指定站点集,我是猜的,反正我没用过这个
/// </summary>
/// <param name="jobName"></param>
/// <param name="service"></param>
/// <param name="server"></param>
/// <param name="targetType"></param>
public OneTimeJob(string jobName, SPService service, SPServer server, SPJobLockType targetType) : base(jobName, service, server, targetType)
{
}
/// <summary>
/// 带有参数2的构造函数,适合部署的本站点集
/// </summary>
/// <param name="jobName"></param>
/// <param name="webApplication"></param>
public OneTimeJob(string jobName, SPWebApplication webApplication) : base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
{
this.Title = jobName;
}
/// <summary>
/// 执行逻辑的方法
/// </summary>
/// <param name="contentDbId"></param>
public override void Execute(Guid contentDbId)
{
//我把邮箱地址,和发送内容存储在"TestWeb"网站下的"TestList"的列表上
string EmailTo = "";
string EmailBody = "";
SPWeb web = null;
SPSecurity.RunWithElevatedPrivileges(delegate()//提升权限,模仿管理员权限在读取列表
{
SPWebApplication webApplication = this.Parent as SPWebApplication;//实例化一个应用管理,只能翻译成这样了,将就看吧,反正我都是猜的
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];//通过GUID找到内容数据库
web = contentDb.Sites[0].OpenWeb("/TestWeb/");//因为我只创建了一个站点集,就用Sites[0],然后找到我要的Web
using (web)
{
SPList list = web.GetList(web.Url + "/Lists/TestList/AllItems.aspx");//找到我要的列表
SPQuery query = new SPQuery();
query.Query = "";//为空时表示搜出所有列表,caml语句不在此讲解
SPListItemCollection items = list.GetItems(query);
if (items != null && items.Count > 0)
{
foreach (SPListItem item in items)
{
if (Convert.ToString(item["Title"]) == "测试用计时器发邮件") //找到我存储字段值的地方
{
EmailTo = Convert.ToString(item["EmailTo"]);
EmailBody = Convert.ToString(item["EmailBody"]);
}
}
}
}
//接下来就是发送邮件了,我得先吐槽一下,sharepoint自带了一个发送邮件功能,叫"Microsoft.SharePoint.Utilities.SPUtility.SendEmail()",
//我曾经用它发送了一个html邮件,内容多时,总有一个字符解析乱码,太NM坑了,有兄弟有解决路子的,别忘分享给我啊,所以我还是用成熟一点的技术来发送邮件。
SendEmail(EmailTo, "测试计时器发送的邮件", EmailBody, "");
});
}
/// <summary>
/// 发送邮件
/// </summary>
/// <param name="mailTo">要发送的邮箱</param>
/// <param name="mailSubject">邮箱主题</param>
/// <param name="mailContent">邮箱内容</param>
/// <returns>返回发送邮箱的结果</returns>
public bool SendEmail(string mailTO, string mailSubject, string mailContent, string _path)
{
// 设置发送方的邮件信息,例如使用网易的smtp
string smtpServer = "192.168.1.1"; //SMTP服务器
string mailFrom = "黑不到我吧"; //登陆用户名
string userPassword = "119";//登陆密码
// 邮件服务设置
SmtpClient smtpClient = new SmtpClient();
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;//指定电子邮件发送方式
smtpClient.Host = smtpServer; //指定SMTP服务器
smtpClient.Credentials = new System.Net.NetworkCredential(mailFrom, userPassword);//用户名和密码
// 发送邮件设置
MailMessage mailMessage = new MailMessage(); // 发送人和收件人
mailMessage.From = new MailAddress(mailFrom, "测试站点");
mailMessage.To.Add(new MailAddress(mailTO, mailTO));//添加发件人
mailMessage.Subject = mailSubject;//主题
mailMessage.Body = mailContent;//内容
mailMessage.BodyEncoding = Encoding.UTF8;//正文编码
mailMessage.IsBodyHtml = true;//设置为HTML格式,可以发送html内容的邮件
mailMessage.Priority = MailPriority.High;//优先级
//添加邮件附件
FileInfo fi;
if (!string.IsNullOrEmpty(_path))
{
fi = new FileInfo(_path);
if (fi.Exists)
{
System.Net.Mail.Attachment firstatt = new System.Net.Mail.Attachment(_path, System.Net.Mime.MediaTypeNames.Application.Octet);
System.Net.Mime.ContentDisposition disposion = new System.Net.Mime.ContentDisposition();
disposion.CreationDate = System.IO.File.GetCreationTime(_path);
disposion.ModificationDate = System.IO.File.GetLastWriteTime(_path);
disposion.ReadDate = System.IO.File.GetLastAccessTime(_path);
mailMessage.Attachments.Add(firstatt);
}
}
try
{
smtpClient.Send(mailMessage); // 发送邮件
return true;
}
catch (SmtpException ex)
{
return false;
}
}
}
}
View Code 5 在Features 文件夹中添加功能,创建一个 Feature 文件,范围选择“Site”,表示你的计时器作用在部署的网站集上,在存取列表值的时候我们一般会通过Site,筛选你要的Web,再通过Web筛选到与你要交互的list. |
6 给新建的Feature添加一个事件接收器,如下图: |
7 添加后,会在其文件下面多出一个“Feature1.EventReceiver.cs”的类文件 |
8 需要override其中的两个函数 override void FeatureDeactivating(SPFeatureReceiverProperties properties) 删除timer job函数 override void FeatureActivated(SPFeatureReceiverProperties properties),部署timer job函数 |
namespace OneTimeJob.Features.Feature1
{
/// <summary>
/// 此类用于处理在激活、停用、安装、卸载和升级功能的过程中引发的事件。
/// </summary>
/// <remarks>
/// 附加到此类的 GUID 可能会在打包期间使用,不应进行修改。
/// </remarks>
[Guid("ed228c48-b397-4755-be4f-a9ffa609c177")]
public class Feature1EventReceiver : SPFeatureReceiver
{
// 取消对以下方法的注释,以便处理激活某个功能后引发的事件。
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
//实例化对应的站点集
SPSite site = properties.Feature.Parent as SPSite;
string Job_Name = "OneTimeJobTest";//指定计时器名称
//遍历此站点集下的所有计时器,如果发现重名的将删除,确保计时器名称的唯一性
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == Job_Name)//匹兑到部署时的计时器名称,然后删除
{
job.Delete();
}
}
//添加计时器
OneTimeJob Doc = new OneTimeJob (Job_Name, site.WebApplication);//实例化任务类
//设置计时器属性,这个可以发布后在sharepoint管理器中的"监控"中重新定义。
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 5;
Doc.Schedule = schedule;
Doc.Update();
}
// 取消对以下方法的注释,以便处理在停用某个功能前引发的事件。
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
//实例化对应的站点集
SPSite site = properties.Feature.Parent as SPSite;
//遍历此站点集下的所有计时器
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == "OneTimeJobTest")//匹兑到部署时的计时器名称,然后删除,为了方便理解,计时器名称我没用全局变量
{
job.Delete();
}
}
}
// 取消对以下方法的注释,以便处理在安装某个功能后引发的事件。
//public override void FeatureInstalled(SPFeatureReceiverProperties properties)
//{
//}
// 取消对以下方法的注释,以便处理在卸载某个功能前引发的事件。
//public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
//{
//}
// 取消对以下方法的注释,以便处理在升级某个功能时引发的事件。
//public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
//{
//}
}
}
View Code 9 此时计时器已经写好了,我们可以部署了,部署之后,打开服务器的“服务”,重启“SharePoint Time Service”,如图 |
10 “sharepoint 管理中心”的“监控”->“计时器作业”->"复查作业定义",可以看到我们的计时器 |
14 下面我们来讲一下部署,用VS可以直接部署成功,但是我们的生产环境中,特别是客户的生产环境中,一般不会去装VS,所以我们会用选用wsp文件去部署, 通常情况,我们第一步先用命令安装wsp文件包,如:stsadm -o addsolution -filename C:\OneTimeJob.wsp 然后我们再部署此wsp,如:stsadm -o deploysolution -name OneTimeJob.wsp -immediate -url http://sharepoint2013/ -allowGacDeployment 那么问题来了,报错啦,显示“此解决方案不包含 Web 应用程序范围的资源,无法将其部署到特 定的 Web 应用程序”,如图 |
15 哈哈,蛋疼了吧,它不按规则出牌了,那我们来找下原因,我们打开“sharepoint管理器”找到此wsp包,如图 |
16 “包含Web应用程序资源”为“否”,跟以前不一样了吧,这种情况我们只能“全局部署”,网上有很多坑,好不容易找到正确的命令:stsadm -o deploysolution -name OneTimeJob.wsp -local -allowGacDeployment,部署后如图 |
17 因为是全局部署,所以每个网站集都包含此Feature,所以我们要去对应的网站中“网站集功能”中激活此Feature,如图 |
18 点击激活,发现:擦,又报错了,又掉下来一个坑,如图 |
19 看来它还挺任性的,那么接下来我们就去解决这个问题吧,既然不给用手去抚摸,那我们就下去命令,让它乖乖服从 stsadm -o activatefeature -id 7bff6c03-76ea-40b5-a339-b9fe6bc1c453 -url http://sharepoint2013/ -force 20 id 指的是Feature 的id,点开Feature设计器中的清单,能找到此id 如图 |
如果有SharePoint项目,欢迎邮件联系我,Email:lychuan_007@163.com
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南