首页  ·  知识 ·  编程语言
创建Windows服务实现MSSql数据库备份
Rock870210  CSDN  .NET  编辑:dezai   图片来源:网络
对于安装的SqlExpress的服务器或服务不够,无法创建Sql作业的服务器上使用.由于代码比较简单,就简化点说

对于安装的SqlExpress的服务器或服务不够,无法创建Sql作业的服务器上使用

由于代码比较简单,就简化点说:

1、在VS下新建一个Windows服务项目。里面自动添加了一个名称为Service1的windows 服务。(直接创建Windows运用程序项目的可以在项目上右键添加Windows服务)

2、添加App.Config配置文件(根据自己需要)

strCon:Sql连接字符串       logPath:日志文件路径         dbPath:备份文件存放路径

<configuration>
  <appSettings>
    <add key="strCon" value="Data Source=./SQLEXPRESS;Initial Catalog=ADV3;User ID=sa;Password=jcc"/>
    <add key="logPath" value="E:/WebSite/AdV3DbBack/DbBackLog.txt"/>
    <add key="dbPath" value="E:/WebSite/AdV3DbBack/"/>
  </appSettings>
</configuration>
 

3、添加System.Configuration引用

4、在Service1中添加代码:

备注:备份系统需要对数据库用户添加权限:grant backup database to 用户名

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Timers;
using System.Configuration;
 
namespace AdBackUpService
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }
        Timer timer = null;
        private int cTime = 604800000;//正常间隔时间7天(每周日23点59分开始备份)
        private string logPath = ConfigurationManager.AppSettings["logPath"];
        private string dbPath = ConfigurationManager.AppSettings["dbPath"];
 
        /// <summary>
        /// 服务启动
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            // TODO: 在此处添加代码以启动服务。
            
            Start();//启动创建日志
            //BackUp();//启动时即时备份一次
            if(timer == null)
                timer = new Timer();
            timer.Interval = GetBackMillisecond();
            timer.Enabled = true;
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        }
 
        protected override void OnStop()
        {
            // TODO: 在此处添加代码以执行停止服务所需的关闭操作。
            timer.Enabled = false;
            timer.Dispose();
            timer = null;
            Stop();
        }
 
        /// <summary>
        /// 获取执行备份剩余时间(毫秒)
        /// </summary>
        /// <returns></returns>
        protected double GetBackMillisecond()
        {
            double millisecond = 3;//默认监控间隔3秒,给系统一个缓冲时间
            DateTime dt = DateTime.Now;
            DateTime temp1 = dt;
            DateTime temp2;
            if(dt.DayOfWeek.ToString() == "Tuesday")
            {
                temp1 = temp1.AddDays(6);
            }
            else if(dt.DayOfWeek.ToString() == "Wednesday")
            {
                temp1 = temp1.AddDays(5);
            }
            else if(dt.DayOfWeek.ToString() == "Thursday")
            {
                temp1 = temp1.AddDays(4);
            }
            else if(dt.DayOfWeek.ToString() == "Friday")
            {
                temp1 = temp1.AddDays(3);
            }
            else if(dt.DayOfWeek.ToString() == "Saturday")
            {
                temp1 = temp1.AddDays(2);
            }
            else if(dt.DayOfWeek.ToString() == "Monday")
            {
                temp1 = temp1.AddDays(1);
            }
            temp2 = new DateTime(temp1.Year, temp1.Month, temp1.Day, 23, 59, 0, 0);
            TimeSpan ts = temp2.Subtract(dt);
            if(ts.TotalMilliseconds > 0)
                millisecond = ts.TotalMilliseconds;
            return millisecond;
        }
 
        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            BackUp();
            if(timer.Interval != cTime)
                timer.Interval = cTime;
        }
 
        protected void BackUp()
        {
            string backName = "V3" + GetDateStr(DateTime.Now);
            string sql = "backup database ADOnlineV3 to disk='" + dbPath + backName + ".bak'";
            try
            {
                DBHelper.ExecuteCommand(sql, CommandType.Text);
                WriteRecord("Success:" + backName + ".bak       Time:" + DateTime.Now.ToString());
            }
            catch(Exception ex)
            {
                WriteRecord("Error:" + ex.Message + "      Time:" + DateTime.Now.ToString());
            }
        }
 
        #region 服务日志
 
        /// <summary>
        /// 服务启动创建日志并添加记录
        /// </summary>
        public void Start()
        {
            FileStream fs = new FileStream(logPath, FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            m_streamWriter.WriteLine(DateTime.Now.ToString() + "--------------------------------------------------------------------------------------------/n");
            m_streamWriter.WriteLine("AdBackUpService: Service Started!     Time:" + DateTime.Now.ToString() + "/n");
            m_streamWriter.Flush();
            m_streamWriter.Close();
            fs.Close();
        }
 
        /// <summary>
        /// 备份操作日志记录
        /// </summary>
        /// <param name="record"></param>
        public void WriteRecord(string record)
        {
            FileStream fs = new FileStream(logPath, FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            m_streamWriter.WriteLine(record + "/n");
            m_streamWriter.Flush();
            m_streamWriter.Close();
            fs.Close();
        }
 
        /// <summary>
        /// 服务停止日志
        /// </summary>
        public void Stop()
        {
            FileStream fs = new FileStream(logPath, FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter m_streamWriter = new StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            m_streamWriter.WriteLine("AdBackUpService: Service Stopped!     Time: " + DateTime.Now.ToString() + "/n");
            m_streamWriter.Flush();
            m_streamWriter.Close();
            fs.Close();
        }
        #endregion
 
        /// <summary>
        /// 转换时间字符串,精确到毫秒
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public string GetDateStr(DateTime dt)
        {
            StringBuilder strDate = new StringBuilder();
            strDate.Append(dt.Year);
            strDate.Append(dt.Month < 10 ? "0" + dt.Month.ToString() : dt.Month.ToString());
            strDate.Append(dt.Day < 10 ? "0" + dt.Day.ToString() : dt.Day.ToString());
            strDate.Append(dt.Hour < 10 ? "0" + dt.Hour.ToString() : dt.Hour.ToString());
            strDate.Append(dt.Minute < 10 ? "0" + dt.Minute.ToString() : dt.Minute.ToString());
            strDate.Append(dt.Second < 10 ? "0" + dt.Second.ToString() : dt.Second.ToString());
            if(dt.Millisecond < 10)
                strDate.Append("00").Append(dt.Millisecond);
            else if(dt.Millisecond < 100)
                strDate.Append("0").Append(dt.Millisecond);
            else
                strDate.Append(dt.Millisecond);
            return strDate.ToString();
        }
    }
}
数据库操作类:
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
 
namespace AdBackUpService
{
    public class DBHelper
    {
        //获取数据库链接字符串
        public static String ConnectionString = ConfigurationManager.AppSettings["strCon"];
 
        /// <summary>
        /// 获取影响多少行
        /// </summary>
        /// <param name="queryString">T-SQL语句</param>
        /// <param name="commandType">命令类型</param>
        /// <param name="param">T-SQL参数</param>
        /// <returns>影响多少行</returns>
        public static int ExecuteCommand(string queryString, CommandType commandType, params SqlParameter[] param)
        {
            int flag = 0;
            using(SqlConnection con = new SqlConnection(ConnectionString))
            {
                SqlCommand command = new SqlCommand(queryString, con);
                command.CommandType = commandType;
 
                if(param != null)
                {
                    for(int i = 0; i < param.Length; i++)
                    {
                        command.Parameters.Add(param[i]);
                    }
                }
                try
                {
                    command.Connection.Open();
                    flag = command.ExecuteNonQuery();
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    command.Connection.Close();
                    command.Dispose();
                    command = null;
                }
            }
            return flag;
        }
 
 
        /// <summary>
        /// 获取DataSet对象
        /// </summary>
        /// <param name="queryString">T-SQL语句</param>
        /// <param name="commandType">命令类型</param>
        /// <param name="param">T-SQL参数</param>
        /// <returns>DataSet对象</returns>
        public static DataSet GetDataSet(string queryString, CommandType commandType, params SqlParameter[] param)
        {
            DataSet ds = new DataSet();
            using(SqlConnection con = new SqlConnection(ConnectionString))
            {
                SqlDataAdapter adapter = new SqlDataAdapter(queryString, con);
                adapter.SelectCommand.CommandType = commandType;
 
                if(param != null)
                {
                    adapter.SelectCommand.Parameters.Clear();
                    for(int i = 0; i < param.Length; i++)
                    {
                        adapter.SelectCommand.Parameters.Add(param[i]);
                    }
                }
 
                try
                {
                    adapter.Fill(ds);
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    adapter.Dispose();
                    adapter = null;
                }
            }
            return ds;
        }
 
 
        /// <summary>
        /// 获取DataReader对象
        /// </summary>
        /// <param name="queryString">T-SQL语句</param>
        /// <param name="commandType">命令类型</param>
        /// <param name="param">T-SQL参数</param>
        /// <returns>DataReader对象</returns>
        public static SqlDataReader GetDataReader(string queryString, CommandType commandType, params SqlParameter[] param)
        {
            SqlDataReader dataReader = null;
            SqlConnection con = new SqlConnection(ConnectionString);
            SqlCommand command = new SqlCommand(queryString, con);
            command.CommandType = commandType;
 
            if(param != null)
            {
                for(int i = 0; i < param.Length; i++)
                {
                    command.Parameters.Add(param[i]);
                }
            }
            try
            {
                command.Connection.Open();
                dataReader = command.ExecuteReader(CommandBehavior.CloseConnection);
            }
            catch(Exception ex)
            {
                throw ex;
            }
            return dataReader;
        }
 
 
        /// <summary>
        /// 查询单个数据
        /// </summary>
        /// <param name="queryString">T-SQL语句</param>
        /// <param name="commandType">命令类型</param>
        /// <param name="param">T-SQL参数</param>
        /// <returns>Object对象</returns>
        public static Object GetScalar(string queryString, CommandType commandType, params SqlParameter[] param)
        {
            Object obj = null;
            using(SqlConnection con = new SqlConnection(ConnectionString))
            {
                SqlCommand command = new SqlCommand(queryString, con);
                command.CommandType = commandType;
 
                if(param != null)
                {
                    for(int i = 0; i < param.Length; i++)
                    {
                        command.Parameters.Add(param[i]);
                    }
                }
 
                try
                {
                    command.Connection.Open();
                    obj = command.ExecuteScalar();
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    command.Connection.Close();
                    command.Dispose();
                    command = null;
                }
            }
            return obj;
        }
    }
}
 

5、代码编写完成后Service1视图上右键,添加安装程序。系统会添加一个名为ProjectInstaller的安装程序。里面包含两个组件

serviceProjectInstaller1和serviceInstaller1

修改serviceProjectInstaller1的属性:Account为LocalSystem,该属性其他枚举值说明

 

    

    

LocalService

充当本地计算机上非特权用户的账户,该账户将匿名凭据提供给所有远程服务器

LocalSystem

具有高特权级别的账户

NetworkService

提供广泛的本地特权的账户,该账户将计算机的凭据提供给所有远程服务器

User

由网络上特定的用户定义的账户。如果为ServiceProcessInstaller.Account成员指定 User,则会使系统在安装服务时提示输入有效的用户名和密码,除非为Service ProcessInstaller实例的UsernamePassword这两个属性设置值

 

 

ServiceProcessInstaller控件属性及说明

 

 

    

    

Account

获取或设置运行该服务应用程序时所使用的账户类型

HelpText

已重写。获取为服务安装选项显示的帮助文本

Parent

获取或设置包含该安装程序所属的集合的安装程序

Password

获取或设置与运行服务应用程序时所使用用户账户关联的密码

Username

获取或设置运行服务应用程序时将使用的用户账户

 

 

选中ServiceInstaller控件,在“属性”窗口中,将其StartType属性设置为Manual

该属性其他枚举值说明:

 

 

 

 

    

Automatic

指示服务在系统启动时将由(或已由)操作系统启动。如果某个自动启动的服务依赖于某个手动启动的服务,则手动启动的服务也会在系统启动时自动启动

Disabled

指示禁用该服务,以便它无法由用户或应用程序启动

Manual

指示服务只由用户(使用“服务控制管理器”)或应用程序手动启动

 

 

ServiceInstaller控件属性

    

    

DisplayName

指示向用户标识服务的友好名称

HelpText

获取安装程序集合中所有安装程序的帮助文字

ServiceName

指示系统用于标识此服务的名称。此属性必须与要安装的服务的ServiceBase. ServiceName相同

ServicesDependedOn

指示为使该服务能够运行而必须正在运行的服务

StartType

指示启动此服务的方式和时间

 

 

Description

指示服务的说明

 

 

最后生成解决方案,到这里服务已经创建完毕。

接下来需要使用命令窗口进行安装:

可以使用Visual  Studio下的Visual Studio 2005命令提示工具,也可以使用Microsoft .NET Framework SDK v2.0下的SDK命令提示 工具

安装卸载命令:

installutil 服务物理路径.exe

installutil /u 服务物理路径.exe

好了。就是这么简单。需要的话,不妨试试!

注:有可能有的服务器没有上述两个命令工具,那一般的命令行工具能不能行呢

 

 

本文作者:Rock870210 来源:CSDN
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读