C# 实现 git 通知

本来, gitlab 是自带邮件通知, 但是需要配置: https://blog.csdn.net/liuruiqun/article/details/50000213

不过, 正好配置人没弄过这个, 也懒得麻烦人家了。

做了一个小程序, 来实现这个功能。

基本思路:

1. 将项目的信息保存到 sqlite 表中;

2. C#调用 Proccess, 轮询检测项目的最后一条日志,如果日志的提交时间 > sqlite 对应项目的最后时间(初始置为 1900-01-01), 则给配置表中相关的人发邮件;

项目解决方案

Sqlite  表结构:

DROP TABLE IF EXISTS "project_data";
CREATE TABLE "project_data" (
  "projectId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  "projectName" nvarchar(100) NOT NULL,
  "localPath" nvarchar(500) NOT NULL,
  "lastUpdateTime" datetime NOT NULL,
  "lastLog" nvarchar(4000) NOT NULL,
  "emailToList" varchar(400) NOT NULL,
  "isEnabled" bit NOT NULL
);

注意事项

1.  邮箱、密码得改成自己的;

2.  可以用 Windows计划任务 或 SQL Server的代理作业来调用 ( 我本人是用自己写的通用定时服务来调用 ) ;

主要代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GitNotifyCommon.Model;
using GitNotifyCommon.DAL;
using GitNotifyCommon;
using System.Diagnostics;
using System.Globalization;

namespace GitNotifyCommon
{
    public class WatcherGit
    {
        public static void Run() 
        {
            //1. 获取所有的项目
            List<Project> list = ProjectDAL.GetList();
            if (list == null || list.Count == 0)
            {
                Logger.Singleton.Error("未获取到任何项目");
                return;
            }

            //2. 依次执行,得到相关的日志,并对比,如果有新的则发送邮件
            foreach (Project item in list) 
            {
                ExecGit(item);
            }
        }

        private static void ExecGit(Project item) 
        {
            try
            {
                using (Process pro = new Process())
                {
                    System.Console.InputEncoding = System.Text.Encoding.UTF8;
                    Process p = new Process();
                    p.StartInfo.WorkingDirectory = item.LocalPath;
                    p.StartInfo.FileName = CommonConfig.LocalGitCmd;
                    p.StartInfo.Arguments = "log -1";
                    p.StartInfo.CreateNoWindow = true;
                    p.StartInfo.UseShellExecute = false;
                    p.StartInfo.RedirectStandardOutput = true;
                    p.StartInfo.StandardOutputEncoding = Encoding.UTF8;
                    p.Start();
                    string info = p.StandardOutput.ReadToEnd();
                    p.WaitForExit();
                    SaveInfo(item, info);
                    //拉取最新版本
                    p.StartInfo.Arguments = "pull";
                    p.Start();
                    p.WaitForExit();
                }
            }
            catch (Exception ex)
            {
                Logger.Singleton.FatalFormat("执行 git 出错, {0}", ex, ex.Message );
            }
        }

        private static string GetDateString(string[] arr, ref int dateIdx) 
        {
            int j = -1;
            for (int i = 0; i < arr.Length; i++) 
            {
                if (arr[i].StartsWith("Date:")) 
                {
                    j = i;
                    break;
                }
            }
            if (j == -1)
                return null;

            dateIdx = j;
            string dateString = arr[j].Replace("Date:", "").Replace("+0800", "").Trim();
            dateString = dateString.Substring(dateString.IndexOf(" ")).Trim();

            string[] monthArr = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
            string[] arr2 = dateString.Split(' ');
            int month = -1;
            for (int i = 0; i < monthArr.Length; i++)
            {
                string monthStr = monthArr[i];
                if (monthStr == arr2[0])
                {
                    month = i;
                    break;
                }
            }
            dateString = string.Format("{0}-{1}-{2} {3}", arr2[3], month, arr2[1], arr2[2]);
            return dateString;
        }


        private static void SaveInfo(Project item, string info) 
        {
            string[] arr = info.Split('\n');
            int dateIdx = 0;
            string dateString = GetDateString(arr, ref dateIdx);
            if (arr.Length < 3 || dateString == null)
            {
                Logger.Singleton.ErrorFormat("字符串中获取不到正确的日期:\r\n{0}", info);
                return;
            }
            
            DateTime dt = DateTime.MinValue;
            if (!DateTime.TryParse(dateString, out dt)) 
            {
                Logger.Singleton.FatalFormat("日期转换错误: {0}",dateString);
                return;
            }

            if (dt == item.LastUpdateTime) 
            {
                Logger.Singleton.DebugFormat("ProjectName:{0}, LastUpdateTime: {1} 无更新。", item.ProjectName, dt);
                return;
            }
            Logger.Singleton.InfoFormat("ProjectName:{0}, LastUpdateTime: {1} 有更新。", item.ProjectName, dt);

            //如果 item 原日期> 1900-01-01, 不是原始记录,发邮件
            if (item.LastUpdateTime.Year > 1900 &&  dt>item.LastUpdateTime)
            {
                string commitId = arr[0];
                string author = arr[1];
                string commitDate = arr[dateIdx];
                StringBuilder sbDesc = new StringBuilder();
                for (int j = dateIdx+1; j < arr.Length; j++) 
                {
                    sbDesc.AppendFormat("{0}<br/>",arr[j]);
                }
                string commitDesc = sbDesc.ToString();
                string html = string.Format(
@"<style>.hr2 {{
    height: 3px;
    border: none;
    border-top: 3px double #33ccff;
    width: 100%;
}}</style>
<div>
    ProjectName: {0}<br/>
    {1}<br/>
    {2}<br/>
    Date: {3}<br/>
    <hr class='hr2' />
    <span style='color:blue;'>{4}</span>
</div>"
                    , item.ProjectName
                    , commitId
                    , author.Replace("<", "&lt;").Replace(">", "&gt;")
                    , dt.ToString("yyyy-MM-dd HH:mm:ss")
                    , commitDesc
                );
                EmailHelper email = new EmailHelper(item.EmailToList
                    , string.Format("【{0}】 git new commit by: {1}", item.ProjectName , author.Replace("Author:",""))
                    , true
                    , html
                    );
                email.Send();
            }
            //如果是新记录 更新记录
            item.LastUpdateTime = dt;
            item.LastLog = info;
            ProjectDAL.Update(item);
        }
    }
}
using System;
using System.Data;
using System.Text.RegularExpressions;
using System.Xml;
using System.IO;
using System.Collections;
using System.Data.SQLite;

namespace GitNotifyCommon
{
    /// <summary>
    /// SQLiteHelper is a utility class similar to "SQLHelper" in MS
    /// Data Access Application Block and follows similar pattern.
    /// </summary>
    public class SQLiteHelper
    {
        /// <summary>
        /// Creates a new <see cref="SQLiteHelper"/> instance. The ctor is marked private since all members are static.
        /// </summary>
        private SQLiteHelper()
        {
        }
        /// <summary>
        /// Creates the command.
        /// </summary>
        /// <param name="connection">Connection.</param>
        /// <param name="commandText">Command text.</param>
        /// <param name="commandParameters">Command parameters.</param>
        /// <returns>SQLite Command</returns>
        public static SQLiteCommand CreateCommand(SQLiteConnection connection, string commandText, params SQLiteParameter[] commandParameters)
        {
            SQLiteCommand cmd = new SQLiteCommand(commandText, connection);
            if (commandParameters.Length > 0)
            {
                foreach (SQLiteParameter parm in commandParameters)
                    cmd.Parameters.Add(parm);
            }
            return cmd;
        }

        /// <summary>
        /// Creates the command.
        /// </summary>
        /// <param name="connectionString">Connection string.</param>
        /// <param name="commandText">Command text.</param>
        /// <param name="commandParameters">Command parameters.</param>
        /// <returns>SQLite Command</returns>
        public static SQLiteCommand CreateCommand(string connectionString, string commandText, params SQLiteParameter[] commandParameters)
        {
            SQLiteConnection cn = new SQLiteConnection(connectionString);

            SQLiteCommand cmd = new SQLiteCommand(commandText, cn);

            if (commandParameters.Length > 0)
            {
                foreach (SQLiteParameter parm in commandParameters)
                    cmd.Parameters.Add(parm);
            }
            return cmd;
        }
        /// <summary>
        /// Creates the parameter.
        /// </summary>
        /// <param name="parameterName">Name of the parameter.</param>
        /// <param name="parameterType">Parameter type.</param>
        /// <param name="parameterValue">Parameter value.</param>
        /// <returns>SQLiteParameter</returns>
        public static SQLiteParameter CreateParameter(string parameterName, System.Data.DbType parameterType, object parameterValue)
        {
            SQLiteParameter parameter = new SQLiteParameter();
            parameter.DbType = parameterType;
            parameter.ParameterName = parameterName;
            parameter.Value = parameterValue;
            return parameter;
        }

        /// <summary>
        /// Shortcut method to execute dataset from SQL Statement and object[] arrray of parameter values
        /// </summary>
        /// <param name="connectionString">SQLite Connection string</param>
        /// <param name="commandText">SQL Statement with embedded "@param" style parameter names</param>
        /// <param name="paramList">object[] array of parameter values</param>
        /// <returns></returns>
        public static DataSet ExecuteDataSet(string connectionString, string commandText, object[] paramList)
        {
            SQLiteConnection cn = new SQLiteConnection(connectionString);
            SQLiteCommand cmd = cn.CreateCommand();


            cmd.CommandText = commandText;
            if (paramList != null)
            {
                AttachParameters(cmd, commandText, paramList);
            }
            DataSet ds = new DataSet();
            if (cn.State == ConnectionState.Closed)
                cn.Open();
            SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
            da.Fill(ds);
            da.Dispose();
            cmd.Dispose();
            cn.Close();
            return ds;
        }
        /// <summary>
        /// Shortcut method to execute dataset from SQL Statement and object[] arrray of  parameter values
        /// </summary>
        /// <param name="cn">Connection.</param>
        /// <param name="commandText">Command text.</param>
        /// <param name="paramList">Param list.</param>
        /// <returns></returns>
        public static DataSet ExecuteDataSet(SQLiteConnection cn, string commandText, object[] paramList)
        {

            SQLiteCommand cmd = cn.CreateCommand();


            cmd.CommandText = commandText;
            if (paramList != null)
            {
                AttachParameters(cmd, commandText, paramList);
            }
            DataSet ds = new DataSet();
            if (cn.State == ConnectionState.Closed)
                cn.Open();
            SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
            da.Fill(ds);
            da.Dispose();
            cmd.Dispose();
            cn.Close();
            return ds;
        }
        /// <summary>
        /// Executes the dataset from a populated Command object.
        /// </summary>
        /// <param name="cmd">Fully populated SQLiteCommand</param>
        /// <returns>DataSet</returns>
        public static DataSet ExecuteDataset(SQLiteCommand cmd)
        {
            if (cmd.Connection.State == ConnectionState.Closed)
                cmd.Connection.Open();
            DataSet ds = new DataSet();
            SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
            da.Fill(ds);
            da.Dispose();
            cmd.Connection.Close();
            cmd.Dispose();
            return ds;
        }

        /// <summary>
        /// Executes the dataset in a SQLite Transaction
        /// </summary>
        /// <param name="transaction">SQLiteTransaction. Transaction consists of Connection, Transaction,  /// and Command, all of which must be created prior to making this method call. </param>
        /// <param name="commandText">Command text.</param>
        /// <param name="commandParameters">Sqlite Command parameters.</param>
        /// <returns>DataSet</returns>
        /// <remarks>user must examine Transaction Object and handle transaction.connection .Close, etc.</remarks>
        public static DataSet ExecuteDataset(SQLiteTransaction transaction, string commandText, params SQLiteParameter[] commandParameters)
        {

            if (transaction == null) throw new ArgumentNullException("transaction");
            if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rolled back or committed, please provide an open transaction.", "transaction");
            IDbCommand cmd = transaction.Connection.CreateCommand();
            cmd.CommandText = commandText;
            foreach (SQLiteParameter parm in commandParameters)
            {
                cmd.Parameters.Add(parm);
            }
            if (transaction.Connection.State == ConnectionState.Closed)
                transaction.Connection.Open();
            DataSet ds = ExecuteDataset((SQLiteCommand)cmd);
            return ds;
        }

        /// <summary>
        /// Executes the dataset with Transaction and object array of parameter values.
        /// </summary>
        /// <param name="transaction">SQLiteTransaction. Transaction consists of Connection, Transaction,    /// and Command, all of which must be created prior to making this method call. </param>
        /// <param name="commandText">Command text.</param>
        /// <param name="commandParameters">object[] array of parameter values.</param>
        /// <returns>DataSet</returns>
        /// <remarks>user must examine Transaction Object and handle transaction.connection .Close, etc.</remarks>
        public static DataSet ExecuteDataset(SQLiteTransaction transaction, string commandText, object[] commandParameters)
        {

            if (transaction == null) throw new ArgumentNullException("transaction");
            if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rolled back or committed,                                                          please provide an open transaction.", "transaction");
            IDbCommand cmd = transaction.Connection.CreateCommand();
            cmd.CommandText = commandText;
            AttachParameters((SQLiteCommand)cmd, cmd.CommandText, commandParameters);
            if (transaction.Connection.State == ConnectionState.Closed)
                transaction.Connection.Open();

            DataSet ds = ExecuteDataset((SQLiteCommand)cmd);
            return ds;
        }

        #region UpdateDataset
        /// <summary>
        /// Executes the respective command for each inserted, updated, or deleted row in the DataSet.
        /// </summary>
        /// <remarks>
        /// e.g.:  
        ///  UpdateDataset(conn, insertCommand, deleteCommand, updateCommand, dataSet, "Order");
        /// </remarks>
        /// <param name="insertCommand">A valid SQL statement  to insert new records into the data source</param>
        /// <param name="deleteCommand">A valid SQL statement to delete records from the data source</param>
        /// <param name="updateCommand">A valid SQL statement used to update records in the data source</param>
        /// <param name="dataSet">The DataSet used to update the data source</param>
        /// <param name="tableName">The DataTable used to update the data source.</param>
        public static void UpdateDataset(SQLiteCommand insertCommand, SQLiteCommand deleteCommand, SQLiteCommand updateCommand, DataSet dataSet, string tableName)
        {
            if (insertCommand == null) throw new ArgumentNullException("insertCommand");
            if (deleteCommand == null) throw new ArgumentNullException("deleteCommand");
            if (updateCommand == null) throw new ArgumentNullException("updateCommand");
            if (tableName == null || tableName.Length == 0) throw new ArgumentNullException("tableName");

            // Create a SQLiteDataAdapter, and dispose of it after we are done
            using (SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter())
            {
                // Set the data adapter commands
                dataAdapter.UpdateCommand = updateCommand;
                dataAdapter.InsertCommand = insertCommand;
                dataAdapter.DeleteCommand = deleteCommand;

                // Update the dataset changes in the data source
                dataAdapter.Update(dataSet, tableName);

                // Commit all the changes made to the DataSet
                dataSet.AcceptChanges();
            }
        }
        #endregion




        /// <summary>
        /// ShortCut method to return IDataReader
        /// NOTE: You should explicitly close the Command.connection you passed in as
        /// well as call Dispose on the Command  after reader is closed.
        /// We do this because IDataReader has no underlying Connection Property.
        /// </summary>
        /// <param name="cmd">SQLiteCommand Object</param>
        /// <param name="commandText">SQL Statement with optional embedded "@param" style parameters</param>
        /// <param name="paramList">object[] array of parameter values</param>
        /// <returns>IDataReader</returns>
        public static IDataReader ExecuteReader(SQLiteCommand cmd, string commandText, object[] paramList)
        {
            if (cmd.Connection == null)
                throw new ArgumentException("Command must have live connection attached.", "cmd");
            cmd.CommandText = commandText;
            AttachParameters(cmd, commandText, paramList);
            if (cmd.Connection.State == ConnectionState.Closed)
                cmd.Connection.Open();
            IDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            return rdr;
        }

        /// <summary>
        /// Shortcut to ExecuteNonQuery with SqlStatement and object[] param values
        /// </summary>
        /// <param name="connectionString">SQLite Connection String</param>
        /// <param name="commandText">Sql Statement with embedded "@param" style parameters</param>
        /// <param name="paramList">object[] array of parameter values</param>
        /// <returns></returns>
        public static int ExecuteNonQuery(string connectionString, string commandText, params object[] paramList)
        {
            SQLiteConnection cn = new SQLiteConnection(connectionString);
            SQLiteCommand cmd = cn.CreateCommand();
            cmd.CommandText = commandText;
            AttachParameters(cmd, commandText, paramList);
            if (cn.State == ConnectionState.Closed)
                cn.Open();
            int result = cmd.ExecuteNonQuery();
            cmd.Dispose();
            cn.Close();

            return result;
        }



        public static int ExecuteNonQuery(SQLiteConnection cn, string commandText, params  object[] paramList)
        {

            SQLiteCommand cmd = cn.CreateCommand();
            cmd.CommandText = commandText;
            AttachParameters(cmd, commandText, paramList);
            if (cn.State == ConnectionState.Closed)
                cn.Open();
            int result = cmd.ExecuteNonQuery();
            cmd.Dispose();
            cn.Close();

            return result;
        }

        /// <summary>
        /// Executes  non-query sql Statment with Transaction
        /// </summary>
        /// <param name="transaction">SQLiteTransaction. Transaction consists of Connection, Transaction,   /// and Command, all of which must be created prior to making this method call. </param>
        /// <param name="commandText">Command text.</param>
        /// <param name="paramList">Param list.</param>
        /// <returns>Integer</returns>
        /// <remarks>user must examine Transaction Object and handle transaction.connection .Close, etc.</remarks>
        public static int ExecuteNonQuery(SQLiteTransaction transaction, string commandText, params  object[] paramList)
        {
            if (transaction == null) throw new ArgumentNullException("transaction");
            if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rolled back or committed,                                                        please provide an open transaction.", "transaction");
            IDbCommand cmd = transaction.Connection.CreateCommand();
            cmd.CommandText = commandText;
            AttachParameters((SQLiteCommand)cmd, cmd.CommandText, paramList);
            if (transaction.Connection.State == ConnectionState.Closed)
                transaction.Connection.Open();
            int result = cmd.ExecuteNonQuery();
            cmd.Dispose();
            return result;
        }


        /// <summary>
        /// Executes the non query.
        /// </summary>
        /// <param name="cmd">CMD.</param>
        /// <returns></returns>
        public static int ExecuteNonQuery(IDbCommand cmd)
        {
            if (cmd.Connection.State == ConnectionState.Closed)
                cmd.Connection.Open();
            int result = cmd.ExecuteNonQuery();
            cmd.Connection.Close();
            cmd.Dispose();
            return result;
        }

        /// <summary>
        /// Shortcut to ExecuteScalar with Sql Statement embedded params and object[] param values
        /// </summary>
        /// <param name="connectionString">SQLite Connection String</param>
        /// <param name="commandText">SQL statment with embedded "@param" style parameters</param>
        /// <param name="paramList">object[] array of param values</param>
        /// <returns></returns>
        public static object ExecuteScalar(string connectionString, string commandText, params  object[] paramList)
        {
            SQLiteConnection cn = new SQLiteConnection(connectionString);
            SQLiteCommand cmd = cn.CreateCommand();
            cmd.CommandText = commandText;
            AttachParameters(cmd, commandText, paramList);
            if (cn.State == ConnectionState.Closed)
                cn.Open();
            object result = cmd.ExecuteScalar();
            cmd.Dispose();
            cn.Close();

            return result;
        }

        /// <summary>
        /// Execute XmlReader with complete Command
        /// </summary>
        /// <param name="command">SQLite Command</param>
        /// <returns>XmlReader</returns>
        public static XmlReader ExecuteXmlReader(IDbCommand command)
        { // open the connection if necessary, but make sure we 
            // know to close it when we�re done.
            if (command.Connection.State != ConnectionState.Open)
            {
                command.Connection.Open();
            }

            // get a data adapter  
            SQLiteDataAdapter da = new SQLiteDataAdapter((SQLiteCommand)command);
            DataSet ds = new DataSet();
            // fill the data set, and return the schema information
            da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
            da.Fill(ds);
            // convert our dataset to XML
            StringReader stream = new StringReader(ds.GetXml());
            command.Connection.Close();
            // convert our stream of text to an XmlReader
            return new XmlTextReader(stream);
        }



        /// <summary>
        /// Parses parameter names from SQL Statement, assigns values from object array ,   /// and returns fully populated ParameterCollection.
        /// </summary>
        /// <param name="commandText">Sql Statement with "@param" style embedded parameters</param>
        /// <param name="paramList">object[] array of parameter values</param>
        /// <returns>SQLiteParameterCollection</returns>
        /// <remarks>Status experimental. Regex appears to be handling most issues. Note that parameter object array must be in same ///order as parameter names appear in SQL statement.</remarks>
        private static SQLiteParameterCollection AttachParameters(SQLiteCommand cmd, string commandText, params  object[] paramList)
        {
            if (paramList == null || paramList.Length == 0) return null;

            SQLiteParameterCollection coll = cmd.Parameters;
            string parmString = commandText.Substring(commandText.IndexOf("@"));
            // pre-process the string so always at least 1 space after a comma.
            parmString = parmString.Replace(",", " ,");
            // get the named parameters into a match collection
            string pattern = @"(@)\S*(.*?)\b";
            Regex ex = new Regex(pattern, RegexOptions.IgnoreCase);
            MatchCollection mc = ex.Matches(parmString);
            string[] paramNames = new string[mc.Count];
            int i = 0;
            foreach (Match m in mc)
            {
                paramNames[i] = m.Value;
                i++;
            }

            // now let's type the parameters
            int j = 0;
            Type t = null;
            foreach (object o in paramList)
            {
                t = o.GetType();

                SQLiteParameter parm = new SQLiteParameter();
                switch (t.ToString())
                {

                    case ("DBNull"):
                    case ("Char"):
                    case ("SByte"):
                    case ("UInt16"):
                    case ("UInt32"):
                    case ("UInt64"):
                        throw new SystemException("Invalid data type");


                    case ("System.String"):
                        parm.DbType = DbType.String;
                        parm.ParameterName = paramNames[j];
                        parm.Value = (string)paramList[j];
                        coll.Add(parm);
                        break;

                    case ("System.Byte[]"):
                        parm.DbType = DbType.Binary;
                        parm.ParameterName = paramNames[j];
                        parm.Value = (byte[])paramList[j];
                        coll.Add(parm);
                        break;

                    case ("System.Int32"):
                        parm.DbType = DbType.Int32;
                        parm.ParameterName = paramNames[j];
                        parm.Value = (int)paramList[j];
                        coll.Add(parm);
                        break;

                    case ("System.Boolean"):
                        parm.DbType = DbType.Boolean;
                        parm.ParameterName = paramNames[j];
                        parm.Value = (bool)paramList[j];
                        coll.Add(parm);
                        break;

                    case ("System.DateTime"):
                        parm.DbType = DbType.DateTime;
                        parm.ParameterName = paramNames[j];
                        parm.Value = Convert.ToDateTime(paramList[j]);
                        coll.Add(parm);
                        break;

                    case ("System.Double"):
                        parm.DbType = DbType.Double;
                        parm.ParameterName = paramNames[j];
                        parm.Value = Convert.ToDouble(paramList[j]);
                        coll.Add(parm);
                        break;

                    case ("System.Decimal"):
                        parm.DbType = DbType.Decimal;
                        parm.ParameterName = paramNames[j];
                        parm.Value = Convert.ToDecimal(paramList[j]);
                        break;

                    case ("System.Guid"):
                        parm.DbType = DbType.Guid;
                        parm.ParameterName = paramNames[j];
                        parm.Value = (System.Guid)(paramList[j]);
                        break;

                    case ("System.Object"):

                        parm.DbType = DbType.Object;
                        parm.ParameterName = paramNames[j];
                        parm.Value = paramList[j];
                        coll.Add(parm);
                        break;

                    default:
                        throw new SystemException("Value is of unknown data type");

                } // end switch

                j++;
            }
            return coll;
        }

        /// <summary>
        /// Executes non query typed params from a DataRow
        /// </summary>
        /// <param name="command">Command.</param>
        /// <param name="dataRow">Data row.</param>
        /// <returns>Integer result code</returns>
        public static int ExecuteNonQueryTypedParams(IDbCommand command, DataRow dataRow)
        {
            int retVal = 0;

            // If the row has values, the store procedure parameters must be initialized
            if (dataRow != null && dataRow.ItemArray.Length > 0)
            {
                // Set the parameters values
                AssignParameterValues(command.Parameters, dataRow);

                retVal = ExecuteNonQuery(command);
            }
            else
            {
                retVal = ExecuteNonQuery(command);
            }

            return retVal;
        }

        /// <summary>
        /// This method assigns dataRow column values to an IDataParameterCollection
        /// </summary>
        /// <param name="commandParameters">The IDataParameterCollection to be assigned values</param>
        /// <param name="dataRow">The dataRow used to hold the command's parameter values</param>
        /// <exception cref="System.InvalidOperationException">Thrown if any of the parameter names are invalid.</exception>
        protected internal static void AssignParameterValues(IDataParameterCollection commandParameters, DataRow dataRow)
        {
            if (commandParameters == null || dataRow == null)
            {
                // Do nothing if we get no data
                return;
            }

            DataColumnCollection columns = dataRow.Table.Columns;

            int i = 0;
            // Set the parameters values
            foreach (IDataParameter commandParameter in commandParameters)
            {
                // Check the parameter name
                if (commandParameter.ParameterName == null ||
                 commandParameter.ParameterName.Length <= 1)
                    throw new InvalidOperationException(string.Format(
                           "Please provide a valid parameter name on the parameter #{0},                            the ParameterName property has the following value: '{1}'.",
                     i, commandParameter.ParameterName));

                if (columns.Contains(commandParameter.ParameterName))
                    commandParameter.Value = dataRow[commandParameter.ParameterName];
                else if (columns.Contains(commandParameter.ParameterName.Substring(1)))
                    commandParameter.Value = dataRow[commandParameter.ParameterName.Substring(1)];

                i++;
            }
        }

        /// <summary>
        /// This method assigns dataRow column values to an array of IDataParameters
        /// </summary>
        /// <param name="commandParameters">Array of IDataParameters to be assigned values</param>
        /// <param name="dataRow">The dataRow used to hold the stored procedure's parameter values</param>
        /// <exception cref="System.InvalidOperationException">Thrown if any of the parameter names are invalid.</exception>
        protected void AssignParameterValues(IDataParameter[] commandParameters, DataRow dataRow)
        {
            if ((commandParameters == null) || (dataRow == null))
            {
                // Do nothing if we get no data
                return;
            }

            DataColumnCollection columns = dataRow.Table.Columns;

            int i = 0;
            // Set the parameters values
            foreach (IDataParameter commandParameter in commandParameters)
            {
                // Check the parameter name
                if (commandParameter.ParameterName == null ||
                 commandParameter.ParameterName.Length <= 1)
                    throw new InvalidOperationException(string.Format(
                     "Please provide a valid parameter name on the parameter #{0}, the ParameterName property has the following value: '{1}'.",
                     i, commandParameter.ParameterName));

                if (columns.Contains(commandParameter.ParameterName))
                    commandParameter.Value = dataRow[commandParameter.ParameterName];
                else if (columns.Contains(commandParameter.ParameterName.Substring(1)))
                    commandParameter.Value = dataRow[commandParameter.ParameterName.Substring(1)];

                i++;
            }
        }

        /// <summary>
        /// This method assigns an array of values to an array of IDataParameters
        /// </summary>
        /// <param name="commandParameters">Array of IDataParameters to be assigned values</param>
        /// <param name="parameterValues">Array of objects holding the values to be assigned</param>
        /// <exception cref="System.ArgumentException">Thrown if an incorrect number of parameters are passed.</exception>
        protected void AssignParameterValues(IDataParameter[] commandParameters, params  object[] parameterValues)
        {
            if ((commandParameters == null) || (parameterValues == null))
            {
                // Do nothing if we get no data
                return;
            }

            // We must have the same number of values as we pave parameters to put them in
            if (commandParameters.Length != parameterValues.Length)
            {
                throw new ArgumentException("Parameter count does not match Parameter Value count.");
            }

            // Iterate through the IDataParameters, assigning the values from the corresponding position in the 
            // value array
            for (int i = 0, j = commandParameters.Length, k = 0; i < j; i++)
            {
                if (commandParameters[i].Direction != ParameterDirection.ReturnValue)
                {
                    // If the current array value derives from IDataParameter, then assign its Value property
                    if (parameterValues[k] is IDataParameter)
                    {
                        IDataParameter paramInstance;
                        paramInstance = (IDataParameter)parameterValues[k];
                        if (paramInstance.Direction == ParameterDirection.ReturnValue)
                        {
                            paramInstance = (IDataParameter)parameterValues[++k];
                        }
                        if (paramInstance.Value == null)
                        {
                            commandParameters[i].Value = DBNull.Value;
                        }
                        else
                        {
                            commandParameters[i].Value = paramInstance.Value;
                        }
                    }
                    else if (parameterValues[k] == null)
                    {
                        commandParameters[i].Value = DBNull.Value;
                    }
                    else
                    {
                        commandParameters[i].Value = parameterValues[k];
                    }
                    k++;
                }
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data.SqlClient;

namespace GitNotifyCommon
{
    /// <summary>
    /// Author     : yenange
    /// Date       : 2014-02-21
    /// Description: 日志辅助类
    /// </summary>
    public sealed class Logger
    {
        #region [ 单例模式 ]
        private static readonly Logger _logger = new Logger();
        private static readonly log4net.ILog _Logger4net = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// 无参私有构造函数
        /// </summary>
        private Logger()
        {
        }

        /// <summary>
        /// 得到单例
        /// </summary>
        public static Logger Singleton
        {
            get
            {
                return _logger;
            }
        }
        #endregion

        #region [ 参数 ]
        public bool IsDebugEnabled
        {
            get { return _Logger4net.IsDebugEnabled; }
        }
        public bool IsInfoEnabled
        {
            get { return _Logger4net.IsInfoEnabled; }
        }
        public bool IsWarnEnabled
        {
            get { return _Logger4net.IsWarnEnabled; }
        }
        public bool IsErrorEnabled
        {
            get { return _Logger4net.IsErrorEnabled; }
        }
        public bool IsFatalEnabled
        {
            get { return _Logger4net.IsFatalEnabled; }
        }
        #endregion

        #region [ 接口方法 ]

        #region [ Debug ]

        #region [ 不带dbId ]
        public void Debug(string message)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, message);
            }
        }

        public void Debug(string message, Exception exception)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, message, exception);
            }
        }

        public void DebugFormat(string format, params object[] args)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, format, args);
            }
        }

        public void DebugFormat(string format, Exception exception, params object[] args)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, string.Format(format, args), exception);
            }
        }
        #endregion

        #region [ 带dbId ]
        public void DebugFormat2(long dbId, string message)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, string.Format("dbId:{0}, {1}", dbId, message));
            }
        }

        public void DebugFormat2(long dbId, string message, Exception exception)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, string.Format("dbId:{0}, {1}", message), exception);
            }
        }

        public void DebugFormat2(long dbId, string format, params object[] args)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)));
            }
        }

        public void DebugFormat2(long dbId, string format, Exception exception, params object[] args)
        {
            if (this.IsDebugEnabled)
            {
                this.Log(LogLevel.Debug, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)), exception);
            }
        }
        #endregion

        #endregion

        #region [ Info ]

        #region [ 不带dbId ]
        public void Info(string message)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, message);
            }
        }

        public void Info(string message, Exception exception)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, message, exception);
            }
        }

        public void InfoFormat(string format, params object[] args)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, format, args);
            }
        }

        public void InfoFormat(string format, Exception exception, params object[] args)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, string.Format(format, args), exception);
            }
        }
        #endregion

        #region [ 带dbId ]
        public void InfoFormat2(long dbId, string message)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, string.Format("dbId:{0}, {1}", dbId, message));
            }
        }

        public void InfoFormat2(long dbId, string message, Exception exception)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, string.Format("dbId:{0}, {1}", dbId, message), exception);
            }
        }

        public void InfoFormat2(long dbId, string format, params object[] args)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)));
            }
        }

        public void InfoFormat2(long dbId, string format, Exception exception, params object[] args)
        {
            if (this.IsInfoEnabled)
            {
                this.Log(LogLevel.Info, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)), exception);
            }
        }
        #endregion

        #endregion

        #region  [ Warn ]

        #region [ 不带dbId ]
        public void Warn(string message)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, message);
            }
        }

        public void Warn(string message, Exception exception)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, message, exception);
            }
        }

        public void WarnFormat(string format, params object[] args)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, format, args);
            }
        }

        public void WarnFormat(string format, Exception exception, params object[] args)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, string.Format(format, args), exception);
            }
        }
        #endregion

        #region [ 带dbId ]
        public void WarnFormat2(long dbId, string message)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, string.Format("dbId:{0}, {1}", dbId, message));
            }
        }

        public void WarnFormat2(long dbId, string message, Exception exception)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, string.Format("dbId:{0}, {1}", dbId, message), exception);
            }
        }

        public void WarnFormat2(long dbId, string format, params object[] args)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)));
            }
        }

        public void WarnFormat2(long dbId, string format, Exception exception, params object[] args)
        {
            if (this.IsWarnEnabled)
            {
                this.Log(LogLevel.Warn, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)), exception);
            }
        }
        #endregion

        #endregion

        #region  [ Error ]

        #region [ 不带dbId ]
        public void Error(string message)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, message);
            }
        }

        public void Error(string message, Exception exception)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, message, exception);
            }
        }

        public void ErrorFormat(string format, params object[] args)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, format, args);
            }
        }

        public void ErrorFormat(string format, Exception exception, params object[] args)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, string.Format(format, args), exception);
            }
        }
        #endregion

        #region [ 带dbId ]

        public void ErrorFormat2(long dbId, string message)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, string.Format("dbId:{0}, {1}", dbId, message));
            }
        }

        public void ErrorFormat2(long dbId, string message, Exception exception)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, string.Format("dbId:{0}, {1}", dbId, message), exception);
            }
        }

        public void ErrorFormat2(long dbId, string format, params object[] args)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)));
            }
        }

        public void ErrorFormat2(long dbId, string format, Exception exception, params object[] args)
        {
            if (this.IsErrorEnabled)
            {
                this.Log(LogLevel.Error, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)), exception);
            }
        }
        #endregion

        #endregion

        #region  [ Fatal ]

        #region [ 不带dbId ]
        public void Fatal(string message)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, message);

                SaveExceptionToDB(message, new Exception(message), 0);
            }
        }

        public void Fatal(string message, Exception exception)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, message, exception);

                SaveExceptionToDB(message, exception, 0);
            }
        }

        public void FatalFormat(string format, params object[] args)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, format, args);

                SaveExceptionToDB(string.Format(format, args), new Exception(string.Format(format, args)), 0);
            }
        }

        public void FatalFormat(string format, Exception exception, params object[] args)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, string.Format(format, args), exception);

                SaveExceptionToDB(string.Format(format, args), exception, 0);
            }
        }
        #endregion

        #region [ 带dbId ]
        public void FatalFormat2(long dbId, string message)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, string.Format("dbId:{0}, {1}", dbId, message));

                SaveExceptionToDB(message, new Exception(message), dbId);
            }
        }

        public void FatalFormat2(long dbId,string message, Exception exception)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, string.Format("dbId:{0}, {1}", dbId, message), exception);

                SaveExceptionToDB(message, exception, dbId);
            }
        }

        public void FatalFormat2(long dbId, string format, params object[] args)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)) );

                SaveExceptionToDB(string.Format(format, args), new Exception(string.Format(format, args)), dbId);
            }
        }

        public void FatalFormat2(long dbId, string format, Exception exception, params object[] args)
        {
            if (this.IsFatalEnabled)
            {
                this.Log(LogLevel.Fatal, string.Format("dbId:{0}, {1}", dbId, string.Format(format, args)), exception);

                SaveExceptionToDB(string.Format(format, args), exception, dbId);
            }
        }
        #endregion

        #endregion

        /// <summary>
        /// 输出到 ErrorLog 表, 便于查找
        /// </summary>
        /// <param name="message">相关信息</param>
        /// <param name="exception">异常对象</param>
        /// <param name="dbId">dbId</param>
        private void SaveExceptionToDB(string message, Exception exception, long dbId)
        {
            //无数据库操作
        }

        #endregion

        #region [ 内部方法 ]
        /// <summary>
        /// 输出普通日志
        /// </summary>
        /// <param name="level"></param>
        /// <param name="format"></param>
        /// <param name="args"></param>
        private void Log(LogLevel level, string format, params object[] args)
        {
            switch (level)
            {
                case LogLevel.Debug:
                    _Logger4net.DebugFormat(format, args);
                    break;
                case LogLevel.Info:
                    _Logger4net.InfoFormat(format, args);
                    break;
                case LogLevel.Warn:
                    _Logger4net.WarnFormat(format, args);
                    break;
                case LogLevel.Error:
                    _Logger4net.ErrorFormat(format, args);
                    break;
                case LogLevel.Fatal:
                    _Logger4net.FatalFormat(format, args);
                    break;
            }
        }

        /// <summary>
        /// 格式化输出异常信息
        /// </summary>
        /// <param name="level"></param>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        private void Log(LogLevel level, string message, Exception exception)
        {
            switch (level)
            {
                case LogLevel.Debug:
                    _Logger4net.Debug(message, exception);
                    break;
                case LogLevel.Info:
                    _Logger4net.Info(message, exception);
                    break;
                case LogLevel.Warn:
                    _Logger4net.Warn(message, exception);
                    break;
                case LogLevel.Error:
                    _Logger4net.Error(message, exception);
                    break;
                case LogLevel.Fatal:
                    _Logger4net.Fatal(message, exception);

                    
                    break;
            }
        }
        #endregion
    }//end of class

    #region [ enum: LogLevel ]
    /// <summary>
    /// 日志级别
    /// </summary>
    public enum LogLevel
    {
        Debug,
        Info,
        Warn,
        Error,
        Fatal
    }
    #endregion
}//end of namespace
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace GitNotifyCommon
{
    public static class CommonConfig
    {
        private static string _SqliteConnString = "no";

        /// <summary>
        /// Sqlite 连接串
        /// </summary>
        public static string SqliteConnString
        {
            get
            {
                if (_SqliteConnString == "no")
                {
                    string strValue = System.Configuration.ConfigurationManager.AppSettings["SqliteConnString"];
                    _SqliteConnString = strValue;
                }
                return _SqliteConnString;
            }
        }

        private static string _LocalGitCmd = "no";

        /// <summary>
        /// 监控目录
        /// </summary>
        public static string LocalGitCmd
        {
            get
            {
                if(_LocalGitCmd=="no")
                {
                    string strValue = System.Configuration.ConfigurationManager.AppSettings["LocalGitCmd"];
                    _LocalGitCmd = strValue;
                }
                return _LocalGitCmd;
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;

namespace GitNotifyCommon
{
    /// <summary>
    /// Author      : yenange
    /// Date        : 2014-02-26
    /// Description : 邮件发送辅助类
    /// </summary>
    public class EmailHelper
    {
        #region [ 属性(发送Email相关) ]
        private string _SmtpHost = string.Empty;
        //private int _SmtpPort = -1;
        private string _FromEmailAddress = string.Empty;
        private string _FormEmailPassword = string.Empty;

        /// <summary>
        /// smtp 服务器 
        /// </summary>
        public string SmtpHost
        {
            get 
            {
                return "smtp.163.com";
            }
        }
        /// <summary>
        /// smtp 服务器端口  默认为25
        /// </summary>
        public int SmtpPort
        {
            get 
            {
                return 25;
            }
        }
        /// <summary>
        /// 发送者 Eamil 地址
        /// </summary>
        public string FromEmailAddress
        {
            get 
            {
                return "xxx@163.com";
            }
        }

        /// <summary>
        /// 发送者 Eamil 密码
        /// </summary>
        public string FromEmailPassword
        {
            get 
            {
                return "xxxx";
            }
        }
        #endregion

        #region [ 属性(邮件相关) ]
        /// <summary>
        /// 收件人 Email 列表,多个邮件地址之间用 半角逗号 分开
        /// </summary>
        public string ToList { get; set; }
        /// <summary>
        /// 邮件的抄送者,支持群发,多个邮件地址之间用 半角逗号 分开
        /// </summary>
        public string CCList { get; set; }
        /// <summary>
        /// 邮件的密送者,支持群发,多个邮件地址之间用 半角逗号 分开
        /// </summary>
        public string BccList { get; set; }
        /// <summary>
        /// 邮件标题
        /// </summary>
        public string Subject { get; set; }
        /// <summary>
        /// 邮件正文
        /// </summary>
        public string Body { get; set; }

        private bool _IsBodyHtml = true;
        /// <summary>
        /// 邮件正文是否为Html格式
        /// </summary>
        public bool IsBodyHtml
        {
            get { return _IsBodyHtml; }
            set { _IsBodyHtml = value; }
        }
        /// <summary>
        /// 附件列表
        /// </summary>
        public List<Attachment> AttachmentList { get; set; }
        #endregion

        #region [ 构造函数 ]

        public EmailHelper() { }

        /// <summary>
        /// 构造函数 (body默认为html格式)
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="body">邮件正文</param>
        public EmailHelper(string toList, string subject, string body)
        {
            this.ToList = toList;
            this.Subject = subject;
            this.Body = body;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        public EmailHelper(string toList, string subject, bool isBodyHtml, string body)
        {
            this.ToList = toList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="ccList">收件人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        public EmailHelper(string toList, string ccList, string subject, bool isBodyHtml, string body)
        {
            this.ToList = toList;
            this.CCList = ccList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="ccList">抄送人列表</param>
        /// <param name="bccList">密送人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        public EmailHelper(string toList, string ccList, string bccList, string subject, bool isBodyHtml, string body)
        {
            this.ToList = toList;
            this.CCList = ccList;
            this.BccList = bccList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="toList">收件人列表</param>
        /// <param name="ccList">抄送人列表</param>
        /// <param name="bccList">密送人列表</param>
        /// <param name="subject">邮件标题</param>
        /// <param name="isBodyHtml">邮件正文是否为Html格式</param>
        /// <param name="body">邮件正文</param>
        /// <param name="attachmentList">附件列表</param>
        public EmailHelper(string toList, string ccList, string bccList, string subject, bool isBodyHtml, string body, List<Attachment> attachmentList)
        {
            this.ToList = toList;
            this.CCList = ccList;
            this.BccList = bccList;
            this.Subject = subject;
            this.IsBodyHtml = isBodyHtml;
            this.Body = body;
            this.AttachmentList = attachmentList;
        }
        #endregion

        #region [ 发送邮件 ]
        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <returns></returns>
        public void Send()
        {
            SmtpClient smtp = new SmtpClient();                 //实例化一个SmtpClient
            smtp.DeliveryMethod = SmtpDeliveryMethod.Network;   //将smtp的出站方式设为 Network
            smtp.EnableSsl = false;                             //smtp服务器是否启用SSL加密
            smtp.Host = this.SmtpHost;                          //指定 smtp 服务器地址
            smtp.Port = this.SmtpPort;                          //指定 smtp 服务器的端口,默认是25,如果采用默认端口,可省去
            smtp.UseDefaultCredentials = true;                  //如果你的SMTP服务器不需要身份认证,则使用下面的方式,不过,目前基本没有不需要认证的了
            smtp.Credentials = new NetworkCredential(this.FromEmailAddress, this.FromEmailPassword);    //如果需要认证,则用下面的方式

            MailMessage mm = new MailMessage(); //实例化一个邮件类
            mm.Priority = MailPriority.Normal; //邮件的优先级,分为 Low, Normal, High,通常用 Normal即可
            mm.From = new MailAddress(this.FromEmailAddress, "管理员", Encoding.GetEncoding(936));

            //收件人
            if (!string.IsNullOrEmpty(this.ToList))
                mm.To.Add(this.ToList);
            //抄送人
            if (!string.IsNullOrEmpty(this.CCList))
                mm.CC.Add(this.CCList);
            //密送人
            if (!string.IsNullOrEmpty(this.BccList))
                mm.Bcc.Add(this.BccList);

            mm.Subject = this.Subject;                      //邮件标题
            mm.SubjectEncoding = Encoding.GetEncoding(936); //这里非常重要,如果你的邮件标题包含中文,这里一定要指定,否则对方收到的极有可能是乱码。
            mm.IsBodyHtml = this.IsBodyHtml;                //邮件正文是否是HTML格式
            mm.BodyEncoding = Encoding.GetEncoding(936);    //邮件正文的编码, 设置不正确, 接收者会收到乱码
            mm.Body = this.Body;                            //邮件正文
            //邮件附件
            if (this.AttachmentList != null && this.AttachmentList.Count > 0)
            {
                foreach (Attachment attachment in this.AttachmentList)
                {
                    mm.Attachments.Add(attachment);
                }
            }
            //发送邮件,如果不返回异常, 则大功告成了。
            smtp.Send(mm);
        }
        #endregion
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GitNotifyCommon.Model;
using System.Data;

namespace GitNotifyCommon.DAL
{
    public class ProjectDAL
    {
        public static List<Project> GetList()
        {
            List<Project> list = new List<Project>();
            string sql = "SELECT * from project_data where isEnabled=1";
            DataTable dt = SQLiteHelper.ExecuteDataSet(CommonConfig.SqliteConnString, sql, null).Tables[0];
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(GetModel(dr));
            }
            return list;
        }

        public static Project GetModel(DataRow dr)
        {
            Project item = new Project()
            {
                ProjectId = Convert.ToInt32(dr["projectId"]),
                ProjectName = Convert.ToString(dr["projectName"]),
                LocalPath = Convert.ToString(dr["localPath"]),
                LastUpdateTime = Convert.ToDateTime(dr["lastUpdateTime"]),
                LastLog = Convert.ToString(dr["lastLog"]),
                EmailToList = Convert.ToString(dr["emailToList"]),
                IsEnabled = Convert.ToBoolean(dr["isEnabled"])
            };
            return item;
        }

        public static void Update(Project item) 
        {
            string sql = "update project_data set lastUpdateTime=@lastUpdateTime,lastLog=@lastLog where projectId=@projectId";
            object[] arr = { item.LastUpdateTime, item.LastLog, item.ProjectId };
            SQLiteHelper.ExecuteNonQuery(CommonConfig.SqliteConnString,sql,arr);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GitNotifyCommon.Model
{
    public class Project
    {
        public int ProjectId { get; set; }
        public string ProjectName { get; set; }
        public string LocalPath { get; set; }
        public DateTime LastUpdateTime { get; set; }
        public string LastLog { get; set; }
        public string EmailToList { get; set; }
        public bool IsEnabled { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FileWatcherCommon;

namespace GitNotify
{
    class Program
    {
        static void Main(string[] args)
        {
            WatcherGit.Run();
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- Sqlite连接串 -->
    <add key="SqliteConnString" value="Data Source=gitInfo.sqlite3;Version=3;Cache Size=2000;Pooling=True;Max Pool Size=5;" />
    <!-- 本地 Git-cmd.exe 完整路径 -->
    <add key="LocalGitCmd" value="C:\Program Files\Git\bin\git.exe" />
  </appSettings>
</configuration>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <log4net>
    <!-- 异常输出 -->
    <appender name="FatalLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="Log\" />
      <rollingStyle value="Composite" />
      <datePattern value='yyyy-MM-dd".log"' />
      <staticLogFileName value="false" />
      <maximumFileSize value="30MB" />
      <countDirection value="-1" />
      <maxSizeRollBackups value="-1" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <header value="-----------程序开始运行-----------&#13;&#10;" />
        <footer value="-----------程序结束运行-----------&#13;&#10;&#13;&#10;" />
        <conversionPattern value="%date [%thread] %-5level [%ndc] - %message%newline" />
      </layout>
    </appender>
    <root>
      <level value="INFO" />
      <appender-ref ref="FatalLogFileAppender" />
    </root>
  </log4net>
</configuration>

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值