[转].net仿传奇机器人配置文件

本文详细介绍了如何使用自定义的机器人库实现定时任务的自动执行,包括配置文件的解析、任务的启动与停止,以及如何根据不同条件设置任务的运行频率(秒、分、小时、天、特定日期和星期)。通过实例展示了如何配置机器人在指定的时间点执行特定方法,并提供了源代码示例。

调用方法:

 /*
假设有以下配置内容:

;机器人配置文件
;重要文件
;SEC:按秒运行
;MIN:按分运行
;HOUR:按小时运行
;DAY:按天运行
;RunOnDay:按每天什么时候运行
;RunOnWeek:按星期几及时间运行
;Name RunOnWeek 5:15:55:59 Method Class,DLL
;星期五15点55分59秒运行 method 方法

;aaa每天10点事件
aaa_10_hour_event RunOnDay 10:00:00 静态方法名 类名,程序集名
;bbb服务每天10点事件
aaa_10_hour_event RunOnDay 10:00:00 静态方法名 类名,程序集名
;ccc服务每天10点事件
aaa_10_hour_event RunOnDay 10:00:00 静态方法名 类名,所在程序集名

;定时运行某程序集下某类的某静态方法

*/

public void init() {
    Robot robot = new Robot(@"c:\robot.txt");
    robot.Error += this.robot_OnError;
    robot.Start();
}

public void robot_OnError(object sender, RobotErrorEventArgs e) {
    _log.Fatal(e.Def, e.Exception);
}

 

此功能很早就完成了,现在放出来,其实作用不是太大,感觉好玩,呵呵!
注:此代码应用在几个项目中稳定运行了两年有余。
完整源代码如下: 
 

 

 using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using System.Xml;

/// <summary>
/// 机器人,自动运行库
/// </summary>
public class Robot : IDisposable {

    private string _def_path;
    private List<RobotDef> _robots;
    private object _robots_lock = new object();
    private FileSystemWatcher _defWatcher;
    public event RobotErrorHandler Error;

    public Robot()
        : this(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"robot.txt")) {
    }
    public Robot(string path) {
        _def_path = path;
    }

    public void Start() {
        Stop();
        if (!File.Exists(_def_path)) return;
        lock (_robots_lock) {
            _robots = LoadDef();
            foreach (RobotDef bot in _robots) {
                bot.RunNow();
            }
        }
        if (_defWatcher == null) {
            _defWatcher = new FileSystemWatcher(Path.GetDirectoryName(_def_path), Path.GetFileName(_def_path));
            _defWatcher.Changed += delegate(object sender, FileSystemEventArgs e) {
                _defWatcher.EnableRaisingEvents = false;
                if (_robots.Count > 0) {
                    Start();
                }
                _defWatcher.EnableRaisingEvents = true;
            };
            _defWatcher.EnableRaisingEvents = true;
        }
    }
    public void Stop() {
        lock (_robots_lock) {
            if (_robots != null) {
                for (int a = 0; a < _robots.Count; a++) {
                    _robots[a].Dispose();
                }
                _robots.Clear();
            }
        }
    }

    #region IDisposable 成员

    public void Dispose() {
        if (_defWatcher != null) {
            _defWatcher.Dispose();
        }
        Stop();
    }

    #endregion

    public List<RobotDef> LoadDef() {
        string defDoc = Encoding.Default.GetString(readFile(_def_path));
        return LoadDef(defDoc);
    }
    public List<RobotDef> LoadDef(string defDoc) {
        Dictionary<string, RobotDef> dic = new Dictionary<string, RobotDef>();
        string[] defs = defDoc.Split(new string[] { "\r\n" }, StringSplitOptions.None);
        int row = 1;
        foreach (string def in defs) {
            string loc1 = def.Trim();
            if (string.IsNullOrEmpty(loc1) || loc1[0] == ';') continue;
            string pattern = @"([^\s]+)\s+(NONE|SEC|MIN|HOUR|DAY|RunOnDay|RunOnWeek)\s+([^\s]+)\s+([^\s]+)\s+([^\s,]+),\s*([^\s]+)";
            Match m = Regex.Match(loc1, pattern, RegexOptions.IgnoreCase);
            if (!m.Success) {
                onError(new Exception("Robot配置错误“" + loc1 + "”, 第" + row + "行"));
                continue;
            }
            RobotDef rd = new RobotDef(this);
            rd._name = m.Groups[1].Value;
            rd._mode = getMode(m.Groups[2].Value);
            rd._parm = m.Groups[3].Value;
            rd._method = m.Groups[4].Value;
            rd._assemblyName = m.Groups[5].Value + "," + m.Groups[6].Value;
            if (rd.Mode == RobotRunMode.NONE) continue;
            if (dic.ContainsKey(rd._name)) {
                onError(new Exception("Robot配置存在重复的名字“" + rd._name + "”, 第" + row + "行"));
                continue;
            }
            if (rd.Interval < 0) {
                onError(new Exception("Robot配置参数错误“" + def + "”, 第" + row + "行"));
                continue;
            }
            dic.Add(rd.Name, rd);
            row++;
        }
        List<RobotDef> rds = new List<RobotDef>();
        foreach (RobotDef rd in dic.Values) {
            rds.Add(rd);
        }
        return rds;
    }

    private void onError(Exception ex) {
        onError(ex, null);
    }
    internal void onError(Exception ex, RobotDef def) {
        if (Error != null) {
            RobotErrorEventArgs e = new RobotErrorEventArgs(ex, def);
            Error(this, e);
        }
    }
    private byte[] readFile(string path) {
        if (File.Exists(path)) {
            string destFileName = Path.GetTempFileName();
            File.Copy(path, destFileName, true);
            int read = 0;
            byte[] data = new byte[1024];
            MemoryStream ms = new MemoryStream();
            using (FileStream fs = new FileStream(destFileName, FileMode.OpenOrCreate, FileAccess.Read)) {
                do {
                    read = fs.Read(data, 0, data.Length);
                    if (read <= 0) break;
                    ms.Write(data, 0, read);
                } while (true);
                fs.Close();
            }
            File.Delete(destFileName);
            data = ms.ToArray();
            ms.Close();
            return data;
        }
        return new byte[] { };
    }
    private RobotRunMode getMode(string mode) {
        mode = string.Concat(mode).ToUpper().Trim();
        switch (mode) {
            case "SEC": return RobotRunMode.SEC;
            case "MIN": return RobotRunMode.MIN;
            case "HOUR": return RobotRunMode.HOUR;
            case "DAY": return RobotRunMode.DAY;
            case "RUNONDAY": return RobotRunMode.RunOnDay;
            case "RUNONWEEK": return RobotRunMode.RunOnWeek;
            default: return RobotRunMode.NONE;
        }
    }
}

public class RobotDef : IDisposable {
    internal string _name;
    internal RobotRunMode _mode = RobotRunMode.NONE;
    internal string _parm;
    internal string _method;
    internal string _assemblyName;

    private Robot _onwer;
    private Timer _timer;

    public RobotDef(Robot onwer) {
        _onwer = onwer;
    }

    public void RunNow() {
        if (_timer == null) {
            _timer = new Timer();
            _timer.AutoReset = false;
            _timer.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e) {
                try {
                    Type type = Type.GetType(_assemblyName, true);
                    if (type != null) {
                        type.InvokeMember(_method, BindingFlags.InvokeMethod, null, null, new object[] { this });
                        RunNow();
                    }
                } catch (Exception ex) {
                    _onwer.onError(ex, this);
                }
            };
        }
        if (_timer != null) {
            _timer.Stop();
            _timer.Interval = Interval;
            _timer.Start();
        }
    }

    public override string ToString() {
        return Name + ", " + Mode + ", " + Parm + ", " + Method + ", " + AssemblyName + ", " + Interval;
    }

    #region IDisposable 成员

    public void Dispose() {
        if (_timer != null) {
            _timer.Stop();
            _timer.Close();
            _timer.Dispose();
        }
    }

    #endregion

    public string Name {
        get { return _name; }
    }
    public RobotRunMode Mode {
        get { return _mode; }
    }
    public string Parm {
        get { return _parm; }
    }
    public string Method {
        get { return _method; }
    }
    public string AssemblyName {
        get { return _assemblyName; }
    }
    public double Interval {
        get {
            DateTime now = DateTime.Now;
            double interval = -1;
            switch (_mode) {
                case RobotRunMode.SEC:
                    double.TryParse(_parm, out interval);
                    interval *= 1000;
                    break;
                case RobotRunMode.MIN:
                    double.TryParse(_parm, out interval);
                    interval *= 60 * 1000;
                    break;
                case RobotRunMode.HOUR:
                    double.TryParse(_parm, out interval);
                    interval *= 60 * 60 * 1000;
                    break;
                case RobotRunMode.DAY:
                    double.TryParse(_parm, out interval);
                    interval *= 24 * 60 * 60 * 1000;
                    break;
                case RobotRunMode.RunOnDay:
                    string[] hhmmss = string.Concat(_parm).Split(':');
                    if (hhmmss.Length == 3) {
                        int hh, mm, ss;
                        if (int.TryParse(hhmmss[0], out hh) && hh >= 0 && hh < 24 &&
                            int.TryParse(hhmmss[1], out mm) && mm >= 0 && mm < 60 &&
                            int.TryParse(hhmmss[2], out ss) && ss >= 0 && ss < 60) {
                            DateTime curt = now.Date.AddHours(hh).AddMinutes(mm).AddSeconds(ss);
                            TimeSpan ts = curt - now;
                            if (ts.TotalSeconds > 0) {
                                interval = ts.TotalSeconds * 1000;
                            } else {
                                curt = curt.AddDays(1);
                                ts = curt - now;
                                interval = ts.TotalSeconds * 1000;
                            }
                        }
                    }
                    break;
                case RobotRunMode.RunOnWeek:
                    string[] wwhhmmss = string.Concat(_parm).Split(':');
                    if (wwhhmmss.Length == 4) {
                        int ww, hh, mm, ss;
                        if (int.TryParse(wwhhmmss[0], out ww) && ww >= 0 && ww < 7 &&
                            int.TryParse(wwhhmmss[1], out hh) && hh >= 0 && hh < 24 &&
                            int.TryParse(wwhhmmss[2], out mm) && mm >= 0 && mm < 60 &&
                            int.TryParse(wwhhmmss[3], out ss) && ss >= 0 && ss < 60) {
                            DateTime curt = now.Date.AddHours(hh).AddMinutes(mm).AddSeconds(ss);
                            TimeSpan ts = curt - now;
                            if (ts.TotalSeconds > 0) {
                                interval = ts.TotalSeconds * 1000;
                            } else {
                                do {
                                    curt = curt.AddDays(1);
                                } while ((int)curt.DayOfWeek != ww);
                                ts = curt - now;
                                interval = ts.TotalSeconds * 1000;
                            }
                        }
                    }
                    break;
            }
            if (interval == 0) interval = 1;
            return interval;
        }
    }
}
/*
;SEC:按秒运行
;MIN:按分运行
;HOUR:按小时运行
;DAY:按天运行
;RunOnDay:按每天什么时候运行
;RUNONWEEK:按星期几及时间运行
Name RunOnWeek 5:15:55:59 Run10Hour Asian,Server.Common
;星期五15点55分59秒运行 method 方法
*/
public enum RobotRunMode {
    /// <summary>
    /// 无
    /// </summary>
    NONE = 0,
    /// <summary>
    /// 按秒运行 
    /// </summary>
    SEC = 1,
    /// <summary>
    /// 按分运行
    /// </summary>
    MIN = 2,
    /// <summary>
    /// 按小时运行
    /// </summary>
    HOUR = 3,
    /// <summary>
    /// 按天运行
    /// </summary>
    DAY = 4,
    /// <summary>
    /// 按每天什么时候运行
    /// </summary>
    RunOnDay = 10,
    /// <summary>
    /// 按星期几及时间运行
    /// </summary>
    RunOnWeek = 11
}

public delegate void RobotErrorHandler(object sender, RobotErrorEventArgs e);
public class RobotErrorEventArgs : EventArgs {

    private Exception _exception;
    private RobotDef _def;

    public RobotErrorEventArgs(Exception exception, RobotDef def) {
        _exception = exception;
        _def = def;
    }

    public Exception Exception {
        get { return _exception; }
    }
    public RobotDef Def {
        get { return _def; }
    }
}

转载于:https://www.cnblogs.com/anduinlothar/archive/2012/09/05/2672676.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值