当前位置: 首页 > news >正文

定时发送邮件

定时发送邮件 方法一 windows服务

 

前言:项目中遇到定时发送邮件或者信息时,想 调用windows的计划任务,查阅了asp.net资料发现没有,

于是上网一搜找到一些方法与大家共享

编写一个Windows服务程序,定时从数据库中拿出记录发送邮件。

测试环境:Visual Studio 2005 SP1、Windows Server 2003 SP2

一、新建项目

打开VS2005,新建一个“Windows 服务”项目。

二、添加Timer

展开“工具箱”,在“组件”标签下找到“Timer”双击,这时就添加了一个Timer组件,修改“Name”属性为“timEmail”、“Enabled”为“false”、“Interval”为“60000”。

接下来要做一些修补工作,不知是VS2005的BUG还是我没找着地方,在VS2003下是不存在该问题的:刚从“组件”下添加的“Timer”按 理说应该来自“System.Timers命名空间”,也只有“System.Timers.Timer”才能在Windows服务程序中正常工作,但是 现在这个Timer却是属于“System.Windows.Forms.Timer”的。所以得稍作修改,打开“.Designer.cs”文件,修改 如下:

#region 组件设计器生成的代码
// ........以上略
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
            
this .components = new System.ComponentModel.Container();
            
// this.timEmail = new System.Windows.Forms.Timer(this.components);原
           this .timEmail = new System.Timers.Timer(); //
             this .timEmail.Interval = 60000 ;
            
this .ServiceName = " Service1 " ;
}
#endregion
// private System.Windows.Forms.Timer timEmail;原
private System.Timers.Timer timEmail; //

三、添加配置文件

服务每次调用配置文件,获取一些基本参数,这样一些变更就可直接修改配置文件而不必修改代码。新建ServiceConfig.xml存放于项目“Bin/Debug/”下:

<? xml version="1.0" encoding="utf-8" ?>
< serviceConfig >
    
< serviceItem
        
name ="sendEmail"
         enable
="true"
         elapsed
="60000"
         connectionString
="your database connection..."
         smtp
="smtp address"
         account
="your email account..."
         password
="your password..." >
    
</ serviceItem >
</ serviceConfig >

四、以下是实现代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Xml; // 操作配置文件
using System.IO; // 写日志
using System.Threading; // 使用线程

namespace ClientWindowsService
{
    
public partial class ClientService : ServiceBase
     {
        
public ClientService()
         {
             InitializeComponent();
         }

        
protected override void OnStart( string [] args)
         {
            
// 服务启动
       this .timEmail.Enabled = true ;
            
this .tSendEmail();
         }

        
protected override void OnStop()
         {
            
// 服务停止
       this .timEmail.Enabled = false ;
         }

        
private void timEmail_Elapsed( object sender, System.Timers.ElapsedEventArgs e)
         {
            
// 定时器
       this .tSendEmail();
         }

        
// 开启新进程发送邮件
     private void tSendEmail()
         {
             Thread t
= new Thread( new ThreadStart(sendEmail));
             t.Start();
         }

        
// 发送邮件函数
     private void sendEmail()
         {
             XmlDocument doc
= new XmlDocument();
            
// 添加System.Windows.Forms引用,获取执行目录
       string configFile = System.Windows.Forms.Application.StartupPath.ToString() + " /ServiceConfig.xml " ;
             doc.Load(@configFile);
             XmlElement root
= doc.DocumentElement;
            
foreach (XmlNode node in root)
             {
                
// 如果配置文件中开启服务
         if (node.Attributes[ " name " ].Value == " sendEmail " && node.Attributes[ " enable " ].Value == " true " )
                 {
                    
try
                     {
                        
// 读取数据库,发送邮件操作,略
                     }
                    
catch (Exception error)
                     {
                        
// 写错误日志
             using (StreamWriter sw = new StreamWriter(System.Windows.Forms.Application.StartupPath.ToString() + @" " + DateTime.Now.ToString( " yyyy-MM-dd " ) + " .txt " , true , System.Text.Encoding.UTF8))
                         {
                             sw.WriteLine(DateTime.Now.ToString()
+ " " );
                             sw.WriteLine(error.ToString());
                             sw.WriteLine(
" --------------------------------------------- " );
                             sw.Close();
                         }
                     }
                 }
             }
// end foreach
         }

     }
// end class
} // end namespace

五、布署服务

在设计模式下右键-->添加安装程序-->设置serviceProcessInstaller1的Account为LocalSystem

设置serviceInstaller1的StartType为Automatic

编译

在命令模式下执行:%systemroot%/microsoft.net/framework/v2.0.50727/installUtil.exe D:/项目目录/bin/Debug/可执行文件名.exe

 

 

定时发送邮件 方法二 仿造windows计划任务
2009年11月18日 星期三 下午 07:55
在 业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称 之为计划任务。实现计划任务的方法也有很多,可以采用SQLAgent执行存储过程来实现,也可以采用Windows任务调度程序来实现,也可以使用 Windows服务来完成我们的计划任务,这些方法都是很好的解决方案。但是,对于Web应用程序来说,这些方法实现起来并不是很简单的,主机服务提供商 或者不能直接提供这样的服务,或者需要你支付许多额外的费用。 本文就介绍一个直接在Web应用程序中使用的简单的方法,这个方法不需要任何额外的配置即可轻松实现。

由于ASP.NET站点是作为Web应用程序运行的,它并不受线程的限制,因此我们可以非常方便地在Application_Start和 Application_End事件中建立和销毁一个计划任务。下面就简单介绍一下在Web站点实现计划任务的方法。我们的例子是定时往文件里添加信息, 作为例子,这里把当前的时间定时地写入文件中。

一个计划任务的工作单元称之为一个任务(Job),下面的代码描述了对所有任务都可以被调度引擎计划执行的一个通用的接口,这里的每个任务实现了Execute方法,供调度引擎进行调用:

public interface ISchedulerJob
{
void Execute();
}

如前所述,我们的例子是实现往文件写如字符日期,下面就是实现这一任务的方法:

public class SampleJob : ISchedulerJob
{
public void Execute()
{
//文件保存的物理路径,CSTest为虚拟目录名称,F:/Inetpub/wwwroot/CSTest为物理路径
string p = @"F:/Inetpub/wwwroot/CSTest";
//我们在虚拟目录的根目录下建立SchedulerJob文件夹,并设置权限为匿名可修改,
//SchedulerJob.txt就是我们所写的文件
string FILE_NAME = p+ "//SchedulerJob//SchedulerJob.txt";
//取得当前服务器时间,并转换成字符串
string c = System.DateTime.Now.ToString("yyyy-mm-dd hh:MM:ss");
//标记是否是新建文件的标量
bool flag = false;
//如果文件不存在,就新建该文件
if (!File.Exists(FILE_NAME))
{
flag = true;
StreamWriter sr = File.CreateText(FILE_NAME);
sr.Close();
}
//向文件写入内容
StreamWriter x = new StreamWriter(FILE_NAME,true,System.Text.Encoding.Default);
if(flag) x.Write("计划任务测试开始:");
x.Write("/r/n"+c);
x.Close();
}
}

接下来,我们建立一个配置对象,告诉调度引擎执行什么任务和执行的时间间隔。

public class SchedulerConfiguration
{
//时间间隔
private int sleepInterval;
//任务列表
private ArrayList jobs = new ArrayList();

public int SleepInterval { get { return sleepInterval; } }
public ArrayList Jobs { get { return jobs; } }

//调度配置类的构造函数
public SchedulerConfiguration(int newSleepInterval)
{
sleepInterval = newSleepInterval;
}
}

下面就是调度引擎,定时执行配置对象的任务

public class Scheduler
{
private SchedulerConfiguration configuration = null;

public Scheduler(SchedulerConfiguration config)
{
configuration = config;
}

public void Start()
{
while(true)
{
//执行每一个任务
foreach(ISchedulerJob job in configuration.Jobs)
{
ThreadStart myThreadDelegate = new ThreadStart(job.Execute);
Thread myThread = new Thread(myThreadDelegate);
myThread.Start();
Thread.Sleep(configuration.SleepInterval);
}
}
}
}

所有的准备工作已经完成,下面就是激活引擎的工作了。为了让我们的任务计划执行,我们在Global.asax.cs文件里的 Applicatio_Start和Application_End里进行建立和销毁工作,首先建立一个调度进程运行的线程,我们这里的运行间隔时间为3 秒钟。

public System.Threading.Thread schedulerThread = null;
protected void Application_Start(Object sender, EventArgs e)
{
SchedulerConfiguration config = new SchedulerConfiguration(1000*3);
config.Jobs.Add(new SampleJob());
Scheduler scheduler = new Scheduler(config);
System.Threading.ThreadStart myThreadStart = new System.Threading.ThreadStart(scheduler.Start);
System.Threading.Thread schedulerThread = new System.Threading.Thread(myThreadStart);
schedulerThread.Start();
}

最后还需要在程序退出时进行销毁:

protected void Application_End(Object sender, EventArgs e)
{
if (null != schedulerThread)
{
schedulerThread.Abort();
}
}

好了,在VS.NET里建立一个C#的Web应用程序工程,建立TaskScheduler.cs类,并修改相应的Global.asax.cs文件。为了能看到效果,我们再建立一个表单WebForm1.aspx,定时刷新来检查我们所记录的数据:

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
Inherits="CSTest.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>在Web应用程序中执行计划任务的例子</title>
<meta http-equiv="refresh" content="10">
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<iframe style="width:100%;height:100%" src="SchedulerJob/SchedulerJob.txt"></iframe>
</form>
</body>
</HTML>

对工程进行编译并运行,就可以看到结果了,结果如下:

计划任务测试开始:
2003-13-10 11:08:15
2003-13-10 11:08:18
2003-13-10 11:08:21
2003-13-10 11:08:24
2003-13-10 11:08:27
2003-13-10 11:08:30

需要说明的是,以上只是在Web应用程序中执行计划任务的简单例子,对于多个任务来说,需要在不同的线程内进行工作,对计划的安排也是很简单的,实际还需要站点堵塞,当机的情况。另外这里也没有进行错误的处理等工作,相信大家会写出更加完美的代码的。  

相关文章:

  • “搭讪学” 这不仅仅是泡妞
  • 与领导谈话的技巧
  • UrlRewriter伪URL的配置
  • 网摘
  • 怎么泡妞
  • [JavaScript]如何讓IE9, IE8, IE7, IE6關閉視窗時不彈出對話訊息
  • DropDownList 控件不能触发SelectedIndexChanged 事件的另一个原因
  • jquery formValidator插件ajax验证,在内容不做修改的前提下提示错误的bug解决方法
  • 男孩如何追女孩
  • 怎样提高自己的内涵、气质
  • 插入中文数据显示乱码 mssql数据库显示乱码 更改中文数据显示乱码
  • 耶鲁大学心态 送给那些正在奋斗的人
  • Ambiguous column name
  • js获取textarea中的空格与回车
  • 简单数据拆分
  • 【刷算法】求1+2+3+...+n
  • 08.Android之View事件问题
  • 78. Subsets
  • Android Studio:GIT提交项目到远程仓库
  • Angular 2 DI - IoC DI - 1
  • bearychat的java client
  • CSS相对定位
  • Github访问慢解决办法
  • HTML中设置input等文本框为不可操作
  • java8-模拟hadoop
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • java概述
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Python_OOP
  • XForms - 更强大的Form
  • 扑朔迷离的属性和特性【彻底弄清】
  • 一个完整Java Web项目背后的密码
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • ​ssh免密码登录设置及问题总结
  • #162 (Div. 2)
  • #define、const、typedef的差别
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (二)fiber的基本认识
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (南京观海微电子)——COF介绍
  • (转)http-server应用
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .bat批处理(六):替换字符串中匹配的子串
  • .net CHARTING图表控件下载地址
  • .net 使用ajax控件后如何调用前端脚本
  • .NET 中 GetProcess 相关方法的性能
  • .Net程序帮助文档制作
  • .NET分布式缓存Memcached从入门到实战
  • .NET文档生成工具ADB使用图文教程
  • .pop ----remove 删除
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [] 与 [[]], -gt 与 > 的比较
  • [2019/05/17]解决springboot测试List接口时JSON传参异常