NewLife/XCoder

合并源码到最新版本,net46版本编译通过,测试可用
大石头 authored at 2018-05-20 00:47:36
9ab6077
Tree
1 Parent(s) 4f2c529
Summary: 83 changed files with 7687 additions and 1486 deletions.
Modified +10 -15
Deleted +0 -61
XCoder/app.manifest
Modified +10 -4
Modified +5 -5
Modified +9 -34
Modified +4 -4
Modified +14 -6
Modified +67 -109
Modified +79 -54
Modified +29 -22
Added +20 -0
Added +38 -0
Modified +71 -21
Modified +11 -1
Added +12 -0
Modified +42 -47
Modified +2 -71
Modified +26 -26
Modified +16 -22
Modified +29 -29
Modified +4 -0
Modified +5 -76
Added +73 -0
Modified +10 -5
Modified +2 -2
Modified +1 -2
Modified +1 -53
Modified +3 -3
Modified +4 -5
Added +47 -0
Added +187 -0
Added +120 -0
Added +63 -0
Added +148 -0
Added +120 -0
Added +62 -0
Added +98 -0
Added +120 -0
Added +343 -0
Added +542 -0
Added +120 -0
Modified +3 -1
Modified +11 -11
Modified +82 -111
Modified +0 -10
Modified +8 -11
Modified +45 -48
Modified +13 -43
Modified +2 -2
Modified +9 -11
Modified +18 -18
Added +79 -0
Added +540 -0
Added +534 -0
Added +141 -0
Added +42 -0
Modified +91 -11
Added +388 -0
Modified +45 -25
Modified +0 -14
Modified +32 -31
Modified +132 -81
Modified +114 -112
Added +439 -0
Added +480 -0
Added +141 -0
Added +81 -0
Modified +191 -110
Modified +104 -57
Modified +6 -0
Added +54 -0
Added +309 -0
Modified +44 -27
Added +74 -0
Added +56 -0
Modified +10 -10
Modified +67 -64
Added +248 -0
Added +307 -0
Added +126 -0
Added +48 -0
Deleted +0 -1
XCoder/发布NuGet.cs
Modified +6 -0
Modified +10 -15
diff --git a/XCoder/App.config b/XCoder/App.config
index 7a967fc..cc400ce 100644
--- a/XCoder/App.config
+++ b/XCoder/App.config
@@ -1,23 +1,18 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="utf-8"?>
 <configuration>
-  <configSections/>
   <appSettings>
-    <!--是否启用全局调试。默认为不启用-->
-    <add key="NewLife.Debug" value="true"/>
-    <!--是否启用调试,默认不启用。输出所有执行的SQL语句-->
-    <add key="XCode.Debug" value="true"/>
+    <add key="EnableWindowsFormsHighDpiAutoResizing" value="true"/>
   </appSettings>
   <connectionStrings>
-    <add name="mssql" connectionString="Data Source=.;Initial Catalog=master;Integrated Security=True;" providerName="System.Data.SqlClient"/>
-    <add name="mssql2" connectionString="Data Source=S3;Initial Catalog=master;user=sa;password=Pass@word;" providerName="System.Data.SqlClient"/>
-    <add name="access" connectionString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=XCMS.mdb"/>
-    <add name="Oracle" connectionString="Data Source=orc;User ID=admin;Password=admin" providerName="System.Data.OracleClient"/>
-    <add name="Oracle2" connectionString="Data Source=(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.34)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = ORC)));User ID=admin;Password=admin;;DllPath=C:\OracleClient" providerName="System.Data.OracleClient"/>
+    <add name="mssql" connectionString="Data Source=S3;Initial Catalog=master;user=sa;password=sa;" providerName="System.Data.SqlClient"/>
+    <add name="mssql2" connectionString="Data Source=.;Initial Catalog=master;Integrated Security=True;" providerName="System.Data.SqlClient"/>
+    <add name="Oracle" connectionString="Data Source=Tcp://10.10.20.104/ORCL;User Id=scott;Password=tiger;" providerName="System.Data.OracleClient"/>
+    <add name="Oracle2" connectionString="Data Source=orc;User ID=admin;Password=admin" providerName="System.Data.OracleClient"/>
     <add name="sqlite" connectionString="Data Source=test.db;" providerName="Sqlite"/>
-    <add name="MySql" connectionString="Server=.;Port=3306;Database=mysql;Uid=root;Pwd=;" providerName="MySql.Data.MySqlClient"/>
-    <add name="SqlCe" connectionString="Data Source=test.sdf;" providerName="SqlCe"/>
-    <add name="Firebird" connectionString="Server=.;Database=test.fdb;User=SYSDBA;Password=masterkey;" providerName="FirebirdSql.Data.FirebirdClient"/>
-    <add name="Firebird_Embed" connectionString="Database=test.fdb;User=SYSDBA;Password=masterkey;ServerType=1" providerName="FirebirdSql.Data.FirebirdClient"/>
+    <add name="MySql" connectionString="Server=127.0.0.1;Port=3306;Database=mysql;Uid=root;Pwd=root;" providerName="MySql.Data.MySqlClient"/>
     <add name="PostgreSQL" connectionString="Server=.;Database=master;Uid=root;Pwd=root;" providerName="PostgreSQL.Data.PostgreSQLClient"/>
+    <!--OLE DB Services=-1表示打开连接池-->
+    <add name="Access" connectionString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=~\App_Data\Test.mdb;Persist Security Info=False;OLE DB Services=-1" providerName="Access"/>
+    <add name="SqlCe" connectionString="Data Source=test.sdf;" providerName="SqlCe"/>
   </connectionStrings>
 </configuration>
Deleted +0 -61
XCoder/app.manifest
Modified +10 -4
diff --git a/XCoder/Engine/Engine.cs b/XCoder/Engine/Engine.cs
index 975fa25..3446350 100644
--- a/XCoder/Engine/Engine.cs
+++ b/XCoder/Engine/Engine.cs
@@ -30,7 +30,7 @@ namespace XCoder
             {
                 if (_FileTemplates == null)
                 {
-                    var list = new List<string>();
+                    var list = new List<String>();
 
                     var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TemplatePath);
                     if (Directory.Exists(dir))
@@ -114,7 +114,13 @@ namespace XCoder
 
         public String[] Render(IDataTable table)
         {
-            var data = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
+            // 检查表格完整性
+            foreach (var dc in table.Columns)
+            {
+                if (dc.DataType == null) throw new ArgumentException("{0}.DataType数据类型错误".F(dc.Name), dc.Name);
+            }
+
+            var data = new Dictionary<String, Object>(StringComparer.OrdinalIgnoreCase);
             //data["Config"] = Config;
             data["Tables"] = Tables;
             data["Table"] = table;
@@ -155,7 +161,7 @@ namespace XCoder
             // 声明模版引擎
             //Template tt = new Template();
             Template.Debug = Config.Debug;
-            var templates = new Dictionary<string, string>();
+            var templates = new Dictionary<String, String>();
             // 每一个模版的编码,用于作为输出文件的编码
             var encs = new List<Encoding>();
 
@@ -221,7 +227,7 @@ namespace XCoder
             if (tempName.StartsWith("*")) tempName = tempName.Substring(1);
             tt.AssemblyName = tempName;
             #endregion
-            
+
             #region 输出目录预处理
             var outpath = Config.OutputPath;
             // 使用正则替换处理 命名空间处已经定义
Modified +5 -5
diff --git a/XCoder/Engine/FileSource.cs b/XCoder/Engine/FileSource.cs
index 1daf425..96d78b4 100644
--- a/XCoder/Engine/FileSource.cs
+++ b/XCoder/Engine/FileSource.cs
@@ -30,14 +30,14 @@ namespace XCoder
 
         public static void ReleaseAllTemplateFiles()
         {
-            String path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Engine.TemplatePath);
-            Dictionary<String, String> dic = GetTemplates();
+            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Engine.TemplatePath);
+            var dic = GetTemplates();
 
-            foreach (String item in dic.Keys)
+            foreach (var item in dic.Keys)
             {
                 // 第一层是目录,然后是文件
-                String dir = item.Substring(0, item.IndexOf("."));
-                String file = item.Substring(dir.Length + 1);
+                var dir = item.Substring(0, item.IndexOf("."));
+                var file = item.Substring(dir.Length + 1);
 
                 dir = Path.Combine(path, dir);
                 file = Path.Combine(dir, file);
Modified +9 -34
diff --git a/XCoder/Engine/ModelConfig.cs b/XCoder/Engine/ModelConfig.cs
index 4ac884e..c490f1e 100644
--- a/XCoder/Engine/ModelConfig.cs
+++ b/XCoder/Engine/ModelConfig.cs
@@ -11,18 +11,9 @@ namespace XCoder
     public class ModelConfig : XmlConfig<ModelConfig>
     {
         #region 属性
-        private String _ConnName;
         /// <summary>链接名</summary>
         [DisplayName("链接名")]
-        public String ConnName
-        {
-            get
-            {
-                if (String.IsNullOrEmpty(_ConnName)) _ConnName = "ConnName";
-                return _ConnName;
-            }
-            set { _ConnName = value; }
-        }
+        public String ConnName { get; set; } = "ConnName";
 
         //private String _Prefix;
         ///// <summary>前缀</summary>
@@ -38,10 +29,9 @@ namespace XCoder
             set { _NameSpace = value; }
         }
 
-        private String _TemplateName;
         /// <summary>模板名</summary>
         [DisplayName("模板名")]
-        public String TemplateName { get { return _TemplateName; } set { _TemplateName = value; } }
+        public String TemplateName { get; set; }
 
         private String _OutputPath;
         /// <summary>输出目录</summary>
@@ -52,10 +42,9 @@ namespace XCoder
             set { _OutputPath = value; }
         }
 
-        private Boolean _Override = true;
         /// <summary>是否覆盖目标文件</summary>
         [DisplayName("是否覆盖目标文件")]
-        public Boolean Override { get { return _Override; } set { _Override = value; } }
+        public Boolean Override { get; set; } = true;
 
         private String _EntityConnName;
         /// <summary>实体链接名</summary>
@@ -79,10 +68,9 @@ namespace XCoder
             set { _BaseClass = value; }
         }
 
-        private Boolean _RenderGenEntity;
         /// <summary>生成泛型实体类</summary>
         [DisplayName("生成泛型实体类")]
-        public Boolean RenderGenEntity { get { return _RenderGenEntity; } set { _RenderGenEntity = value; } }
+        public Boolean RenderGenEntity { get; set; }
 
         //private Boolean _NeedFix = true;
         ///// <summary>是否需要修正。默认true,将根据配置删除前缀、自动化大小写和完善注释等</summary>
@@ -112,43 +100,30 @@ namespace XCoder
         //    set { _AutoFixWord = value; }
         //}
 
-        private Boolean _UseCNFileName;
         /// <summary>使用中文文件名</summary>
         [DisplayName("使用中文文件名")]
-        public Boolean UseCNFileName { get { return _UseCNFileName; } set { _UseCNFileName = value; } }
+        public Boolean UseCNFileName { get; set; }
 
         //private Boolean _UseID;
         ///// <summary>强制使用ID</summary>
         //[DisplayName("强制使用ID")]
         //public Boolean UseID { get { return _UseID; } set { _UseID = value; } }
 
-        private Boolean _UseHeadTemplate;
         /// <summary>使用头部模版</summary>
         [DisplayName("使用头部模版")]
-        public Boolean UseHeadTemplate
-        {
-            get { return _UseHeadTemplate; }
-            set { _UseHeadTemplate = value; }
-        }
+        public Boolean UseHeadTemplate { get; set; }
 
-        private String _HeadTemplate;
         /// <summary>头部模版</summary>
         [DisplayName("头部模版")]
-        public String HeadTemplate
-        {
-            get { return _HeadTemplate; }
-            set { _HeadTemplate = value; }
-        }
+        public String HeadTemplate { get; set; }
 
-        private Boolean _Debug;
         /// <summary>调试</summary>
         [DisplayName("调试")]
-        public Boolean Debug { get { return _Debug; } set { _Debug = value; } }
+        public Boolean Debug { get; set; }
 
-        private SerializableDictionary<String, String> _Items;
         /// <summary> 字典属性</summary>
         [DisplayName("数据字典")]
-        public SerializableDictionary<String, String> Items { get { return _Items ?? (_Items = new SerializableDictionary<string, string>()); } set { _Items = value; } }
+        public SerializableDictionary<String, String> Items { get; set; } = new SerializableDictionary<String, String>();
         #endregion
 
         #region 加载/保存
Modified +4 -4
diff --git a/XCoder/Engine/UIConfig.cs b/XCoder/Engine/UIConfig.cs
index e3fddd4..0788290 100644
--- a/XCoder/Engine/UIConfig.cs
+++ b/XCoder/Engine/UIConfig.cs
@@ -133,7 +133,7 @@ namespace XCoder
             return ui;
         }
 
-        static ToolStripItem Find(ToolStripItemCollection items, String key, bool searchAllChildren)
+        static ToolStripItem Find(ToolStripItemCollection items, String key, Boolean searchAllChildren)
         {
             var tis = items.Find(key, searchAllChildren);
             if (tis != null && tis.Length > 0) return tis[0];
@@ -158,7 +158,7 @@ namespace XCoder
             return null;
         }
 
-        static void mi字体_Click(object sender, EventArgs e)
+        static void mi字体_Click(Object sender, EventArgs e)
         {
             var ti = sender as ToolStripItem;
             var txt = (ti.Owner as ContextMenuStrip).SourceControl as TextBoxBase;
@@ -174,7 +174,7 @@ namespace XCoder
             ui.Save();
         }
 
-        static void mi前景色_Click(object sender, EventArgs e)
+        static void mi前景色_Click(Object sender, EventArgs e)
         {
             var ti = sender as ToolStripItem;
             var txt = (ti.Owner as ContextMenuStrip).SourceControl as TextBoxBase;
@@ -190,7 +190,7 @@ namespace XCoder
             ui.Save();
         }
 
-        static void mi背景色_Click(object sender, EventArgs e)
+        static void mi背景色_Click(Object sender, EventArgs e)
         {
             // ((System.Windows.Forms.ContextMenuStrip)(((System.Windows.Forms.ToolStripItem)(sender)).Owner)).SourceControl
             var ti = sender as ToolStripItem;
Modified +14 -6
diff --git a/XCoder/Engine/XConfig.cs b/XCoder/Engine/XConfig.cs
index 97335a6..48be88a 100644
--- a/XCoder/Engine/XConfig.cs
+++ b/XCoder/Engine/XConfig.cs
@@ -11,7 +11,7 @@ namespace XCoder
         #region 属性
         /// <summary>标题</summary>
         [Description("标题")]
-        public String Title { get; set; }
+        public String Title { get; set; } = "";
 
         /// <summary>宽度</summary>
         [Description("宽度")]
@@ -31,11 +31,19 @@ namespace XCoder
 
         /// <summary>扩展数据</summary>
         [Description("扩展数据")]
-        public String Extend { get; set; }
+        public String Extend { get; set; } = "";
+
+        /// <summary>日志着色</summary>
+        [Description("日志着色")]
+        public Boolean ColorLog { get; set; } = true;
+
+        /// <summary>语音提示。默认true</summary>
+        [Description("语音提示。默认true")]
+        public Boolean SpeechTip { get; set; } = true;
 
         /// <summary>更新服务器</summary>
         [Description("更新服务器")]
-        public String UpdateServer { get; set; }
+        public String UpdateServer { get; set; } = "";
 
         /// <summary>最后更新时间</summary>
         [DisplayName("最后更新时间")]
@@ -43,7 +51,7 @@ namespace XCoder
 
         /// <summary>最后一个使用的工具</summary>
         [DisplayName("最后一个使用的工具")]
-        public String LastTool { get; set; }
+        public String LastTool { get; set; } = "";
         #endregion
 
         #region 加载/保存
@@ -53,8 +61,8 @@ namespace XCoder
 
         protected override void OnLoaded()
         {
-            if (UpdateServer.IsNullOrEmpty()) UpdateServer = "http://www.newlifex.com/showtopic-260.aspx";
-            
+            if (UpdateServer.IsNullOrEmpty() || UpdateServer.EqualIgnoreCase("http://x.newlifex.com/")) UpdateServer = NewLife.Setting.Current.PluginServer;
+
             base.OnLoaded();
         }
         #endregion
Modified +67 -109
diff --git a/XCoder/FileEncoding/FrmMain.cs b/XCoder/FileEncoding/FrmMain.cs
index 38c9d9b..e9471be 100644
--- a/XCoder/FileEncoding/FrmMain.cs
+++ b/XCoder/FileEncoding/FrmMain.cs
@@ -8,42 +8,39 @@ using NewLife.IO;
 namespace XCoder.FileEncoding
 {
     [DisplayName("文件编码工具")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
-        string[] EncodeType = new string[] { "UTF-8", "ASNI", "Unicode", "Default" };
-        private string ChiocePath { get; set; }
-
-        private Int32 Count { get; set; }
         public FrmMain()
         {
             InitializeComponent();
+
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
         }
 
-        private void FrmEncodeReplace_Load(object sender, EventArgs e)
+        private void FrmEncodeReplace_Load(Object sender, EventArgs e)
         {
-            txt_file_suffix_name.Text = ".cs,.aspx";
-            cmb_file_encode_name.DataSource = EncodeType;
-            cmb_file_encode_name.Text = "UTF-8";
+            txtSuffix.Text = "*.cs;*.aspx";
+            var encs = new String[] { "UTF-8", "UTF-8 NoBOM", "ASNI", "Unicode", "Default" };
+            //var encs = new Encoding[] { Encoding.UTF8, new UTF8Encoding(false), Encoding.ASCII, Encoding.UTF8 };
+            ddlEncodes.DataSource = encs;
+            ddlEncodes.Text = "UTF-8";
             //cmb_tag.Text = "UTF-8";
-            btn_replace.Enabled = false;
+            btnReplace.Enabled = false;
         }
 
 
-        private void btn_choice_file_Click(object sender, EventArgs e)
+        private void btn_choice_file_Click(Object sender, EventArgs e)
         {
+            if (!txtPath.Text.IsNullOrEmpty()) fbd_choice_folder.SelectedPath = txtPath.Text;
             if (fbd_choice_folder.ShowDialog() != DialogResult.OK) return;
 
-            gv_data.Rows.Clear();
-            txt_file_path.Text = fbd_choice_folder.SelectedPath;
-            ChiocePath = txt_file_path.Text;
-            Count = 1;
-            FileFilter(new DirectoryInfo(ChiocePath));
-            btn_replace.Enabled = true;
+            txtPath.Text = fbd_choice_folder.SelectedPath;
         }
 
-        private void btn_replace_Click(object sender, EventArgs e)
+        private void btn_replace_Click(Object sender, EventArgs e)
         {
-            if (string.IsNullOrEmpty(txt_file_path.Text))
+            if (String.IsNullOrEmpty(txtPath.Text))
             {
                 MessageBox.Show("请选择文件夹");
                 return;
@@ -59,25 +56,38 @@ namespace XCoder.FileEncoding
                 return;
 
 
-            var targetCharset = cmb_file_encode_name.Text.Trim();
-            var targetEncoding = GetEncode();
+            var enc = Encoding.UTF8;
+            switch (ddlEncodes.Text)
+            {
+                case "UTF-8": enc = Encoding.UTF8; break;
+                case "UTF-8 NoBOM": enc = new UTF8Encoding(false); break;
+                case "ASNI": enc = Encoding.ASCII; break;
+                case "Unicode": enc = Encoding.Unicode; break;
+            }
+
+            var count = 0;
             foreach (DataGridViewRow item in gv_data.Rows)
             {
-                if (item.Cells["序号"].Value == null) { continue; }
+                if (item.Cells["序号"].Value == null) continue;
                 var fileCharset = item.Cells["编码"].Value.ToString();
-                if (string.Equals(fileCharset, targetCharset, StringComparison.OrdinalIgnoreCase)) { continue; }
+                if (fileCharset.EqualIgnoreCase(ddlEncodes.Text)) continue;
 
                 try
                 {
-                    ReplaceEncoding(txt_file_path.Text + item.Cells["名称"].Value.ToString(), fileCharset, targetEncoding);
+                    //ReplaceEncoding(txtPath.Text + item.Cells["名称"].Value.ToString(), fileCharset, enc);
+                    var file = txtPath.Text + item.Cells["名称"].Value;
+                    var txt = File.ReadAllText(file);
+                    File.WriteAllText(file, txt, enc);
+
+                    count++;
                 }
                 catch (Exception ex)
                 {
-                    MessageBox.Show("文件[" + txt_file_path.Text + item.Cells["名称"].Value.ToString() + "]" + "转换时出错,请手动转换" + ex.Message);
+                    MessageBox.Show("文件[" + txtPath.Text + item.Cells["名称"].Value.ToString() + "]" + "转换时出错,请手动转换" + ex.Message);
                 }
             }
 
-            MessageBox.Show("转换完成");
+            MessageBox.Show("转换{0}个文件完成".F(count));
             gv_data.Rows.Clear();
         }
 
@@ -85,15 +95,15 @@ namespace XCoder.FileEncoding
         /// 替换文件编码
         /// </summary>
         /// <param name="file"></param>
-        private void ReplaceEncoding(string file, string charset, Encoding targetEncoding)
+        private void ReplaceEncoding(String file, String charset, Encoding targetEncoding)
         {
-            string fileInfo = "";
-            using (StreamReader sr = new StreamReader(file, Encoding.GetEncoding(charset), false))
+            var fileInfo = "";
+            using (var sr = new StreamReader(file, Encoding.GetEncoding(charset), false))
             {
                 fileInfo = sr.ReadToEnd();
             }
 
-            using (StreamWriter sw = new StreamWriter(file, false, targetEncoding))
+            using (var sw = new StreamWriter(file, false, targetEncoding))
             {
                 sw.Write(fileInfo);
             }
@@ -102,9 +112,9 @@ namespace XCoder.FileEncoding
         Encoding GetEncode()
         {
             // "UTF-8", "ASNI", "Unicode", "Default" 
-            var e = cmb_file_encode_name.Text;
+            var e = ddlEncodes.Text;
 
-            var result = Encoding.Default;
+            var result = Encoding.UTF8;
             switch (e)
             {
                 case "UTF-8": result = Encoding.UTF8; break;
@@ -114,68 +124,32 @@ namespace XCoder.FileEncoding
             return result;
         }
 
-
         /// <summary>
         /// 文件过滤
         /// </summary>
         /// <param name="info"></param>
-        public void FileFilter(FileSystemInfo info)
+        public void FileFilter(String path)
         {
-            //var info = new DirectoryInfo(ChiocePath);
-            if (!info.Exists) return;
-
-            var dir = info as DirectoryInfo;
-            //不是目录
-            if (dir == null) return;
+            var di = path.AsDirectory();
+            if (!di.Exists) return;
 
-            var files = dir.GetFileSystemInfos();
-
-            for (int i = 0; i < files.Length; i++)
+            var Count = 1;
+            foreach (var file in di.GetAllFiles(txtSuffix.Text, true))
             {
-                FileInfo file = files[i] as FileInfo;
-                //是文件
-                if (file != null)
-                {
-                    if (!file.Name.Contains(".")) continue;
-                    var b = IsContainsType(file.Name);
-                    if (b)
-                    {
-                        string fileEncoding = EncodePelaceHelper.GetEncoding(file.FullName);
-                        if (fileEncoding.ToUpper().IndexOf("UTF".ToUpper()) < 0)
-                        {
-                            gv_data.Rows.Add(Count, fileEncoding, file.FullName.ToString().Substring(ChiocePath.Length));
-                            Count++;
-                        }
-                    }
-                }
-                //对于子目录,进行递归调用
-                else
+                var enc = EncodePelaceHelper.GetEncoding(file.FullName);
+                if (enc != null && !enc.WebName.EqualIgnoreCase(ddlEncodes.Text))
                 {
-                    FileFilter(files[i]);
+                    gv_data.Rows.Add(Count++, enc.WebName, file.FullName.Substring(path.Length));
                 }
             }
         }
 
-        /// <summary>
-        /// 判断是否包含对应类型文件
-        /// </summary>
-        bool IsContainsType(string filename)
+        private void btnFind_Click(Object sender, EventArgs e)
         {
-            var t = txt_file_suffix_name.Text;
-            if (string.IsNullOrEmpty(t)) return true;
-
-            var s = t.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
-            string fileLastName = filename.Substring(filename.LastIndexOf(".")).ToUpper();
-
-            foreach (var item in s)
-            {
-                if (fileLastName.IndexOf(item.ToUpper()) >= 0) return true;
-            }
-
-            return false;
+            gv_data.Rows.Clear();
+            FileFilter(txtPath.Text);
+            btnReplace.Enabled = true;
         }
-
-
     }
 
     /// <summary>
@@ -184,13 +158,13 @@ namespace XCoder.FileEncoding
     public class EncodePelaceHelper
     {
         /// <summary>
-        /// 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符,Encoding.Default将被返回。
+        /// 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符,Encoding.UTF8将被返回。
         /// </summary>
         /// <param name="fileName">文件名</param>
         /// 
-        public static string GetEncoding(string fileName)
+        public static Encoding GetEncoding(String fileName)
         {
-            return GetEncoding(fileName, Encoding.Default);
+            return GetEncoding(fileName, Encoding.UTF8);
         }
 
         /// <summary>取得一个文本文件的编码方式。</summary>
@@ -198,28 +172,12 @@ namespace XCoder.FileEncoding
         /// <param name="defaultEncoding">默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。</param>
         /// <returns></returns>
         /// 
-        public static string GetEncoding(string fileName, Encoding defaultEncoding)
+        public static Encoding GetEncoding(String fileName, Encoding defaultEncoding)
         {
             using (var fs = File.OpenRead(fileName))
             {
-                //var cdet = new Ude.CharsetDetector();
-                //cdet.Feed(fs);
-                //cdet.DataEnd();
-                //if (cdet.Charset != null)
-                //{
-                //    return cdet.Charset;
-                //}
-                //else
-                //{
-                //    return defaultEncoding.WebName;
-                //}
-                var enc = fs.Detect() ?? defaultEncoding;
-                return enc != null ? enc.WebName : null;
+                return fs.Detect() ?? defaultEncoding;
             }
-            //FileStream fs = new FileStream(fileName, FileMode.Open);
-            //Encoding targetEncoding = GetEncoding(fs, defaultEncoding);
-            //fs.Close();
-            //return targetEncoding;
         }
 
         ///// <summary>
@@ -230,7 +188,7 @@ namespace XCoder.FileEncoding
         ///// 
         //public static Encoding GetEncoding(FileStream stream)
         //{
-        //    return GetEncoding(stream, Encoding.Default);
+        //    return GetEncoding(stream, Encoding.UTF8);
         //}
 
         ///// <summary>
@@ -259,19 +217,19 @@ namespace XCoder.FileEncoding
         /// 
         public static Encoding GetEncoding(FileStream stream, Encoding defaultEncoding)
         {
-            Encoding targetEncoding = defaultEncoding;
+            var targetEncoding = defaultEncoding;
             if (stream != null && stream.Length >= 2)
             {
                 //保存文件流的前4个字节
-                byte byte1 = 0;
-                byte byte2 = 0;
-                byte byte3 = 0;
-                byte byte4 = 0;
+                Byte byte1 = 0;
+                Byte byte2 = 0;
+                Byte byte3 = 0;
+                Byte byte4 = 0;
 
                 //保存当前Seek位置
-                long origPos = stream.Seek(0, SeekOrigin.Begin);
+                var origPos = stream.Seek(0, SeekOrigin.Begin);
                 stream.Seek(0, SeekOrigin.Begin);
-                int nByte = stream.ReadByte();
+                var nByte = stream.ReadByte();
                 byte1 = Convert.ToByte(nByte);
                 byte2 = Convert.ToByte(stream.ReadByte());
 
Modified +79 -54
diff --git a/XCoder/FileEncoding/FrmMain.Designer.cs b/XCoder/FileEncoding/FrmMain.Designer.cs
index 51686aa..95f446c 100644
--- a/XCoder/FileEncoding/FrmMain.Designer.cs
+++ b/XCoder/FileEncoding/FrmMain.Designer.cs
@@ -29,17 +29,19 @@
         private void InitializeComponent()
         {
             this.lbl_file_suffix_name = new System.Windows.Forms.Label();
-            this.txt_file_suffix_name = new System.Windows.Forms.TextBox();
+            this.txtSuffix = new System.Windows.Forms.TextBox();
             this.lbl_file_encode_name = new System.Windows.Forms.Label();
-            this.cmb_file_encode_name = new System.Windows.Forms.ComboBox();
-            this.btn_choice_file = new System.Windows.Forms.Button();
-            this.txt_file_path = new System.Windows.Forms.TextBox();
-            this.btn_replace = new System.Windows.Forms.Button();
+            this.ddlEncodes = new System.Windows.Forms.ComboBox();
+            this.btnChoice = new System.Windows.Forms.Button();
+            this.txtPath = new System.Windows.Forms.TextBox();
+            this.btnReplace = new System.Windows.Forms.Button();
             this.gv_data = new System.Windows.Forms.DataGridView();
             this.序号 = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.编码 = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.名称 = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.fbd_choice_folder = new System.Windows.Forms.FolderBrowserDialog();
+            this.label1 = new System.Windows.Forms.Label();
+            this.btnFind = new System.Windows.Forms.Button();
             ((System.ComponentModel.ISupportInitialize)(this.gv_data)).BeginInit();
             this.SuspendLayout();
             // 
@@ -48,60 +50,60 @@
             this.lbl_file_suffix_name.AutoSize = true;
             this.lbl_file_suffix_name.Location = new System.Drawing.Point(12, 20);
             this.lbl_file_suffix_name.Name = "lbl_file_suffix_name";
-            this.lbl_file_suffix_name.Size = new System.Drawing.Size(65, 12);
+            this.lbl_file_suffix_name.Size = new System.Drawing.Size(29, 12);
             this.lbl_file_suffix_name.TabIndex = 0;
-            this.lbl_file_suffix_name.Text = "文件后缀名";
+            this.lbl_file_suffix_name.Text = "后缀";
             // 
-            // txt_file_suffix_name
+            // txtSuffix
             // 
-            this.txt_file_suffix_name.Location = new System.Drawing.Point(83, 16);
-            this.txt_file_suffix_name.Name = "txt_file_suffix_name";
-            this.txt_file_suffix_name.Size = new System.Drawing.Size(85, 21);
-            this.txt_file_suffix_name.TabIndex = 1;
+            this.txtSuffix.Location = new System.Drawing.Point(47, 16);
+            this.txtSuffix.Name = "txtSuffix";
+            this.txtSuffix.Size = new System.Drawing.Size(85, 21);
+            this.txtSuffix.TabIndex = 1;
             // 
             // lbl_file_encode_name
             // 
             this.lbl_file_encode_name.AutoSize = true;
-            this.lbl_file_encode_name.Location = new System.Drawing.Point(187, 20);
+            this.lbl_file_encode_name.Location = new System.Drawing.Point(480, 20);
             this.lbl_file_encode_name.Name = "lbl_file_encode_name";
-            this.lbl_file_encode_name.Size = new System.Drawing.Size(65, 12);
+            this.lbl_file_encode_name.Size = new System.Drawing.Size(53, 12);
             this.lbl_file_encode_name.TabIndex = 2;
-            this.lbl_file_encode_name.Text = "文件编码名";
+            this.lbl_file_encode_name.Text = "目标编码";
             // 
-            // cmb_file_encode_name
+            // ddlEncodes
             // 
-            this.cmb_file_encode_name.FormattingEnabled = true;
-            this.cmb_file_encode_name.Location = new System.Drawing.Point(258, 16);
-            this.cmb_file_encode_name.Name = "cmb_file_encode_name";
-            this.cmb_file_encode_name.Size = new System.Drawing.Size(84, 20);
-            this.cmb_file_encode_name.TabIndex = 3;
+            this.ddlEncodes.FormattingEnabled = true;
+            this.ddlEncodes.Location = new System.Drawing.Point(539, 16);
+            this.ddlEncodes.Name = "ddlEncodes";
+            this.ddlEncodes.Size = new System.Drawing.Size(154, 20);
+            this.ddlEncodes.TabIndex = 3;
             // 
-            // btn_choice_file
+            // btnChoice
             // 
-            this.btn_choice_file.Location = new System.Drawing.Point(533, 15);
-            this.btn_choice_file.Name = "btn_choice_file";
-            this.btn_choice_file.Size = new System.Drawing.Size(31, 23);
-            this.btn_choice_file.TabIndex = 4;
-            this.btn_choice_file.Text = "...";
-            this.btn_choice_file.UseVisualStyleBackColor = true;
-            this.btn_choice_file.Click += new System.EventHandler(this.btn_choice_file_Click);
+            this.btnChoice.Location = new System.Drawing.Point(361, 15);
+            this.btnChoice.Name = "btnChoice";
+            this.btnChoice.Size = new System.Drawing.Size(31, 23);
+            this.btnChoice.TabIndex = 4;
+            this.btnChoice.Text = "...";
+            this.btnChoice.UseVisualStyleBackColor = true;
+            this.btnChoice.Click += new System.EventHandler(this.btn_choice_file_Click);
             // 
-            // txt_file_path
+            // txtPath
             // 
-            this.txt_file_path.Location = new System.Drawing.Point(370, 16);
-            this.txt_file_path.Name = "txt_file_path";
-            this.txt_file_path.Size = new System.Drawing.Size(157, 21);
-            this.txt_file_path.TabIndex = 5;
+            this.txtPath.Location = new System.Drawing.Point(198, 16);
+            this.txtPath.Name = "txtPath";
+            this.txtPath.Size = new System.Drawing.Size(157, 21);
+            this.txtPath.TabIndex = 5;
             // 
-            // btn_replace
+            // btnReplace
             // 
-            this.btn_replace.Location = new System.Drawing.Point(581, 15);
-            this.btn_replace.Name = "btn_replace";
-            this.btn_replace.Size = new System.Drawing.Size(97, 23);
-            this.btn_replace.TabIndex = 6;
-            this.btn_replace.Text = "批量替换编码";
-            this.btn_replace.UseVisualStyleBackColor = true;
-            this.btn_replace.Click += new System.EventHandler(this.btn_replace_Click);
+            this.btnReplace.Location = new System.Drawing.Point(699, 15);
+            this.btnReplace.Name = "btnReplace";
+            this.btnReplace.Size = new System.Drawing.Size(66, 23);
+            this.btnReplace.TabIndex = 6;
+            this.btnReplace.Text = "批量转换";
+            this.btnReplace.UseVisualStyleBackColor = true;
+            this.btnReplace.Click += new System.EventHandler(this.btn_replace_Click);
             // 
             // gv_data
             // 
@@ -135,20 +137,41 @@
             this.名称.HeaderText = "名称";
             this.名称.Name = "名称";
             // 
-            // FrmEncodeReplace
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(152, 20);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(29, 12);
+            this.label1.TabIndex = 8;
+            this.label1.Text = "路径";
+            // 
+            // btnFind
+            // 
+            this.btnFind.Location = new System.Drawing.Point(398, 15);
+            this.btnFind.Name = "btnFind";
+            this.btnFind.Size = new System.Drawing.Size(61, 23);
+            this.btnFind.TabIndex = 9;
+            this.btnFind.Text = "查找";
+            this.btnFind.UseVisualStyleBackColor = true;
+            this.btnFind.Click += new System.EventHandler(this.btnFind_Click);
+            // 
+            // FrmMain
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(789, 681);
+            this.Controls.Add(this.btnFind);
+            this.Controls.Add(this.label1);
             this.Controls.Add(this.gv_data);
-            this.Controls.Add(this.btn_replace);
-            this.Controls.Add(this.txt_file_path);
-            this.Controls.Add(this.btn_choice_file);
-            this.Controls.Add(this.cmb_file_encode_name);
+            this.Controls.Add(this.btnReplace);
+            this.Controls.Add(this.txtPath);
+            this.Controls.Add(this.btnChoice);
+            this.Controls.Add(this.ddlEncodes);
             this.Controls.Add(this.lbl_file_encode_name);
-            this.Controls.Add(this.txt_file_suffix_name);
+            this.Controls.Add(this.txtSuffix);
             this.Controls.Add(this.lbl_file_suffix_name);
-            this.Name = "FrmEncodeReplace";
+            this.Name = "FrmMain";
             this.Text = "文件编码名";
             this.Load += new System.EventHandler(this.FrmEncodeReplace_Load);
             ((System.ComponentModel.ISupportInitialize)(this.gv_data)).EndInit();
@@ -160,16 +183,18 @@
         #endregion
 
         private System.Windows.Forms.Label lbl_file_suffix_name;
-        private System.Windows.Forms.TextBox txt_file_suffix_name;
+        private System.Windows.Forms.TextBox txtSuffix;
         private System.Windows.Forms.Label lbl_file_encode_name;
-        private System.Windows.Forms.ComboBox cmb_file_encode_name;
-        private System.Windows.Forms.Button btn_choice_file;
-        private System.Windows.Forms.TextBox txt_file_path;
-        private System.Windows.Forms.Button btn_replace;
+        private System.Windows.Forms.ComboBox ddlEncodes;
+        private System.Windows.Forms.Button btnChoice;
+        private System.Windows.Forms.TextBox txtPath;
+        private System.Windows.Forms.Button btnReplace;
         private System.Windows.Forms.DataGridView gv_data;
         private System.Windows.Forms.DataGridViewTextBoxColumn 序号;
         private System.Windows.Forms.DataGridViewTextBoxColumn 编码;
         private System.Windows.Forms.DataGridViewTextBoxColumn 名称;
         private System.Windows.Forms.FolderBrowserDialog fbd_choice_folder;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Button btnFind;
     }
 }
\ No newline at end of file
Modified +29 -22
diff --git a/XCoder/FolderInfo/FrmMain.cs b/XCoder/FolderInfo/FrmMain.cs
index 8306c7e..335e0e3 100644
--- a/XCoder/FolderInfo/FrmMain.cs
+++ b/XCoder/FolderInfo/FrmMain.cs
@@ -8,23 +8,30 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using NewLife.Log;
-using NewLife.Threading;
 
 namespace XCoder.FolderInfo
 {
     [DisplayName("文件夹大小统计")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
+        /// <summary>业务日志输出</summary>
+        ILog BizLog;
+
         #region 初始化
         public FrmMain()
         {
             InitializeComponent();
 
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
             Icon = IcoHelper.GetIcon("文件");
         }
 
-        private void Form1_Load(object sender, EventArgs e)
+        private void Form1_Load(Object sender, EventArgs e)
         {
+            var log = TextFileLog.Create(null, "Folder_{0:yyyy_MM_dd}.log");
+            BizLog = txtLog.Combine(log);
             txtLog.UseWinFormControl();
 
             foreach (var item in DriveInfo.GetDrives())
@@ -43,7 +50,7 @@ namespace XCoder.FolderInfo
         #region 构造目录树
         void MakeTree(String path, TreeNode Node)
         {
-            XTrace.WriteLine("展开目录 {0}", path);
+            BizLog.Info("展开目录 {0}", path);
 
             Node.Nodes.Clear();
 
@@ -61,7 +68,7 @@ namespace XCoder.FolderInfo
             list.AddRange(dis);
             list.AddRange(fis);
 
-            int max = 0;
+            var max = 0;
             foreach (var item in list)
             {
                 max = Math.Max(max, StrLen(item.Name));
@@ -69,9 +76,9 @@ namespace XCoder.FolderInfo
             max++;
             foreach (var item in list)
             {
-                Int32 len = max;
+                var len = max;
                 len -= (StrLen(item.Name) - item.Name.Length);
-                long size = 0;
+                Int64 size = 0;
 
                 if (item is FileInfo)
                     size = (item as FileInfo).Length;
@@ -92,10 +99,10 @@ namespace XCoder.FolderInfo
             }
         }
 
-        String FormatSize(long size)
+        String FormatSize(Int64 size)
         {
             if (size < 1024) return size.ToString() + " Byte";
-            Double ds = (double)size / 1024;
+            var ds = (Double)size / 1024;
             if (ds < 1024) return ds.ToString("N2") + " K";
             ds = ds / 1024;
             if (ds < 1024) return ds.ToString("N2") + " M";
@@ -108,7 +115,7 @@ namespace XCoder.FolderInfo
 
         Int32 StrLen(String str)
         {
-            return Encoding.Default.GetBytes(str).Length;
+            return Encoding.UTF8.GetBytes(str).Length;
         }
         #endregion
 
@@ -123,10 +130,10 @@ namespace XCoder.FolderInfo
         //    return FolderSize(si as DirectoryInfo);
         //}
 
-        Dictionary<String, long> cache = new Dictionary<String, long>();
-        long FolderSize(DirectoryInfo di)
+        Dictionary<String, Int64> cache = new Dictionary<String, Int64>();
+        Int64 FolderSize(DirectoryInfo di)
         {
-            long size = 0;
+            Int64 size = 0;
             if (cache.ContainsKey(di.FullName)) return cache[di.FullName];
             lock (di.FullName)
             {
@@ -154,7 +161,7 @@ namespace XCoder.FolderInfo
         {
             var node = obj as TreeNode;
             if (node == null || node.Tag == null) return;
-            long size = FolderSize(node.Tag as DirectoryInfo);
+            var size = FolderSize(node.Tag as DirectoryInfo);
             var str = node.Text.Substring(0, node.Text.Length - 10) + String.Format("{0,10}", FormatSize(size));
             //SetNodeText(node, str, GetColor(size));
             this.Invoke(() =>
@@ -164,7 +171,7 @@ namespace XCoder.FolderInfo
             });
         }
 
-        Color GetColor(long size)
+        Color GetColor(Int64 size)
         {
             var color = Color.White;
             if (size > 1024) color = Color.MistyRose;
@@ -191,7 +198,7 @@ namespace XCoder.FolderInfo
         #endregion
 
         #region 展开折叠目录树
-        private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
+        private void treeView1_BeforeExpand(Object sender, TreeViewCancelEventArgs e)
         {
             var node = e.Node;
             if (node.Nodes != null && node.Nodes.Count > 0 && node.Nodes[0].Text == "no")
@@ -208,7 +215,7 @@ namespace XCoder.FolderInfo
             }
         }
 
-        private void treeView1_AfterCollapse(object sender, TreeViewEventArgs e)
+        private void treeView1_AfterCollapse(Object sender, TreeViewEventArgs e)
         {
             // 折叠后清空,使得再次展开时重新计算
             if (e.Node != null && e.Node.Nodes != null)
@@ -231,7 +238,7 @@ namespace XCoder.FolderInfo
             return node.Tag.ToString();
         }
 
-        private void 打开目录ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 打开目录ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             var path = GetSelectedPath();
             if (String.IsNullOrEmpty(path)) return;
@@ -251,7 +258,7 @@ namespace XCoder.FolderInfo
             }
         }
 
-        private void 删除ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 删除ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             var path = GetSelectedPath();
             if (String.IsNullOrEmpty(path)) return;
@@ -284,14 +291,14 @@ namespace XCoder.FolderInfo
             // 删除本目录文件
             foreach (var item in di.GetFiles())
             {
-                XTrace.WriteLine("删除 {0}", item.FullName);
+                BizLog.Info("删除 {0}", item.FullName);
                 try
                 {
                     item.Delete();
                 }
                 catch (Exception ex)
                 {
-                    XTrace.WriteException(ex);
+                    BizLog.Error(ex?.GetTrue().ToString());
                 }
             }
             // 递归子目录
@@ -306,7 +313,7 @@ namespace XCoder.FolderInfo
             }
             catch (Exception ex)
             {
-                XTrace.WriteException(ex);
+                BizLog.Error(ex?.GetTrue().ToString());
             }
         }
         #endregion
Added +20 -0
diff --git a/XCoder/FolderInfo/FrmSplitFile.cs b/XCoder/FolderInfo/FrmSplitFile.cs
new file mode 100644
index 0000000..b6d6a35
--- /dev/null
+++ b/XCoder/FolderInfo/FrmSplitFile.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace XCoder.FolderInfo
+{
+    public partial class FrmSplitFile : Form
+    {
+        public FrmSplitFile()
+        {
+            InitializeComponent();
+        }
+    }
+}
Added +38 -0
diff --git a/XCoder/FolderInfo/FrmSplitFile.Designer.cs b/XCoder/FolderInfo/FrmSplitFile.Designer.cs
new file mode 100644
index 0000000..6e67a9e
--- /dev/null
+++ b/XCoder/FolderInfo/FrmSplitFile.Designer.cs
@@ -0,0 +1,38 @@
+namespace XCoder.FolderInfo
+{
+    partial class FrmSplitFile
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Text = "FrmSplitFile";
+        }
+
+        #endregion
+    }
+}
\ No newline at end of file
Modified +71 -21
diff --git a/XCoder/FrmMDI.cs b/XCoder/FrmMDI.cs
index 89c204e..4839639 100644
--- a/XCoder/FrmMDI.cs
+++ b/XCoder/FrmMDI.cs
@@ -5,6 +5,10 @@ using System.Reflection;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using NewLife.Reflection;
+using NewLife.Net;
+using System.IO;
+using NewLife.Log;
+using NewLife.Threading;
 
 namespace XCoder
 {
@@ -15,14 +19,17 @@ namespace XCoder
 
         public FrmMDI()
         {
-            _load = Task<Type[]>.Factory.StartNew(() => typeof(Form).GetAllSubclasses(true).Where(e => e.Name == "FrmMain").ToArray());
+            _load = Task<Type[]>.Factory.StartNew(() => typeof(IXForm).GetAllSubclasses(true).ToArray());
 
             InitializeComponent();
 
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
             Icon = Source.GetIcon();
         }
 
-        private void FrmMDI_Shown(object sender, EventArgs e)
+        private void FrmMDI_Shown(Object sender, EventArgs e)
         {
             var set = XConfig.Current;
             if (set.Width > 0 || set.Height > 0)
@@ -38,6 +45,8 @@ namespace XCoder
             Text = String.Format("{2} v{0} {1:HH:mm:ss}", asm.CompileVersion, asm.Compile, set.Title);
 
             _load.ContinueWith(t => LoadForms(t.Result));
+
+            ThreadPoolX.QueueUserWorkItem(() => CheckUpdate(true));
         }
 
         void LoadForms(Type[] ts)
@@ -69,6 +78,20 @@ namespace XCoder
                 }
             });
         }
+
+        private void FrmMDI_FormClosing(Object sender, FormClosingEventArgs e)
+        {
+            var set = XConfig.Current;
+            var area = Screen.PrimaryScreen.WorkingArea;
+            if (Left >= 0 && Top >= 0 && Width < area.Width - 60 && Height < area.Height - 60)
+            {
+                set.Width = Width;
+                set.Height = Height;
+                set.Top = Top;
+                set.Left = Left;
+                set.Save();
+            }
+        }
         #endregion
 
         #region 应用窗口
@@ -103,42 +126,69 @@ namespace XCoder
         #endregion
 
         #region 菜单控制
-        private void ShowNewForm(object sender, EventArgs e) { }
+        private void ShowNewForm(Object sender, EventArgs e) { }
 
-        private void CascadeToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.Cascade); }
+        private void CascadeToolStripMenuItem_Click(Object sender, EventArgs e) { LayoutMdi(MdiLayout.Cascade); }
 
-        private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.TileVertical); }
+        private void TileVerticalToolStripMenuItem_Click(Object sender, EventArgs e) { LayoutMdi(MdiLayout.TileVertical); }
 
-        private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.TileHorizontal); }
+        private void TileHorizontalToolStripMenuItem_Click(Object sender, EventArgs e) { LayoutMdi(MdiLayout.TileHorizontal); }
 
-        private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.ArrangeIcons); }
+        private void ArrangeIconsToolStripMenuItem_Click(Object sender, EventArgs e) { LayoutMdi(MdiLayout.ArrangeIcons); }
 
-        private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e)
+        private void CloseAllToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             foreach (var childForm in MdiChildren)
             {
                 childForm.Close();
             }
         }
+
+        private void aboutToolStripMenuItem_Click(Object sender, EventArgs e)
+        {
+            Process.Start("http://www.NewLifeX.com");
+        }
         #endregion
 
-        private void FrmMDI_FormClosing(object sender, FormClosingEventArgs e)
+        #region 自动更新
+        private void 检查更新ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
-            var set = XConfig.Current;
-            var area = Screen.PrimaryScreen.WorkingArea;
-            if (Left >= 0 && Top >= 0 && Width < area.Width - 60 && Height < area.Height - 60)
-            {
-                set.Width = Width;
-                set.Height = Height;
-                set.Top = Top;
-                set.Left = Left;
-                set.Save();
-            }
+            ThreadPoolX.QueueUserWorkItem(() => CheckUpdate(false));
         }
 
-        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
+        private void CheckUpdate(Boolean auto)
         {
-            Process.Start("http://www.NewLifeX.com");
+            if (auto) XTrace.WriteLine("自动更新!");
+
+            Upgrade.DeleteBuckup();
+
+            var cfg = XConfig.Current;
+            if (cfg.LastUpdate.Date < DateTime.Now.Date || !auto)
+            {
+                cfg.LastUpdate = DateTime.Now;
+                cfg.Save();
+
+                var root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+                var up = new Upgrade();
+                up.Log = XTrace.Log;
+                up.Name = "XCoder";
+                up.Server = cfg.UpdateServer;
+                up.UpdatePath = root.CombinePath(up.UpdatePath);
+                if (up.Check())
+                {
+                    up.Download();
+                    if (!auto || MessageBox.Show("发现新版本{0},是否更新?".F(up.Links[0].Time), "自动更新", MessageBoxButtons.YesNo) == DialogResult.Yes)
+                        up.Update();
+                }
+                else if (!auto)
+                {
+                    if (up.Links != null && up.Links.Length > 0)
+                        MessageBox.Show("没有可用更新!最新{0}".F(up.Links[0].Time), "自动更新");
+                    else
+                        MessageBox.Show("没有可用更新!", "自动更新");
+                }
+            }
         }
+        #endregion
     }
 }
\ No newline at end of file
Modified +11 -1
diff --git a/XCoder/FrmMDI.Designer.cs b/XCoder/FrmMDI.Designer.cs
index 07072a6..c454582 100644
--- a/XCoder/FrmMDI.Designer.cs
+++ b/XCoder/FrmMDI.Designer.cs
@@ -41,6 +41,7 @@
             this.contentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
             this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.检查更新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.menuStrip.SuspendLayout();
             this.SuspendLayout();
             // 
@@ -123,6 +124,7 @@
             this.helpMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.contentsToolStripMenuItem,
             this.toolStripSeparator8,
+            this.检查更新ToolStripMenuItem,
             this.aboutToolStripMenuItem});
             this.helpMenu.Name = "helpMenu";
             this.helpMenu.Size = new System.Drawing.Size(61, 21);
@@ -148,6 +150,13 @@
             this.aboutToolStripMenuItem.Text = "关于(&A) ... ...";
             this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
             // 
+            // 检查更新ToolStripMenuItem
+            // 
+            this.检查更新ToolStripMenuItem.Name = "检查更新ToolStripMenuItem";
+            this.检查更新ToolStripMenuItem.Size = new System.Drawing.Size(166, 22);
+            this.检查更新ToolStripMenuItem.Text = "检查更新";
+            this.检查更新ToolStripMenuItem.Click += new System.EventHandler(this.检查更新ToolStripMenuItem_Click);
+            // 
             // FrmMDI
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -158,7 +167,7 @@
             this.MainMenuStrip = this.menuStrip;
             this.Name = "FrmMDI";
             this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
-            this.Text = "新生命超级码神工具";
+            this.Text = "新生命码神工具";
             this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmMDI_FormClosing);
             this.Shown += new System.EventHandler(this.FrmMDI_Shown);
             this.menuStrip.ResumeLayout(false);
@@ -183,6 +192,7 @@
         private System.Windows.Forms.ToolStripMenuItem arrangeIconsToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem helpMenu;
         private System.Windows.Forms.ToolStripMenuItem contentsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem 检查更新ToolStripMenuItem;
     }
 }
 
Added +12 -0
diff --git a/XCoder/IXForm.cs b/XCoder/IXForm.cs
new file mode 100644
index 0000000..71982c4
--- /dev/null
+++ b/XCoder/IXForm.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XCoder
+{
+    public interface IXForm
+    {
+    }
+}
\ No newline at end of file
Modified +42 -47
diff --git a/XCoder/NewModelForm/AddField.cs b/XCoder/NewModelForm/AddField.cs
index 0b47b8f..18fa8ae 100644
--- a/XCoder/NewModelForm/AddField.cs
+++ b/XCoder/NewModelForm/AddField.cs
@@ -1,9 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Text;
 using System.Windows.Forms;
 using XCode.DataAccessLayer;
 
@@ -18,9 +13,9 @@ namespace XCoder
 
         private IDataColumn DataColumn;
         //是否添加,默认是添加数据
-        private Boolean IsNew = true ;
+        private Boolean IsNew = true;
 
-        public AddField(IDataColumn dc,bool isNew)
+        public AddField(IDataColumn dc, Boolean isNew)
         {
             InitializeComponent();
             IsNew = isNew;
@@ -33,29 +28,29 @@ namespace XCoder
             DataColumn = dc;
 
             //修改的话,直接绑定数据到文本框
-            if(!IsNew)  BandText ();
+            if (!IsNew) BandText();
         }
 
         //绑定数据
         void BandText()
         {
             txtName.Text = DataColumn.Name;
-            txtDefault.Text = DataColumn.Default;
+            //txtDefault.Text = DataColumn.Default;
             txtDescription.Text = DataColumn.Description;
             txtLength.Text = DataColumn.Length.ToString();
-            txtNumOfByte.Text = DataColumn.NumOfByte.ToString();
-            txtPrecision.Text = DataColumn.Precision.ToString();
-            if (DataColumn.DataType !=null )
+            //txtNumOfByte.Text = DataColumn.NumOfByte.ToString();
+            //txtPrecision.Text = DataColumn.Precision.ToString();
+            if (DataColumn.DataType != null)
             {
-                txtDataType.Text = DataColumn.DataType.Name;     
+                txtDataType.Text = DataColumn.DataType.Name;
             }
             if (DataColumn.RawType.Contains("nvarchar")) combRawType.SelectedIndex = 3;
-            else  combRawType.SelectedIndex = PrimitiveType.TypeList.FindIndex(n => n.Name.Contains(DataColumn.RawType));
+            else combRawType.SelectedIndex = PrimitiveType.TypeList.FindIndex(n => n.Name.Contains(DataColumn.RawType));
 
             combRawType.Text = DataColumn.RawType;
 
             ckbIdentity.Checked = DataColumn.Identity;
-        
+
             ckbNullable.Checked = DataColumn.Nullable;
             ckbPrimarykey.Checked = DataColumn.PrimaryKey;
         }
@@ -64,11 +59,11 @@ namespace XCoder
         void SaveValue()
         {
             DataColumn.Name = txtName.Text.Trim();
-            DataColumn.Default = txtDefault.Text.Trim();
+            //DataColumn.Default = txtDefault.Text.Trim();
             DataColumn.Description = txtDescription.Text.Trim();
             DataColumn.Length = Convert.ToInt32(txtLength.Text.Trim());
-            DataColumn.NumOfByte = Convert.ToInt32(txtNumOfByte.Text.Trim());
-            DataColumn.Precision = Convert.ToInt32(txtPrecision.Text.Trim());        
+            //DataColumn.NumOfByte = Convert.ToInt32(txtNumOfByte.Text.Trim());
+            //DataColumn.Precision = Convert.ToInt32(txtPrecision.Text.Trim());
             DataColumn.DataType = Type.GetType(txtDataType.Text.Trim());
 
             if (combRawType.SelectedIndex != 3)
@@ -77,68 +72,68 @@ namespace XCoder
             }
             else
             {
-                DataColumn.RawType = string.Format(combRawType.Text.Trim() + "({0})", DataColumn.Length);
+                DataColumn.RawType = String.Format(combRawType.Text.Trim() + "({0})", DataColumn.Length);
             }
 
-            DataColumn.Identity = ckbIdentity.Checked ;       
-            DataColumn.Nullable = ckbNullable.Checked ;
-            DataColumn.PrimaryKey = ckbPrimarykey.Checked ;
+            DataColumn.Identity = ckbIdentity.Checked;
+            DataColumn.Nullable = ckbNullable.Checked;
+            DataColumn.PrimaryKey = ckbPrimarykey.Checked;
             DataColumn.ColumnName = DataColumn.Name;
         }
 
-        public static BaseForm CreateForm(IDataColumn column, bool isNew)
+        public static BaseForm CreateForm(IDataColumn column, Boolean isNew)
         {
-            AddField frm = new AddField(column, isNew);
+            var frm = new AddField(column, isNew);
             frm.Dock = DockStyle.Fill;
             return WinFormHelper.CreateForm(frm, "编辑字段信息");
-        }      
+        }
 
-        private void combRawType_SelectedIndexChanged(object sender, EventArgs e)
-        {        
-            if (combRawType.SelectedIndex == 3) 
+        private void combRawType_SelectedIndexChanged(Object sender, EventArgs e)
+        {
+            if (combRawType.SelectedIndex == 3)
             {
                 txtLength.Enabled = true;
-                if (!IsNew ) txtLength.Text = DataColumn.Length.ToString () ;
-                else 
+                if (!IsNew) txtLength.Text = DataColumn.Length.ToString();
+                else
                 {
-                    txtDataType.Text  = PrimitiveType.TypeList[combRawType.SelectedIndex].DataType;
-                    txtLength.Text    = PrimitiveType.TypeList[combRawType.SelectedIndex].Length.ToString();
-                    txtNumOfByte.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].NumOfByte.ToString();
-                    txtPrecision.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].Precision.ToString();
+                    txtDataType.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].DataType;
+                    txtLength.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].Length.ToString();
+                    //txtNumOfByte.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].NumOfByte.ToString();
+                    //txtPrecision.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].Precision.ToString();
                 }
             }
             else
             {
                 txtLength.Enabled = false;
-                txtDataType.Text  = PrimitiveType.TypeList[combRawType.SelectedIndex].DataType;
-                txtLength.Text    = PrimitiveType.TypeList[combRawType.SelectedIndex].Length.ToString();
-                txtNumOfByte.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].NumOfByte.ToString();
-                txtPrecision.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].Precision.ToString();
+                txtDataType.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].DataType;
+                txtLength.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].Length.ToString();
+                //txtNumOfByte.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].NumOfByte.ToString();
+                //txtPrecision.Text = PrimitiveType.TypeList[combRawType.SelectedIndex].Precision.ToString();
             }
         }
 
-        private void btnSave_Click(object sender, EventArgs e)
+        private void btnSave_Click(Object sender, EventArgs e)
         {
             SaveValue();
             ParentForm.DialogResult = DialogResult.OK;
             ParentForm.Close();
         }
 
-        private void btnCancle_Click(object sender, EventArgs e)
+        private void btnCancle_Click(Object sender, EventArgs e)
         {
-            ParentForm.DialogResult = DialogResult.Cancel ;
+            ParentForm.DialogResult = DialogResult.Cancel;
             ParentForm.Close();
         }
 
-        private void txtLength_TextChanged(object sender, EventArgs e)
+        private void txtLength_TextChanged(Object sender, EventArgs e)
         {
-            if (combRawType.SelectedIndex == 3)
-            {
-                txtNumOfByte.Text = txtPrecision.Text = txtLength.Text;
-            }
+            //if (combRawType.SelectedIndex == 3)
+            //{
+            //    txtPrecision.Text = txtLength.Text;
+            //}
         }
 
-        private void txtLength_KeyPress(object sender, KeyPressEventArgs e)
+        private void txtLength_KeyPress(Object sender, KeyPressEventArgs e)
         {
             WinFormHelper.SetControlOnlyZS(sender, e);
         }
Modified +2 -71
diff --git a/XCoder/NewModelForm/AddField.Designer.cs b/XCoder/NewModelForm/AddField.Designer.cs
index ac47693..74d716f 100644
--- a/XCoder/NewModelForm/AddField.Designer.cs
+++ b/XCoder/NewModelForm/AddField.Designer.cs
@@ -33,21 +33,15 @@
             this.btnSave = new System.Windows.Forms.Button();
             this.txtDataType = new System.Windows.Forms.TextBox();
             this.txtDescription = new System.Windows.Forms.TextBox();
-            this.txtPrecision = new System.Windows.Forms.TextBox();
             this.label2 = new System.Windows.Forms.Label();
             this.ckbNullable = new System.Windows.Forms.CheckBox();
-            this.txtNumOfByte = new System.Windows.Forms.TextBox();
             this.txtLength = new System.Windows.Forms.TextBox();
-            this.txtDefault = new System.Windows.Forms.TextBox();
             this.ckbPrimarykey = new System.Windows.Forms.CheckBox();
             this.ckbIdentity = new System.Windows.Forms.CheckBox();
             this.combRawType = new System.Windows.Forms.ComboBox();
             this.txtName = new System.Windows.Forms.TextBox();
             this.label13 = new System.Windows.Forms.Label();
-            this.label12 = new System.Windows.Forms.Label();
             this.label10 = new System.Windows.Forms.Label();
-            this.label8 = new System.Windows.Forms.Label();
-            this.label7 = new System.Windows.Forms.Label();
             this.label6 = new System.Windows.Forms.Label();
             this.label3 = new System.Windows.Forms.Label();
             this.label1 = new System.Windows.Forms.Label();
@@ -60,21 +54,15 @@
             this.gbInfo.Controls.Add(this.btnSave);
             this.gbInfo.Controls.Add(this.txtDataType);
             this.gbInfo.Controls.Add(this.txtDescription);
-            this.gbInfo.Controls.Add(this.txtPrecision);
             this.gbInfo.Controls.Add(this.label2);
             this.gbInfo.Controls.Add(this.ckbNullable);
-            this.gbInfo.Controls.Add(this.txtNumOfByte);
             this.gbInfo.Controls.Add(this.txtLength);
-            this.gbInfo.Controls.Add(this.txtDefault);
             this.gbInfo.Controls.Add(this.ckbPrimarykey);
             this.gbInfo.Controls.Add(this.ckbIdentity);
             this.gbInfo.Controls.Add(this.combRawType);
             this.gbInfo.Controls.Add(this.txtName);
             this.gbInfo.Controls.Add(this.label13);
-            this.gbInfo.Controls.Add(this.label12);
             this.gbInfo.Controls.Add(this.label10);
-            this.gbInfo.Controls.Add(this.label8);
-            this.gbInfo.Controls.Add(this.label7);
             this.gbInfo.Controls.Add(this.label6);
             this.gbInfo.Controls.Add(this.label3);
             this.gbInfo.Controls.Add(this.label1);
@@ -116,19 +104,11 @@
             // 
             // txtDescription
             // 
-            this.txtDescription.Location = new System.Drawing.Point(326, 153);
+            this.txtDescription.Location = new System.Drawing.Point(326, 116);
             this.txtDescription.Name = "txtDescription";
             this.txtDescription.Size = new System.Drawing.Size(130, 29);
             this.txtDescription.TabIndex = 25;
             // 
-            // txtPrecision
-            // 
-            this.txtPrecision.Enabled = false;
-            this.txtPrecision.Location = new System.Drawing.Point(326, 114);
-            this.txtPrecision.Name = "txtPrecision";
-            this.txtPrecision.Size = new System.Drawing.Size(130, 29);
-            this.txtPrecision.TabIndex = 23;
-            // 
             // label2
             // 
             this.label2.AutoSize = true;
@@ -148,14 +128,6 @@
             this.ckbNullable.Text = "是否允许空";
             this.ckbNullable.UseVisualStyleBackColor = true;
             // 
-            // txtNumOfByte
-            // 
-            this.txtNumOfByte.Enabled = false;
-            this.txtNumOfByte.Location = new System.Drawing.Point(326, 75);
-            this.txtNumOfByte.Name = "txtNumOfByte";
-            this.txtNumOfByte.Size = new System.Drawing.Size(130, 29);
-            this.txtNumOfByte.TabIndex = 20;
-            // 
             // txtLength
             // 
             this.txtLength.Enabled = false;
@@ -166,14 +138,6 @@
             this.txtLength.TextChanged += new System.EventHandler(this.txtLength_TextChanged);
             this.txtLength.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtLength_KeyPress);
             // 
-            // txtDefault
-            // 
-            this.txtDefault.Location = new System.Drawing.Point(101, 153);
-            this.txtDefault.Name = "txtDefault";
-            this.txtDefault.Size = new System.Drawing.Size(155, 29);
-            this.txtDefault.TabIndex = 18;
-            this.txtDefault.Text = "0";
-            // 
             // ckbPrimarykey
             // 
             this.ckbPrimarykey.AutoSize = true;
@@ -216,21 +180,12 @@
             // label13
             // 
             this.label13.AutoSize = true;
-            this.label13.Location = new System.Drawing.Point(281, 156);
+            this.label13.Location = new System.Drawing.Point(281, 120);
             this.label13.Name = "label13";
             this.label13.Size = new System.Drawing.Size(42, 21);
             this.label13.TabIndex = 12;
             this.label13.Text = "说明";
             // 
-            // label12
-            // 
-            this.label12.AutoSize = true;
-            this.label12.Location = new System.Drawing.Point(40, 156);
-            this.label12.Name = "label12";
-            this.label12.Size = new System.Drawing.Size(58, 21);
-            this.label12.TabIndex = 11;
-            this.label12.Text = "默认值";
-            // 
             // label10
             // 
             this.label10.AutoSize = true;
@@ -239,24 +194,6 @@
             this.label10.Size = new System.Drawing.Size(0, 21);
             this.label10.TabIndex = 9;
             // 
-            // label8
-            // 
-            this.label8.AutoSize = true;
-            this.label8.Location = new System.Drawing.Point(281, 117);
-            this.label8.Name = "label8";
-            this.label8.Size = new System.Drawing.Size(42, 21);
-            this.label8.TabIndex = 7;
-            this.label8.Text = "精度";
-            // 
-            // label7
-            // 
-            this.label7.AutoSize = true;
-            this.label7.Location = new System.Drawing.Point(265, 78);
-            this.label7.Name = "label7";
-            this.label7.Size = new System.Drawing.Size(58, 21);
-            this.label7.TabIndex = 6;
-            this.label7.Text = "字节数";
-            // 
             // label6
             // 
             this.label6.AutoSize = true;
@@ -305,20 +242,14 @@
         private System.Windows.Forms.Label label3;
         private System.Windows.Forms.Label label6;
         private System.Windows.Forms.Label label10;
-        private System.Windows.Forms.Label label8;
-        private System.Windows.Forms.Label label7;
         private System.Windows.Forms.Label label13;
-        private System.Windows.Forms.Label label12;
         private System.Windows.Forms.TextBox txtName;
         private System.Windows.Forms.ComboBox combRawType;
         private System.Windows.Forms.CheckBox ckbIdentity;
         private System.Windows.Forms.CheckBox ckbPrimarykey;
-        private System.Windows.Forms.TextBox txtDefault;
-        private System.Windows.Forms.TextBox txtNumOfByte;
         private System.Windows.Forms.TextBox txtLength;
         private System.Windows.Forms.CheckBox ckbNullable;
         private System.Windows.Forms.TextBox txtDescription;
-        private System.Windows.Forms.TextBox txtPrecision;
         private System.Windows.Forms.TextBox txtDataType;
         private System.Windows.Forms.Button btnSave;
         private System.Windows.Forms.Button btnCancle;
Modified +26 -26
diff --git a/XCoder/NewModelForm/AddTable.cs b/XCoder/NewModelForm/AddTable.cs
index c514df9..28f7599 100644
--- a/XCoder/NewModelForm/AddTable.cs
+++ b/XCoder/NewModelForm/AddTable.cs
@@ -7,7 +7,7 @@ using System.Text;
 using System.Windows.Forms;
 
 using XCode;
-using XCode.DataAccessLayer ;
+using XCode.DataAccessLayer;
 
 namespace XCoder
 {
@@ -27,7 +27,7 @@ namespace XCoder
             combDbType.DataSource = BindComboxEnumType<DatabaseType>.BindTyps;
             //combDbType.DisplayMember = "Name";
             //combDbType.ValueMember = "Type";
-            
+
             CurrentTable = table;
             //绑定Table信息到文本框
             txtTableName.Text = CurrentTable.TableName;
@@ -35,62 +35,62 @@ namespace XCoder
             combDbType.SelectedValue = CurrentTable.DbType;
 
             list = new BindingList<IDataColumn>();
-            
+
             //绑定字段到表格
-            if(CurrentTable.Columns.Count >0 ) dgvColumns.DataSource = CurrentTable.Columns;
+            if (CurrentTable.Columns.Count > 0) dgvColumns.DataSource = CurrentTable.Columns;
 
             BandingDGV();
         }
 
         private void BandingDGV()
         {
-            if (CurrentTable.Columns.Count >0 )
+            if (CurrentTable.Columns.Count > 0)
             {
                 list.Clear();
-                foreach (var item in CurrentTable.Columns )
+                foreach (var item in CurrentTable.Columns)
                 {
                     list.Add(item);
                 }
                 dgvColumns.DataSource = null;
                 dgvColumns.DataSource = list;
             }
-            else  dgvColumns.DataSource = null;
+            else dgvColumns.DataSource = null;
         }
 
         public static BaseForm CreateForm(IDataTable table)
         {
-            AddTable frm = new AddTable(table );
-            frm.Dock = DockStyle.Fill;            
-            return WinFormHelper.CreateForm(frm , "添加表");
+            var frm = new AddTable(table);
+            frm.Dock = DockStyle.Fill;
+            return WinFormHelper.CreateForm(frm, "添加表");
         }
 
-        private void toolAddColumns_Click(object sender, EventArgs e)
+        private void toolAddColumns_Click(Object sender, EventArgs e)
         {
-            IDataColumn dc = CurrentTable.CreateColumn();
+            var dc = CurrentTable.CreateColumn();
             //CurrentTable.Columns.Add(dc);
-            dc.ID = CurrentTable.Columns.Count + 1;
-            dc.ColumnName = "Column" + dc.ID;
-            dc.Description = "字段" + dc.ID;
-            DialogResult dr = AddField.CreateForm(dc, true).ShowDialog();
-            if (dr != DialogResult.Cancel) 
+            var id = CurrentTable.Columns.Count + 1;
+            dc.ColumnName = "Column" + id;
+            dc.Description = "字段" + id;
+            var dr = AddField.CreateForm(dc, true).ShowDialog();
+            if (dr != DialogResult.Cancel)
             {
                 CurrentTable.Columns.Add(dc);
                 BandingDGV();
             }
         }
 
-        private void toolEidtColumn_Click(object sender, EventArgs e)
+        private void toolEidtColumn_Click(Object sender, EventArgs e)
         {
 
-            DataGridViewRow row = dgvColumns.Rows[dgvColumns.CurrentCell.RowIndex ];
+            var row = dgvColumns.Rows[dgvColumns.CurrentCell.RowIndex];
             if (row == null) return;
 
-            AddField.CreateForm((IDataColumn)row.DataBoundItem , false ).ShowDialog();
+            AddField.CreateForm((IDataColumn)row.DataBoundItem, false).ShowDialog();
 
             BandingDGV();
-        }      
+        }
 
-        private void toolStripButton1_Click(object sender, EventArgs e)
+        private void toolStripButton1_Click(Object sender, EventArgs e)
         {
             if (MessageBox.Show("是否需要保存数据?", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
             {
@@ -99,19 +99,19 @@ namespace XCoder
             else
             {
                 ParentForm.Close();
-            }          
+            }
         }
 
-        private void toolSave_Click(object sender, EventArgs e)
+        private void toolSave_Click(Object sender, EventArgs e)
         {
             CurrentTable.TableName = txtTableName.Text.Trim();
             CurrentTable.Description = txtTableRemark.Text.Trim();
             CurrentTable.DbType = (DatabaseType)Enum.Parse(typeof(DatabaseType), combDbType.SelectedValue.ToString());
 
-            BandingDGV();      
+            BandingDGV();
         }
 
-        private void toolDelete_Click(object sender, EventArgs e)
+        private void toolDelete_Click(Object sender, EventArgs e)
         {
             CurrentTable.Columns.RemoveAt(dgvColumns.CurrentCell.RowIndex);
             BandingDGV();
Modified +16 -22
diff --git a/XCoder/NewModelForm/NewModel.cs b/XCoder/NewModelForm/NewModel.cs
index b47536d..f6cef2b 100644
--- a/XCoder/NewModelForm/NewModel.cs
+++ b/XCoder/NewModelForm/NewModel.cs
@@ -9,14 +9,8 @@ namespace XCoder
 {
     public partial class NewModel : UserControl
     {
-        private List<IDataTable> _tables;
+        public List<IDataTable> Tables { get; set; }
 
-        public List<IDataTable> Tables
-        {
-            get { return _tables; }
-            set { _tables = value; }
-        }
-        
 
         public NewModel()
         {
@@ -26,41 +20,41 @@ namespace XCoder
 
         public static BaseForm CreateForm()
         {
-            NewModel frm = new NewModel();
+            var frm = new NewModel();
             frm.Dock = DockStyle.Fill;
 
             return WinFormHelper.CreateForm(frm, "添加模型");
         }
 
-        private void toolAddTable_Click(object sender, EventArgs e)
+        private void toolAddTable_Click(Object sender, EventArgs e)
         {
             //为了触发XCodeService的静态构造函数
             var temp = ModelResolver.Current;
             if (temp == null) return;
 
-            IDataTable current = ObjectContainer.Current.Resolve <IDataTable >();
+            var current = ObjectContainer.Current.Resolve<IDataTable>();
             Tables.Add(current);
-            current.ID = Tables.Count;
-            current.TableName = "NewTable" + current.ID;
-            current.Description = "新建表" + current.ID;
+            var id = Tables.Count;
+            current.TableName = "NewTable" + id;
+            current.Description = "新建表" + id;
             current.DbType = DatabaseType.SqlServer;
             current.Description = "默认说明";
 
-            AddTable.CreateForm(current).ShowDialog() ;
+            AddTable.CreateForm(current).ShowDialog();
 
             dgvTables.DataSource = null;
             dgvTables.DataSource = Tables;
         }
 
-        private void toolEidtTable_Click(object sender, EventArgs e)
+        private void toolEidtTable_Click(Object sender, EventArgs e)
         {
-            DataGridViewRow row = dgvTables.Rows[dgvTables.CurrentCell.RowIndex];
+            var row = dgvTables.Rows[dgvTables.CurrentCell.RowIndex];
             if (row == null) return;
 
             AddTable.CreateForm((IDataTable)row.DataBoundItem).ShowDialog();
         }
 
-        private void toolClose_Click(object sender, EventArgs e)
+        private void toolClose_Click(Object sender, EventArgs e)
         {
             if (MessageBox.Show("是否需要保存?", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
             {
@@ -69,21 +63,21 @@ namespace XCoder
             else
             {
                 ParentForm.Close();
-            }            
+            }
         }
 
         //保存模型
-        private void toolStripButton1_Click(object sender, EventArgs e)
+        private void toolStripButton1_Click(Object sender, EventArgs e)
         {
             if (Tables == null || Tables.Count < 1)
             {
                 MessageBox.Show(Text, "数据库架构为空!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                 return;
-            }            
+            }
             if (saveFileDialog1.ShowDialog() != DialogResult.OK || String.IsNullOrEmpty(saveFileDialog1.FileName)) return;
             try
             {
-                String xml = DAL.Export(Tables);
+                var xml = DAL.Export(Tables);
                 File.WriteAllText(saveFileDialog1.FileName, xml);
 
                 MessageBox.Show("保存模型成功!", "保存模型", MessageBoxButtons.OK);
@@ -95,7 +89,7 @@ namespace XCoder
             }
         }
 
-        private void toolDeleteTable_Click(object sender, EventArgs e)
+        private void toolDeleteTable_Click(Object sender, EventArgs e)
         {
             Tables.RemoveAt(dgvTables.CurrentCell.RowIndex);
 
Modified +29 -29
diff --git a/XCoder/NewModelForm/WinFormHelper.cs b/XCoder/NewModelForm/WinFormHelper.cs
index ae3e657..ea0cd68 100644
--- a/XCoder/NewModelForm/WinFormHelper.cs
+++ b/XCoder/NewModelForm/WinFormHelper.cs
@@ -14,9 +14,9 @@ namespace XCoder
         /// </summary>
         /// <param name="cl">控件</param>
         /// <param name="titleText">标题文本</param>        
-        public static BaseForm CreateForm(Control cl, string titleText = "")
+        public static BaseForm CreateForm(Control cl, String titleText = "")
         {
-            BaseForm tf = new BaseForm();
+            var tf = new BaseForm();
             tf.Size = new Size(cl.Width + 15, cl.Size.Height + 40);
             tf.Controls.Add(cl);//将控件添加到窗体中
             tf.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
@@ -31,9 +31,9 @@ namespace XCoder
         /// </summary>
         /// <param name="sender"></param>
         /// <param name="e"></param>
-        public static void SetControlOnlyValue(object sender, KeyPressEventArgs e)
+        public static void SetControlOnlyValue(Object sender, KeyPressEventArgs e)
         {
-            e.Handled = !(Char.IsNumber(e.KeyChar) || e.KeyChar == (char)8 || e.KeyChar == '.' || e.KeyChar == '-');
+            e.Handled = !(Char.IsNumber(e.KeyChar) || e.KeyChar == (Char)8 || e.KeyChar == '.' || e.KeyChar == '-');
             if (!e.Handled)
                 (sender as TextBox).Tag = (sender as TextBox).Text;//记录最后一次正确输入
         }
@@ -42,9 +42,9 @@ namespace XCoder
         /// </summary>
         /// <param name="sender"></param>
         /// <param name="e"></param>
-        public static void SetControlOnlyZS(object sender, KeyPressEventArgs e)
+        public static void SetControlOnlyZS(Object sender, KeyPressEventArgs e)
         {
-            e.Handled = !(Char.IsNumber(e.KeyChar) || e.KeyChar == (char)8 || e.KeyChar == '.');
+            e.Handled = !(Char.IsNumber(e.KeyChar) || e.KeyChar == (Char)8 || e.KeyChar == '.');
             if (!e.Handled)
                 (sender as TextBox).Tag = (sender as TextBox).Text;//记录最后一次正确输入
         }
@@ -55,7 +55,7 @@ namespace XCoder
     public class BindComboxEnumType<T>
     {
         /// <summary>类型的名字</summary>
-        public string Name { get; set; }
+        public String Name { get; set; }
 
         /// <summary>类型</summary>
         public T Type { get; set; }
@@ -66,13 +66,13 @@ namespace XCoder
         {
             bindTyps = new List<BindComboxEnumType<T>>();
 
-            foreach(var name in Enum.GetNames(typeof(T)))
+            foreach (var name in Enum.GetNames(typeof(T)))
             {
                 bindTyps.Add(new BindComboxEnumType<T>()
-                                 {
-                                     Name = name,
-                                     Type = (T)Enum.Parse(typeof(T), name)
-                                 });
+                {
+                    Name = name,
+                    Type = (T)Enum.Parse(typeof(T), name)
+                });
             }
         }
 
@@ -85,12 +85,12 @@ namespace XCoder
 
     /// <summary>暂时支持的数据类型,常规的</summary>
     public enum SupportDataType
-    {       
+    {
         Boolean = 3,
-        DateTime = 6,      
+        DateTime = 6,
         Double = 8,
-        Int32 =9,
-        Int64 =10,
+        Int32 = 9,
+        Int64 = 10,
         SByte = 11,
         String = 12
     }
@@ -99,27 +99,27 @@ namespace XCoder
     public class PrimitiveType
     {
         /// <summary>原始类型名称</summary>
-        public string  Name { get; set; }
+        public String Name { get; set; }
         /// <summary>类型长度</summary>
-        public int Length { get; set; }
-        /// <summary>字节数/summary>
-        public int NumOfByte { get; set; }
+        public Int32 Length { get; set; }
+        ///// <summary>字节数/summary>
+        //public Int32 NumOfByte { get; set; }
         /// <summary>精度</summary>
-        public int Precision { get; set; }
+        public Int32 Precision { get; set; }
         /// <summary>数据类型</summary>
-        public string DataType { get; set; }
+        public String DataType { get; set; }
 
-        public static List<PrimitiveType> TypeList ;
+        public static List<PrimitiveType> TypeList;
 
         static PrimitiveType()
         {
             TypeList = new List<PrimitiveType>();
-            TypeList.Add(new PrimitiveType() { Name = "bool", Length = 1, NumOfByte = 1, DataType = "System.Boolean", Precision = 1 });
-            TypeList.Add(new PrimitiveType() { Name = "int", Length = 10, NumOfByte = 10, DataType = "System.Int32", Precision = 10 });
-            TypeList.Add(new PrimitiveType() { Name = "double", Length = 22, NumOfByte = 22, DataType = "System.Double", Precision = 22 });
-            TypeList.Add(new PrimitiveType() { Name = "nvarchar", Length = 20, NumOfByte = 20, DataType = "System.String", Precision = 20 });
-            TypeList.Add(new PrimitiveType() { Name = "ntext", Length = 65535, NumOfByte = 65535, DataType = "System.String", Precision = 65535 });
-            TypeList.Add(new PrimitiveType() { Name = "datetime", Length = 20, NumOfByte = 20, DataType = "System.DateTime", Precision = 20 });
+            TypeList.Add(new PrimitiveType() { Name = "bool", Length = 1, DataType = "System.Boolean", Precision = 1 });
+            TypeList.Add(new PrimitiveType() { Name = "int", Length = 10, DataType = "System.Int32", Precision = 10 });
+            TypeList.Add(new PrimitiveType() { Name = "double", Length = 22, DataType = "System.Double", Precision = 22 });
+            TypeList.Add(new PrimitiveType() { Name = "nvarchar", Length = 20, DataType = "System.String", Precision = 20 });
+            TypeList.Add(new PrimitiveType() { Name = "ntext", Length = 65535, DataType = "System.String", Precision = 65535 });
+            TypeList.Add(new PrimitiveType() { Name = "datetime", Length = 20, DataType = "System.DateTime", Precision = 20 });
         }
     }
 }
\ No newline at end of file
Modified +4 -0
diff --git a/XCoder/packages.config b/XCoder/packages.config
index 55225cb..4736998 100644
--- a/XCoder/packages.config
+++ b/XCoder/packages.config
@@ -1,4 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="NewLife.Core" version="7.0.6712.2419" targetFramework="net46" />
+  <package id="NewLife.Net" version="3.2.6700.37161" targetFramework="net46" />
+  <package id="NewLife.XCode" version="9.7.6712.2420" targetFramework="net46" />
+  <package id="NewLife.XTemplate" version="2.0.6700.37161" targetFramework="net46" />
   <package id="UDE.CSharp" version="1.1.0" targetFramework="net40" />
 </packages>
\ No newline at end of file
Modified +5 -76
diff --git a/XCoder/Program.cs b/XCoder/Program.cs
index ab458fd..416926d 100644
--- a/XCoder/Program.cs
+++ b/XCoder/Program.cs
@@ -20,6 +20,8 @@ namespace XCoder
         {
             XTrace.UseWinForm();
 
+            StringHelper.EnableSpeechTip = XConfig.Current.SpeechTip;
+
             // 参数启动
             var args = Environment.GetCommandLineArgs();
             if (args != null && args.Length > 1)
@@ -35,37 +37,20 @@ namespace XCoder
                 return;
             }
 
-            try
-            {
-                Update(true);
-
-                if (!Runtime.Mono) new TimerX(s => Runtime.ReleaseMemory(), null, 5000, 10000);
-            }
-            catch (Exception ex)
-            {
-                XTrace.WriteException(ex);
-            }
+            if (!Runtime.Mono) new TimerX(s => Runtime.ReleaseMemory(), null, 60000, 60000) { Async = true };
 
-            if (XConfig.Current.IsNew) "学无先后达者为师,欢迎使用新生命超级码神工具!".SpeechTip();
+            if (XConfig.Current.IsNew) "学无先后达者为师,欢迎使用新生命码神工具!".SpeechTip();
 
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);
             Application.Run(new FrmMDI());
-
-            // 此时执行自动更新
-            var up = _upgrade;
-            if (up != null)
-            {
-                _upgrade = null;
-                up.Update();
-            }
         }
 
         /// <summary>参数启动</summary>
         static void StartWithParameter(String[] args)
         {
             var dic = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
-            for (int i = 2; i < args.Length - 1; i++)
+            for (var i = 2; i < args.Length - 1; i++)
             {
                 switch (args[i].ToLower())
                 {
@@ -106,54 +91,11 @@ namespace XCoder
                 case "-makemodel":
                     MakeModel(dic["Model"], dic["ConnStr"], dic["Provider"]);
                     return;
-                case "-update":
-                    Update(false);
-                    return;
                 default:
                     break;
             }
         }
 
-        static Upgrade _upgrade;
-        static void Update(Boolean isAsync)
-        {
-            if (!isAsync) XTrace.WriteLine("自动更新!");
-
-            var cfg = XConfig.Current;
-            if (cfg.LastUpdate.Date < DateTime.Now.Date)
-            {
-                cfg.LastUpdate = DateTime.Now;
-
-                var root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
-                var up = new Upgrade();
-                up.Log = XTrace.Log;
-                up.Name = "XCoder";
-                up.Server = cfg.UpdateServer;
-                up.UpdatePath = root.CombinePath(up.UpdatePath);
-                if (up.Check())
-                {
-                    up.Download();
-                    if (!isAsync)
-                        up.Update();
-                    else
-                        // 留到执行完成以后自动更新
-                        _upgrade = up;
-                }
-                cfg.Save();
-            }
-
-            if (isAsync)
-            {
-                // 释放T4模版
-                var b = File.Exists("XCoder.tt");
-                var txt = Source.GetText("XCoder.tt");
-                txt = txt.Replace("{XCoderPath}", AppDomain.CurrentDomain.BaseDirectory);
-                File.WriteAllText("XCoder.tt", txt);
-
-                //if (!b) MessageBox.Show("新版本增加XCoder.tt,拷贝到类库项目里面。\r\nVS中修改文件内参数,右键执行自定义工具!", "提示");
-            }
-        }
-
         static void Render(String mdl, String cfg)
         {
             XTrace.WriteLine("生成代码:模型{0} 配置{1}", mdl, cfg);
@@ -173,19 +115,6 @@ namespace XCoder
                 engine.Render(item);
             }
 
-            // 重新整理模型
-            Int32 i = 0;
-            foreach (var item in tables)
-            {
-                item.ID = ++i;
-
-                Int32 j = 0;
-                foreach (var dc in item.Columns)
-                {
-                    dc.ID = ++j;
-                }
-            }
-
             // 如果有改变,才重新写入模型文件
             var xml2 = DAL.Export(tables);
             if (xml2 != xml) File.WriteAllText(mdl, xml2);
Added +73 -0
diff --git a/XCoder/Properties/app.manifest b/XCoder/Properties/app.manifest
new file mode 100644
index 0000000..97e2ffc
--- /dev/null
+++ b/XCoder/Properties/app.manifest
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <!-- UAC 清单选项
+             如果想要更改 Windows 用户帐户控制级别,请使用
+             以下节点之一替换 requestedExecutionLevel 节点。n
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
+        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
+
+            指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
+            如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
+            元素。
+        -->
+        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
+           Windows 版本的列表。取消评论适当的元素,Windows 将
+           自动选择最兼容的环境。 -->
+
+      <!-- Windows Vista -->
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+
+      <!-- Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+      <!-- Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+      <!-- Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+      <!-- Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+    </application>
+  </compatibility>
+
+  <!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
+       自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
+       选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
+       在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+    </windowsSettings>
+  </application>
+
+  <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
+  <!--
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity
+          type="win32"
+          name="Microsoft.Windows.Common-Controls"
+          version="6.0.0.0"
+          processorArchitecture="*"
+          publicKeyToken="6595b64144ccf1df"
+          language="*"
+        />
+    </dependentAssembly>
+  </dependency>
+  -->
+
+</assembly>
Modified +10 -5
diff --git a/XCoder/Properties/AssemblyInfo.cs b/XCoder/Properties/AssemblyInfo.cs
index 2d10a20..26b43f7 100644
--- a/XCoder/Properties/AssemblyInfo.cs
+++ b/XCoder/Properties/AssemblyInfo.cs
@@ -4,10 +4,13 @@ using System.Runtime.InteropServices;
 // 有关程序集的常规信息通过下列属性集
 // 控制。更改这些属性值可修改
 // 与程序集关联的信息。
-[assembly: AssemblyTitle("新生命超级码神工具")]
+[assembly: AssemblyTitle("新生命码神工具")]
 [assembly: AssemblyDescription("基于编译型模版引擎的代码生成器,以及众多开发者工具")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyProduct("XCoder")]
+[assembly: AssemblyCompany("新生命开发团队")]
+[assembly: AssemblyCopyright("©2002-2018 新生命开发团队 http://www.NewLifeX.com")]
+[assembly: AssemblyTrademark("四叶草")]
 [assembly: AssemblyCulture("")]
 
 // 将 ComVisible 设置为 false 使此程序集中的类型
@@ -25,11 +28,13 @@ using System.Runtime.InteropServices;
 //      内部版本号
 //      修订号
 //
-[assembly: AssemblyVersion("6.8.*")]
-[assembly: AssemblyFileVersion("6.8.2016.0504")]
+[assembly: AssemblyVersion("6.9.*")]
+[assembly: AssemblyFileVersion("6.9.2017.0526")]
 
 /*
- * v6.8.2016.0504   增加操作语音提示和语音识别辅助操作
+ * v6.9.2017.0101   增加消息调试工具,支持调试网络库的消息收发功能
+ * 
+ * v6.9.2016.0504   增加操作语音提示和语音识别辅助操作
  * 
  * v6.7.2016.0418   异步加载子工具,支持外部FrmMain窗体
  * 
@@ -152,4 +157,4 @@ using System.Runtime.InteropServices;
  * 
  * v1.7.2009.0321   加载所有表时,按表名排序
  *
-**/
\ No newline at end of file
+**/
Modified +2 -2
diff --git a/XCoder/Properties/Settings.Designer.cs b/XCoder/Properties/Settings.Designer.cs
index bed6e31..e9db686 100644
--- a/XCoder/Properties/Settings.Designer.cs
+++ b/XCoder/Properties/Settings.Designer.cs
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     此代码由工具生成。
-//     运行时版本:4.0.30319.239
+//     运行时版本:4.0.30319.42000
 //
 //     对此文件的更改可能会导致不正确的行为,并且如果
 //     重新生成代码,这些更改将会丢失。
@@ -12,7 +12,7 @@ namespace XCoder.Properties {
     
     
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
     internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
         
         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
Modified +1 -2
diff --git "a/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\344\270\255\346\226\207\345\220\215.Biz.cs" "b/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\344\270\255\346\226\207\345\220\215.Biz.cs"
index 06a5458..e741824 100644
--- "a/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\344\270\255\346\226\207\345\220\215.Biz.cs"
+++ "b/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\344\270\255\346\226\207\345\220\215.Biz.cs"
@@ -42,7 +42,6 @@ if(Config.RenderGenEntity){#>
         #endregion
 
         #region 扩展属性
-            <#@include Name="扩展属性.xt"#>
         #endregion
 
         #region 扩展查询
@@ -59,7 +58,7 @@ if(Config.RenderGenEntity){#>
         /// <param name="key">关键字</param>
         /// <param name="param">分页排序参数,同时返回满足条件的总记录数</param>
         /// <returns>实体集</returns>
-        public static EntityList<<#=myClassName#>> Search(Int32 userid, DateTime start, DateTime end, String key, PageParameter param)
+        public static IList<<#=myClassName#>> Search(Int32 userid, DateTime start, DateTime end, String key, PageParameter param)
         {
             // WhereExpression重载&和|运算符,作为And和Or的替代
             // SearchWhereByKeys系列方法用于构建针对字符串字段的模糊搜索,第二个参数可指定要搜索的字段
Modified +1 -53
diff --git "a/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\345\257\271\350\261\241\346\223\215\344\275\234.xt" "b/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\345\257\271\350\261\241\346\223\215\344\275\234.xt"
index 773ac6e..a4a3489 100644
--- "a/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\345\257\271\350\261\241\346\223\215\344\275\234.xt"
+++ "b/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\345\257\271\350\261\241\346\223\215\344\275\234.xt"
@@ -118,64 +118,12 @@
             else if(dc.DataType==typeof(Guid)){#>
         //    entity.<#=dc.Name#> = Guid.NewGuid();<#}
             else{#>
-        //    entity.<#=dc.Name#> = <#=TypeX.CreateInstance(dc.DataType)#>;<#}
+        //    entity.<#=dc.Name#> = <#=dc.DataType.CreateInstance()#>;<#}
         }#>
         //    entity.Insert();
 
         //    if (XTrace.Debug) XTrace.WriteLine("完成初始化{0}[{1}]数据!", typeof(<#=Config.RenderGenEntity?"TEntity":Table.Name#>).Name, Meta.Table.DataTable.DisplayName);
         //}
-<#
-if(Table.Relations!=null && Table.Relations.Count>0)
-{
-    // 是否有一对多和一对一的扩展属性,如果有,删除
-    Boolean hasMutil=false;
-    foreach(IDataRelation dr in Table.Relations)
-    {
-        if(!dr.Unique) continue;
-
-        IDataTable rtable = FindTable(dr.RelationTable);
-        if (rtable == null) continue;
-
-        hasMutil=true;
-        break;
-    }
-    if(hasMutil)
-    {
-#>
-        /// <summary>已重载。删除关联数据</summary>
-        /// <returns></returns>
-        protected override int OnDelete()
-        {<#	
-    foreach(IDataRelation dr in Table.Relations)
-    {
-        if(!dr.Unique) continue;
-
-        IDataTable rtable = FindTable(dr.RelationTable);
-        if (rtable == null) continue;
-
-        Boolean b=dr.Unique;
-        // 如果是唯一的,应该判断对方的唯一性,如果对方也是唯一,那么就构成一对一
-        if(b&&rtable.Relations!=null)
-        {
-            foreach(IDataRelation dr2 in rtable.Relations)
-            {
-                if(dr2.Column==dr.RelationColumn && dr2.RelationTable==Table.TableName && dr2.RelationColumn==dr.Column)
-                {
-                    if(dr2.Unique) b=false;
-                }
-            }
-        }
-        String proName=rtable.Name;
-        if(b) proName+="s";
-        #>
-            if (<#=proName#> != null) <#=proName#>.Delete();<#
-    }
-#>
-
-            return base.OnDelete();
-        }<#
-    }
-}#>
 
         ///// <summary>已重载。基类先调用Valid(true)验证数据,然后在事务保护内调用OnInsert</summary>
         ///// <returns></returns>
Modified +3 -3
diff --git "a/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\346\211\251\345\261\225\346\237\245\350\257\242.xt" "b/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\346\211\251\345\261\225\346\237\245\350\257\242.xt"
index 732f777..64de702 100644
--- "a/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\346\211\251\345\261\225\346\237\245\350\257\242.xt"
+++ "b/XCoder/Template/\345\256\236\344\275\223\344\270\232\345\212\241/\346\211\251\345\261\225\346\237\245\350\257\242.xt"
@@ -11,7 +11,7 @@ if(Table.Indexes!=null&&Table.Indexes.Count>0){
         String action="Find";
         String IsAll=String.Empty;
         if (!di.Unique){
-            returnType=String.Format("EntityList<{0}>",myClassName);
+            returnType=String.Format("IList<{0}>",myClassName);
             IsAll="All";
             action="FindAll";
         }
@@ -63,14 +63,14 @@ if(Table.Indexes!=null&&Table.Indexes.Count>0){
             if (Meta.Count >= 1000)
                 return <#=action#>(new String[] { <#=sb2#> }, new Object[] { <#=sb3#> });
             else // 实体缓存
-                return Meta.Cache.Entities.<#=action#>(e => <#for(int i=0;i<columns.Length;i++){if(i>0)Write(" && ");#>e.<#=columns[i].Name#> == <#=Args[i]#><#}#>);<#
+                return Meta.Cache.FindAll(e => <#for(int i=0;i<columns.Length;i++){if(i>0)Write(" && ");#>e.<#=columns[i].Name#> == <#=Args[i]#><#}#>);<#
         }else{
             String pname=columns[0].Name;
     #>
             if (Meta.Count >= 1000)
                 return <#=action#>(__.<#=pname#>, <#=Args[0]#>);
             else // 实体缓存
-                return Meta.Cache.Entities.<#=action#>(__.<#=pname#>, <#=Args[0]#>);<#if(di.Unique){#>
+                return Meta.Cache.Find(e => e.<#=pname#> == <#=Args[0]#>);<#if(di.Unique){#>
             // 单对象缓存
             //return Meta.SingleCache[<#=Args[0]#>];<#}}#>
         }
Modified +4 -5
diff --git "a/XCoder/Template/\345\256\236\344\275\223\346\225\260\346\215\256/\344\270\255\346\226\207\345\220\215.cs" "b/XCoder/Template/\345\256\236\344\275\223\346\225\260\346\215\256/\344\270\255\346\226\207\345\220\215.cs"
index 1079c7c..6b79149 100644
--- "a/XCoder/Template/\345\256\236\344\275\223\346\225\260\346\215\256/\344\270\255\346\226\207\345\220\215.cs"
+++ "b/XCoder/Template/\345\256\236\344\275\223\346\225\260\346\215\256/\344\270\255\346\226\207\345\220\215.cs"
@@ -22,11 +22,10 @@ namespace <#=Config.NameSpace#>
 foreach(IDataIndex di in Table.Indexes){if(di.Columns==null||di.Columns.Length<1)continue;#>
     [BindIndex("<#=di.Name#>", <#=di.Unique.ToString().ToLower()#>, "<#=String.Join(",", di.Columns)#>")]<#
 }
-foreach(IDataRelation dr in Table.Relations){#>
-    [BindRelation("<#=dr.Column#>", <#=dr.Unique.ToString().ToLower()#>, "<#=dr.RelationTable#>", "<#=dr.RelationColumn#>")]<#}#>
+#>
     [BindTable("<#=Table.TableName#>", Description = "<#=tdes#>", ConnName = "<#=Table.ConnName ?? Config.EntityConnName#>", DbType = DatabaseType.<#=Table.DbType#><#if(Table.IsView){#>, IsView = true<#}#>)]<#
 if(Config.RenderGenEntity){#>
-    public abstract partial class <#=Table.Name#><TEntity> : I<#=Table.Name#><#
+    public partial class <#=Table.Name#><TEntity> : I<#=Table.Name#><#
 }else{#>
     public partial class <#=Table.Name#> : I<#=Table.Name#><#
 }#>
@@ -47,7 +46,7 @@ if(Table.Columns.Count>0)
         [DisplayName("<#=dis#>")]
         [Description("<#=des#>")]
         [DataObjectField(<#=Field.PrimaryKey.ToString().ToLower()#>, <#=Field.Identity.ToString().ToLower()#>, <#=Field.Nullable.ToString().ToLower()#>, <#=Field.Length#>)]
-        [BindColumn(<#=Field.ID#>, "<#=Field.ColumnName#>", "<#=des#>", <#=Field.Default==null?"null":"\""+Field.Default.Replace("\\", "\\\\")+"\""#>, "<#=Field.RawType#>", <#=Field.Precision#>, <#=Field.Scale#>, <#=Field.IsUnicode.ToString().ToLower()#><#if(Field.Master){#>, Master=<#=Field.Master.ToString().ToLower()#><#}#>)]
+        [BindColumn("<#=Field.ColumnName#>", "<#=des#>", "<#=Field.RawType#>"<#if(Field.Master){#>, Master=<#=Field.Master.ToString().ToLower()#><#}#>)]
         public virtual <#=Field.DataType==null?"":Field.DataType.Name#> <#=Field.Name#>
         {
             get { return _<#=Field.Name#>; }
@@ -106,7 +105,7 @@ if(Table.Columns.Count>0)
 #>
         #region 字段名
         /// <summary>取得<#=tdis#>字段信息的快捷方式</summary>
-        <#if(!Config.RenderGenEntity){#>public <#}#>partial class _
+        public partial class _
         {<#
 foreach(IDataColumn Field in Table.GetAllColumns(Tables, true))
 {
Added +47 -0
diff --git a/XCoder/Tools/FrmGPS.cs b/XCoder/Tools/FrmGPS.cs
new file mode 100644
index 0000000..f3d4fde
--- /dev/null
+++ b/XCoder/Tools/FrmGPS.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace XCoder.Tools
+{
+    public partial class FrmGPS : Form
+    {
+        public FrmGPS()
+        {
+            InitializeComponent();
+        }
+
+        private void btn_16_latlong_Click(Object sender, EventArgs e)
+        {
+            var temp = txt_16_latlong.Text.Trim();
+            var _lat = temp.Substring(0, 8);
+            var _long = temp.Substring(8);
+
+            SetText(_lat, _long);
+        }
+
+        private void btn_latlong_Click(Object sender, EventArgs e)
+        {
+            var _lat = txt_16_lat.Text.Trim();
+            var _long = txt_16_long.Text.Trim();
+
+            SetText(_lat, _long);
+        }
+
+        private void SetText(String _lat, String _long)
+        {
+            var v_lat = BitConverter.ToSingle(_lat.ToHex(), 0);
+            var v_long = BitConverter.ToSingle(_long.ToHex(), 0);
+
+            txt_lat.Text = v_lat + "";
+            txt_long.Text = v_long + "";
+            txt_latlong.Text = "{0},{1}".F(v_lat, v_long);
+        }
+    }
+}
Added +187 -0
diff --git a/XCoder/Tools/FrmGPS.Designer.cs b/XCoder/Tools/FrmGPS.Designer.cs
new file mode 100644
index 0000000..2d37bbb
--- /dev/null
+++ b/XCoder/Tools/FrmGPS.Designer.cs
@@ -0,0 +1,187 @@
+namespace XCoder.Tools
+{
+    partial class FrmGPS
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.txt_latlong = new System.Windows.Forms.TextBox();
+            this.btn_latlong = new System.Windows.Forms.Button();
+            this.txt_16_long = new System.Windows.Forms.TextBox();
+            this.txt_16_lat = new System.Windows.Forms.TextBox();
+            this.txt_long = new System.Windows.Forms.TextBox();
+            this.txt_lat = new System.Windows.Forms.TextBox();
+            this.btn_16_latlong = new System.Windows.Forms.Button();
+            this.txt_16_latlong = new System.Windows.Forms.TextBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.groupBox1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox1.Controls.Add(this.label3);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.txt_latlong);
+            this.groupBox1.Controls.Add(this.btn_latlong);
+            this.groupBox1.Controls.Add(this.txt_16_long);
+            this.groupBox1.Controls.Add(this.txt_16_lat);
+            this.groupBox1.Controls.Add(this.txt_long);
+            this.groupBox1.Controls.Add(this.txt_lat);
+            this.groupBox1.Controls.Add(this.btn_16_latlong);
+            this.groupBox1.Controls.Add(this.txt_16_latlong);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Location = new System.Drawing.Point(12, 12);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(558, 149);
+            this.groupBox1.TabIndex = 1;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "GPS HEX转坐标";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(21, 113);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(53, 12);
+            this.label3.TabIndex = 10;
+            this.label3.Text = "HEX Long";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(27, 88);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(47, 12);
+            this.label2.TabIndex = 9;
+            this.label2.Text = "HEX Lat";
+            // 
+            // txt_latlong
+            // 
+            this.txt_latlong.Location = new System.Drawing.Point(318, 94);
+            this.txt_latlong.Name = "txt_latlong";
+            this.txt_latlong.Size = new System.Drawing.Size(215, 21);
+            this.txt_latlong.TabIndex = 8;
+            // 
+            // btn_latlong
+            // 
+            this.btn_latlong.Location = new System.Drawing.Point(270, 92);
+            this.btn_latlong.Name = "btn_latlong";
+            this.btn_latlong.Size = new System.Drawing.Size(34, 23);
+            this.btn_latlong.TabIndex = 7;
+            this.btn_latlong.Text = ">>";
+            this.btn_latlong.UseVisualStyleBackColor = true;
+            this.btn_latlong.Click += new System.EventHandler(this.btn_latlong_Click);
+            // 
+            // txt_16_long
+            // 
+            this.txt_16_long.Location = new System.Drawing.Point(77, 110);
+            this.txt_16_long.Name = "txt_16_long";
+            this.txt_16_long.Size = new System.Drawing.Size(177, 21);
+            this.txt_16_long.TabIndex = 6;
+            // 
+            // txt_16_lat
+            // 
+            this.txt_16_lat.Location = new System.Drawing.Point(77, 83);
+            this.txt_16_lat.Name = "txt_16_lat";
+            this.txt_16_lat.Size = new System.Drawing.Size(177, 21);
+            this.txt_16_lat.TabIndex = 5;
+            // 
+            // txt_long
+            // 
+            this.txt_long.Location = new System.Drawing.Point(318, 49);
+            this.txt_long.Name = "txt_long";
+            this.txt_long.Size = new System.Drawing.Size(215, 21);
+            this.txt_long.TabIndex = 4;
+            // 
+            // txt_lat
+            // 
+            this.txt_lat.Location = new System.Drawing.Point(318, 22);
+            this.txt_lat.Name = "txt_lat";
+            this.txt_lat.Size = new System.Drawing.Size(215, 21);
+            this.txt_lat.TabIndex = 3;
+            // 
+            // btn_16_latlong
+            // 
+            this.btn_16_latlong.Location = new System.Drawing.Point(270, 18);
+            this.btn_16_latlong.Name = "btn_16_latlong";
+            this.btn_16_latlong.Size = new System.Drawing.Size(34, 23);
+            this.btn_16_latlong.TabIndex = 2;
+            this.btn_16_latlong.Text = ">>";
+            this.btn_16_latlong.UseVisualStyleBackColor = true;
+            this.btn_16_latlong.Click += new System.EventHandler(this.btn_16_latlong_Click);
+            // 
+            // txt_16_latlong
+            // 
+            this.txt_16_latlong.Location = new System.Drawing.Point(77, 21);
+            this.txt_16_latlong.Name = "txt_16_latlong";
+            this.txt_16_latlong.Size = new System.Drawing.Size(177, 21);
+            this.txt_16_latlong.TabIndex = 1;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(3, 25);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(71, 12);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "HEX LatLong";
+            // 
+            // FrmGPS
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(582, 172);
+            this.Controls.Add(this.groupBox1);
+            this.Name = "FrmGPS";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "GPS坐标转换";
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.TextBox txt_latlong;
+        private System.Windows.Forms.Button btn_latlong;
+        private System.Windows.Forms.TextBox txt_16_long;
+        private System.Windows.Forms.TextBox txt_16_lat;
+        private System.Windows.Forms.TextBox txt_long;
+        private System.Windows.Forms.TextBox txt_lat;
+        private System.Windows.Forms.Button btn_16_latlong;
+        private System.Windows.Forms.TextBox txt_16_latlong;
+        private System.Windows.Forms.Label label1;
+    }
+}
\ No newline at end of file
Added +120 -0
diff --git a/XCoder/Tools/FrmGPS.resx b/XCoder/Tools/FrmGPS.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/XCoder/Tools/FrmGPS.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
Added +63 -0
diff --git a/XCoder/Tools/FrmInclude.cs b/XCoder/Tools/FrmInclude.cs
new file mode 100644
index 0000000..5b72ced
--- /dev/null
+++ b/XCoder/Tools/FrmInclude.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace XCoder.Tools
+{
+    public partial class FrmInclude : Form
+    {
+        public FrmInclude()
+        {
+            InitializeComponent();
+        }
+
+        private void btn_FilePath_Click(Object sender, EventArgs e)
+        {
+            var open = new OpenFileDialog();
+            open.Filter = "项目文件|*.csproj";
+            if (open.ShowDialog() == DialogResult.OK)
+                txt_FilePath.Text = open.FileName;
+        }
+
+        private void btn_ReadFile_Click(Object sender, EventArgs e)
+        {
+            var _split = txt_Split.Text;//比对.csproj中待替换字符串
+            var _target = txt_Target.Text;//替换字符串
+
+            // Load the xml document
+            var xmlDoc = XDocument.Load(txt_FilePath.Text);
+
+            // Get the xml namespace
+            var nameSpace = xmlDoc.Root.Name.Namespace;
+            var elem = xmlDoc.Descendants(nameSpace + "Project")
+                          .Where(t => t.Attribute("ToolsVersion") != null)
+                          .Elements(nameSpace + "ItemGroup")
+                          .Elements(nameSpace + "Compile")
+                          .Where(r => r.Attribute("Include") != null);
+
+            foreach (var item in elem)
+            {
+                if (item.FirstAttribute.Value.Contains(_split))
+                {
+                    var temp = item.FirstAttribute.Value;
+                    var _next = item.Elements(nameSpace + "DependentUpon");
+                    if (_next.Count() == 0)
+                    {
+                        rtb_msg.AppendText(String.Format("{0} {1}{2}", temp, " 准备注入依赖项", "  -->  "));
+                        var _s = temp.Replace(_split, _target).Split('\\');
+                        var _value = _s[_s.Length - 1];
+                        rtb_msg.AppendText(String.Format("{0} {1}{2}", _value, " 依赖项", "  -->  "));
+                        item.SetElementValue(nameSpace + "DependentUpon", _value);
+                        xmlDoc.Save(txt_FilePath.Text);
+                        rtb_msg.AppendText(String.Format("{0} {1}{2}", temp, " 依赖项注入完毕", "\r\n"));
+                    }
+                    else
+                    {
+                        rtb_msg.AppendText(String.Format("{0} {1}{2}", temp, " 已经拥有依赖项", "\r\n"));
+                    }
+                }
+            }
+        }
+    }
+}
Added +148 -0
diff --git a/XCoder/Tools/FrmInclude.Designer.cs b/XCoder/Tools/FrmInclude.Designer.cs
new file mode 100644
index 0000000..c2f88a0
--- /dev/null
+++ b/XCoder/Tools/FrmInclude.Designer.cs
@@ -0,0 +1,148 @@
+namespace XCoder.Tools
+{
+    partial class FrmInclude
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label2 = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.txt_Target = new System.Windows.Forms.TextBox();
+            this.txt_Split = new System.Windows.Forms.TextBox();
+            this.rtb_msg = new System.Windows.Forms.RichTextBox();
+            this.btn_FilePath = new System.Windows.Forms.Button();
+            this.txt_FilePath = new System.Windows.Forms.TextBox();
+            this.btn_ReadFile = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Font = new System.Drawing.Font("微软雅黑", 7F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.label2.ForeColor = System.Drawing.Color.Red;
+            this.label2.Location = new System.Drawing.Point(20, 61);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(181, 16);
+            this.label2.TabIndex = 16;
+            this.label2.Text = "选择.csproj项目文件,然后点击按钮执行";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.label1.Location = new System.Drawing.Point(126, 41);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(35, 16);
+            this.label1.TabIndex = 15;
+            this.label1.Text = "-->";
+            // 
+            // txt_Target
+            // 
+            this.txt_Target.Location = new System.Drawing.Point(174, 39);
+            this.txt_Target.Name = "txt_Target";
+            this.txt_Target.Size = new System.Drawing.Size(100, 21);
+            this.txt_Target.TabIndex = 14;
+            this.txt_Target.Text = ".cs";
+            // 
+            // txt_Split
+            // 
+            this.txt_Split.Location = new System.Drawing.Point(20, 39);
+            this.txt_Split.Name = "txt_Split";
+            this.txt_Split.Size = new System.Drawing.Size(100, 21);
+            this.txt_Split.TabIndex = 13;
+            this.txt_Split.Text = ".Biz.cs";
+            // 
+            // rtb_msg
+            // 
+            this.rtb_msg.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.rtb_msg.Location = new System.Drawing.Point(12, 80);
+            this.rtb_msg.Name = "rtb_msg";
+            this.rtb_msg.Size = new System.Drawing.Size(404, 167);
+            this.rtb_msg.TabIndex = 12;
+            this.rtb_msg.Text = "";
+            // 
+            // btn_FilePath
+            // 
+            this.btn_FilePath.Location = new System.Drawing.Point(280, 12);
+            this.btn_FilePath.Name = "btn_FilePath";
+            this.btn_FilePath.Size = new System.Drawing.Size(33, 23);
+            this.btn_FilePath.TabIndex = 11;
+            this.btn_FilePath.Text = "...";
+            this.btn_FilePath.UseVisualStyleBackColor = true;
+            this.btn_FilePath.Click += new System.EventHandler(this.btn_FilePath_Click);
+            // 
+            // txt_FilePath
+            // 
+            this.txt_FilePath.Location = new System.Drawing.Point(20, 12);
+            this.txt_FilePath.Name = "txt_FilePath";
+            this.txt_FilePath.Size = new System.Drawing.Size(254, 21);
+            this.txt_FilePath.TabIndex = 10;
+            // 
+            // btn_ReadFile
+            // 
+            this.btn_ReadFile.Location = new System.Drawing.Point(336, 10);
+            this.btn_ReadFile.Name = "btn_ReadFile";
+            this.btn_ReadFile.Size = new System.Drawing.Size(75, 23);
+            this.btn_ReadFile.TabIndex = 9;
+            this.btn_ReadFile.Text = "依赖注入";
+            this.btn_ReadFile.UseVisualStyleBackColor = true;
+            this.btn_ReadFile.Click += new System.EventHandler(this.btn_ReadFile_Click);
+            // 
+            // FrmInclude
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(424, 250);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.txt_Target);
+            this.Controls.Add(this.txt_Split);
+            this.Controls.Add(this.rtb_msg);
+            this.Controls.Add(this.btn_FilePath);
+            this.Controls.Add(this.txt_FilePath);
+            this.Controls.Add(this.btn_ReadFile);
+            this.Name = "FrmInclude";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "xcode  csproj项目文件包含更新";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox txt_Target;
+        private System.Windows.Forms.TextBox txt_Split;
+        private System.Windows.Forms.RichTextBox rtb_msg;
+        private System.Windows.Forms.Button btn_FilePath;
+        private System.Windows.Forms.TextBox txt_FilePath;
+        private System.Windows.Forms.Button btn_ReadFile;
+    }
+}
\ No newline at end of file
Added +120 -0
diff --git a/XCoder/Tools/FrmInclude.resx b/XCoder/Tools/FrmInclude.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/XCoder/Tools/FrmInclude.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
Added +62 -0
diff --git a/XCoder/Tools/FrmMain.cs b/XCoder/Tools/FrmMain.cs
new file mode 100644
index 0000000..09ea038
--- /dev/null
+++ b/XCoder/Tools/FrmMain.cs
@@ -0,0 +1,62 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using NewLife;
+
+namespace XCoder.Tools
+{
+    [DisplayName("小工具")]
+    public partial class FrmMain : Form, IXForm
+    {
+        public FrmMain()
+        {
+            InitializeComponent();
+
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+        }
+
+        private void FrmMain_Load(Object sender, EventArgs e)
+        {
+            var frm = new FrmGPS();
+            ShowForm(frm);
+        }
+        private void btn_Include_Click(Object sender, EventArgs e)
+        {
+#if !NET4
+            var frm = new FrmInclude();
+            ShowForm(frm);
+#endif
+        }
+        private void btn_gps_Click(Object sender, EventArgs e)
+        {
+            var frm = new FrmGPS();
+            ShowForm(frm);
+        }
+        public void ShowForm(Form frm)
+        {
+            frm.TopLevel = false;
+            frm.Dock = DockStyle.Fill;
+            frm.FormBorderStyle = FormBorderStyle.None;
+
+            frm.Parent = this;
+
+            var sps = panel2.Controls;
+            foreach (var item in sps)
+            {
+                try
+                {
+                    var mm = item as Form;
+                    if (mm != null) mm.Close();
+                }
+                catch { }
+                item.TryDispose();
+            }
+            sps.Clear();
+            sps.Add(frm);
+            frm.Show();
+        }
+
+
+    }
+}
Added +98 -0
diff --git a/XCoder/Tools/FrmMain.Designer.cs b/XCoder/Tools/FrmMain.Designer.cs
new file mode 100644
index 0000000..7eaf344
--- /dev/null
+++ b/XCoder/Tools/FrmMain.Designer.cs
@@ -0,0 +1,98 @@
+namespace XCoder.Tools
+{
+    partial class FrmMain
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.btn_gps = new System.Windows.Forms.Button();
+            this.btn_Include = new System.Windows.Forms.Button();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.panel2 = new System.Windows.Forms.Panel();
+            this.panel1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btn_gps
+            // 
+            this.btn_gps.Location = new System.Drawing.Point(22, 12);
+            this.btn_gps.Name = "btn_gps";
+            this.btn_gps.Size = new System.Drawing.Size(75, 23);
+            this.btn_gps.TabIndex = 1;
+            this.btn_gps.Text = "GPS坐标转换";
+            this.btn_gps.UseVisualStyleBackColor = true;
+            this.btn_gps.Click += new System.EventHandler(this.btn_gps_Click);
+            // 
+            // btn_Include
+            // 
+            this.btn_Include.Location = new System.Drawing.Point(131, 11);
+            this.btn_Include.Name = "btn_Include";
+            this.btn_Include.Size = new System.Drawing.Size(101, 23);
+            this.btn_Include.TabIndex = 2;
+            this.btn_Include.Text = "Xcode实体包含";
+            this.btn_Include.UseVisualStyleBackColor = true;
+            this.btn_Include.Click += new System.EventHandler(this.btn_Include_Click);
+            // 
+            // panel1
+            // 
+            this.panel1.Controls.Add(this.btn_Include);
+            this.panel1.Controls.Add(this.btn_gps);
+            this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
+            this.panel1.Location = new System.Drawing.Point(0, 0);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(674, 47);
+            this.panel1.TabIndex = 3;
+            // 
+            // panel2
+            // 
+            this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.panel2.Location = new System.Drawing.Point(0, 47);
+            this.panel2.Name = "panel2";
+            this.panel2.Size = new System.Drawing.Size(674, 422);
+            this.panel2.TabIndex = 4;
+            // 
+            // FrmMain
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(674, 469);
+            this.Controls.Add(this.panel2);
+            this.Controls.Add(this.panel1);
+            this.Name = "FrmMain";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "小工具";
+            this.Load += new System.EventHandler(this.FrmMain_Load);
+            this.panel1.ResumeLayout(false);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+        private System.Windows.Forms.Button btn_gps;
+        private System.Windows.Forms.Button btn_Include;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Panel panel2;
+    }
+}
\ No newline at end of file
Added +120 -0
diff --git a/XCoder/Tools/FrmMain.resx b/XCoder/Tools/FrmMain.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/XCoder/Tools/FrmMain.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
Added +343 -0
diff --git a/XCoder/Tools/FrmSecurity.cs b/XCoder/Tools/FrmSecurity.cs
new file mode 100644
index 0000000..a8b1a95
--- /dev/null
+++ b/XCoder/Tools/FrmSecurity.cs
@@ -0,0 +1,343 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Web;
+using System.Windows.Forms;
+using NewLife.Security;
+
+namespace XCoder.Tools
+{
+    [DisplayName("加密解密")]
+    public partial class FrmSecurity : Form, IXForm
+    {
+        public FrmSecurity()
+        {
+            InitializeComponent();
+
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+        }
+
+        #region 辅助
+        /// <summary>从字符串中获取字节数组</summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        private Byte[] GetBytes(String str)
+        {
+            if (str.IsNullOrEmpty()) return new Byte[0];
+
+            try
+            {
+                return str.ToHex();
+            }
+            catch { }
+
+            try
+            {
+                return str.ToBase64();
+            }
+            catch { }
+
+            return str.GetBytes();
+        }
+
+        /// <summary>从原文中获取字节数组</summary>
+        /// <returns></returns>
+        private Byte[] GetBytes()
+        {
+            var v = rtSource.Text;
+            return GetBytes(v);
+        }
+
+        private void SetResult(params String[] rs)
+        {
+            var sb = new StringBuilder();
+            foreach (var item in rs)
+            {
+                if (sb.Length > 0)
+                {
+                    sb.AppendLine();
+                    sb.AppendLine();
+                }
+                sb.Append(item);
+            }
+            rtResult.Text = sb.ToString();
+        }
+
+        private void SetResult(Byte[] data)
+        {
+            SetResult("/*HEX编码、Base64编码、Url改进Base64编码*/", data.ToHex(), data.ToBase64(), data.ToUrlBase64());
+        }
+
+        private void SetResult2(Byte[] data)
+        {
+            SetResult("/*字符串、HEX编码、Base64编码*/", data.ToStr(), data.ToHex(), data.ToBase64());
+        }
+        #endregion
+
+        private void btnExchange_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            var v2 = rtResult.Text;
+            // 结果区只要第一行
+            if (!v2.IsNullOrEmpty())
+            {
+                var ss = v2.Split("\n");
+                var n = 0;
+                if (ss.Length > n + 1 && ss[n].StartsWith("/*") && ss[n].EndsWith("*/")) n++;
+                v2 = ss[n];
+            }
+            rtSource.Text = v2;
+            rtResult.Text = v;
+        }
+
+        private void btnHex_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            //rtResult.Text = buf.ToHex(" ", 32);
+            SetResult(buf.ToHex(), buf.ToHex(" ", 32), buf.ToHex("-", 32));
+        }
+
+        private void btnHex2_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            rtResult.Text = v.ToHex().ToStr();
+        }
+
+        private void btnB64_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            //rtResult.Text = buf.ToBase64();
+            SetResult(buf.ToBase64(), buf.ToUrlBase64());
+        }
+
+        private void btnB642_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            //rtResult.Text = v.ToBase64().ToStr();
+            var buf = v.ToBase64();
+            //rtResult.Text = buf.ToStr() + Environment.NewLine + buf.ToHex();
+            SetResult(buf.ToStr(), buf.ToHex());
+        }
+
+        private void btnMD5_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var str = buf.MD5().ToHex();
+            rtResult.Text = str.ToUpper() + Environment.NewLine + str.ToLower();
+        }
+
+        private void btnMD52_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var str = buf.MD5().ToHex(0, 8);
+            rtResult.Text = str.ToUpper() + Environment.NewLine + str.ToLower();
+        }
+
+        private void btnSHA1_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var key = GetBytes(rtPass.Text);
+
+            buf = buf.SHA1(key);
+            SetResult(buf);
+        }
+
+        private void btnSHA256_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var key = GetBytes(rtPass.Text);
+
+            buf = buf.SHA256(key);
+            SetResult(buf);
+        }
+
+        private void btnSHA384_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var key = GetBytes(rtPass.Text);
+
+            buf = buf.SHA384(key);
+            SetResult(buf);
+        }
+
+        private void btnSHA512_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var key = GetBytes(rtPass.Text);
+
+            buf = buf.SHA512(key);
+            SetResult(buf);
+        }
+
+        private void btnCRC_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            rtResult.Text = "{0:X8}\r\n{0}".F(buf.Crc());
+        }
+
+        private void btnCRC2_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            rtResult.Text = "{0:X4}\r\n{0}".F(buf.Crc16());
+        }
+
+        private void btnDES_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = GetBytes(rtPass.Text);
+
+            var des = new DESCryptoServiceProvider();
+            buf = des.Encrypt(buf, pass);
+
+            SetResult(buf);
+        }
+
+        private void btnDES2_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = GetBytes(rtPass.Text);
+
+            var des = new DESCryptoServiceProvider();
+            buf = des.Descrypt(buf, pass);
+
+            SetResult2(buf);
+        }
+
+        private void btnAES_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = GetBytes(rtPass.Text);
+
+            var aes = new AesCryptoServiceProvider();
+            buf = aes.Encrypt(buf, pass);
+
+            SetResult(buf);
+        }
+
+        private void btnAES2_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = GetBytes(rtPass.Text);
+
+            var aes = new AesCryptoServiceProvider();
+            buf = aes.Descrypt(buf, pass);
+
+            SetResult2(buf);
+        }
+
+        private void btnRC4_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = GetBytes(rtPass.Text);
+            buf = buf.RC4(pass);
+
+            SetResult(buf);
+        }
+
+        private void btnRC42_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = GetBytes(rtPass.Text);
+            buf = buf.RC4(pass);
+
+            SetResult2(buf);
+        }
+
+        private void btnRSA_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var key = rtPass.Text;
+
+            if (key.Length < 100)
+            {
+                key = RSAHelper.GenerateKey().First();
+                rtPass.Text = key;
+            }
+
+            buf = RSAHelper.Encrypt(buf, key);
+
+            SetResult(buf);
+        }
+
+        private void btnRSA2_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = rtPass.Text;
+
+            try
+            {
+                buf = RSAHelper.Decrypt(buf, pass, true);
+            }
+            catch (CryptographicException)
+            {
+                // 换一种填充方式
+                buf = RSAHelper.Decrypt(buf, pass, false);
+            }
+
+            SetResult2(buf);
+        }
+
+        private void btnDSA_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var key = rtPass.Text;
+
+            if (key.Length < 100)
+            {
+                key = DSAHelper.GenerateKey().First();
+                rtPass.Text = key;
+            }
+
+            buf = DSAHelper.Sign(buf, key);
+
+            SetResult(buf);
+        }
+
+        private void btnDSA2_Click(Object sender, EventArgs e)
+        {
+            var buf = GetBytes();
+            var pass = rtPass.Text;
+
+            var v = rtResult.Text;
+            if (v.Contains("\n\n")) v = v.Substring(null, "\n\n");
+            var sign = GetBytes(v);
+
+            var rs = DSAHelper.Verify(buf, pass, sign);
+            if (rs)
+                MessageBox.Show("验证通过", "DSA数字签名", MessageBoxButtons.OK, MessageBoxIcon.Information);
+            else
+                MessageBox.Show("验证失败", "DSA数字签名", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        }
+
+        private void btnUrl_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            v = HttpUtility.UrlEncode(v);
+            rtResult.Text = v;
+        }
+
+        private void btnUrl2_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            v = HttpUtility.UrlDecode(v);
+            rtResult.Text = v;
+        }
+
+        private void btnHtml_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            v = HttpUtility.HtmlEncode(v);
+            rtResult.Text = v;
+        }
+
+        private void btnHtml2_Click(Object sender, EventArgs e)
+        {
+            var v = rtSource.Text;
+            v = HttpUtility.HtmlDecode(v);
+            rtResult.Text = v;
+        }
+    }
+}
\ No newline at end of file
Added +542 -0
diff --git a/XCoder/Tools/FrmSecurity.Designer.cs b/XCoder/Tools/FrmSecurity.Designer.cs
new file mode 100644
index 0000000..8be178e
--- /dev/null
+++ b/XCoder/Tools/FrmSecurity.Designer.cs
@@ -0,0 +1,542 @@
+namespace XCoder.Tools
+{
+    partial class FrmSecurity
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.gbFunc = new System.Windows.Forms.GroupBox();
+            this.btnHtml2 = new System.Windows.Forms.Button();
+            this.btnHtml = new System.Windows.Forms.Button();
+            this.btnUrl2 = new System.Windows.Forms.Button();
+            this.btnUrl = new System.Windows.Forms.Button();
+            this.btnDSA2 = new System.Windows.Forms.Button();
+            this.btnDSA = new System.Windows.Forms.Button();
+            this.btnRSA2 = new System.Windows.Forms.Button();
+            this.btnRSA = new System.Windows.Forms.Button();
+            this.btnRC42 = new System.Windows.Forms.Button();
+            this.btnRC4 = new System.Windows.Forms.Button();
+            this.btnAES2 = new System.Windows.Forms.Button();
+            this.btnAES = new System.Windows.Forms.Button();
+            this.btnDES2 = new System.Windows.Forms.Button();
+            this.btnDES = new System.Windows.Forms.Button();
+            this.btnCRC2 = new System.Windows.Forms.Button();
+            this.btnCRC = new System.Windows.Forms.Button();
+            this.btnMD52 = new System.Windows.Forms.Button();
+            this.btnMD5 = new System.Windows.Forms.Button();
+            this.btnB642 = new System.Windows.Forms.Button();
+            this.btnB64 = new System.Windows.Forms.Button();
+            this.btnHex2 = new System.Windows.Forms.Button();
+            this.btnHex = new System.Windows.Forms.Button();
+            this.gbSource = new System.Windows.Forms.GroupBox();
+            this.rtSource = new System.Windows.Forms.RichTextBox();
+            this.gbResult = new System.Windows.Forms.GroupBox();
+            this.rtResult = new System.Windows.Forms.RichTextBox();
+            this.gbPass = new System.Windows.Forms.GroupBox();
+            this.rtPass = new System.Windows.Forms.RichTextBox();
+            this.btnExchange = new System.Windows.Forms.Button();
+            this.btnSHA256 = new System.Windows.Forms.Button();
+            this.btnSHA1 = new System.Windows.Forms.Button();
+            this.btnSHA512 = new System.Windows.Forms.Button();
+            this.btnSHA384 = new System.Windows.Forms.Button();
+            this.gbFunc.SuspendLayout();
+            this.gbSource.SuspendLayout();
+            this.gbResult.SuspendLayout();
+            this.gbPass.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // gbFunc
+            // 
+            this.gbFunc.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left)));
+            this.gbFunc.Controls.Add(this.btnSHA512);
+            this.gbFunc.Controls.Add(this.btnSHA384);
+            this.gbFunc.Controls.Add(this.btnSHA256);
+            this.gbFunc.Controls.Add(this.btnSHA1);
+            this.gbFunc.Controls.Add(this.btnHtml2);
+            this.gbFunc.Controls.Add(this.btnHtml);
+            this.gbFunc.Controls.Add(this.btnUrl2);
+            this.gbFunc.Controls.Add(this.btnUrl);
+            this.gbFunc.Controls.Add(this.btnDSA2);
+            this.gbFunc.Controls.Add(this.btnDSA);
+            this.gbFunc.Controls.Add(this.btnRSA2);
+            this.gbFunc.Controls.Add(this.btnRSA);
+            this.gbFunc.Controls.Add(this.btnRC42);
+            this.gbFunc.Controls.Add(this.btnRC4);
+            this.gbFunc.Controls.Add(this.btnAES2);
+            this.gbFunc.Controls.Add(this.btnAES);
+            this.gbFunc.Controls.Add(this.btnDES2);
+            this.gbFunc.Controls.Add(this.btnDES);
+            this.gbFunc.Controls.Add(this.btnCRC2);
+            this.gbFunc.Controls.Add(this.btnCRC);
+            this.gbFunc.Controls.Add(this.btnMD52);
+            this.gbFunc.Controls.Add(this.btnMD5);
+            this.gbFunc.Controls.Add(this.btnB642);
+            this.gbFunc.Controls.Add(this.btnB64);
+            this.gbFunc.Controls.Add(this.btnHex2);
+            this.gbFunc.Controls.Add(this.btnHex);
+            this.gbFunc.Location = new System.Drawing.Point(24, 24);
+            this.gbFunc.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbFunc.Name = "gbFunc";
+            this.gbFunc.Padding = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbFunc.Size = new System.Drawing.Size(344, 1210);
+            this.gbFunc.TabIndex = 0;
+            this.gbFunc.TabStop = false;
+            this.gbFunc.Text = "加密解密";
+            // 
+            // btnHtml2
+            // 
+            this.btnHtml2.Location = new System.Drawing.Point(174, 880);
+            this.btnHtml2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnHtml2.Name = "btnHtml2";
+            this.btnHtml2.Size = new System.Drawing.Size(150, 60);
+            this.btnHtml2.TabIndex = 21;
+            this.btnHtml2.Text = "Html解码";
+            this.btnHtml2.UseVisualStyleBackColor = true;
+            this.btnHtml2.Click += new System.EventHandler(this.btnHtml2_Click);
+            // 
+            // btnHtml
+            // 
+            this.btnHtml.Location = new System.Drawing.Point(12, 880);
+            this.btnHtml.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnHtml.Name = "btnHtml";
+            this.btnHtml.Size = new System.Drawing.Size(150, 60);
+            this.btnHtml.TabIndex = 20;
+            this.btnHtml.Text = "Html编码";
+            this.btnHtml.UseVisualStyleBackColor = true;
+            this.btnHtml.Click += new System.EventHandler(this.btnHtml_Click);
+            // 
+            // btnUrl2
+            // 
+            this.btnUrl2.Location = new System.Drawing.Point(174, 810);
+            this.btnUrl2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnUrl2.Name = "btnUrl2";
+            this.btnUrl2.Size = new System.Drawing.Size(150, 60);
+            this.btnUrl2.TabIndex = 19;
+            this.btnUrl2.Text = "Url解码";
+            this.btnUrl2.UseVisualStyleBackColor = true;
+            this.btnUrl2.Click += new System.EventHandler(this.btnUrl2_Click);
+            // 
+            // btnUrl
+            // 
+            this.btnUrl.Location = new System.Drawing.Point(12, 810);
+            this.btnUrl.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnUrl.Name = "btnUrl";
+            this.btnUrl.Size = new System.Drawing.Size(150, 60);
+            this.btnUrl.TabIndex = 18;
+            this.btnUrl.Text = "Url编码";
+            this.btnUrl.UseVisualStyleBackColor = true;
+            this.btnUrl.Click += new System.EventHandler(this.btnUrl_Click);
+            // 
+            // btnDSA2
+            // 
+            this.btnDSA2.Location = new System.Drawing.Point(174, 740);
+            this.btnDSA2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnDSA2.Name = "btnDSA2";
+            this.btnDSA2.Size = new System.Drawing.Size(150, 60);
+            this.btnDSA2.TabIndex = 17;
+            this.btnDSA2.Text = "DSA验证";
+            this.btnDSA2.UseVisualStyleBackColor = true;
+            this.btnDSA2.Click += new System.EventHandler(this.btnDSA2_Click);
+            // 
+            // btnDSA
+            // 
+            this.btnDSA.Location = new System.Drawing.Point(12, 740);
+            this.btnDSA.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnDSA.Name = "btnDSA";
+            this.btnDSA.Size = new System.Drawing.Size(150, 60);
+            this.btnDSA.TabIndex = 16;
+            this.btnDSA.Text = "DSA签名";
+            this.btnDSA.UseVisualStyleBackColor = true;
+            this.btnDSA.Click += new System.EventHandler(this.btnDSA_Click);
+            // 
+            // btnRSA2
+            // 
+            this.btnRSA2.Location = new System.Drawing.Point(174, 670);
+            this.btnRSA2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnRSA2.Name = "btnRSA2";
+            this.btnRSA2.Size = new System.Drawing.Size(150, 60);
+            this.btnRSA2.TabIndex = 15;
+            this.btnRSA2.Text = "RSA解密";
+            this.btnRSA2.UseVisualStyleBackColor = true;
+            this.btnRSA2.Click += new System.EventHandler(this.btnRSA2_Click);
+            // 
+            // btnRSA
+            // 
+            this.btnRSA.Location = new System.Drawing.Point(12, 670);
+            this.btnRSA.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnRSA.Name = "btnRSA";
+            this.btnRSA.Size = new System.Drawing.Size(150, 60);
+            this.btnRSA.TabIndex = 14;
+            this.btnRSA.Text = "RSA加密";
+            this.btnRSA.UseVisualStyleBackColor = true;
+            this.btnRSA.Click += new System.EventHandler(this.btnRSA_Click);
+            // 
+            // btnRC42
+            // 
+            this.btnRC42.Location = new System.Drawing.Point(174, 600);
+            this.btnRC42.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnRC42.Name = "btnRC42";
+            this.btnRC42.Size = new System.Drawing.Size(150, 60);
+            this.btnRC42.TabIndex = 13;
+            this.btnRC42.Text = "RC4解密";
+            this.btnRC42.UseVisualStyleBackColor = true;
+            this.btnRC42.Click += new System.EventHandler(this.btnRC42_Click);
+            // 
+            // btnRC4
+            // 
+            this.btnRC4.Location = new System.Drawing.Point(12, 600);
+            this.btnRC4.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnRC4.Name = "btnRC4";
+            this.btnRC4.Size = new System.Drawing.Size(150, 60);
+            this.btnRC4.TabIndex = 12;
+            this.btnRC4.Text = "RC4加密";
+            this.btnRC4.UseVisualStyleBackColor = true;
+            this.btnRC4.Click += new System.EventHandler(this.btnRC4_Click);
+            // 
+            // btnAES2
+            // 
+            this.btnAES2.Location = new System.Drawing.Point(174, 530);
+            this.btnAES2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnAES2.Name = "btnAES2";
+            this.btnAES2.Size = new System.Drawing.Size(150, 60);
+            this.btnAES2.TabIndex = 11;
+            this.btnAES2.Text = "AES解密";
+            this.btnAES2.UseVisualStyleBackColor = true;
+            this.btnAES2.Click += new System.EventHandler(this.btnAES2_Click);
+            // 
+            // btnAES
+            // 
+            this.btnAES.Location = new System.Drawing.Point(12, 530);
+            this.btnAES.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnAES.Name = "btnAES";
+            this.btnAES.Size = new System.Drawing.Size(150, 60);
+            this.btnAES.TabIndex = 10;
+            this.btnAES.Text = "AES加密";
+            this.btnAES.UseVisualStyleBackColor = true;
+            this.btnAES.Click += new System.EventHandler(this.btnAES_Click);
+            // 
+            // btnDES2
+            // 
+            this.btnDES2.Location = new System.Drawing.Point(174, 460);
+            this.btnDES2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnDES2.Name = "btnDES2";
+            this.btnDES2.Size = new System.Drawing.Size(150, 60);
+            this.btnDES2.TabIndex = 9;
+            this.btnDES2.Text = "DES解密";
+            this.btnDES2.UseVisualStyleBackColor = true;
+            this.btnDES2.Click += new System.EventHandler(this.btnDES2_Click);
+            // 
+            // btnDES
+            // 
+            this.btnDES.Location = new System.Drawing.Point(12, 460);
+            this.btnDES.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnDES.Name = "btnDES";
+            this.btnDES.Size = new System.Drawing.Size(150, 60);
+            this.btnDES.TabIndex = 8;
+            this.btnDES.Text = "DES加密";
+            this.btnDES.UseVisualStyleBackColor = true;
+            this.btnDES.Click += new System.EventHandler(this.btnDES_Click);
+            // 
+            // btnCRC2
+            // 
+            this.btnCRC2.Location = new System.Drawing.Point(174, 390);
+            this.btnCRC2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnCRC2.Name = "btnCRC2";
+            this.btnCRC2.Size = new System.Drawing.Size(150, 60);
+            this.btnCRC2.TabIndex = 7;
+            this.btnCRC2.Text = "CRC_16";
+            this.btnCRC2.UseVisualStyleBackColor = true;
+            this.btnCRC2.Click += new System.EventHandler(this.btnCRC2_Click);
+            // 
+            // btnCRC
+            // 
+            this.btnCRC.Location = new System.Drawing.Point(12, 390);
+            this.btnCRC.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnCRC.Name = "btnCRC";
+            this.btnCRC.Size = new System.Drawing.Size(150, 60);
+            this.btnCRC.TabIndex = 6;
+            this.btnCRC.Text = "CRC_32";
+            this.btnCRC.UseVisualStyleBackColor = true;
+            this.btnCRC.Click += new System.EventHandler(this.btnCRC_Click);
+            // 
+            // btnMD52
+            // 
+            this.btnMD52.Location = new System.Drawing.Point(174, 180);
+            this.btnMD52.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnMD52.Name = "btnMD52";
+            this.btnMD52.Size = new System.Drawing.Size(150, 60);
+            this.btnMD52.TabIndex = 5;
+            this.btnMD52.Text = "MD5_16";
+            this.btnMD52.UseVisualStyleBackColor = true;
+            this.btnMD52.Click += new System.EventHandler(this.btnMD52_Click);
+            // 
+            // btnMD5
+            // 
+            this.btnMD5.Location = new System.Drawing.Point(12, 180);
+            this.btnMD5.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnMD5.Name = "btnMD5";
+            this.btnMD5.Size = new System.Drawing.Size(150, 60);
+            this.btnMD5.TabIndex = 4;
+            this.btnMD5.Text = "MD5_32";
+            this.btnMD5.UseVisualStyleBackColor = true;
+            this.btnMD5.Click += new System.EventHandler(this.btnMD5_Click);
+            // 
+            // btnB642
+            // 
+            this.btnB642.Location = new System.Drawing.Point(174, 110);
+            this.btnB642.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnB642.Name = "btnB642";
+            this.btnB642.Size = new System.Drawing.Size(150, 60);
+            this.btnB642.TabIndex = 3;
+            this.btnB642.Text = "Base64解码";
+            this.btnB642.UseVisualStyleBackColor = true;
+            this.btnB642.Click += new System.EventHandler(this.btnB642_Click);
+            // 
+            // btnB64
+            // 
+            this.btnB64.Location = new System.Drawing.Point(12, 110);
+            this.btnB64.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnB64.Name = "btnB64";
+            this.btnB64.Size = new System.Drawing.Size(150, 60);
+            this.btnB64.TabIndex = 2;
+            this.btnB64.Text = "Base64编码";
+            this.btnB64.UseVisualStyleBackColor = true;
+            this.btnB64.Click += new System.EventHandler(this.btnB64_Click);
+            // 
+            // btnHex2
+            // 
+            this.btnHex2.Location = new System.Drawing.Point(174, 40);
+            this.btnHex2.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnHex2.Name = "btnHex2";
+            this.btnHex2.Size = new System.Drawing.Size(150, 60);
+            this.btnHex2.TabIndex = 1;
+            this.btnHex2.Text = "HEX解码";
+            this.btnHex2.UseVisualStyleBackColor = true;
+            this.btnHex2.Click += new System.EventHandler(this.btnHex2_Click);
+            // 
+            // btnHex
+            // 
+            this.btnHex.Location = new System.Drawing.Point(12, 40);
+            this.btnHex.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnHex.Name = "btnHex";
+            this.btnHex.Size = new System.Drawing.Size(150, 60);
+            this.btnHex.TabIndex = 0;
+            this.btnHex.Text = "HEX编码";
+            this.btnHex.UseVisualStyleBackColor = true;
+            this.btnHex.Click += new System.EventHandler(this.btnHex_Click);
+            // 
+            // gbSource
+            // 
+            this.gbSource.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbSource.Controls.Add(this.rtSource);
+            this.gbSource.Location = new System.Drawing.Point(380, 24);
+            this.gbSource.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbSource.Name = "gbSource";
+            this.gbSource.Padding = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbSource.Size = new System.Drawing.Size(1342, 500);
+            this.gbSource.TabIndex = 3;
+            this.gbSource.TabStop = false;
+            this.gbSource.Text = "原文";
+            // 
+            // rtSource
+            // 
+            this.rtSource.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rtSource.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.rtSource.Location = new System.Drawing.Point(6, 34);
+            this.rtSource.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.rtSource.Name = "rtSource";
+            this.rtSource.Size = new System.Drawing.Size(1330, 460);
+            this.rtSource.TabIndex = 2;
+            this.rtSource.Text = "学无先后达者为师";
+            // 
+            // gbResult
+            // 
+            this.gbResult.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbResult.Controls.Add(this.rtResult);
+            this.gbResult.Location = new System.Drawing.Point(380, 736);
+            this.gbResult.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbResult.Name = "gbResult";
+            this.gbResult.Padding = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbResult.Size = new System.Drawing.Size(1342, 500);
+            this.gbResult.TabIndex = 4;
+            this.gbResult.TabStop = false;
+            this.gbResult.Text = "结果";
+            // 
+            // rtResult
+            // 
+            this.rtResult.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rtResult.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.rtResult.Location = new System.Drawing.Point(6, 34);
+            this.rtResult.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.rtResult.Name = "rtResult";
+            this.rtResult.Size = new System.Drawing.Size(1330, 460);
+            this.rtResult.TabIndex = 2;
+            this.rtResult.Text = "";
+            // 
+            // gbPass
+            // 
+            this.gbPass.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbPass.Controls.Add(this.rtPass);
+            this.gbPass.Location = new System.Drawing.Point(380, 530);
+            this.gbPass.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbPass.Name = "gbPass";
+            this.gbPass.Padding = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.gbPass.Size = new System.Drawing.Size(1192, 200);
+            this.gbPass.TabIndex = 5;
+            this.gbPass.TabStop = false;
+            this.gbPass.Text = "密码";
+            // 
+            // rtPass
+            // 
+            this.rtPass.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rtPass.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.rtPass.Location = new System.Drawing.Point(6, 34);
+            this.rtPass.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.rtPass.Name = "rtPass";
+            this.rtPass.Size = new System.Drawing.Size(1180, 160);
+            this.rtPass.TabIndex = 2;
+            this.rtPass.Text = "NewLife";
+            // 
+            // btnExchange
+            // 
+            this.btnExchange.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnExchange.Location = new System.Drawing.Point(1578, 612);
+            this.btnExchange.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.btnExchange.Name = "btnExchange";
+            this.btnExchange.Size = new System.Drawing.Size(138, 68);
+            this.btnExchange.TabIndex = 6;
+            this.btnExchange.Text = "上下互换";
+            this.btnExchange.UseVisualStyleBackColor = true;
+            this.btnExchange.Click += new System.EventHandler(this.btnExchange_Click);
+            // 
+            // btnSHA256
+            // 
+            this.btnSHA256.Location = new System.Drawing.Point(174, 250);
+            this.btnSHA256.Margin = new System.Windows.Forms.Padding(6);
+            this.btnSHA256.Name = "btnSHA256";
+            this.btnSHA256.Size = new System.Drawing.Size(150, 60);
+            this.btnSHA256.TabIndex = 23;
+            this.btnSHA256.Text = "SHA256";
+            this.btnSHA256.UseVisualStyleBackColor = true;
+            this.btnSHA256.Click += new System.EventHandler(this.btnSHA256_Click);
+            // 
+            // btnSHA1
+            // 
+            this.btnSHA1.Location = new System.Drawing.Point(12, 250);
+            this.btnSHA1.Margin = new System.Windows.Forms.Padding(6);
+            this.btnSHA1.Name = "btnSHA1";
+            this.btnSHA1.Size = new System.Drawing.Size(150, 60);
+            this.btnSHA1.TabIndex = 22;
+            this.btnSHA1.Text = "SHA1";
+            this.btnSHA1.UseVisualStyleBackColor = true;
+            this.btnSHA1.Click += new System.EventHandler(this.btnSHA1_Click);
+            // 
+            // btnSHA512
+            // 
+            this.btnSHA512.Location = new System.Drawing.Point(174, 320);
+            this.btnSHA512.Margin = new System.Windows.Forms.Padding(6);
+            this.btnSHA512.Name = "btnSHA512";
+            this.btnSHA512.Size = new System.Drawing.Size(150, 60);
+            this.btnSHA512.TabIndex = 25;
+            this.btnSHA512.Text = "SHA512";
+            this.btnSHA512.UseVisualStyleBackColor = true;
+            this.btnSHA512.Click += new System.EventHandler(this.btnSHA512_Click);
+            // 
+            // btnSHA384
+            // 
+            this.btnSHA384.Location = new System.Drawing.Point(12, 320);
+            this.btnSHA384.Margin = new System.Windows.Forms.Padding(6);
+            this.btnSHA384.Name = "btnSHA384";
+            this.btnSHA384.Size = new System.Drawing.Size(150, 60);
+            this.btnSHA384.TabIndex = 24;
+            this.btnSHA384.Text = "SHA384";
+            this.btnSHA384.UseVisualStyleBackColor = true;
+            this.btnSHA384.Click += new System.EventHandler(this.btnSHA384_Click);
+            // 
+            // FrmSecurity
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 24F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(1738, 1258);
+            this.Controls.Add(this.btnExchange);
+            this.Controls.Add(this.gbPass);
+            this.Controls.Add(this.gbResult);
+            this.Controls.Add(this.gbSource);
+            this.Controls.Add(this.gbFunc);
+            this.Margin = new System.Windows.Forms.Padding(6, 6, 6, 6);
+            this.Name = "FrmSecurity";
+            this.Text = "加密解密";
+            this.gbFunc.ResumeLayout(false);
+            this.gbSource.ResumeLayout(false);
+            this.gbResult.ResumeLayout(false);
+            this.gbPass.ResumeLayout(false);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbFunc;
+        private System.Windows.Forms.GroupBox gbSource;
+        private System.Windows.Forms.RichTextBox rtSource;
+        private System.Windows.Forms.GroupBox gbResult;
+        private System.Windows.Forms.RichTextBox rtResult;
+        private System.Windows.Forms.Button btnHex2;
+        private System.Windows.Forms.Button btnHex;
+        private System.Windows.Forms.Button btnB642;
+        private System.Windows.Forms.Button btnB64;
+        private System.Windows.Forms.Button btnMD52;
+        private System.Windows.Forms.Button btnMD5;
+        private System.Windows.Forms.Button btnCRC2;
+        private System.Windows.Forms.Button btnCRC;
+        private System.Windows.Forms.Button btnHtml2;
+        private System.Windows.Forms.Button btnHtml;
+        private System.Windows.Forms.Button btnUrl2;
+        private System.Windows.Forms.Button btnUrl;
+        private System.Windows.Forms.Button btnDSA2;
+        private System.Windows.Forms.Button btnDSA;
+        private System.Windows.Forms.Button btnRSA2;
+        private System.Windows.Forms.Button btnRSA;
+        private System.Windows.Forms.Button btnRC42;
+        private System.Windows.Forms.Button btnRC4;
+        private System.Windows.Forms.Button btnAES2;
+        private System.Windows.Forms.Button btnAES;
+        private System.Windows.Forms.Button btnDES2;
+        private System.Windows.Forms.Button btnDES;
+        private System.Windows.Forms.GroupBox gbPass;
+        private System.Windows.Forms.RichTextBox rtPass;
+        private System.Windows.Forms.Button btnExchange;
+        private System.Windows.Forms.Button btnSHA512;
+        private System.Windows.Forms.Button btnSHA384;
+        private System.Windows.Forms.Button btnSHA256;
+        private System.Windows.Forms.Button btnSHA1;
+    }
+}
\ No newline at end of file
Added +120 -0
diff --git a/XCoder/Tools/FrmSecurity.resx b/XCoder/Tools/FrmSecurity.resx
new file mode 100644
index 0000000..29dcb1b
--- /dev/null
+++ b/XCoder/Tools/FrmSecurity.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
Modified +3 -1
diff --git a/XCoder/UpdateInfo.txt b/XCoder/UpdateInfo.txt
index e77dec7..49a7da2 100644
--- a/XCoder/UpdateInfo.txt
+++ b/XCoder/UpdateInfo.txt
@@ -1,4 +1,6 @@
-v6.8.2016.0504   增加操作语音提示和语音识别辅助操作
+v6.9.2017.0101   增加消息调试工具,支持调试网络库的消息收发功能
+
+v6.8.2016.0504   增加操作语音提示和语音识别辅助操作
 
 v6.7.2016.0418   异步加载子工具,支持外部FrmMain窗体
 
Modified +11 -11
diff --git a/XCoder/Windows/FrmItems.cs b/XCoder/Windows/FrmItems.cs
index dec9a67..acfdfa7 100644
--- a/XCoder/Windows/FrmItems.cs
+++ b/XCoder/Windows/FrmItems.cs
@@ -37,9 +37,9 @@ namespace XCoder
         /// <summary>初始化界面</summary>
         /// <param name="dic"></param>
         /// <returns></returns>
-        public static FrmItems Create(Dictionary<string, string> dic)
+        public static FrmItems Create(Dictionary<String, String> dic)
         {
-            FrmItems item = new FrmItems();
+            var item = new FrmItems();
 
             if (dic == null) item.CreatDic();
             else
@@ -53,7 +53,7 @@ namespace XCoder
         /// <returns></returns>
         public static FrmItems Create(ModelConfig xconfig)
         {
-            FrmItems item = new FrmItems();
+            var item = new FrmItems();
 
             if (xconfig == null) throw new Exception("配置信息异常");
 
@@ -69,7 +69,7 @@ namespace XCoder
         /// <summary>初始化字典</summary>
         private void CreatDic()
         {
-            Dictionary<string, string> dic = new Dictionary<string, string>();
+            var dic = new Dictionary<String, String>();
             dic.Add("key", "value");
             Dic = dic;
 
@@ -79,15 +79,15 @@ namespace XCoder
 
         #region 加载
         //加载
-        void SetDic(Dictionary<string, string> dic)
+        void SetDic(Dictionary<String, String> dic)
         {
-            DataGridViewColumnCollection columns = dataGridView1.Columns;
+            var columns = dataGridView1.Columns;
             columns.Add("key", "键");
             columns.Add("value", "值");
 
             foreach (var item in dic)
             {
-                DataGridViewRowCollection rows = dataGridView1.Rows;
+                var rows = dataGridView1.Rows;
                 rows.Add(item.Key, item.Value);
             }
         }
@@ -106,7 +106,7 @@ namespace XCoder
             var rows = dataGridView1.Rows;
             var column = dataGridView1.Columns;
 
-            for (int i = 0; i < rows.Count-1; i++)
+            for (var i = 0; i < rows.Count-1; i++)
             {
                 XConfig.Items.Add(rows[i].Cells[0].Value.ToString(), rows[i].Cells[1].Value.ToString());
             }
@@ -122,12 +122,12 @@ namespace XCoder
 
         #endregion
 
-        private void FrmItems_Load(object sender, EventArgs e)
+        private void FrmItems_Load(Object sender, EventArgs e)
         {
             SetDic(Dic);
         }
 
-        private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e)
+        private void dataGridView1_RowEnter(Object sender, DataGridViewCellEventArgs e)
         {
             //if(e.RowIndex<0) return ;
 
@@ -140,7 +140,7 @@ namespace XCoder
             //propertyGrid1.SelectedObject = row.Cells;
         }
 
-        private void button1_Click(object sender, EventArgs e)
+        private void button1_Click(Object sender, EventArgs e)
         {
             AddItems();
         }
Modified +82 -111
diff --git a/XCoder/Windows/FrmMain.cs b/XCoder/Windows/FrmMain.cs
index dcad031..3ef5ff0 100644
--- a/XCoder/Windows/FrmMain.cs
+++ b/XCoder/Windows/FrmMain.cs
@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
-using System.Configuration;
 using System.Data;
 using System.Data.Common;
 using System.Diagnostics;
@@ -14,14 +13,16 @@ using System.Windows.Forms;
 using NewLife.Log;
 using NewLife.Net;
 using NewLife.Reflection;
-using NewLife.Threading;
 using XCode.DataAccessLayer;
 using XTemplate.Templating;
+#if !NET4
+using TaskEx = System.Threading.Tasks.Task;
+#endif
 
 namespace XCoder
 {
     [DisplayName("数据建模工具")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
         #region 属性
         /// <summary>配置</summary>
@@ -41,18 +42,21 @@ namespace XCoder
         {
             InitializeComponent();
 
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
             Icon = IcoHelper.GetIcon("模型");
 
             AutoLoadTables(Config.ConnName);
         }
 
-        private void FrmMain_Shown(object sender, EventArgs e)
+        private void FrmMain_Shown(Object sender, EventArgs e)
         {
             //var asm = AssemblyX.Create(Assembly.GetExecutingAssembly());
             //Text = String.Format("新生命数据模型工具 v{0} {1:HH:mm:ss}编译", asm.CompileVersion, asm.Compile);
         }
 
-        private void FrmMain_Load(object sender, EventArgs e)
+        private void FrmMain_Load(Object sender, EventArgs e)
         {
             LoadConfig();
 
@@ -72,7 +76,7 @@ namespace XCoder
             Task.Factory.StartNew(AutoDetectDatabase).LogException();
         }
 
-        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
+        private void FrmMain_FormClosing(Object sender, FormClosingEventArgs e)
         {
             try
             {
@@ -83,7 +87,7 @@ namespace XCoder
         #endregion
 
         #region 连接、自动检测数据库、加载表
-        private void bt_Connection_Click(object sender, EventArgs e)
+        private void bt_Connection_Click(Object sender, EventArgs e)
         {
             SaveConfig();
 
@@ -116,15 +120,11 @@ namespace XCoder
                 Engine = null;
 
                 // 断开的时候再取一次,确保下次能及时得到新的
-                try
-                {
-                    var list = DAL.Create(Config.ConnName).Tables;
-                }
-                catch { }
+                TaskEx.Run(() => DAL.Create(Config.ConnName).Tables);
             }
         }
 
-        private void cbConn_SelectionChangeCommitted(object sender, EventArgs e)
+        private void cbConn_SelectionChangeCommitted(Object sender, EventArgs e)
         {
             if (!String.IsNullOrEmpty(cbConn.Text)) toolTip1.SetToolTip(cbConn, DAL.Create(cbConn.Text).ConnStr);
 
@@ -138,8 +138,8 @@ namespace XCoder
         void AutoDetectDatabase()
         {
             // 加上本机MSSQL
-            String localName = "local_MSSQL";
-            String localstr = "Data Source=.;Initial Catalog=master;Integrated Security=True;";
+            var localName = "local_MSSQL";
+            var localstr = "Data Source=.;Initial Catalog=master;Integrated Security=True;";
             if (!ContainConnStr(localstr)) DAL.AddConnStr(localName, localstr, null, "mssql");
 
             // 检测本地Access和SQLite
@@ -154,12 +154,11 @@ namespace XCoder
 
         void DetectFile()
         {
-            var sw = new Stopwatch();
-            sw.Start();
+            var sw = Stopwatch.StartNew();
 
             var n = 0;
             var ss = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.TopDirectoryOnly);
-            foreach (String item in ss)
+            foreach (var item in ss)
             {
                 var ext = Path.GetExtension(item);
                 //if (ext.EqualIC(".exe")) continue;
@@ -183,7 +182,7 @@ namespace XCoder
             var list = new List<String>();
             foreach (var item in DAL.ConnStrs)
             {
-                if (!String.IsNullOrEmpty(item.Value.ConnectionString)) list.Add(item.Key);
+                if (!String.IsNullOrEmpty(item.Value)) list.Add(item.Key);
             }
 
             // 远程数据库耗时太长,这里先列出来
@@ -192,8 +191,8 @@ namespace XCoder
 
         Boolean DetectFileDb(String item)
         {
-            String access = "Standard Jet DB";
-            String sqlite = "SQLite";
+            var access = "Standard Jet DB";
+            var sqlite = "SQLite";
 
             using (var fs = new FileStream(item, FileMode.Open, FileAccess.Read, FileShare.Read))
             {
@@ -250,8 +249,7 @@ namespace XCoder
                 var dal = DAL.Create(item);
                 if (dal.DbType != DatabaseType.SqlServer) return;
 
-                var sw = new Stopwatch();
-                sw.Start();
+                var sw = Stopwatch.StartNew();
 
                 DataTable dt = null;
 
@@ -279,10 +277,10 @@ namespace XCoder
                 var sysdbnames = new String[] { "master", "tempdb", "model", "msdb" };
                 foreach (DataRow dr in dt.Rows)
                 {
-                    String dbname = dr[0].ToString();
+                    var dbname = dr[0].ToString();
                     if (Array.IndexOf(sysdbnames, dbname) >= 0) continue;
 
-                    String connName = String.Format("{0}_{1}", item, dbname);
+                    var connName = String.Format("{0}_{1}", item, dbname);
 
                     builder["Database"] = dbname;
                     DAL.AddConnStr(connName, builder.ToString(), null, dbprovider);
@@ -290,7 +288,7 @@ namespace XCoder
 
                     try
                     {
-                        String ver = dal.Db.ServerVersion;
+                        var ver = dal.Db.ServerVersion;
                         names.Add(connName);
                     }
                     catch
@@ -308,7 +306,7 @@ namespace XCoder
                     var list = new List<String>();
                     foreach (var elm in DAL.ConnStrs)
                     {
-                        if (!String.IsNullOrEmpty(elm.Value.ConnectionString)) list.Add(elm.Key);
+                        if (!String.IsNullOrEmpty(elm.Value)) list.Add(elm.Key);
                     }
                     list.AddRange(names);
 
@@ -326,7 +324,7 @@ namespace XCoder
             var list = new List<String>();
             foreach (var item in DAL.ConnStrs)
             {
-                if (!String.IsNullOrEmpty(item.Value.ConnectionString)) list.Add(item.Key);
+                if (!String.IsNullOrEmpty(item.Value)) list.Add(item.Key);
             }
 
             var localName = "local_MSSQL";
@@ -343,14 +341,14 @@ namespace XCoder
         {
             foreach (var item in DAL.ConnStrs)
             {
-                if (connstr.EqualIgnoreCase(item.Value.ConnectionString)) return true;
+                if (connstr.EqualIgnoreCase(item.Value)) return true;
             }
             return false;
         }
 
         void SetDatabaseList(List<String> list)
         {
-            String str = cbConn.Text;
+            var str = cbConn.Text;
 
             cbConn.DataSource = list;
             //cbConn.DisplayMember = "value";
@@ -367,21 +365,27 @@ namespace XCoder
 
         void LoadTables()
         {
-            try
+            TaskEx.Run(() =>
             {
-                var list = DAL.Create(Config.ConnName).Tables;
-                if (!cbIncludeView.Checked) list = list.Where(t => !t.IsView).ToList();
-                //if (Config.NeedFix) list = Engine.FixTable(list);
-                Engine.Tables = list;
-            }
-            catch (Exception ex)
-            {
-                MessageBox.Show(ex.ToString(), Text);
-                return;
-            }
+                try
+                {
+                    var list = DAL.Create(Config.ConnName).Tables;
+                    if (!cbIncludeView.Checked) list = list.Where(t => !t.IsView).ToList();
+                    //if (Config.NeedFix) list = Engine.FixTable(list);
+                    Engine.Tables = list;
+                }
+                catch (Exception ex)
+                {
+                    MessageBox.Show(ex.ToString(), Text);
+                    return;
+                }
 
-            SetTables(null);
-            SetTables(Engine.Tables);
+                this.Invoke(() =>
+                {
+                    SetTables(null);
+                    SetTables(Engine.Tables);
+                });
+            });
         }
 
         void SetTables(Object source)
@@ -425,15 +429,13 @@ namespace XCoder
         void AutoLoadTables(String name)
         {
             if (String.IsNullOrEmpty(name)) return;
-            //if (!DAL.ConnStrs.ContainsKey(name) || String.IsNullOrEmpty(DAL.ConnStrs[name].ConnectionString)) return;
-            ConnectionStringSettings setting;
-            if (!DAL.ConnStrs.TryGetValue(name, out setting) || setting.ConnectionString.IsNullOrWhiteSpace()) return;
+            if (!DAL.ConnStrs.TryGetValue(name, out var connstr) || connstr.IsNullOrWhiteSpace()) return;
 
             // 异步加载
             Task.Factory.StartNew(() => { var tables = DAL.Create(name).Tables; }).LogException();
         }
 
-        private void btnRefreshTable_Click(object sender, EventArgs e)
+        private void btnRefreshTable_Click(Object sender, EventArgs e)
         {
             LoadTables();
         }
@@ -441,7 +443,7 @@ namespace XCoder
 
         #region 生成
         Stopwatch sw = new Stopwatch();
-        private void bt_GenTable_Click(object sender, EventArgs e)
+        private void bt_GenTable_Click(Object sender, EventArgs e)
         {
             SaveConfig();
 
@@ -472,7 +474,7 @@ namespace XCoder
             lb_Status.Text = "生成 " + cbTableList.Text + " 完成!耗时:" + sw.Elapsed;
         }
 
-        private void bt_GenAll_Click(object sender, EventArgs e)
+        private void bt_GenAll_Click(Object sender, EventArgs e)
         {
             SaveConfig();
 
@@ -533,12 +535,12 @@ namespace XCoder
         #endregion
 
         #region 附加信息
-        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        private void linkLabel1_LinkClicked(Object sender, LinkLabelLinkClickedEventArgs e)
         {
             var control = sender as Control;
             if (control == null) return;
 
-            String url = String.Empty;
+            var url = String.Empty;
             if (control.Tag != null) url = control.Tag.ToString();
             if (String.IsNullOrEmpty(url)) url = control.Text;
             if (String.IsNullOrEmpty(url)) return;
@@ -546,7 +548,7 @@ namespace XCoder
             Process.Start(url);
         }
 
-        private void label3_Click(object sender, EventArgs e)
+        private void label3_Click(Object sender, EventArgs e)
         {
             Clipboard.SetData("1600800", null);
             MessageBox.Show("QQ群号已复制到剪切板!", "提示");
@@ -554,7 +556,7 @@ namespace XCoder
         #endregion
 
         #region 打开输出目录
-        private void btnOpenOutputDir_Click(object sender, EventArgs e)
+        private void btnOpenOutputDir_Click(Object sender, EventArgs e)
         {
             var dir = txt_OutPath.Text.GetFullPath();
             if (!Directory.Exists(dir)) dir = AppDomain.CurrentDomain.BaseDirectory;
@@ -564,7 +566,7 @@ namespace XCoder
             //Process.Start("explorer.exe", "/select," + dir);
         }
 
-        private void frmItems_Click(object sender, EventArgs e)
+        private void frmItems_Click(Object sender, EventArgs e)
         {
             //FrmItems.Create(XConfig.Current.Items).Show();
 
@@ -580,12 +582,12 @@ namespace XCoder
             {
                 list.Add("[文件]" + item);
             }
-            foreach (String item in Engine.Templates.Keys)
+            foreach (var item in Engine.Templates.Keys)
             {
-                String[] ks = item.Split('.');
+                var ks = item.Split('.');
                 if (ks == null || ks.Length < 1) continue;
 
-                String name = "[内置]" + ks[0];
+                var name = "[内置]" + ks[0];
                 if (!list.Contains(name)) list.Add(name);
             }
             cb.Items.Clear();
@@ -594,7 +596,7 @@ namespace XCoder
             cb.Update();
         }
 
-        private void btnRelease_Click(object sender, EventArgs e)
+        private void btnRelease_Click(Object sender, EventArgs e)
         {
             try
             {
@@ -606,7 +608,7 @@ namespace XCoder
             }
         }
 
-        private void lbEditHeader_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        private void lbEditHeader_LinkClicked(Object sender, LinkLabelLinkClickedEventArgs e)
         {
             var frm = FrmText.Create("C#文件头模版", Config.HeadTemplate);
             frm.ShowDialog();
@@ -616,76 +618,45 @@ namespace XCoder
         #endregion
 
         #region 菜单
-        private void 退出XToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 退出XToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             //Application.Exit();
             Close();
         }
 
-        private void 组件手册ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 组件手册ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             var file = "X组件手册.chm";
             if (!File.Exists(file)) file = Path.Combine(@"C:\X\DLL", file);
             if (File.Exists(file)) Process.Start(file);
         }
 
-        private void 表名字段名命名规范ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 表名字段名命名规范ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             FrmText.Create("表名字段名命名规范", Source.GetText("数据库命名规范")).Show();
         }
 
-        private void 在线帮助文档ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 在线帮助文档ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             Process.Start("http://www.NewLifeX.com/showtopic-260.aspx?r=XCoder_v" + AssemblyX.Create(Assembly.GetExecutingAssembly()).Version);
         }
 
-        private void 检查更新ToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            var cfg = XConfig.Current;
-            cfg.LastUpdate = DateTime.Now;
-            cfg.Save();
-
-            try
-            {
-                var root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
-                var up = new Upgrade();
-                up.Log = XTrace.Log;
-                up.Name = "XCoder";
-                up.Server = cfg.UpdateServer;
-                up.UpdatePath = root.CombinePath(up.UpdatePath);
-                if (up.Check())
-                {
-                    up.Download();
-                    up.Update();
-                }
-                else if (up.Links != null && up.Links.Length > 0)
-                    MessageBox.Show("没有可用更新!最新{0}".F(up.Links[0].Time), "自动更新");
-                else
-                    MessageBox.Show("没有可用更新!", "自动更新");
-            }
-            catch (Exception ex)
-            {
-                XTrace.WriteException(ex);
-                MessageBox.Show("更新失败!" + ex.Message, "自动更新");
-            }
-        }
-
-        private void 关于ToolStripMenuItem1_Click(object sender, EventArgs e)
+        private void 关于ToolStripMenuItem1_Click(Object sender, EventArgs e)
         {
             FrmText.Create("升级历史", Source.GetText("UpdateInfo")).Show();
         }
 
-        private void 博客ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 博客ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             Process.Start("http://nnhy.cnblogs.com");
         }
 
-        private void qQ群1600800ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void qQ群1600800ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             Process.Start("http://www.NewLifeX.com/?r=XCoder_v" + AssemblyX.Create(Assembly.GetExecutingAssembly()).Version);
         }
 
-        private void oracle客户端运行时检查ToolStripMenuItem1_Click(object sender, EventArgs e)
+        private void oracle客户端运行时检查ToolStripMenuItem1_Click(Object sender, EventArgs e)
         {
             Task.Factory.StartNew(CheckOracle);
         }
@@ -705,14 +676,14 @@ namespace XCoder
             }
         }
 
-        private void 自动格式化设置ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 自动格式化设置ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             //FrmFix.Create(Config).ShowDialog();
         }
         #endregion
 
         #region 模型管理
-        private void 模型管理MToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 模型管理MToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             var tables = Engine.Tables;
             if (tables == null || tables.Count < 1) return;
@@ -720,7 +691,7 @@ namespace XCoder
             FrmModel.Create(tables).Show();
         }
 
-        private void 导出模型EToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 导出模型EToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             var tables = Engine.Tables;
             if (tables == null || tables.Count < 1)
@@ -743,7 +714,7 @@ namespace XCoder
             if (saveFileDialog1.ShowDialog() != DialogResult.OK || String.IsNullOrEmpty(saveFileDialog1.FileName)) return;
             try
             {
-                String xml = DAL.Export(tables);
+                var xml = DAL.Export(tables);
                 File.WriteAllText(saveFileDialog1.FileName, xml);
 
                 MessageBox.Show("导出架构成功!", "导出架构", MessageBoxButtons.OK);
@@ -755,23 +726,23 @@ namespace XCoder
             }
         }
 
-        private void 架构管理SToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 架构管理SToolStripMenuItem_Click(Object sender, EventArgs e)
         {
-            String connName = "" + cbConn.SelectedValue;
+            var connName = "" + cbConn.SelectedValue;
             if (String.IsNullOrEmpty(connName)) return;
 
             FrmSchema.Create(DAL.Create(connName).Db).Show();
         }
 
-        private void sQL查询器QToolStripMenuItem_Click(object sender, EventArgs e)
+        private void sQL查询器QToolStripMenuItem_Click(Object sender, EventArgs e)
         {
-            String connName = "" + cbConn.SelectedValue;
+            var connName = "" + cbConn.SelectedValue;
             if (String.IsNullOrEmpty(connName)) return;
 
             FrmQuery.Create(DAL.Create(connName)).Show();
         }
 
-        private void btnImport_Click(object sender, EventArgs e)
+        private void btnImport_Click(Object sender, EventArgs e)
         {
             var btn = sender as Button;
             if (btn != null && btn.Text == "导出模型")
@@ -807,13 +778,13 @@ namespace XCoder
         #endregion
 
         #region 网页
-        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
+        private void webBrowser1_DocumentCompleted(Object sender, WebBrowserDocumentCompletedEventArgs e)
         {
             // 网页加载完成后,自动向下滚动一段距离,越过头部
             webBrowser1.Document.Window.ScrollTo(0, 90);
         }
 
-        private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
+        private void webBrowser1_Navigating(Object sender, WebBrowserNavigatingEventArgs e)
         {
             if (e.Url != null)
             {
@@ -833,7 +804,7 @@ namespace XCoder
             }
         }
 
-        private void timer1_Tick(object sender, EventArgs e)
+        private void timer1_Tick(Object sender, EventArgs e)
         {
             timer1.Enabled = false;
 
@@ -845,7 +816,7 @@ namespace XCoder
         #endregion
 
         #region 添加模型-@宁波-小董 2013
-        private void 添加模型ToolStripMenuItem_Click(object sender, EventArgs e)
+        private void 添加模型ToolStripMenuItem_Click(Object sender, EventArgs e)
         {
             NewModel.CreateForm().Show();
         }
Modified +0 -10
diff --git a/XCoder/Windows/FrmMain.designer.cs b/XCoder/Windows/FrmMain.designer.cs
index 99111f7..8501d43 100644
--- a/XCoder/Windows/FrmMain.designer.cs
+++ b/XCoder/Windows/FrmMain.designer.cs
@@ -83,7 +83,6 @@
             this.qQ群1600800ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.qQ群1600800ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
             this.博客ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.检查更新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.关于ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
             this.label9 = new System.Windows.Forms.Label();
             this.timer1 = new System.Windows.Forms.Timer(this.components);
@@ -625,7 +624,6 @@
             this.qQ群1600800ToolStripMenuItem,
             this.qQ群1600800ToolStripMenuItem1,
             this.博客ToolStripMenuItem,
-            this.检查更新ToolStripMenuItem,
             this.关于ToolStripMenuItem1});
             this.关于ToolStripMenuItem.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold);
             this.关于ToolStripMenuItem.Name = "关于ToolStripMenuItem";
@@ -678,13 +676,6 @@
             this.博客ToolStripMenuItem.Text = "博客nnhy.cnblogs.com";
             this.博客ToolStripMenuItem.Click += new System.EventHandler(this.博客ToolStripMenuItem_Click);
             // 
-            // 检查更新ToolStripMenuItem
-            // 
-            this.检查更新ToolStripMenuItem.Name = "检查更新ToolStripMenuItem";
-            this.检查更新ToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
-            this.检查更新ToolStripMenuItem.Text = "检查更新(&U)";
-            this.检查更新ToolStripMenuItem.Click += new System.EventHandler(this.检查更新ToolStripMenuItem_Click);
-            // 
             // 关于ToolStripMenuItem1
             // 
             this.关于ToolStripMenuItem1.Name = "关于ToolStripMenuItem1";
@@ -795,7 +786,6 @@
         private System.Windows.Forms.ToolStripMenuItem sQL查询器QToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem 表名字段名命名规范ToolStripMenuItem;
         private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
-        private System.Windows.Forms.ToolStripMenuItem 检查更新ToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem 关于ToolStripMenuItem1;
         private System.Windows.Forms.ToolStripMenuItem 组件手册ToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem qQ群1600800ToolStripMenuItem;
Modified +8 -11
diff --git a/XCoder/Windows/FrmMain.resx b/XCoder/Windows/FrmMain.resx
index 426319e..3181d57 100644
--- a/XCoder/Windows/FrmMain.resx
+++ b/XCoder/Windows/FrmMain.resx
@@ -112,30 +112,27 @@
     <value>2.0</value>
   </resheader>
   <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>228, 17</value>
   </metadata>
-  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>107, 17</value>
   </metadata>
-  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>228, 17</value>
-  </metadata>
-  <metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>329, 17</value>
   </metadata>
-  <metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>477, 17</value>
   </metadata>
-  <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>621, 17</value>
   </metadata>
-  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>17, 17</value>
   </metadata>
 </root>
\ No newline at end of file
Modified +45 -48
diff --git a/XCoder/Windows/FrmModel.cs b/XCoder/Windows/FrmModel.cs
index f845d04..50c278b 100644
--- a/XCoder/Windows/FrmModel.cs
+++ b/XCoder/Windows/FrmModel.cs
@@ -32,13 +32,13 @@ namespace XCoder
         {
             if (tables == null || tables.Count < 1) throw new ArgumentNullException("tables");
 
-            FrmModel frm = new FrmModel();
+            var frm = new FrmModel();
             frm.Tables = tables;
 
             return frm;
         }
 
-        private void FrmModel_Load(object sender, EventArgs e)
+        private void FrmModel_Load(Object sender, EventArgs e)
         {
             SetTables(Tables, 0);
             SetDbTypes();
@@ -48,15 +48,15 @@ namespace XCoder
         #region 选择数据表
         IDataTable GetSelectedTable()
         {
-            ComboBox cb = cbTables;
+            var cb = cbTables;
             if (cb == null || cb.SelectedItem == null) return null;
 
             return cb.SelectedItem as IDataTable;
         }
 
-        private void cbTables_SelectedIndexChanged(object sender, EventArgs e)
+        private void cbTables_SelectedIndexChanged(Object sender, EventArgs e)
         {
-            IDataTable table = GetSelectedTable();
+            var table = GetSelectedTable();
             if (table == null) return;
 
             pgTable.SelectedObject = table;
@@ -64,17 +64,17 @@ namespace XCoder
 
             gv.DataSource = table.Columns;
             dgvIndex.DataSource = table.Indexes;
-            dgvRelation.DataSource = table.Relations;
+            //dgvRelation.DataSource = table.Relations;
         }
 
-        private void gv_RowEnter(object sender, DataGridViewCellEventArgs e)
+        private void gv_RowEnter(Object sender, DataGridViewCellEventArgs e)
         {
             if (e.RowIndex < 0) return;
 
-            DataGridView dgv = sender as DataGridView;
+            var dgv = sender as DataGridView;
             if (dgv == null) return;
 
-            DataGridViewRow row = dgv.Rows[e.RowIndex];
+            var row = dgv.Rows[e.RowIndex];
             if (row == null) return;
 
             pgColumn.SelectedObject = row.DataBoundItem;
@@ -85,7 +85,7 @@ namespace XCoder
             cbTables.Items.Clear();
             if (Tables != null && tables.Count > 0)
             {
-                foreach (IDataTable item in tables)
+                foreach (var item in tables)
                 {
                     cbTables.Items.Add(item);
                 }
@@ -98,46 +98,46 @@ namespace XCoder
         #endregion
 
         #region 添加
-        private void btnAddTable_Click(object sender, EventArgs e)
+        private void btnAddTable_Click(Object sender, EventArgs e)
         {
             if (Tables == null || Tables.Count < 1) return;
 
-            Type type = Tables[0].GetType();
+            var type = Tables[0].GetType();
             if (type == null) return;
 
-            IDataTable table = type.CreateInstance() as IDataTable;
+            var table = type.CreateInstance() as IDataTable;
             if (table == null) return;
 
             Tables.Add(table);
-            table.ID = Tables.Count;
-            table.TableName = "NewTable" + table.ID;
-            table.Description = "新建表" + table.ID;
+            var id = Tables.Count;
+            table.TableName = "NewTable" + id;
+            table.Description = "新建表" + id;
 
             SetTables(Tables, Tables.Count - 1);
         }
 
-        private void btnAddColumn_Click(object sender, EventArgs e)
+        private void btnAddColumn_Click(Object sender, EventArgs e)
         {
-            IDataTable table = GetSelectedTable();
+            var table = GetSelectedTable();
             if (table == null) return;
 
-            IDataColumn dc = table.CreateColumn();
+            var dc = table.CreateColumn();
             table.Columns.Add(dc);
-            dc.ID = table.Columns.Count;
-            dc.ColumnName = "Column" + dc.ID;
-            dc.Description = "字段" + dc.ID;
+            var id = table.Columns.Count;
+            dc.ColumnName = "Column" + id;
+            dc.Description = "字段" + id;
 
             gv.DataSource = null;
             gv.DataSource = table.Columns;
             pgColumn.SelectedObject = dc;
         }
 
-        private void btnAddIndex_Click(object sender, EventArgs e)
+        private void btnAddIndex_Click(Object sender, EventArgs e)
         {
-            IDataTable table = GetSelectedTable();
+            var table = GetSelectedTable();
             if (table == null) return;
 
-            IDataIndex di = table.CreateIndex();
+            var di = table.CreateIndex();
             table.Indexes.Add(di);
 
             dgvIndex.DataSource = null;
@@ -145,18 +145,18 @@ namespace XCoder
             pgColumn.SelectedObject = di;
         }
 
-        private void btnAddRelation_Click(object sender, EventArgs e)
-        {
-            IDataTable table = GetSelectedTable();
-            if (table == null) return;
+        //private void btnAddRelation_Click(Object sender, EventArgs e)
+        //{
+        //    IDataTable table = GetSelectedTable();
+        //    if (table == null) return;
 
-            IDataRelation dr = table.CreateRelation();
-            table.Relations.Add(dr);
+        //    IDataRelation dr = table.CreateRelation();
+        //    table.Relations.Add(dr);
 
-            dgvRelation.DataSource = null;
-            dgvRelation.DataSource = table.Relations;
-            pgColumn.SelectedObject = dr;
-        }
+        //    dgvRelation.DataSource = null;
+        //    dgvRelation.DataSource = table.Relations;
+        //    pgColumn.SelectedObject = dr;
+        //}
         #endregion
 
         #region 建表语句
@@ -166,11 +166,11 @@ namespace XCoder
             cbConn.Update();
         }
 
-        private void btnCreateTableSQL_Click(object sender, EventArgs e)
+        private void btnCreateTableSQL_Click(Object sender, EventArgs e)
         {
             if (cbConn.SelectedItem == null) return;
 
-            IDataTable table = GetSelectedTable();
+            var table = GetSelectedTable();
             if (table == null) return;
 
             var dal = DAL.Create("" + cbConn.SelectedItem);
@@ -178,7 +178,7 @@ namespace XCoder
 
             try
             {
-                IMetaData md = dal.Db.CreateMetaData();
+                var md = dal.Db.CreateMetaData();
                 var sql = CreateTable(md, table);
 
                 FrmText.Create(table.TableName + "表建表语句", sql).Show();
@@ -191,7 +191,7 @@ namespace XCoder
 
         static String CreateTable(IMetaData md, IDataTable table)
         {
-            String sql = md.GetSchemaSQL(DDLSchema.CreateTable, table);
+            var sql = md.GetSchemaSQL(DDLSchema.CreateTable, table);
 
             var sb = new StringBuilder();
             if (!String.IsNullOrEmpty(sql)) sb.AppendLine(sql + "; ");
@@ -204,7 +204,7 @@ namespace XCoder
             }
 
             // 加上字段注释
-            foreach (IDataColumn item in table.Columns)
+            foreach (var item in table.Columns)
             {
                 if (!String.IsNullOrEmpty(item.Description))
                 {
@@ -216,7 +216,7 @@ namespace XCoder
             // 加上索引
             if (table.Indexes != null)
             {
-                foreach (IDataIndex item in table.Indexes)
+                foreach (var item in table.Indexes)
                 {
                     if (!item.PrimaryKey)
                     {
@@ -229,7 +229,7 @@ namespace XCoder
             return sb.ToString();
         }
 
-        private void btnCreateDbSQL_Click(object sender, EventArgs e)
+        private void btnCreateDbSQL_Click(Object sender, EventArgs e)
         {
             if (cbConn.SelectedItem == null) return;
 
@@ -238,7 +238,7 @@ namespace XCoder
 
             try
             {
-                IMetaData md = dal.Db.CreateMetaData();
+                var md = dal.Db.CreateMetaData();
                 var sb = new StringBuilder();
                 foreach (var table in Tables)
                 {
@@ -254,7 +254,7 @@ namespace XCoder
             }
         }
 
-        private void btnCreateDb_Click(object sender, EventArgs e)
+        private void btnCreateDb_Click(Object sender, EventArgs e)
         {
             if (cbConn.SelectedItem == null) return;
 
@@ -264,10 +264,7 @@ namespace XCoder
             try
             {
                 var md = dal.Db.CreateMetaData();
-                var set = new NegativeSetting();
-                set.CheckOnly = false;
-                set.NoDelete = false;
-                md.SetTables(set, Tables.ToArray());
+                md.SetTables(Migration.Full, Tables.ToArray());
 
                 MessageBox.Show("成功建立" + Tables.Count + "张数据表!", Text);
             }
Modified +13 -43
diff --git a/XCoder/Windows/FrmModel.Designer.cs b/XCoder/Windows/FrmModel.Designer.cs
index 9af9873..b74028a 100644
--- a/XCoder/Windows/FrmModel.Designer.cs
+++ b/XCoder/Windows/FrmModel.Designer.cs
@@ -25,7 +25,6 @@
         private void InitializeComponent()
         {
             this.groupBox1 = new System.Windows.Forms.GroupBox();
-            this.btnAddRelation = new System.Windows.Forms.Button();
             this.btnAddIndex = new System.Windows.Forms.Button();
             this.btnAddColumn = new System.Windows.Forms.Button();
             this.btnAddTable = new System.Windows.Forms.Button();
@@ -35,17 +34,15 @@
             this.pgTable = new System.Windows.Forms.PropertyGrid();
             this.pgColumn = new System.Windows.Forms.PropertyGrid();
             this.dgvIndex = new System.Windows.Forms.DataGridView();
-            this.dgvRelation = new System.Windows.Forms.DataGridView();
             this.btnCreateTableSQL = new System.Windows.Forms.Button();
             this.label2 = new System.Windows.Forms.Label();
             this.cbConn = new System.Windows.Forms.ComboBox();
             this.groupBox2 = new System.Windows.Forms.GroupBox();
-            this.btnCreateDbSQL = new System.Windows.Forms.Button();
             this.btnCreateDb = new System.Windows.Forms.Button();
+            this.btnCreateDbSQL = new System.Windows.Forms.Button();
             this.groupBox1.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.gv)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.dgvIndex)).BeginInit();
-            ((System.ComponentModel.ISupportInitialize)(this.dgvRelation)).BeginInit();
             this.groupBox2.SuspendLayout();
             this.SuspendLayout();
             // 
@@ -53,7 +50,6 @@
             // 
             this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-            this.groupBox1.Controls.Add(this.btnAddRelation);
             this.groupBox1.Controls.Add(this.btnAddIndex);
             this.groupBox1.Controls.Add(this.btnAddColumn);
             this.groupBox1.Controls.Add(this.btnAddTable);
@@ -65,16 +61,6 @@
             this.groupBox1.TabIndex = 2;
             this.groupBox1.TabStop = false;
             // 
-            // btnAddRelation
-            // 
-            this.btnAddRelation.Location = new System.Drawing.Point(461, 11);
-            this.btnAddRelation.Name = "btnAddRelation";
-            this.btnAddRelation.Size = new System.Drawing.Size(68, 27);
-            this.btnAddRelation.TabIndex = 5;
-            this.btnAddRelation.Text = "添加关系";
-            this.btnAddRelation.UseVisualStyleBackColor = true;
-            this.btnAddRelation.Click += new System.EventHandler(this.btnAddRelation_Click);
-            // 
             // btnAddIndex
             // 
             this.btnAddIndex.Location = new System.Drawing.Point(387, 11);
@@ -133,7 +119,7 @@
             this.gv.Location = new System.Drawing.Point(194, 52);
             this.gv.Name = "gv";
             this.gv.RowTemplate.Height = 23;
-            this.gv.Size = new System.Drawing.Size(629, 187);
+            this.gv.Size = new System.Drawing.Size(629, 286);
             this.gv.TabIndex = 3;
             this.gv.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.gv_RowEnter);
             // 
@@ -162,25 +148,13 @@
             this.dgvIndex.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
             this.dgvIndex.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-            this.dgvIndex.Location = new System.Drawing.Point(194, 245);
+            this.dgvIndex.Location = new System.Drawing.Point(194, 344);
             this.dgvIndex.Name = "dgvIndex";
             this.dgvIndex.RowTemplate.Height = 23;
             this.dgvIndex.Size = new System.Drawing.Size(629, 112);
             this.dgvIndex.TabIndex = 6;
             this.dgvIndex.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.gv_RowEnter);
             // 
-            // dgvRelation
-            // 
-            this.dgvRelation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.dgvRelation.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-            this.dgvRelation.Location = new System.Drawing.Point(194, 363);
-            this.dgvRelation.Name = "dgvRelation";
-            this.dgvRelation.RowTemplate.Height = 23;
-            this.dgvRelation.Size = new System.Drawing.Size(629, 102);
-            this.dgvRelation.TabIndex = 7;
-            this.dgvRelation.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.gv_RowEnter);
-            // 
             // btnCreateTableSQL
             // 
             this.btnCreateTableSQL.Location = new System.Drawing.Point(207, 11);
@@ -222,16 +196,6 @@
             this.groupBox2.TabIndex = 8;
             this.groupBox2.TabStop = false;
             // 
-            // btnCreateDbSQL
-            // 
-            this.btnCreateDbSQL.Location = new System.Drawing.Point(281, 11);
-            this.btnCreateDbSQL.Name = "btnCreateDbSQL";
-            this.btnCreateDbSQL.Size = new System.Drawing.Size(88, 27);
-            this.btnCreateDbSQL.TabIndex = 9;
-            this.btnCreateDbSQL.Text = "建所有表语句";
-            this.btnCreateDbSQL.UseVisualStyleBackColor = true;
-            this.btnCreateDbSQL.Click += new System.EventHandler(this.btnCreateDbSQL_Click);
-            // 
             // btnCreateDb
             // 
             this.btnCreateDb.Location = new System.Drawing.Point(375, 11);
@@ -242,13 +206,22 @@
             this.btnCreateDb.UseVisualStyleBackColor = true;
             this.btnCreateDb.Click += new System.EventHandler(this.btnCreateDb_Click);
             // 
+            // btnCreateDbSQL
+            // 
+            this.btnCreateDbSQL.Location = new System.Drawing.Point(281, 11);
+            this.btnCreateDbSQL.Name = "btnCreateDbSQL";
+            this.btnCreateDbSQL.Size = new System.Drawing.Size(88, 27);
+            this.btnCreateDbSQL.TabIndex = 9;
+            this.btnCreateDbSQL.Text = "建所有表语句";
+            this.btnCreateDbSQL.UseVisualStyleBackColor = true;
+            this.btnCreateDbSQL.Click += new System.EventHandler(this.btnCreateDbSQL_Click);
+            // 
             // FrmModel
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(1020, 468);
             this.Controls.Add(this.groupBox2);
-            this.Controls.Add(this.dgvRelation);
             this.Controls.Add(this.dgvIndex);
             this.Controls.Add(this.pgColumn);
             this.Controls.Add(this.pgTable);
@@ -262,7 +235,6 @@
             this.groupBox1.PerformLayout();
             ((System.ComponentModel.ISupportInitialize)(this.gv)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.dgvIndex)).EndInit();
-            ((System.ComponentModel.ISupportInitialize)(this.dgvRelation)).EndInit();
             this.groupBox2.ResumeLayout(false);
             this.groupBox2.PerformLayout();
             this.ResumeLayout(false);
@@ -278,8 +250,6 @@
         private System.Windows.Forms.PropertyGrid pgTable;
         private System.Windows.Forms.PropertyGrid pgColumn;
         private System.Windows.Forms.DataGridView dgvIndex;
-        private System.Windows.Forms.DataGridView dgvRelation;
-        private System.Windows.Forms.Button btnAddRelation;
         private System.Windows.Forms.Button btnAddIndex;
         private System.Windows.Forms.Button btnAddColumn;
         private System.Windows.Forms.Button btnAddTable;
Modified +2 -2
diff --git a/XCoder/Windows/FrmModel.resx b/XCoder/Windows/FrmModel.resx
index 5ea0895..29dcb1b 100644
--- a/XCoder/Windows/FrmModel.resx
+++ b/XCoder/Windows/FrmModel.resx
@@ -112,9 +112,9 @@
     <value>2.0</value>
   </resheader>
   <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
 </root>
\ No newline at end of file
Modified +9 -11
diff --git a/XCoder/Windows/FrmQuery.cs b/XCoder/Windows/FrmQuery.cs
index 14adebf..e92b63c 100644
--- a/XCoder/Windows/FrmQuery.cs
+++ b/XCoder/Windows/FrmQuery.cs
@@ -29,32 +29,31 @@ namespace XCoder
         {
             if (db == null) throw new ArgumentNullException("db");
 
-            FrmQuery frm = new FrmQuery();
+            var frm = new FrmQuery();
             frm.Dal = db;
 
             return frm;
         }
 
-        private void FrmQuery_Load(object sender, EventArgs e)
+        private void FrmQuery_Load(Object sender, EventArgs e)
         {
         }
         #endregion
 
-        private void btnQuery_Click(object sender, EventArgs e)
+        private void btnQuery_Click(Object sender, EventArgs e)
         {
             var sql = txtSQL.Text;
             if (sql.IsNullOrWhiteSpace()) return;
 
             Task.Factory.StartNew(() =>
             {
-                var sw = new Stopwatch();
-                sw.Start();
+                var sw = Stopwatch.StartNew();
 
                 String msg = null;
                 DataTable dt = null;
                 try
                 {
-                    DataSet ds = Dal.Session.Query(sql);
+                    var ds = Dal.Session.Query(sql);
                     if (ds != null && ds.Tables != null && ds.Tables.Count > 0) dt = ds.Tables[0];
 
                     msg = "查询完成!";
@@ -75,20 +74,19 @@ namespace XCoder
             }).LogException();
         }
 
-        private void btnExecute_Click(object sender, EventArgs e)
+        private void btnExecute_Click(Object sender, EventArgs e)
         {
             var sql = txtSQL.Text;
             if (sql.IsNullOrWhiteSpace()) return;
 
             Task.Factory.StartNew(() =>
             {
-                var sw = new Stopwatch();
-                sw.Start();
+                var sw = Stopwatch.StartNew();
 
                 String msg = null;
                 try
                 {
-                    Int32 n = Dal.Session.Execute(sql);
+                    var n = Dal.Session.Execute(sql);
 
                     msg = String.Format("执行完成!共影响{0}行!", n);
                 }
@@ -100,7 +98,7 @@ namespace XCoder
                 {
                     sw.Stop();
 
-                    msg += String.Format(" 耗时{0:HH:mm:ss.zzz}", sw.Elapsed);
+                    msg += String.Format(" 耗时{0}", sw.Elapsed);
                 }
 
                 this.Invoke(() => lbStatus.Text = msg);
Modified +18 -18
diff --git a/XCoder/Windows/FrmSchema.cs b/XCoder/Windows/FrmSchema.cs
index f4bd64e..9d25c14 100644
--- a/XCoder/Windows/FrmSchema.cs
+++ b/XCoder/Windows/FrmSchema.cs
@@ -2,11 +2,9 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Data;
-using System.Data.Common;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using NewLife.Log;
-using NewLife.Threading;
 using XCode.DataAccessLayer;
 
 namespace XCoder
@@ -33,15 +31,15 @@ namespace XCoder
 
         public static FrmSchema Create(IDatabase db)
         {
-            if (db == null) throw new ArgumentNullException("db");
-
-            FrmSchema frm = new FrmSchema();
-            frm.Db = db;
+            var frm = new FrmSchema
+            {
+                Db = db ?? throw new ArgumentNullException("db")
+            };
 
             return frm;
         }
 
-        private void FrmSchema_Load(object sender, EventArgs e)
+        private void FrmSchema_Load(Object sender, EventArgs e)
         {
             Task.Factory.StartNew(() =>
             {
@@ -66,7 +64,7 @@ namespace XCoder
                 if (!(data is IList))
                 {
                     var list = new List<Object>();
-                    foreach (Object item in data)
+                    foreach (var item in data)
                     {
                         list.Add(item);
                     }
@@ -83,37 +81,39 @@ namespace XCoder
         }
         #endregion
 
-        private void cbTables_SelectedIndexChanged(object sender, EventArgs e)
+        private void cbTables_SelectedIndexChanged(Object sender, EventArgs e)
         {
-            ComboBox cb = sender as ComboBox;
+            var cb = sender as ComboBox;
             if (cb == null) return;
 
-            Object obj = cb.SelectedItem;
+            var obj = cb.SelectedItem;
             if (obj == null) return;
 
             try
             {
+                var ss = Db.CreateSession();
                 if (obj is IDataTable)
                 {
-                    //obj = (obj as IDataTable).Columns;
-                    DbCommand cmd = Db.CreateSession().CreateCommand();
-                    cmd.CommandText = "select * from " + (obj as IDataTable).TableName;
+                    var sql = "select * from " + (obj as IDataTable).TableName;
                     DataTable dt = null;
                     try
                     {
-                        using (DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
+                        using (var cmd = ss.CreateCommand(sql))
+                        using (var reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
                         {
                             dt = reader.GetSchemaTable();
                         }
                     }
                     finally
                     {
-                        Db.CreateSession().AutoClose();
+                        ss.AutoClose();
                     }
                     obj = dt;
                 }
                 else if (obj is String)
-                    obj = Db.CreateSession().GetSchema((String)obj, null);
+                {
+                    obj = ss.GetSchema((String)obj, null);
+                }
                 gv.DataSource = obj;
                 gv.Update();
             }
@@ -123,4 +123,4 @@ namespace XCoder
             }
         }
     }
-}
+}
\ No newline at end of file
Added +79 -0
diff --git a/XCoder/XApi/ApiConfig.cs b/XCoder/XApi/ApiConfig.cs
new file mode 100644
index 0000000..1a25e9c
--- /dev/null
+++ b/XCoder/XApi/ApiConfig.cs
@@ -0,0 +1,79 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using NewLife.Xml;
+
+namespace XApi
+{
+    /// <summary>Api配置</summary>
+    [XmlConfigFile("Config\\Api.config")]
+    public class ApiConfig : XmlConfig<ApiConfig>
+    {
+        #region 属性
+        /// <summary>端口</summary>
+        [Description("端口")]
+        public Int32 Port { get; set; } = 777;
+
+        /// <summary>地址</summary>
+        [Description("地址")]
+        public String Address { get; set; } = "";
+
+        /// <summary>模式</summary>
+        [Description("模式")]
+        public String Mode { get; set; } = "服务端";
+
+        /// <summary>发送内容</summary>
+        [Description("发送内容")]
+        public String SendContent { get; set; } = "新生命开发团队,学无先后达者为师";
+
+        /// <summary>发送次数</summary>
+        [Description("发送次数")]
+        public Int32 SendTimes { get; set; } = 1;
+
+        /// <summary>发送间隔。毫秒</summary>
+        [Description("发送间隔。毫秒")]
+        public Int32 SendSleep { get; set; } = 1000;
+
+        /// <summary>发送用户数</summary>
+        [Description("发送用户数")]
+        public Int32 SendUsers { get; set; } = 1;
+
+        /// <summary>显示应用日志</summary>
+        [Description("显示应用日志")]
+        public Boolean ShowLog { get; set; } = true;
+
+        /// <summary>显示编码日志</summary>
+        [Description("显示编码日志")]
+        public Boolean ShowEncoderLog { get; set; } = true;
+
+        /// <summary>显示发送数据</summary>
+        [Description("显示发送数据")]
+        public Boolean ShowSend { get; set; }
+
+        /// <summary>显示接收数据</summary>
+        [Description("显示接收数据")]
+        public Boolean ShowReceive { get; set; }
+
+        /// <summary>显示统计信息</summary>
+        [Description("显示统计信息")]
+        public Boolean ShowStat { get; set; } = true;
+
+        /// <summary>日志着色</summary>
+        [Description("日志着色")]
+        public Boolean ColorLog { get; set; } = true;
+        #endregion
+
+        #region 方法
+        public ApiConfig() { }
+
+        public void AddAddress(String addr)
+        {
+            var addrs = (Address + "").Split(";").Distinct().ToList();
+            addrs.Insert(0, addr);
+            addrs = addrs.Distinct().ToList();
+            while (addrs.Count > 10) addrs.RemoveAt(addrs.Count - 1);
+            Address = addrs.Join(";");
+        }
+        #endregion
+    }
+}
\ No newline at end of file
Added +540 -0
diff --git a/XCoder/XApi/FrmMain.cs b/XCoder/XApi/FrmMain.cs
new file mode 100644
index 0000000..483f9ad
--- /dev/null
+++ b/XCoder/XApi/FrmMain.cs
@@ -0,0 +1,540 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using NewLife.Data;
+using NewLife.Log;
+using NewLife.Net;
+using NewLife.Reflection;
+using NewLife.Remoting;
+using NewLife.Serialization;
+using NewLife.Threading;
+using NewLife.Windows;
+using XCoder;
+#if !NET4
+using TaskEx = System.Threading.Tasks.Task;
+#endif
+
+namespace XApi
+{
+    [DisplayName("Api调试")]
+    public partial class FrmMain : Form, IXForm
+    {
+        ApiServer _Server;
+        ApiClient _Client;
+
+        /// <summary>业务日志输出</summary>
+        ILog BizLog;
+
+        #region 窗体
+        public FrmMain()
+        {
+            InitializeComponent();
+
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
+            //Font = new Font("宋体", 9F, FontStyle.Regular, GraphicsUnit.Point, 134);
+            Icon = IcoHelper.GetIcon("Api");
+        }
+
+        private void FrmMain_Load(Object sender, EventArgs e)
+        {
+            var log = TextFileLog.Create(null, "Api_{0:yyyy_MM_dd}.log");
+            BizLog = txtReceive.Combine(log);
+            txtReceive.UseWinFormControl();
+
+            txtReceive.SetDefaultStyle(12);
+            txtSend.SetDefaultStyle(12);
+            numMutilSend.SetDefaultStyle(12);
+
+            gbReceive.Tag = gbReceive.Text;
+            gbSend.Tag = gbSend.Text;
+
+            var cfg = ApiConfig.Current;
+            //cbMode.SelectedItem = cbMode.Items[0] + "";
+            cbMode.SelectedItem = cfg.Mode;
+            var flag = (cfg.Mode == "服务端");
+            numPort.Enabled = flag;
+            cbAddr.Enabled = !flag;
+
+            // 加载保存的颜色
+            UIConfig.Apply(txtReceive);
+
+            LoadConfig();
+
+            // 语音识别
+            Task.Factory.StartNew(() =>
+            {
+                var sp = SpeechRecognition.Current;
+                if (!sp.Enable) return;
+
+                sp.Register("打开", () => this.Invoke(Connect))
+                .Register("关闭", () => this.Invoke(Disconnect))
+                .Register("退出", () => Application.Exit())
+                .Register("发送", () => this.Invoke(() => btnSend_Click(null, null)));
+
+                BizLog.Info("语音识别前缀:{0} 可用命令:{1}", sp.Name, sp.GetAllKeys().Join());
+            });
+        }
+        #endregion
+
+        #region 加载/保存 配置
+        void LoadConfig()
+        {
+            var cfg = ApiConfig.Current;
+            mi显示应用日志.Checked = cfg.ShowLog;
+            mi显示编码日志.Checked = cfg.ShowEncoderLog;
+            mi显示发送数据.Checked = cfg.ShowSend;
+            mi显示接收数据.Checked = cfg.ShowReceive;
+            mi显示统计信息.Checked = cfg.ShowStat;
+
+            cbMode.SelectedItem = cfg.Mode;
+            numPort.Value = cfg.Port;
+            // 历史地址列表
+            if (!cfg.Address.IsNullOrEmpty()) cbAddr.DataSource = cfg.Address.Split(";");
+
+            txtSend.Text = cfg.SendContent;
+            numMutilSend.Value = cfg.SendTimes;
+            numSleep.Value = cfg.SendSleep;
+            numThreads.Value = cfg.SendUsers;
+            mi日志着色.Checked = cfg.ColorLog;
+        }
+
+        void SaveConfig()
+        {
+            var cfg = ApiConfig.Current;
+            cfg.ShowLog = mi显示应用日志.Checked;
+            cfg.ShowEncoderLog = mi显示编码日志.Checked;
+            cfg.ShowSend = mi显示发送数据.Checked;
+            cfg.ShowReceive = mi显示接收数据.Checked;
+            cfg.ShowStat = mi显示统计信息.Checked;
+
+            cfg.Mode = cbMode.SelectedItem + "";
+            cfg.Port = (Int32)numPort.Value;
+            cfg.AddAddress(cbAddr.Text);
+
+            cfg.SendContent = txtSend.Text;
+            cfg.SendTimes = (Int32)numMutilSend.Value;
+            cfg.SendSleep = (Int32)numSleep.Value;
+            cfg.SendUsers = (Int32)numThreads.Value;
+            cfg.ColorLog = mi日志着色.Checked;
+
+            cfg.Save();
+        }
+        #endregion
+
+        #region 收发数据
+        void Connect()
+        {
+            _Server = null;
+            _Client = null;
+
+            var port = (Int32)numPort.Value;
+            var uri = new NetUri(cbAddr.Text);
+
+            var cfg = ApiConfig.Current;
+            var log = BizLog;
+
+            switch (cbMode.Text)
+            {
+                case "服务端":
+                    var svr = new ApiServer(port)
+                    {
+                        Log = cfg.ShowLog ? log : Logger.Null,
+                        EncoderLog = cfg.ShowEncoderLog ? log : Logger.Null
+                    };
+
+                    if (cfg.ShowSend || cfg.ShowReceive)
+                    {
+                        var ns = svr.Server as NetServer;
+                        ns.Log = log;
+                        ns.LogSend = cfg.ShowSend;
+                        ns.LogReceive = cfg.ShowReceive;
+                    }
+
+                    svr.Register<MyApiController>();
+                    svr.Start();
+
+                    "正在监听{0}".F(port).SpeechTip();
+
+                    _Server = svr;
+                    break;
+                case "客户端":
+                    var client = new ApiClient(uri + "")
+                    {
+                        Log = cfg.ShowLog ? log : Logger.Null,
+                        EncoderLog = cfg.ShowEncoderLog ? log : Logger.Null
+                    };
+
+                    if (cfg.ShowSend || cfg.ShowReceive)
+                    {
+                        var ct = client.Client;
+                        ct.Log = log;
+                        ct.LogSend = cfg.ShowSend;
+                        ct.LogReceive = cfg.ShowReceive;
+                    }
+
+                    _Client = client;
+                    client.Open();
+                    // 连接成功后拉取Api列表
+                    GetApiAll();
+
+                    "已连接服务器".SpeechTip();
+
+                    break;
+                default:
+                    return;
+            }
+
+            pnlSetting.Enabled = false;
+            btnConnect.Text = "关闭";
+
+            // 添加地址
+            var addr = uri.ToString();
+            var list = cfg.Address.Split(";").ToList();
+            if (!list.Contains(addr))
+            {
+                list.Insert(0, addr);
+                cfg.Address = list.Join(";");
+            }
+
+            cfg.Save();
+
+            _timer = new TimerX(ShowStat, null, 5000, 5000) { Async = true };
+        }
+
+        async void GetApiAll()
+        {
+            var apis = await _Client.InvokeAsync<String[]>("Api/All");
+            if (apis != null) this.Invoke(() =>
+            {
+                cbAction.Items.Clear();
+                foreach (var item in apis)
+                {
+                    cbAction.Items.Add(item);
+                }
+                cbAction.SelectedIndex = 0;
+                cbAction.Visible = true;
+            });
+        }
+
+        void Disconnect()
+        {
+            if (_Client != null)
+            {
+                _Client.Dispose();
+                _Client = null;
+
+                "关闭连接".SpeechTip();
+            }
+            if (_Server != null)
+            {
+                "停止服务".SpeechTip();
+                _Server.Dispose();
+                _Server = null;
+            }
+            if (_timer != null)
+            {
+                _timer.Dispose();
+                _timer = null;
+            }
+
+            pnlSetting.Enabled = true;
+            btnConnect.Text = "打开";
+        }
+
+        TimerX _timer;
+        String _lastStat;
+        void ShowStat(Object state)
+        {
+            if (!ApiConfig.Current.ShowStat) return;
+
+            var msg = "";
+            if (_Client != null)
+                msg = _Client.GetStat();
+            else if (_Server != null)
+                msg = _Server.GetStat();
+
+            if (_Invoke > 0)
+            {
+                var ms = (Double)_Cost / _Invoke / 1000;
+                if (ms > 1)
+                    msg += $" Invoke={_Invoke} {ms:n0}ms";
+                else
+                    msg += $" Invoke={_Invoke} {ms:n3}ms";
+
+                if (_TotalCost > 0) msg += $" Speed={_Invoke * 1000d / _TotalCost:n0}tps";
+            }
+
+            if (!msg.IsNullOrEmpty() && msg != _lastStat)
+            {
+                _lastStat = msg;
+                BizLog.Info(msg);
+            }
+        }
+
+        private void btnConnect_Click(Object sender, EventArgs e)
+        {
+            SaveConfig();
+
+            var btn = sender as Button;
+            if (btn.Text == "打开")
+                Connect();
+            else
+                Disconnect();
+        }
+
+        Int32 _pColor = 0;
+        Int32 BytesOfReceived = 0;
+        Int32 BytesOfSent = 0;
+        Int32 lastReceive = 0;
+        Int32 lastSend = 0;
+        private void timer1_Tick(Object sender, EventArgs e)
+        {
+            //if (!pnlSetting.Enabled)
+            {
+                var rcount = BytesOfReceived;
+                var tcount = BytesOfSent;
+                if (rcount != lastReceive)
+                {
+                    gbReceive.Text = (gbReceive.Tag + "").Replace("0", rcount + "");
+                    lastReceive = rcount;
+                }
+                if (tcount != lastSend)
+                {
+                    gbSend.Text = (gbSend.Tag + "").Replace("0", tcount + "");
+                    lastSend = tcount;
+                }
+
+                var set = ApiConfig.Current;
+                if (set.ColorLog) txtReceive.ColourDefault(_pColor);
+                _pColor = txtReceive.TextLength;
+            }
+        }
+
+        private async void btnSend_Click(Object sender, EventArgs e)
+        {
+            var str = txtSend.Text;
+            if (String.IsNullOrEmpty(str))
+            {
+                MessageBox.Show("发送内容不能为空!", Text);
+                txtSend.Focus();
+                return;
+            }
+
+            // 多次发送
+            var count = (Int32)numMutilSend.Value;
+            var sleep = (Int32)numSleep.Value;
+            var ths = (Int32)numThreads.Value;
+            if (count <= 0) count = 1;
+            if (sleep <= 0) sleep = 1;
+
+            SaveConfig();
+
+            var uri = new NetUri(cbAddr.Text);
+            var cfg = ApiConfig.Current;
+
+            // 处理换行
+            str = str.Replace("\n", "\r\n");
+
+            var act = cbAction.SelectedItem + "";
+            var action = act.Substring(" ", "(");
+            if (action.IsNullOrEmpty()) return;
+
+            var rtype = act.Substring(null, " ").GetTypeEx();
+            if (rtype == null) rtype = typeof(Object);
+            var ps = act.Substring("(", ")").Split(",");
+
+            // 构造消息,二进制优先
+            Object args = null;
+            if (ps.Length == 1 && ps[0].StartsWith("Packet "))
+            {
+                args = new Packet(str.GetBytes());
+            }
+            else
+            {
+                var dic = new JsonParser(str).Decode() as IDictionary<String, Object>;
+                if (dic == null || dic.Count == 0) dic = null;
+                args = dic;
+            }
+
+            if (_Client == null) return;
+
+            _Invoke = 0;
+            _Cost = 0;
+            _TotalCost = 0;
+
+            var ct = _Client.Client;
+            var list = new List<ApiClient> { _Client };
+            for (var i = 0; i < ths - 1; i++)
+            {
+                var client = new ApiClient(uri + "");
+                var ct2 = client.Client;
+                ct2.Log = ct.Log;
+                ct2.LogSend = ct.LogSend;
+                ct2.LogReceive = ct.LogReceive;
+                ct2.StatSend = ct.StatSend;
+                ct2.StatReceive = ct.StatReceive;
+
+                client.StatSend = _Client.StatSend;
+                client.StatReceive = _Client.StatReceive;
+
+                list.Add(client);
+            }
+            //Parallel.ForEach(list, k => OnSend(k, act, args, count));
+            var sw = Stopwatch.StartNew();
+            var ts = list.Select(k => OnSend(k, rtype, action, args, count, sleep)).ToList();
+
+            await TaskEx.WhenAll(ts);
+            sw.Stop();
+            _TotalCost = sw.Elapsed.TotalMilliseconds;
+        }
+
+        Int64 _Invoke;
+        Int64 _Cost;
+        Double _TotalCost;
+        private async Task OnSend(ApiClient client, Type rtype, String act, Object args, Int32 count, Int32 sleep)
+        {
+            client.Open();
+
+            // 间隔1开启同步发送不等待
+            if (sleep == 1)
+            {
+                var sw = Stopwatch.StartNew();
+                for (var i = 0; i < count; i++)
+                {
+                    try
+                    {
+                        Interlocked.Increment(ref _Invoke);
+
+                        client.Invoke(act, args);
+                    }
+                    catch (ApiException ex)
+                    {
+                        BizLog.Info(ex.Message);
+                    }
+                }
+                sw.Stop();
+                Interlocked.Add(ref _Cost, (Int64)(sw.Elapsed.TotalMilliseconds * 1000));
+            }
+            // 间隔2~10多任务异步发送
+            else if (sleep <= 10)
+            {
+                var ts = new List<Task>();
+                for (var i = 0; i < count; i++)
+                {
+                    ts.Add(TaskEx.Run(async () =>
+                    {
+                        try
+                        {
+                            //var sw = Stopwatch.StartNew();
+                            await client.InvokeAsync(rtype, act, args);
+                            //sw.Stop();
+
+                            Interlocked.Increment(ref _Invoke);
+                            //Interlocked.Add(ref _Cost, (Int64)(sw.Elapsed.TotalMilliseconds * 1000));
+                        }
+                        catch (ApiException ex)
+                        {
+                            BizLog.Info(ex.Message);
+                        }
+                    }));
+                }
+
+                await TaskEx.WhenAll(ts);
+            }
+            // 间隔>10单任务异步发送
+            else
+            {
+                for (var i = 0; i < count; i++)
+                {
+                    try
+                    {
+                        var sw = Stopwatch.StartNew();
+                        await client.InvokeAsync(rtype, act, args);
+                        sw.Stop();
+
+                        Interlocked.Increment(ref _Invoke);
+                        Interlocked.Add(ref _Cost, (Int64)(sw.Elapsed.TotalMilliseconds * 1000));
+                    }
+                    catch (ApiException ex)
+                    {
+                        BizLog.Info(ex.Message);
+                    }
+
+                    await TaskEx.Delay(sleep);
+                }
+            }
+        }
+        #endregion
+
+        #region 右键菜单
+        private void mi清空_Click(Object sender, EventArgs e)
+        {
+            txtReceive.Clear();
+            BytesOfReceived = 0;
+        }
+
+        private void mi清空2_Click(Object sender, EventArgs e)
+        {
+            txtSend.Clear();
+            BytesOfSent = 0;
+        }
+
+        private void miCheck_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
+        #endregion
+
+        private void cbAction_SelectedIndexChanged(Object sender, EventArgs e)
+        {
+            if (!(sender is ComboBox cb)) return;
+
+            var txt = cb.SelectedItem + "";
+            if (txt.IsNullOrEmpty()) return;
+
+            var set = ApiConfig.Current;
+
+            // 截取参数部分
+            var pis = txt.Substring("(", ")").Split(",");
+
+            // 生成参数
+            var ps = new Dictionary<String, Object>();
+            foreach (var item in pis)
+            {
+                var ss = item.Split(" ");
+                Object val = null;
+                switch (ss[0])
+                {
+                    case "String":
+                        val = "";
+                        break;
+                    case "Int32":
+                        val = 0;
+                        break;
+                    default:
+                        break;
+                }
+                ps[ss[1]] = val;
+            }
+
+            txtSend.Text = ps.ToJson();
+        }
+
+        private void cbMode_SelectedIndexChanged(Object sender, EventArgs e)
+        {
+            var mode = cbMode.SelectedItem + "";
+            var flag = mode == "服务端";
+            numPort.Enabled = flag;
+            cbAddr.Enabled = !flag;
+        }
+    }
+}
\ No newline at end of file
Added +534 -0
diff --git a/XCoder/XApi/FrmMain.designer.cs b/XCoder/XApi/FrmMain.designer.cs
new file mode 100644
index 0000000..d4ae1a6
--- /dev/null
+++ b/XCoder/XApi/FrmMain.designer.cs
@@ -0,0 +1,534 @@
+namespace XApi
+{
+    partial class FrmMain
+    {
+        /// <summary>
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows 窗体设计器生成的代码
+
+        /// <summary>
+        /// 设计器支持所需的方法 - 不要
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.gbReceive = new System.Windows.Forms.GroupBox();
+            this.txtReceive = new System.Windows.Forms.RichTextBox();
+            this.menuReceive = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi日志着色 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
+            this.mi显示应用日志 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示编码日志 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示发送数据 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示接收数据 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示统计信息 = new System.Windows.Forms.ToolStripMenuItem();
+            this.menuSend = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.mi清空2 = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnConnect = new System.Windows.Forms.Button();
+            this.timer1 = new System.Windows.Forms.Timer(this.components);
+            this.fontDialog1 = new System.Windows.Forms.FontDialog();
+            this.colorDialog1 = new System.Windows.Forms.ColorDialog();
+            this.label1 = new System.Windows.Forms.Label();
+            this.lbAddr = new System.Windows.Forms.Label();
+            this.cbMode = new System.Windows.Forms.ComboBox();
+            this.cbAddr = new System.Windows.Forms.ComboBox();
+            this.pnlSetting = new System.Windows.Forms.Panel();
+            this.numPort = new System.Windows.Forms.NumericUpDown();
+            this.label5 = new System.Windows.Forms.Label();
+            this.cbAction = new System.Windows.Forms.ComboBox();
+            this.gbSend = new System.Windows.Forms.GroupBox();
+            this.numThreads = new System.Windows.Forms.NumericUpDown();
+            this.numSleep = new System.Windows.Forms.NumericUpDown();
+            this.txtSend = new System.Windows.Forms.RichTextBox();
+            this.btnSend = new System.Windows.Forms.Button();
+            this.numMutilSend = new System.Windows.Forms.NumericUpDown();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label7 = new System.Windows.Forms.Label();
+            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.label3 = new System.Windows.Forms.Label();
+            this.gbReceive.SuspendLayout();
+            this.menuReceive.SuspendLayout();
+            this.menuSend.SuspendLayout();
+            this.pnlSetting.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numPort)).BeginInit();
+            this.gbSend.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numThreads)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numSleep)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numMutilSend)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // gbReceive
+            // 
+            this.gbReceive.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbReceive.Controls.Add(this.txtReceive);
+            this.gbReceive.Location = new System.Drawing.Point(14, 117);
+            this.gbReceive.Margin = new System.Windows.Forms.Padding(4);
+            this.gbReceive.Name = "gbReceive";
+            this.gbReceive.Padding = new System.Windows.Forms.Padding(4);
+            this.gbReceive.Size = new System.Drawing.Size(978, 298);
+            this.gbReceive.TabIndex = 4;
+            this.gbReceive.TabStop = false;
+            this.gbReceive.Text = "接收区:已接收0字节";
+            // 
+            // txtReceive
+            // 
+            this.txtReceive.ContextMenuStrip = this.menuReceive;
+            this.txtReceive.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.txtReceive.HideSelection = false;
+            this.txtReceive.Location = new System.Drawing.Point(4, 25);
+            this.txtReceive.Margin = new System.Windows.Forms.Padding(4);
+            this.txtReceive.Name = "txtReceive";
+            this.txtReceive.Size = new System.Drawing.Size(970, 269);
+            this.txtReceive.TabIndex = 1;
+            this.txtReceive.Text = "";
+            // 
+            // menuReceive
+            // 
+            this.menuReceive.ImageScalingSize = new System.Drawing.Size(32, 32);
+            this.menuReceive.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStripMenuItem1,
+            this.mi日志着色,
+            this.toolStripMenuItem3,
+            this.mi显示应用日志,
+            this.mi显示编码日志,
+            this.mi显示发送数据,
+            this.mi显示接收数据,
+            this.mi显示统计信息});
+            this.menuReceive.Name = "menuSend";
+            this.menuReceive.Size = new System.Drawing.Size(189, 206);
+            // 
+            // toolStripMenuItem1
+            // 
+            this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+            this.toolStripMenuItem1.Size = new System.Drawing.Size(188, 28);
+            this.toolStripMenuItem1.Text = "清空";
+            this.toolStripMenuItem1.Click += new System.EventHandler(this.mi清空_Click);
+            // 
+            // mi日志着色
+            // 
+            this.mi日志着色.Name = "mi日志着色";
+            this.mi日志着色.Size = new System.Drawing.Size(188, 28);
+            this.mi日志着色.Text = "日志着色";
+            this.mi日志着色.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // toolStripMenuItem3
+            // 
+            this.toolStripMenuItem3.Name = "toolStripMenuItem3";
+            this.toolStripMenuItem3.Size = new System.Drawing.Size(185, 6);
+            // 
+            // mi显示应用日志
+            // 
+            this.mi显示应用日志.Name = "mi显示应用日志";
+            this.mi显示应用日志.Size = new System.Drawing.Size(188, 28);
+            this.mi显示应用日志.Text = "显示应用日志";
+            this.mi显示应用日志.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // mi显示编码日志
+            // 
+            this.mi显示编码日志.Name = "mi显示编码日志";
+            this.mi显示编码日志.Size = new System.Drawing.Size(188, 28);
+            this.mi显示编码日志.Text = "显示编码日志";
+            this.mi显示编码日志.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // mi显示发送数据
+            // 
+            this.mi显示发送数据.Name = "mi显示发送数据";
+            this.mi显示发送数据.Size = new System.Drawing.Size(188, 28);
+            this.mi显示发送数据.Text = "显示发送数据";
+            this.mi显示发送数据.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // mi显示接收数据
+            // 
+            this.mi显示接收数据.Name = "mi显示接收数据";
+            this.mi显示接收数据.Size = new System.Drawing.Size(188, 28);
+            this.mi显示接收数据.Text = "显示接收数据";
+            this.mi显示接收数据.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // mi显示统计信息
+            // 
+            this.mi显示统计信息.Name = "mi显示统计信息";
+            this.mi显示统计信息.Size = new System.Drawing.Size(188, 28);
+            this.mi显示统计信息.Text = "显示统计信息";
+            this.mi显示统计信息.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // menuSend
+            // 
+            this.menuSend.ImageScalingSize = new System.Drawing.Size(32, 32);
+            this.menuSend.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.mi清空2});
+            this.menuSend.Name = "menuSend";
+            this.menuSend.Size = new System.Drawing.Size(117, 32);
+            // 
+            // mi清空2
+            // 
+            this.mi清空2.Name = "mi清空2";
+            this.mi清空2.Size = new System.Drawing.Size(116, 28);
+            this.mi清空2.Text = "清空";
+            this.mi清空2.Click += new System.EventHandler(this.mi清空2_Click);
+            // 
+            // btnConnect
+            // 
+            this.btnConnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnConnect.Location = new System.Drawing.Point(748, 12);
+            this.btnConnect.Margin = new System.Windows.Forms.Padding(4);
+            this.btnConnect.Name = "btnConnect";
+            this.btnConnect.Size = new System.Drawing.Size(100, 44);
+            this.btnConnect.TabIndex = 3;
+            this.btnConnect.Text = "打开";
+            this.btnConnect.UseVisualStyleBackColor = true;
+            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
+            // 
+            // timer1
+            // 
+            this.timer1.Enabled = true;
+            this.timer1.Interval = 300;
+            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(10, 14);
+            this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(62, 18);
+            this.label1.TabIndex = 6;
+            this.label1.Text = "模式:";
+            // 
+            // lbAddr
+            // 
+            this.lbAddr.AutoSize = true;
+            this.lbAddr.Location = new System.Drawing.Point(374, 14);
+            this.lbAddr.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.lbAddr.Name = "lbAddr";
+            this.lbAddr.Size = new System.Drawing.Size(62, 18);
+            this.lbAddr.TabIndex = 7;
+            this.lbAddr.Text = "地址:";
+            // 
+            // cbMode
+            // 
+            this.cbMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbMode.FormattingEnabled = true;
+            this.cbMode.Items.AddRange(new object[] {
+            "服务端",
+            "客户端"});
+            this.cbMode.Location = new System.Drawing.Point(72, 11);
+            this.cbMode.Margin = new System.Windows.Forms.Padding(4);
+            this.cbMode.Name = "cbMode";
+            this.cbMode.Size = new System.Drawing.Size(138, 26);
+            this.cbMode.TabIndex = 9;
+            this.cbMode.SelectedIndexChanged += new System.EventHandler(this.cbMode_SelectedIndexChanged);
+            // 
+            // cbAddr
+            // 
+            this.cbAddr.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cbAddr.FormattingEnabled = true;
+            this.cbAddr.Location = new System.Drawing.Point(444, 11);
+            this.cbAddr.Margin = new System.Windows.Forms.Padding(4);
+            this.cbAddr.Name = "cbAddr";
+            this.cbAddr.Size = new System.Drawing.Size(247, 26);
+            this.cbAddr.TabIndex = 10;
+            // 
+            // pnlSetting
+            // 
+            this.pnlSetting.Controls.Add(this.numPort);
+            this.pnlSetting.Controls.Add(this.label5);
+            this.pnlSetting.Controls.Add(this.cbAddr);
+            this.pnlSetting.Controls.Add(this.label1);
+            this.pnlSetting.Controls.Add(this.lbAddr);
+            this.pnlSetting.Controls.Add(this.cbMode);
+            this.pnlSetting.Location = new System.Drawing.Point(14, 12);
+            this.pnlSetting.Margin = new System.Windows.Forms.Padding(4);
+            this.pnlSetting.Name = "pnlSetting";
+            this.pnlSetting.Size = new System.Drawing.Size(708, 46);
+            this.pnlSetting.TabIndex = 13;
+            // 
+            // numPort
+            // 
+            this.numPort.Location = new System.Drawing.Point(270, 10);
+            this.numPort.Margin = new System.Windows.Forms.Padding(4);
+            this.numPort.Maximum = new decimal(new int[] {
+            65535,
+            0,
+            0,
+            0});
+            this.numPort.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numPort.Name = "numPort";
+            this.numPort.Size = new System.Drawing.Size(94, 28);
+            this.numPort.TabIndex = 16;
+            this.numPort.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.numPort.Value = new decimal(new int[] {
+            777,
+            0,
+            0,
+            0});
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(218, 14);
+            this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(62, 18);
+            this.label5.TabIndex = 17;
+            this.label5.Text = "端口:";
+            // 
+            // cbAction
+            // 
+            this.cbAction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cbAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbAction.FormattingEnabled = true;
+            this.cbAction.Location = new System.Drawing.Point(76, 71);
+            this.cbAction.Margin = new System.Windows.Forms.Padding(4);
+            this.cbAction.Name = "cbAction";
+            this.cbAction.Size = new System.Drawing.Size(470, 26);
+            this.cbAction.TabIndex = 12;
+            this.cbAction.Visible = false;
+            this.cbAction.SelectedIndexChanged += new System.EventHandler(this.cbAction_SelectedIndexChanged);
+            // 
+            // gbSend
+            // 
+            this.gbSend.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbSend.Controls.Add(this.numThreads);
+            this.gbSend.Controls.Add(this.numSleep);
+            this.gbSend.Controls.Add(this.txtSend);
+            this.gbSend.Controls.Add(this.btnSend);
+            this.gbSend.Controls.Add(this.numMutilSend);
+            this.gbSend.Controls.Add(this.label2);
+            this.gbSend.Controls.Add(this.label7);
+            this.gbSend.Location = new System.Drawing.Point(14, 424);
+            this.gbSend.Margin = new System.Windows.Forms.Padding(4);
+            this.gbSend.Name = "gbSend";
+            this.gbSend.Padding = new System.Windows.Forms.Padding(4);
+            this.gbSend.Size = new System.Drawing.Size(978, 126);
+            this.gbSend.TabIndex = 15;
+            this.gbSend.TabStop = false;
+            this.gbSend.Text = "发送区:已发送0字节";
+            // 
+            // numThreads
+            // 
+            this.numThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.numThreads.Location = new System.Drawing.Point(890, 33);
+            this.numThreads.Margin = new System.Windows.Forms.Padding(4);
+            this.numThreads.Maximum = new decimal(new int[] {
+            100000,
+            0,
+            0,
+            0});
+            this.numThreads.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numThreads.Name = "numThreads";
+            this.numThreads.Size = new System.Drawing.Size(78, 28);
+            this.numThreads.TabIndex = 18;
+            this.numThreads.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.toolTip1.SetToolTip(this.numThreads, "模拟多客户端发送,用于压力测试!");
+            this.numThreads.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            // 
+            // numSleep
+            // 
+            this.numSleep.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.numSleep.Location = new System.Drawing.Point(776, 81);
+            this.numSleep.Margin = new System.Windows.Forms.Padding(4);
+            this.numSleep.Maximum = new decimal(new int[] {
+            1000000,
+            0,
+            0,
+            0});
+            this.numSleep.Name = "numSleep";
+            this.numSleep.Size = new System.Drawing.Size(109, 28);
+            this.numSleep.TabIndex = 16;
+            this.numSleep.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.numSleep.Value = new decimal(new int[] {
+            1000,
+            0,
+            0,
+            0});
+            // 
+            // txtSend
+            // 
+            this.txtSend.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtSend.ContextMenuStrip = this.menuSend;
+            this.txtSend.HideSelection = false;
+            this.txtSend.Location = new System.Drawing.Point(0, 28);
+            this.txtSend.Margin = new System.Windows.Forms.Padding(4);
+            this.txtSend.Name = "txtSend";
+            this.txtSend.Size = new System.Drawing.Size(721, 86);
+            this.txtSend.TabIndex = 2;
+            this.txtSend.Text = "";
+            // 
+            // btnSend
+            // 
+            this.btnSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnSend.Location = new System.Drawing.Point(894, 74);
+            this.btnSend.Margin = new System.Windows.Forms.Padding(4);
+            this.btnSend.Name = "btnSend";
+            this.btnSend.Size = new System.Drawing.Size(75, 45);
+            this.btnSend.TabIndex = 1;
+            this.btnSend.Text = "发送";
+            this.btnSend.UseVisualStyleBackColor = true;
+            this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
+            // 
+            // numMutilSend
+            // 
+            this.numMutilSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.numMutilSend.Location = new System.Drawing.Point(776, 33);
+            this.numMutilSend.Margin = new System.Windows.Forms.Padding(4);
+            this.numMutilSend.Maximum = new decimal(new int[] {
+            1000000,
+            0,
+            0,
+            0});
+            this.numMutilSend.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numMutilSend.Name = "numMutilSend";
+            this.numMutilSend.Size = new System.Drawing.Size(109, 28);
+            this.numMutilSend.TabIndex = 14;
+            this.numMutilSend.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.numMutilSend.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            // 
+            // label2
+            // 
+            this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(729, 87);
+            this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(62, 18);
+            this.label2.TabIndex = 17;
+            this.label2.Text = "间隔:";
+            // 
+            // label7
+            // 
+            this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(729, 39);
+            this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(62, 18);
+            this.label7.TabIndex = 15;
+            this.label7.Text = "次数:";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(15, 74);
+            this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(62, 18);
+            this.label3.TabIndex = 16;
+            this.label3.Text = "服务:";
+            // 
+            // FrmMain
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(1000, 568);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.cbAction);
+            this.Controls.Add(this.gbSend);
+            this.Controls.Add(this.pnlSetting);
+            this.Controls.Add(this.btnConnect);
+            this.Controls.Add(this.gbReceive);
+            this.Margin = new System.Windows.Forms.Padding(4);
+            this.Name = "FrmMain";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "Api调试";
+            this.Load += new System.EventHandler(this.FrmMain_Load);
+            this.gbReceive.ResumeLayout(false);
+            this.menuReceive.ResumeLayout(false);
+            this.menuSend.ResumeLayout(false);
+            this.pnlSetting.ResumeLayout(false);
+            this.pnlSetting.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numPort)).EndInit();
+            this.gbSend.ResumeLayout(false);
+            this.gbSend.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numThreads)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numSleep)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numMutilSend)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbReceive;
+        private System.Windows.Forms.Button btnConnect;
+        private System.Windows.Forms.Timer timer1;
+        private System.Windows.Forms.ContextMenuStrip menuSend;
+        private System.Windows.Forms.ToolStripMenuItem mi清空2;
+        private System.Windows.Forms.RichTextBox txtReceive;
+        private System.Windows.Forms.FontDialog fontDialog1;
+        private System.Windows.Forms.ColorDialog colorDialog1;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label lbAddr;
+        private System.Windows.Forms.ComboBox cbMode;
+        private System.Windows.Forms.ComboBox cbAddr;
+        private System.Windows.Forms.Panel pnlSetting;
+        private System.Windows.Forms.ContextMenuStrip menuReceive;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
+        private System.Windows.Forms.GroupBox gbSend;
+        private System.Windows.Forms.NumericUpDown numSleep;
+        private System.Windows.Forms.RichTextBox txtSend;
+        private System.Windows.Forms.Button btnSend;
+        private System.Windows.Forms.NumericUpDown numMutilSend;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.ToolStripMenuItem mi显示统计信息;
+        private System.Windows.Forms.NumericUpDown numThreads;
+        private System.Windows.Forms.ToolStripMenuItem mi显示应用日志;
+        private System.Windows.Forms.ToolStripMenuItem mi显示编码日志;
+        private System.Windows.Forms.ToolTip toolTip1;
+        private System.Windows.Forms.ComboBox cbAction;
+        private System.Windows.Forms.ToolStripMenuItem mi日志着色;
+        private System.Windows.Forms.NumericUpDown numPort;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.ToolStripMenuItem mi显示发送数据;
+        private System.Windows.Forms.ToolStripMenuItem mi显示接收数据;
+    }
+}
+
Added +141 -0
diff --git a/XCoder/XApi/FrmMain.resx b/XCoder/XApi/FrmMain.resx
new file mode 100644
index 0000000..fdafb9b
--- /dev/null
+++ b/XCoder/XApi/FrmMain.resx
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="menuReceive.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>104, 13</value>
+  </metadata>
+  <metadata name="menuSend.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>237, 17</value>
+  </metadata>
+  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="fontDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>352, 17</value>
+  </metadata>
+  <metadata name="colorDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>474, 17</value>
+  </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>601, 17</value>
+  </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>601, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
Added +42 -0
diff --git a/XCoder/XApi/MyApiController.cs b/XCoder/XApi/MyApiController.cs
new file mode 100644
index 0000000..e57d7c9
--- /dev/null
+++ b/XCoder/XApi/MyApiController.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NewLife.Data;
+using NewLife.Remoting;
+using NewLife.Security;
+
+namespace XApi
+{
+    /// <summary>API控制器</summary>
+    //[AllowAnonymous]
+    public class MyApiController
+    {
+        /// <summary>获取指定种类的环境信息</summary>
+        /// <param name="kind"></param>
+        /// <returns></returns>
+        public String Info(String kind)
+        {
+            switch ((kind + "").ToLower())
+            {
+                case "machine": return Environment.MachineName;
+                case "user": return Environment.UserName;
+                case "ip": return NetHelper.MyIP() + "";
+                case "time": return DateTime.Now.ToFullString();
+                default:
+                    throw new ApiException(505, "不支持类型" + kind);
+            }
+        }
+
+        /// <summary>加密数据</summary>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        public Packet Encrypt(Packet data)
+        {
+            //Log.XTrace.WriteLine("加密数据{0:n0}字节", data.Total);
+
+            var buf = data.ToArray().RC4("NewLife".GetBytes());
+
+            return buf;
+        }
+    }
+}
\ No newline at end of file
Modified +91 -11
diff --git a/XCoder/XCoder.csproj b/XCoder/XCoder.csproj
index 43db01f..1e356b7 100644
--- a/XCoder/XCoder.csproj
+++ b/XCoder/XCoder.csproj
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -11,27 +11,37 @@
     <RootNamespace>XCoder</RootNamespace>
     <AssemblyName>XCoder</AssemblyName>
     <ApplicationIcon>leaf.ico</ApplicationIcon>
+    <TargetFrameworkProfile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
     <DebugSymbols>true</DebugSymbols>
     <OutputPath>..\..\XCoder\</OutputPath>
-    <DefineConstants>TRACE;DEBUG;NET4</DefineConstants>
+    <DefineConstants>TRACE;DEBUG</DefineConstants>
     <DebugType>full</DebugType>
     <PlatformTarget>AnyCPU</PlatformTarget>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
     <OutputPath>..\..\XCoder\</OutputPath>
-    <DefineConstants>TRACE;NET4</DefineConstants>
+    <DefineConstants>TRACE</DefineConstants>
     <Optimize>true</Optimize>
     <DebugType>pdbonly</DebugType>
     <PlatformTarget>AnyCPU</PlatformTarget>
+    <WarningLevel>3</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   <PropertyGroup>
-    <ApplicationManifest>app.manifest</ApplicationManifest>
+    <ApplicationManifest>Properties\app.manifest</ApplicationManifest>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="NewLife.Core, Version=7.0.6712.2419, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.Core.7.0.6712.2419\lib\net45\NewLife.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="NewLife.Net, Version=3.2.6700.37161, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.Net.3.2.6700.37161\lib\net45\NewLife.Net.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.configuration" />
     <Reference Include="System.Data" />
@@ -42,11 +52,15 @@
     <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.XML" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="XCode, Version=9.7.6712.2420, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.XCode.9.7.6712.2420\lib\net45\XCode.dll</HintPath>
+    </Reference>
+    <Reference Include="XTemplate, Version=2.0.6700.37161, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.XTemplate.2.0.6700.37161\lib\net45\XTemplate.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="..\NewLife.Core\Properties\AssemblyInfo_.cs">
-      <Link>Properties\AssemblyInfo_.cs</Link>
-    </Compile>
     <Compile Include="Engine\IcoHelper.cs" />
     <Compile Include="Engine\ModelConfig.cs" />
     <Compile Include="FileEncoding\FrmMain.cs">
@@ -61,12 +75,42 @@
     <Compile Include="FolderInfo\FrmMain.Designer.cs">
       <DependentUpon>FrmMain.cs</DependentUpon>
     </Compile>
+    <Compile Include="FolderInfo\FrmSplitFile.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FolderInfo\FrmSplitFile.Designer.cs">
+      <DependentUpon>FrmSplitFile.cs</DependentUpon>
+    </Compile>
     <Compile Include="FrmMDI.cs">
       <SubType>Form</SubType>
     </Compile>
     <Compile Include="FrmMDI.Designer.cs">
       <DependentUpon>FrmMDI.cs</DependentUpon>
     </Compile>
+    <Compile Include="IXForm.cs" />
+    <Compile Include="Tools\FrmSecurity.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmSecurity.Designer.cs">
+      <DependentUpon>FrmSecurity.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XApi\ApiConfig.cs" />
+    <Compile Include="XApi\MyApiController.cs" />
+    <Compile Include="XApi\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="XApi\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XNet\IPPacket.cs" />
+    <Compile Include="XNet\RawSocket.cs" />
+    <Compile Include="XNet\TcpPacket.cs" />
+    <Compile Include="Yun\FrmMap.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Yun\FrmMap.Designer.cs">
+      <DependentUpon>FrmMap.cs</DependentUpon>
+    </Compile>
     <Compile Include="NewModelForm\AddField.cs">
       <SubType>UserControl</SubType>
     </Compile>
@@ -89,6 +133,24 @@
       <DependentUpon>NewModel.cs</DependentUpon>
     </Compile>
     <Compile Include="NewModelForm\WinFormHelper.cs" />
+    <Compile Include="Tools\FrmGPS.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmGPS.Designer.cs">
+      <DependentUpon>FrmGPS.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\FrmInclude.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmInclude.Designer.cs">
+      <DependentUpon>FrmInclude.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmMain.Designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
     <Compile Include="XCom\FrmMain.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -118,6 +180,7 @@
     <Compile Include="XNet\FrmMain.designer.cs">
       <DependentUpon>FrmMain.cs</DependentUpon>
     </Compile>
+    <Compile Include="Yun\MapSetting.cs" />
     <EmbeddedResource Include="FileEncoding\FrmMain.resx">
       <DependentUpon>FrmMain.cs</DependentUpon>
     </EmbeddedResource>
@@ -127,6 +190,15 @@
     <EmbeddedResource Include="FrmMDI.resx">
       <DependentUpon>FrmMDI.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmSecurity.resx">
+      <DependentUpon>FrmSecurity.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="XApi\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Yun\FrmMap.resx">
+      <DependentUpon>FrmMap.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="NewModelForm\AddField.resx">
       <DependentUpon>AddField.cs</DependentUpon>
     </EmbeddedResource>
@@ -205,6 +277,15 @@
     <EmbeddedResource Include="NewModelForm\BaseForm.resx">
       <DependentUpon>BaseForm.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmGPS.resx">
+      <DependentUpon>FrmGPS.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmInclude.resx">
+      <DependentUpon>FrmInclude.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Windows\FrmItems.resx">
       <DependentUpon>FrmItems.cs</DependentUpon>
     </EmbeddedResource>
@@ -254,7 +335,7 @@
     <None Include="App.config">
       <SubType>Designer</SubType>
     </None>
-    <None Include="app.manifest" />
+    <None Include="Properties\app.manifest" />
     <None Include="packages.config" />
     <None Include="Properties\Settings.settings">
       <Generator>SettingsSingleFileGenerator</Generator>
@@ -262,7 +343,6 @@
     </None>
     <EmbeddedResource Include="Template\实体业务\对象操作.xt" />
     <EmbeddedResource Include="Template\实体业务\扩展查询.xt" />
-    <EmbeddedResource Include="Template\实体业务\扩展属性.xt" />
     <EmbeddedResource Include="XCoder.tt">
       <LastGenOutput>XCoder.log</LastGenOutput>
     </EmbeddedResource>
Added +388 -0
diff --git a/XCoder/XCoder40.csproj b/XCoder/XCoder40.csproj
new file mode 100644
index 0000000..6f81e01
--- /dev/null
+++ b/XCoder/XCoder40.csproj
@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>XCoder</RootNamespace>
+    <AssemblyName>XCoder</AssemblyName>
+    <ApplicationIcon>leaf.ico</ApplicationIcon>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\XCoder4\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;NET4</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <OutputPath>..\..\XCoder4\</OutputPath>
+    <DefineConstants>TRACE;NET4</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <WarningLevel>3</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup />
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.configuration" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.EnterpriseServices" />
+    <Reference Include="System.Management" />
+    <Reference Include="System.Messaging" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.XML" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="NewLife.Core, Version=7.0.6712.2419, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.Core.7.0.6712.2419\lib\net40\NewLife.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="NewLife.Net, Version=3.2.6700.37161, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.Net.3.2.6700.37161\lib\net40\NewLife.Net.dll</HintPath>
+    </Reference>
+    <Reference Include="XCode, Version=9.7.6712.2420, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.XCode.9.7.6712.2420\lib\net40\XCode.dll</HintPath>
+    </Reference>
+    <Reference Include="XTemplate, Version=2.0.6700.37161, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NewLife.XTemplate.2.0.6700.37161\lib\net40\XTemplate.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Engine\IcoHelper.cs" />
+    <Compile Include="Engine\ModelConfig.cs" />
+    <Compile Include="FileEncoding\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FileEncoding\FrmMain.Designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="FolderInfo\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FolderInfo\FrmMain.Designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="FolderInfo\FrmSplitFile.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FolderInfo\FrmSplitFile.Designer.cs">
+      <DependentUpon>FrmSplitFile.cs</DependentUpon>
+    </Compile>
+    <Compile Include="FrmMDI.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FrmMDI.Designer.cs">
+      <DependentUpon>FrmMDI.cs</DependentUpon>
+    </Compile>
+    <Compile Include="IXForm.cs" />
+    <Compile Include="NewModelForm\AddField.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="NewModelForm\AddField.Designer.cs">
+      <DependentUpon>AddField.cs</DependentUpon>
+    </Compile>
+    <Compile Include="NewModelForm\AddTable.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="NewModelForm\AddTable.Designer.cs">
+      <DependentUpon>AddTable.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Engine\FileSource.cs" />
+    <Compile Include="Engine\XConfig.cs" />
+    <Compile Include="Engine\XCoderBase.cs" />
+    <Compile Include="NewModelForm\NewModel.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="NewModelForm\NewModel.Designer.cs">
+      <DependentUpon>NewModel.cs</DependentUpon>
+    </Compile>
+    <Compile Include="NewModelForm\WinFormHelper.cs" />
+    <Compile Include="Tools\FrmGPS.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmGPS.Designer.cs">
+      <DependentUpon>FrmGPS.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\FrmInclude.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmInclude.Designer.cs">
+      <DependentUpon>FrmInclude.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmMain.Designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Tools\FrmSecurity.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Tools\FrmSecurity.Designer.cs">
+      <DependentUpon>FrmSecurity.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XApi\MyApiController.cs" />
+    <Compile Include="XCom\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="XCom\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Engine\UIConfig.cs" />
+    <Compile Include="XICO\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="XICO\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XICO\IconFile.cs" />
+    <Compile Include="XApi\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="XApi\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XApi\ApiConfig.cs" />
+    <Compile Include="XNet\NetConfig.cs" />
+    <Compile Include="XNet\WorkModes.cs" />
+    <Compile Include="XRegex\FileResource.cs" />
+    <Compile Include="XRegex\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="XRegex\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XNet\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="XNet\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Yun\FrmMap.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Yun\FrmMap.Designer.cs">
+      <DependentUpon>FrmMap.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Yun\MapSetting.cs" />
+    <EmbeddedResource Include="FileEncoding\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="FolderInfo\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="FrmMDI.resx">
+      <DependentUpon>FrmMDI.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="NewModelForm\AddField.resx">
+      <DependentUpon>AddField.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="NewModelForm\AddTable.resx">
+      <DependentUpon>AddTable.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="NewModelForm\NewModel.resx">
+      <DependentUpon>NewModel.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面ExtAspNet\类名.aspx.cs">
+      <DependentUpon>类名.aspx</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面ExtAspNet\类名Form.aspx.cs">
+      <DependentUpon>类名Form.aspx</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面基类ExtAspNet\MyEntityForm.cs">
+      <SubType>ASPXCodeBehind</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面基类ExtAspNet\MyEntityList.cs">
+      <SubType>ASPXCodeBehind</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面基类ExtAspNet\MyEntityUserControl.cs">
+      <SubType>ASPXCodeBehind</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\实体业务\中文名.Biz.cs" />
+    <Compile Include="NewModelForm\BaseForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="NewModelForm\BaseForm.designer.cs">
+      <DependentUpon>BaseForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\FrmItems.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\FrmItems.Designer.cs">
+      <DependentUpon>FrmItems.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\FrmMain.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\FrmMain.designer.cs">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Engine\Engine.cs" />
+    <Compile Include="Windows\FrmModel.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\FrmModel.Designer.cs">
+      <DependentUpon>FrmModel.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\FrmQuery.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\FrmQuery.Designer.cs">
+      <DependentUpon>FrmQuery.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\FrmSchema.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\FrmSchema.Designer.cs">
+      <DependentUpon>FrmSchema.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\FrmText.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\FrmText.Designer.cs">
+      <DependentUpon>FrmText.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+      <DependentUpon>Settings.settings</DependentUpon>
+    </Compile>
+    <EmbeddedResource Include="NewModelForm\BaseForm.resx">
+      <DependentUpon>BaseForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmGPS.resx">
+      <DependentUpon>FrmGPS.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmInclude.resx">
+      <DependentUpon>FrmInclude.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Tools\FrmSecurity.resx">
+      <DependentUpon>FrmSecurity.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\FrmItems.resx">
+      <DependentUpon>FrmItems.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\FrmModel.resx">
+      <DependentUpon>FrmModel.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\FrmQuery.resx">
+      <DependentUpon>FrmQuery.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\FrmSchema.resx">
+      <DependentUpon>FrmSchema.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Windows\FrmText.resx">
+      <DependentUpon>FrmText.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面\类名.aspx.cs">
+      <DependentUpon>类名.aspx</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面\类名Form.aspx.cs">
+      <DependentUpon>类名Form.aspx</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面基类\MyEntityForm.cs">
+      <SubType>ASPXCodeBehind</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面基类\MyEntityList.cs">
+      <SubType>ASPXCodeBehind</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\页面基类\MyEntityUserControl.cs">
+      <SubType>ASPXCodeBehind</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Template\实体数据\中文名.cs" />
+    <EmbeddedResource Include="Template\纯属性\I中文名.cs" />
+    <EmbeddedResource Include="Template\纯属性\中文名.cs" />
+    <EmbeddedResource Include="Windows\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="leaf.ico" />
+    <EmbeddedResource Include="Template\页面\类名.aspx" />
+    <EmbeddedResource Include="Template\页面\类名Form.aspx" />
+    <EmbeddedResource Include="UpdateInfo.txt" />
+    <EmbeddedResource Include="Template\数据字典\连接名数据字典.htm" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config">
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="packages.config" />
+    <None Include="Properties\app.manifest" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <EmbeddedResource Include="Template\实体业务\对象操作.xt" />
+    <EmbeddedResource Include="Template\实体业务\扩展查询.xt" />
+    <EmbeddedResource Include="XCoder.tt">
+      <LastGenOutput>XCoder.log</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Template\页面ExtAspNet\类名.aspx" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Template\页面ExtAspNet\类名Form.aspx" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="XCom\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="XICO\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="XApi\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="XRegex\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="XNet\FrmMain.resx">
+      <DependentUpon>FrmMain.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Yun\FrmMap.resx">
+      <DependentUpon>FrmMap.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="数据库命名规范.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="XICO\leaf.png" />
+    <EmbeddedResource Include="XRegex\Pattern\Html\无嵌套标记.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\SQL查询\嵌套查询.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\SQL查询\简单.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\平衡组\完整示例.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\平衡组\完整示例固化分组.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\平衡组\标准.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\平衡组\标准固化分组.txt" />
+    <EmbeddedResource Include="XRegex\Pattern\网页\最外层嵌套.txt" />
+    <EmbeddedResource Include="XRegex\Sample\SQL查询\MSSQL表结构.txt" />
+    <EmbeddedResource Include="XRegex\Sample\SQL查询\普通嵌套查询.txt" />
+    <EmbeddedResource Include="XRegex\Sample\SQL查询\普通查询.txt" />
+    <EmbeddedResource Include="XRegex\Sample\平衡组\算术表达式.txt" />
+    <EmbeddedResource Include="XRegex\Sample\网页\最外层嵌套.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
Modified +45 -25
diff --git a/XCoder/XCom/FrmMain.cs b/XCoder/XCom/FrmMain.cs
index 8a89da8..517e1e9 100644
--- a/XCoder/XCom/FrmMain.cs
+++ b/XCoder/XCom/FrmMain.cs
@@ -1,31 +1,38 @@
 using System;
 using System.ComponentModel;
+using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using NewLife.Log;
-using NewLife.Threading;
 using NewLife.Windows;
 using XCoder;
 
 namespace XCom
 {
     [DisplayName("串口调试工具")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
+        /// <summary>业务日志输出</summary>
+        ILog BizLog;
+
         #region 窗体
         public FrmMain()
         {
             InitializeComponent();
 
-            //var asmx = AssemblyX.Entry;
-            //this.Text = asmx.Title;
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
 
             Icon = IcoHelper.GetIcon("串口");
         }
 
-        private void FrmMain_Load(object sender, EventArgs e)
+        private void FrmMain_Load(Object sender, EventArgs e)
         {
+            var log = TextFileLog.Create(null, "Serial_{0:yyyy_MM_dd}.log");
+            BizLog = txtReceive.Combine(log);
+            txtReceive.UseWinFormControl();
+
             txtReceive.SetDefaultStyle(12);
             txtSend.SetDefaultStyle(12);
             numMutilSend.SetDefaultStyle(12);
@@ -33,20 +40,23 @@ namespace XCom
             gbReceive.Tag = gbReceive.Text;
             gbSend.Tag = gbSend.Text;
 
-            //spList.ReceivedString += OnReceived;
-
             var menu = spList.Menu;
             txtReceive.ContextMenuStrip = menu;
 
             // 添加清空
             menu.Items.Insert(0, new ToolStripSeparator());
-            //var ti = menu.Items.Add("清空");
             var ti = new ToolStripMenuItem("清空");
             menu.Items.Insert(0, ti);
             ti.Click += mi清空_Click;
 
             // 加载保存的颜色
             UIConfig.Apply(txtReceive);
+
+            ti = new ToolStripMenuItem("日志着色");
+            ti.Name = "日志着色";
+            menu.Items.Insert(2, ti);
+            ti.Click += miCheck_Click;
+            ti.Checked = XConfig.Current.ColorLog;
         }
         #endregion
 
@@ -66,19 +76,27 @@ namespace XCom
             {
                 var cmd = "AT+SET=00070000000000";
                 st.Send(cmd.GetBytes());
-                //XTrace.WriteLine(cmd);
-                TextControlLog.WriteLog(txtReceive, cmd);
+                BizLog.Info(cmd);
+                //TextControlLog.WriteLog(txtReceive, cmd);
             }
 
             "连接串口{0}".F(st.PortName).SpeechTip();
 
             btnConnect.Text = "关闭";
 
-            BizLog = TextFileLog.Create("SerialLog");
+            var menu = txtReceive.ContextMenuStrip;
+            var mi = menu.Items.Find("日志着色", false).FirstOrDefault() as ToolStripMenuItem;
+
+            var cfg = XConfig.Current;
+            cfg.ColorLog = mi.Checked;
+            cfg.Save();
         }
 
         void Disconnect()
         {
+            //if (spList.Enabled) return;
+            if (btnConnect.Text == "打开") return;
+
             var st = spList.Port;
             if (st != null) st.Disconnected -= (s, e) => this.Invoke(Disconnect);
             spList.Disconnect();
@@ -88,7 +106,7 @@ namespace XCom
             btnConnect.Text = "打开";
         }
 
-        private void btnConnect_Click(object sender, EventArgs e)
+        private void btnConnect_Click(Object sender, EventArgs e)
         {
             var btn = sender as Button;
             if (btn.Text == "打开")
@@ -97,22 +115,18 @@ namespace XCom
                 Disconnect();
         }
 
-        /// <summary>业务日志输出</summary>
-        ILog BizLog;
-
         void OnReceived(Object sender, StringEventArgs e)
         {
             var line = e.Value;
-            //XTrace.UseWinFormWriteLog(txtReceive, line, 100000);
-            TextControlLog.WriteLog(txtReceive, line);
+            //TextControlLog.WriteLog(txtReceive, line);
 
-            if (BizLog != null) BizLog.Info(line);
+            BizLog?.Info(line);
         }
 
         Int32 _pColor = 0;
         Int32 lastReceive = 0;
         Int32 lastSend = 0;
-        private void timer1_Tick(object sender, EventArgs e)
+        private void timer1_Tick(Object sender, EventArgs e)
         {
             var sp = spList.Port;
             if (sp != null)
@@ -137,13 +151,13 @@ namespace XCom
                     lastSend = tcount;
                 }
 
-                //ChangeColor();
-                if (cbColor.Checked) txtReceive.ColourDefault(_pColor);
+                var set = XConfig.Current;
+                if (set.ColorLog) txtReceive.ColourDefault(_pColor);
                 _pColor = txtReceive.TextLength;
             }
         }
 
-        private void btnSend_Click(object sender, EventArgs e)
+        private void btnSend_Click(Object sender, EventArgs e)
         {
             var str = txtSend.Text;
             if (String.IsNullOrEmpty(str))
@@ -170,7 +184,7 @@ namespace XCom
 
             Task.Factory.StartNew(() =>
             {
-                for (int i = 0; i < count; i++)
+                for (var i = 0; i < count; i++)
                 {
                     spList.Send(str);
 
@@ -181,17 +195,23 @@ namespace XCom
         #endregion
 
         #region 右键菜单
-        private void mi清空_Click(object sender, EventArgs e)
+        private void mi清空_Click(Object sender, EventArgs e)
         {
             txtReceive.Clear();
             spList.ClearReceive();
         }
 
-        private void mi清空2_Click(object sender, EventArgs e)
+        private void mi清空2_Click(Object sender, EventArgs e)
         {
             txtSend.Clear();
             spList.ClearSend();
         }
+
+        private void miCheck_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
         #endregion
     }
 }
\ No newline at end of file
Modified +0 -14
diff --git a/XCoder/XCom/FrmMain.designer.cs b/XCoder/XCom/FrmMain.designer.cs
index 3a90bb0..9d8e4a1 100644
--- a/XCoder/XCom/FrmMain.designer.cs
+++ b/XCoder/XCom/FrmMain.designer.cs
@@ -45,7 +45,6 @@
             this.fontDialog1 = new System.Windows.Forms.FontDialog();
             this.colorDialog1 = new System.Windows.Forms.ColorDialog();
             this.spList = new NewLife.Windows.SerialPortList();
-            this.cbColor = new System.Windows.Forms.CheckBox();
             ((System.ComponentModel.ISupportInitialize)(this.numMutilSend)).BeginInit();
             this.gbReceive.SuspendLayout();
             this.gbSend.SuspendLayout();
@@ -217,22 +216,11 @@
             this.spList.TabIndex = 6;
             this.spList.ReceivedString += new System.EventHandler<NewLife.Windows.StringEventArgs>(this.OnReceived);
             // 
-            // cbColor
-            // 
-            this.cbColor.AutoSize = true;
-            this.cbColor.Location = new System.Drawing.Point(423, 14);
-            this.cbColor.Name = "cbColor";
-            this.cbColor.Size = new System.Drawing.Size(72, 16);
-            this.cbColor.TabIndex = 7;
-            this.cbColor.Text = "日志着色";
-            this.cbColor.UseVisualStyleBackColor = true;
-            // 
             // FrmMain
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(565, 386);
-            this.Controls.Add(this.cbColor);
             this.Controls.Add(this.spList);
             this.Controls.Add(this.gbSend);
             this.Controls.Add(this.btnConnect);
@@ -248,7 +236,6 @@
             ((System.ComponentModel.ISupportInitialize)(this.numSleep)).EndInit();
             this.menuSend.ResumeLayout(false);
             this.ResumeLayout(false);
-            this.PerformLayout();
 
         }
 
@@ -270,7 +257,6 @@
         private System.Windows.Forms.ColorDialog colorDialog1;
         private System.Windows.Forms.Label label1;
         private System.Windows.Forms.NumericUpDown numSleep;
-        private System.Windows.Forms.CheckBox cbColor;
     }
 }
 
Modified +32 -31
diff --git a/XCoder/XICO/FrmMain.cs b/XCoder/XICO/FrmMain.cs
index 867fc1f..7cc7ef9 100644
--- a/XCoder/XICO/FrmMain.cs
+++ b/XCoder/XICO/FrmMain.cs
@@ -11,22 +11,25 @@ using XCoder;
 namespace XICO
 {
     [DisplayName("图标水印处理工具")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
         #region 窗口初始化
         public FrmMain()
         {
             InitializeComponent();
 
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
             //AllowDrop = true;
             picSrc.AllowDrop = true;
 
             Icon = IcoHelper.GetIcon("图标");
         }
 
-        private void FrmMain_Shown(object sender, EventArgs e)
+        private void FrmMain_Shown(Object sender, EventArgs e)
         {
-            sfd.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
+            //sfd.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
 
             var ms = FileSource.GetFileResource(null, "XCoder.XICO.leaf.png");
             if (ms != null) picSrc.Image = new Bitmap(ms);
@@ -39,7 +42,7 @@ namespace XICO
         #endregion
 
         #region 水印
-        private void label3_Click(object sender, EventArgs e)
+        private void label3_Click(Object sender, EventArgs e)
         {
             fontDialog1.Font = (Font)lbFont.Tag;
             if (fontDialog1.ShowDialog() != DialogResult.OK) return;
@@ -51,7 +54,7 @@ namespace XICO
             MakeWater();
         }
 
-        private void label4_Click(object sender, EventArgs e)
+        private void label4_Click(Object sender, EventArgs e)
         {
             colorDialog1.Color = lbFont.ForeColor;
             if (colorDialog1.ShowDialog() != DialogResult.OK) return;
@@ -62,11 +65,11 @@ namespace XICO
             MakeWater();
         }
 
-        private void btnWater_Click(object sender, EventArgs e)
+        private void btnWater_Click(Object sender, EventArgs e)
         {
         }
 
-        private void txt_TextChanged(object sender, EventArgs e)
+        private void txt_TextChanged(Object sender, EventArgs e)
         {
             //var str = txt.Text;
             //if (String.IsNullOrEmpty(str)) str = "字体样板";
@@ -75,7 +78,7 @@ namespace XICO
             MakeWater();
         }
 
-        private void numX_ValueChanged(object sender, EventArgs e)
+        private void numX_ValueChanged(Object sender, EventArgs e)
         {
             MakeWater();
         }
@@ -109,7 +112,7 @@ namespace XICO
             return bmp;
         }
 
-        private void btnSave_Click(object sender, EventArgs e)
+        private void btnSave_Click(Object sender, EventArgs e)
         {
             var bmp = MakeWater(true);
 
@@ -123,14 +126,15 @@ namespace XICO
         #endregion
 
         #region 图标
-        private void btnMakeICO_Click(object sender, EventArgs e)
+        private void btnMakeICO_Click(Object sender, EventArgs e)
         {
             var list = new List<Int32>();
             foreach (var item in groupBox2.Controls)
             {
                 var chk = item as CheckBox;
-                if (chk != null && chk.Checked) list.Add(Int16.Parse(chk.Name.Substring(3)));
+                if (chk != null && chk.Checked) list.Add(chk.Name.Substring(3).ToInt());
             }
+            list.Sort();
 
             if (list.Count < 1)
             {
@@ -141,7 +145,8 @@ namespace XICO
             var bmp = MakeWater(true);
 
             var ms = new MemoryStream();
-            IconFile.Convert(bmp, ms, list.ToArray(), new Int32[] { 8, 32 });
+            //IconFile.Convert(bmp, ms, list.ToArray(), new Int32[] { 8, 32 });
+            IconFile.Convert(bmp, ms, list.ToArray(), new Int32[] { 32 });
 
             //sfd.DefaultExt = "ico";
             sfd.Filter = "ICO图标(*.ico)|*.ico";
@@ -153,36 +158,32 @@ namespace XICO
         #endregion
 
         #region 图片加载
-        private void picSrc_DragDrop(object sender, DragEventArgs e)
+        private void picSrc_DragDrop(Object sender, DragEventArgs e)
         {
             var fs = (String[])e.Data.GetData(DataFormats.FileDrop);
             if (fs != null && fs.Length > 0)
             {
-                try
-                {
-                    var fi = fs[0];
-                    sfd.FileName = fi;
-                    picSrc.Load(fi);
+                var fi = fs[0];
+                sfd.FileName = fi;
 
-                    // 如果是图标,读取信息
-                    if (fi.EndsWithIgnoreCase(".ico"))
+                // 如果是图标,读取信息
+                if (fi.EndsWithIgnoreCase(".ico"))
+                {
+                    var ico = new IconFile(fi);
+                    //ico.Sort();
+                    var sb = new StringBuilder();
+                    foreach (var item in ico.Items)
                     {
-                        var ico = new IconFile(fi);
-                        ico.Sort();
-                        var sb = new StringBuilder();
-                        foreach (var item in ico.Items)
-                        {
-                            if (sb.Length > 0) sb.Append(",");
-                            sb.AppendFormat("{0}*{1}", item.Width, item.BitCount);
-                        }
-                        MessageBox.Show(sb.ToString());
+                        if (sb.Length > 0) sb.AppendLine();
+                        sb.AppendFormat("{0}*{1}*{2}", item.Width, item.Height, item.BitCount);
                     }
+                    MessageBox.Show(sb.ToString());
                 }
-                catch { }
+                picSrc.Load(fi);
             }
         }
 
-        private void picSrc_DragEnter(object sender, DragEventArgs e)
+        private void picSrc_DragEnter(Object sender, DragEventArgs e)
         {
             if (e.Data.GetDataPresent(DataFormats.FileDrop))
                 e.Effect = DragDropEffects.Link;
Modified +132 -81
diff --git a/XCoder/XICO/FrmMain.designer.cs b/XCoder/XICO/FrmMain.designer.cs
index c6f478b..068d06a 100644
--- a/XCoder/XICO/FrmMain.designer.cs
+++ b/XCoder/XICO/FrmMain.designer.cs
@@ -47,14 +47,17 @@
             this.btnSave = new System.Windows.Forms.Button();
             this.groupBox1 = new System.Windows.Forms.GroupBox();
             this.groupBox2 = new System.Windows.Forms.GroupBox();
+            this.chk16 = new System.Windows.Forms.CheckBox();
+            this.chk24 = new System.Windows.Forms.CheckBox();
+            this.chk32 = new System.Windows.Forms.CheckBox();
             this.chk48 = new System.Windows.Forms.CheckBox();
-            this.chk256 = new System.Windows.Forms.CheckBox();
-            this.chk128 = new System.Windows.Forms.CheckBox();
             this.chk64 = new System.Windows.Forms.CheckBox();
-            this.chk32 = new System.Windows.Forms.CheckBox();
-            this.chk16 = new System.Windows.Forms.CheckBox();
+            this.chk128 = new System.Windows.Forms.CheckBox();
+            this.chk256 = new System.Windows.Forms.CheckBox();
             this.sfd = new System.Windows.Forms.SaveFileDialog();
-            this.chk24 = new System.Windows.Forms.CheckBox();
+            this.chb96 = new System.Windows.Forms.CheckBox();
+            this.chb512 = new System.Windows.Forms.CheckBox();
+            this.chb768 = new System.Windows.Forms.CheckBox();
             ((System.ComponentModel.ISupportInitialize)(this.picSrc)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.picDes)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.numX)).BeginInit();
@@ -108,7 +111,7 @@
             // txt
             // 
             this.txt.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
-            this.txt.Location = new System.Drawing.Point(55, 22);
+            this.txt.Location = new System.Drawing.Point(57, 22);
             this.txt.Name = "txt";
             this.txt.Size = new System.Drawing.Size(106, 21);
             this.txt.TabIndex = 1;
@@ -131,11 +134,11 @@
             // 
             this.btnMakeICO.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.btnMakeICO.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
-            this.btnMakeICO.Location = new System.Drawing.Point(154, 74);
+            this.btnMakeICO.Location = new System.Drawing.Point(263, 41);
             this.btnMakeICO.Name = "btnMakeICO";
-            this.btnMakeICO.Size = new System.Drawing.Size(73, 36);
+            this.btnMakeICO.Size = new System.Drawing.Size(57, 36);
             this.btnMakeICO.TabIndex = 8;
-            this.btnMakeICO.Text = "存图标";
+            this.btnMakeICO.Text = "保存";
             this.btnMakeICO.UseVisualStyleBackColor = true;
             this.btnMakeICO.Click += new System.EventHandler(this.btnMakeICO_Click);
             // 
@@ -239,11 +242,11 @@
             // 
             this.btnSave.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.btnSave.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
-            this.btnSave.Location = new System.Drawing.Point(179, 77);
+            this.btnSave.Location = new System.Drawing.Point(144, 77);
             this.btnSave.Name = "btnSave";
-            this.btnSave.Size = new System.Drawing.Size(94, 35);
+            this.btnSave.Size = new System.Drawing.Size(50, 35);
             this.btnSave.TabIndex = 16;
-            this.btnSave.Text = "保存图片";
+            this.btnSave.Text = "保存";
             this.btnSave.UseVisualStyleBackColor = true;
             this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
             // 
@@ -263,13 +266,16 @@
             this.groupBox1.Controls.Add(this.label4);
             this.groupBox1.Location = new System.Drawing.Point(12, 12);
             this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Size = new System.Drawing.Size(279, 123);
+            this.groupBox1.Size = new System.Drawing.Size(197, 123);
             this.groupBox1.TabIndex = 17;
             this.groupBox1.TabStop = false;
             this.groupBox1.Text = "水印";
             // 
             // groupBox2
             // 
+            this.groupBox2.Controls.Add(this.chb768);
+            this.groupBox2.Controls.Add(this.chb512);
+            this.groupBox2.Controls.Add(this.chb96);
             this.groupBox2.Controls.Add(this.chk16);
             this.groupBox2.Controls.Add(this.chk24);
             this.groupBox2.Controls.Add(this.chk32);
@@ -278,13 +284,55 @@
             this.groupBox2.Controls.Add(this.chk128);
             this.groupBox2.Controls.Add(this.chk256);
             this.groupBox2.Controls.Add(this.btnMakeICO);
-            this.groupBox2.Location = new System.Drawing.Point(295, 12);
+            this.groupBox2.Location = new System.Drawing.Point(212, 12);
             this.groupBox2.Name = "groupBox2";
-            this.groupBox2.Size = new System.Drawing.Size(233, 120);
+            this.groupBox2.Size = new System.Drawing.Size(329, 120);
             this.groupBox2.TabIndex = 18;
             this.groupBox2.TabStop = false;
             this.groupBox2.Text = "图标";
             // 
+            // chk16
+            // 
+            this.chk16.AutoSize = true;
+            this.chk16.Checked = true;
+            this.chk16.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chk16.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chk16.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chk16.Location = new System.Drawing.Point(6, 12);
+            this.chk16.Name = "chk16";
+            this.chk16.Size = new System.Drawing.Size(77, 26);
+            this.chk16.TabIndex = 11;
+            this.chk16.Text = "16*16";
+            this.chk16.UseVisualStyleBackColor = true;
+            // 
+            // chk24
+            // 
+            this.chk24.AutoSize = true;
+            this.chk24.Checked = true;
+            this.chk24.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chk24.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chk24.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chk24.Location = new System.Drawing.Point(83, 12);
+            this.chk24.Name = "chk24";
+            this.chk24.Size = new System.Drawing.Size(77, 26);
+            this.chk24.TabIndex = 12;
+            this.chk24.Text = "24*24";
+            this.chk24.UseVisualStyleBackColor = true;
+            // 
+            // chk32
+            // 
+            this.chk32.AutoSize = true;
+            this.chk32.Checked = true;
+            this.chk32.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chk32.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chk32.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chk32.Location = new System.Drawing.Point(160, 12);
+            this.chk32.Name = "chk32";
+            this.chk32.Size = new System.Drawing.Size(77, 26);
+            this.chk32.TabIndex = 13;
+            this.chk32.Text = "32*32";
+            this.chk32.UseVisualStyleBackColor = true;
+            // 
             // chk48
             // 
             this.chk48.AutoSize = true;
@@ -292,39 +340,13 @@
             this.chk48.CheckState = System.Windows.Forms.CheckState.Checked;
             this.chk48.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.chk48.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk48.Location = new System.Drawing.Point(6, 44);
+            this.chk48.Location = new System.Drawing.Point(243, 12);
             this.chk48.Name = "chk48";
             this.chk48.Size = new System.Drawing.Size(77, 26);
             this.chk48.TabIndex = 14;
             this.chk48.Text = "48*48";
             this.chk48.UseVisualStyleBackColor = true;
             // 
-            // chk256
-            // 
-            this.chk256.AutoSize = true;
-            this.chk256.Checked = true;
-            this.chk256.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.chk256.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.chk256.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk256.Location = new System.Drawing.Point(6, 80);
-            this.chk256.Name = "chk256";
-            this.chk256.Size = new System.Drawing.Size(97, 26);
-            this.chk256.TabIndex = 17;
-            this.chk256.Text = "256*256";
-            this.chk256.UseVisualStyleBackColor = true;
-            // 
-            // chk128
-            // 
-            this.chk128.AutoSize = true;
-            this.chk128.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.chk128.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk128.Location = new System.Drawing.Point(150, 44);
-            this.chk128.Name = "chk128";
-            this.chk128.Size = new System.Drawing.Size(97, 26);
-            this.chk128.TabIndex = 16;
-            this.chk128.Text = "128*128";
-            this.chk128.UseVisualStyleBackColor = true;
-            // 
             // chk64
             // 
             this.chk64.AutoSize = true;
@@ -332,65 +354,91 @@
             this.chk64.CheckState = System.Windows.Forms.CheckState.Checked;
             this.chk64.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.chk64.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk64.Location = new System.Drawing.Point(79, 44);
+            this.chk64.Location = new System.Drawing.Point(6, 46);
             this.chk64.Name = "chk64";
             this.chk64.Size = new System.Drawing.Size(77, 26);
             this.chk64.TabIndex = 15;
             this.chk64.Text = "64*64";
             this.chk64.UseVisualStyleBackColor = true;
             // 
-            // chk32
+            // chk128
             // 
-            this.chk32.AutoSize = true;
-            this.chk32.Checked = true;
-            this.chk32.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.chk32.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.chk32.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk32.Location = new System.Drawing.Point(79, 12);
-            this.chk32.Name = "chk32";
-            this.chk32.Size = new System.Drawing.Size(77, 26);
-            this.chk32.TabIndex = 12;
-            this.chk32.Text = "32*32";
-            this.chk32.UseVisualStyleBackColor = true;
+            this.chk128.AutoSize = true;
+            this.chk128.Checked = true;
+            this.chk128.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chk128.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chk128.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chk128.Location = new System.Drawing.Point(160, 46);
+            this.chk128.Name = "chk128";
+            this.chk128.Size = new System.Drawing.Size(97, 26);
+            this.chk128.TabIndex = 17;
+            this.chk128.Text = "128*128";
+            this.chk128.UseVisualStyleBackColor = true;
             // 
-            // chk16
+            // chk256
             // 
-            this.chk16.AutoSize = true;
-            this.chk16.Checked = true;
-            this.chk16.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.chk16.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.chk16.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk16.Location = new System.Drawing.Point(6, 12);
-            this.chk16.Name = "chk16";
-            this.chk16.Size = new System.Drawing.Size(77, 26);
-            this.chk16.TabIndex = 11;
-            this.chk16.Text = "16*16";
-            this.chk16.UseVisualStyleBackColor = true;
+            this.chk256.AutoSize = true;
+            this.chk256.Checked = true;
+            this.chk256.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chk256.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chk256.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chk256.Location = new System.Drawing.Point(6, 80);
+            this.chk256.Name = "chk256";
+            this.chk256.Size = new System.Drawing.Size(97, 26);
+            this.chk256.TabIndex = 18;
+            this.chk256.Text = "256*256";
+            this.chk256.UseVisualStyleBackColor = true;
             // 
             // sfd
             // 
             this.sfd.Filter = "PNG图片(*.png)|*.png|ICO图标(*.ico)|*.ico|所有文件(*.*)|*.*";
             // 
-            // chk24
-            // 
-            this.chk24.AutoSize = true;
-            this.chk24.Checked = true;
-            this.chk24.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.chk24.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.chk24.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
-            this.chk24.Location = new System.Drawing.Point(150, 14);
-            this.chk24.Name = "chk24";
-            this.chk24.Size = new System.Drawing.Size(77, 26);
-            this.chk24.TabIndex = 13;
-            this.chk24.Text = "24*24";
-            this.chk24.UseVisualStyleBackColor = true;
+            // chb96
+            // 
+            this.chb96.AutoSize = true;
+            this.chb96.Checked = true;
+            this.chb96.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chb96.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chb96.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chb96.Location = new System.Drawing.Point(83, 46);
+            this.chb96.Name = "chb96";
+            this.chb96.Size = new System.Drawing.Size(77, 26);
+            this.chb96.TabIndex = 16;
+            this.chb96.Text = "96*96";
+            this.chb96.UseVisualStyleBackColor = true;
+            // 
+            // chb512
+            // 
+            this.chb512.AutoSize = true;
+            this.chb512.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chb512.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chb512.Location = new System.Drawing.Point(109, 80);
+            this.chb512.Name = "chb512";
+            this.chb512.Size = new System.Drawing.Size(97, 26);
+            this.chb512.TabIndex = 19;
+            this.chb512.Text = "512*512";
+            this.chb512.UseVisualStyleBackColor = true;
+            // 
+            // chb768
+            // 
+            this.chb768.AutoSize = true;
+            this.chb768.Checked = true;
+            this.chb768.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chb768.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.chb768.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(0)))), ((int)(((byte)(192)))));
+            this.chb768.Location = new System.Drawing.Point(212, 80);
+            this.chb768.Name = "chb768";
+            this.chb768.Size = new System.Drawing.Size(97, 26);
+            this.chb768.TabIndex = 20;
+            this.chb768.Text = "768*768";
+            this.chb768.UseVisualStyleBackColor = true;
             // 
             // FrmMain
             // 
             this.AllowDrop = true;
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(540, 414);
+            this.ClientSize = new System.Drawing.Size(544, 414);
             this.Controls.Add(this.groupBox2);
             this.Controls.Add(this.groupBox1);
             this.Controls.Add(this.picDes);
@@ -440,6 +488,9 @@
         private System.Windows.Forms.CheckBox chk128;
         private System.Windows.Forms.CheckBox chk256;
         private System.Windows.Forms.SaveFileDialog sfd;
+        private System.Windows.Forms.CheckBox chb768;
+        private System.Windows.Forms.CheckBox chb512;
+        private System.Windows.Forms.CheckBox chb96;
     }
 }
 
Modified +114 -112
diff --git a/XCoder/XICO/IconFile.cs b/XCoder/XICO/IconFile.cs
index 82ea55c..a1752c5 100644
--- a/XCoder/XICO/IconFile.cs
+++ b/XCoder/XICO/IconFile.cs
@@ -1,10 +1,11 @@
 using System;
-using System.Linq;
 using System.Collections;
 using System.Collections.Generic;
 using System.Drawing;
 using System.Drawing.Imaging;
 using System.IO;
+using System.Linq;
+using System.Xml.Serialization;
 
 namespace XICO
 {
@@ -90,9 +91,11 @@ namespace XICO
         /// <summary>排序</summary>
         public void Sort()
         {
-            var list = Items.OrderBy(e => e.Width).OrderBy(e => e.BitCount).ToList();
+            var list = Items.OrderByDescending(e => e.Width == 0 ? 256 : e.Width).ThenByDescending(e => e.BitCount).ToList();
             Items.Clear();
             Items.AddRange(list);
+
+            ResetOffset();
         }
 
         /// <summary>根据索引返回图形</summary>
@@ -117,6 +120,7 @@ namespace XICO
             item.Size = (UInt32)item.Data.Length;
             item.BitCount = (UInt16)bit;
 
+            if (size >= 256) size = 0;
             item.Width = (Byte)size;
             item.Height = (Byte)size;
 
@@ -199,6 +203,11 @@ namespace XICO
             }
         }
 
+        /// <summary>转换源图片到目标ICO文件,指定大小和位深</summary>
+        /// <param name="bmp"></param>
+        /// <param name="des"></param>
+        /// <param name="sizes"></param>
+        /// <param name="bits"></param>
         public static void Convert(Image bmp, Stream des, Int32[] sizes, Int32[] bits)
         {
             var ico = new IconFile();
@@ -220,42 +229,47 @@ namespace XICO
 
         public class IconItem
         {
+            /*
+typedef struct
+{
+    BYTE        bWidth;          // Width, in pixels, of the image
+    BYTE        bHeight;         // Height, in pixels, of the image
+    BYTE        bColorCount;     // Number of colors in image (0 if >=8bpp)
+    BYTE        bReserved;       // Reserved ( must be 0)
+    WORD        wPlanes;         // Color Planes
+    WORD        wBitCount;       // Bits per pixel
+    DWORD       dwBytesInRes;    // How many bytes in this resource?
+    DWORD       dwImageOffset;   // Where in the file is this image?
+} ICONDIRENTRY, *LPICONDIRENTRY;
+             */
             #region 属性
-            private byte _Width = 16;
             /// <summary>图像宽度,以象素为单位。一个字节</summary>
-            public byte Width { get { return _Width; } set { _Width = value; } }
+            public Byte Width { get; set; } = 16;
 
-            private byte _Height = 16;
             /// <summary>图像高度,以象素为单位。一个字节</summary>
-            public byte Height { get { return _Height; } set { _Height = value; } }
+            public Byte Height { get; set; } = 16;
 
-            private byte _ColorCount = 0;
             /// <summary>图像中的颜色数(如果是>=8bpp的位图则为0)</summary>
-            public byte ColorCount { get { return _ColorCount; } set { _ColorCount = value; } }
+            public Byte ColorCount { get; set; }
 
-            private byte _Reserved = 0;        //4 
             /// <summary>保留字必须是0</summary>
-            public byte Reserved { get { return _Reserved; } set { _Reserved = value; } }
+            public Byte Reserved { get; set; }
 
-            private UInt16 _Planes = 1;
             /// <summary>为目标设备说明位面数,其值将总是被设为1</summary>
-            public UInt16 Planes { get { return _Planes; } set { _Planes = value; } }
+            public UInt16 Planes { get; set; } = 1;
 
-            private UInt16 _BitCount = 32;      //8
             /// <summary>每象素所占位数。</summary>
-            public UInt16 BitCount { get { return _BitCount; } set { _BitCount = value; } }
+            public UInt16 BitCount { get; set; } = 32;      //8
 
-            private UInt32 _Size = 0;
             /// <summary>字节大小。</summary>
-            public UInt32 Size { get { return _Size; } set { _Size = value; } }
+            public UInt32 Size { get; set; }
 
-            private UInt32 _Offset = 0;         //16
             /// <summary>起点偏移位置。</summary>
-            public UInt32 Offset { get { return _Offset; } set { _Offset = value; } }
+            public UInt32 Offset { get; set; }
 
-            private byte[] _Data;
             /// <summary>图形数据</summary>
-            public byte[] Data { get { return _Data; } set { _Data = value; } }
+            [XmlIgnore]
+            public Byte[] Data { get; set; }
             #endregion
 
             #region 构造
@@ -267,20 +281,20 @@ namespace XICO
             #region 方法
             public IconItem Load(BinaryReader reader)
             {
-                _Width = reader.ReadByte();
-                _Height = reader.ReadByte();
-                _ColorCount = reader.ReadByte();
-                _Reserved = reader.ReadByte();
+                Width = reader.ReadByte();
+                Height = reader.ReadByte();
+                ColorCount = reader.ReadByte();
+                Reserved = reader.ReadByte();
 
-                _Planes = reader.ReadUInt16();
-                _BitCount = reader.ReadUInt16();
-                _Size = reader.ReadUInt32();
-                _Offset = reader.ReadUInt32();
+                Planes = reader.ReadUInt16();
+                BitCount = reader.ReadUInt16();
+                Size = reader.ReadUInt32();
+                Offset = reader.ReadUInt32();
 
                 var ms = reader.BaseStream;
                 var p = ms.Position;
-                ms.Position = _Offset;
-                _Data = reader.ReadBytes((Int32)_Size);
+                ms.Position = Offset;
+                Data = reader.ReadBytes((Int32)Size);
                 ms.Position = p;
 
                 return this;
@@ -288,15 +302,15 @@ namespace XICO
 
             public IconItem Save(BinaryWriter writer)
             {
-                writer.Write(_Width);
-                writer.Write(_Height);
-                writer.Write(_ColorCount);
-                writer.Write(_Reserved);
+                writer.Write(Width);
+                writer.Write(Height);
+                writer.Write(ColorCount);
+                writer.Write(Reserved);
 
-                writer.Write(_Planes);
-                writer.Write(_BitCount);
-                writer.Write(_Size);
-                writer.Write(_Offset);
+                writer.Write(Planes);
+                writer.Write(BitCount);
+                writer.Write(Size);
+                writer.Write(Offset);
 
                 return this;
             }
@@ -308,130 +322,118 @@ namespace XICO
             #region 属性
             public IList<Color> ColorTable = new List<Color>();
 
-            private UInt32 biSize = 40;
             /// <summary>
             /// 占4位,位图信息头(Bitmap Info Header)的长度,一般为$28  
             /// </summary>
-            public UInt32 InfoSize { get { return biSize; } set { biSize = value; } }
+            public UInt32 InfoSize { get; set; } = 40;
 
-            private UInt32 biWidth;
             /// <summary>
             /// 占4位,位图的宽度,以象素为单位
             /// </summary>
-            public UInt32 Width { get { return biWidth; } set { biWidth = value; } }
+            public UInt32 Width { get; set; }
 
-            private UInt32 biHeight;
             /// <summary>
             /// 占4位,位图的高度,以象素为单位  
             /// </summary>
-            public UInt32 Height { get { return biHeight; } set { biHeight = value; } }
+            public UInt32 Height { get; set; }
 
-            private UInt16 biPlanes = 1;
             /// <summary>
             /// 占2位,位图的位面数(注:该值将总是1)  
             /// </summary>
-            public UInt16 Planes { get { return biPlanes; } set { biPlanes = value; } }
+            public UInt16 Planes { get; set; } = 1;
 
-            private UInt16 biBitCount;
             /// <summary>
             /// 占2位,每个象素的位数,设为32(32Bit位图)  
             /// </summary>
-            public UInt16 BitCount { get { return biBitCount; } set { biBitCount = value; } }
+            public UInt16 BitCount { get; set; }
 
-            private UInt32 biCompression = 0;
             /// <summary>
             /// 占4位,压缩说明,设为0(不压缩)   
             /// </summary>
-            public UInt32 Compression { get { return biCompression; } set { biCompression = value; } }
+            public UInt32 Compression { get; set; }
 
-            private UInt32 biSizeImage;
             /// <summary>
             /// 占4位,用字节数表示的位图数据的大小。该数必须是4的倍数  
             /// </summary>
-            public UInt32 SizeImage { get { return biSizeImage; } set { biSizeImage = value; } }
+            public UInt32 SizeImage { get; set; }
 
-            private UInt32 biXPelsPerMeter;
             /// <summary>
             ///  占4位,用象素/米表示的水平分辨率 
             /// </summary>
-            public UInt32 XPelsPerMeter { get { return biXPelsPerMeter; } set { biXPelsPerMeter = value; } }
+            public UInt32 XPelsPerMeter { get; set; }
 
-            private UInt32 biYPelsPerMeter;
             /// <summary>
             /// 占4位,用象素/米表示的垂直分辨率  
             /// </summary>
-            public UInt32 YPelsPerMeter { get { return biYPelsPerMeter; } set { biYPelsPerMeter = value; } }
+            public UInt32 YPelsPerMeter { get; set; }
 
-            private UInt32 biClrUsed;
             /// <summary>
             /// 占4位,位图使用的颜色数  
             /// </summary>
-            public UInt32 ClrUsed { get { return biClrUsed; } set { biClrUsed = value; } }
+            public UInt32 ClrUsed { get; set; }
 
-            private UInt32 biClrImportant;
             /// <summary>占4位,指定重要的颜色数(到此处刚好40个字节,$28)</summary>
-            public UInt32 ClrImportant { get { return biClrImportant; } set { biClrImportant = value; } }
+            public UInt32 ClrImportant { get; set; }
 
-            private Bitmap _IconBitMap;
             /// <summary>图形</summary>
-            public Bitmap IconBmp { get { return _IconBitMap; } set { _IconBitMap = value; } }
+            public Bitmap IconBmp { get; set; }
             #endregion
 
-            public BitmapInfo(byte[] data)
+            public BitmapInfo(Byte[] data)
             {
                 var reader = new BinaryReader(new MemoryStream(data));
 
                 #region 基本数据
-                biSize = reader.ReadUInt32();
-                if (biSize != 40) return;
-
-                biWidth = reader.ReadUInt32();
-                biHeight = reader.ReadUInt32();
-                biPlanes = reader.ReadUInt16();
-                biBitCount = reader.ReadUInt16();
-                biCompression = reader.ReadUInt32();
-                biSizeImage = reader.ReadUInt32();
-                biXPelsPerMeter = reader.ReadUInt32();
-                biYPelsPerMeter = reader.ReadUInt32();
-                biClrUsed = reader.ReadUInt32();
-                biClrImportant = reader.ReadUInt32();
+                InfoSize = reader.ReadUInt32();
+                if (InfoSize != 40) return;
+
+                Width = reader.ReadUInt32();
+                Height = reader.ReadUInt32();
+                Planes = reader.ReadUInt16();
+                BitCount = reader.ReadUInt16();
+                Compression = reader.ReadUInt32();
+                SizeImage = reader.ReadUInt32();
+                XPelsPerMeter = reader.ReadUInt32();
+                YPelsPerMeter = reader.ReadUInt32();
+                ClrUsed = reader.ReadUInt32();
+                ClrImportant = reader.ReadUInt32();
                 #endregion
 
-                Int32 count = RgbCount();
+                var count = RgbCount();
                 if (count == -1) return;
 
-                for (Int32 i = 0; i != count; i++)
+                for (var i = 0; i != count; i++)
                 {
-                    byte Blue = reader.ReadByte();
-                    byte Green = reader.ReadByte();
-                    byte Red = reader.ReadByte();
-                    byte Reserved = reader.ReadByte();
-                    ColorTable.Add(Color.FromArgb((Int32)Reserved, (Int32)Red, (Int32)Green, (Int32)Blue));
+                    var Blue = reader.ReadByte();
+                    var Green = reader.ReadByte();
+                    var Red = reader.ReadByte();
+                    var Reserved = reader.ReadByte();
+                    ColorTable.Add(Color.FromArgb(Reserved, Red, Green, Blue));
                 }
 
-                Int32 Size = (Int32)(biBitCount * biWidth) / 8;       // 象素的大小*象素数 /字节数              
-                if ((double)Size < biBitCount * biWidth / 8) Size++;       //如果是 宽19*4(16色)/8 =9.5 就+1;
-                if (Size < 4) Size = 4;
-                byte[] WidthByte = new byte[Size];
+                var size = (Int32)(BitCount * Width) / 8;       // 象素的大小*象素数 /字节数              
+                if ((Double)size < BitCount * Width / 8) size++;       //如果是 宽19*4(16色)/8 =9.5 就+1;
+                if (size < 4) size = 4;
+                var WidthByte = new Byte[size];
 
-                _IconBitMap = new Bitmap((Int32)biWidth, (Int32)(biHeight / 2));
-                for (Int32 i = (Int32)(biHeight / 2); i != 0; i--)
+                IconBmp = new Bitmap((Int32)Width, (Int32)(Height / 2));
+                for (var i = (Int32)(Height / 2); i != 0; i--)
                 {
                     //for (Int32 z = 0; z != Size; z++)
                     //{
                     //    WidthByte[z] = data[idx + z];
                     //}
                     //idx += Size;
-                    WidthByte = reader.ReadBytes(Size);
-                    IconSet(_IconBitMap, i - 1, WidthByte);
+                    WidthByte = reader.ReadBytes(size);
+                    IconSet(IconBmp, i - 1, WidthByte);
                 }
 
                 //取掩码
-                Int32 MaskSize = (Int32)(biWidth / 8);
-                if ((double)MaskSize < biWidth / 8) MaskSize++;       //如果是 宽19*4(16色)/8 =9.5 就+1;
+                var MaskSize = (Int32)(Width / 8);
+                if ((Double)MaskSize < Width / 8) MaskSize++;       //如果是 宽19*4(16色)/8 =9.5 就+1;
                 if (MaskSize < 4) MaskSize = 4;
-                byte[] MashByte = new byte[MaskSize];
-                for (Int32 i = (Int32)(biHeight / 2); i != 0; i--)
+                var MashByte = new Byte[MaskSize];
+                for (var i = (Int32)(Height / 2); i != 0; i--)
                 {
                     //for (Int32 z = 0; z != MaskSize; z++)
                     //{
@@ -439,13 +441,13 @@ namespace XICO
                     //}
                     //idx += MaskSize;
                     MashByte = reader.ReadBytes(MaskSize);
-                    IconMask(_IconBitMap, i - 1, MashByte);
+                    IconMask(IconBmp, i - 1, MashByte);
                 }
             }
 
             private Int32 RgbCount()
             {
-                switch (biBitCount)
+                switch (BitCount)
                 {
                     case 1:
                         return 2;
@@ -462,16 +464,16 @@ namespace XICO
                 }
             }
 
-            private void IconSet(Bitmap IconImage, Int32 RowIndex, byte[] ImageByte)
+            private void IconSet(Bitmap IconImage, Int32 RowIndex, Byte[] ImageByte)
             {
-                Int32 idx = 0;
-                switch (biBitCount)
+                var idx = 0;
+                switch (BitCount)
                 {
                     case 1:
                         #region 一次读8位 绘制8个点
-                        for (Int32 i = 0; i != ImageByte.Length; i++)
+                        for (var i = 0; i != ImageByte.Length; i++)
                         {
-                            var MyArray = new BitArray(new byte[] { ImageByte[i] });
+                            var MyArray = new BitArray(new Byte[] { ImageByte[i] });
 
                             if (idx >= IconImage.Width) return;
                             IconImage.SetPixel(idx, RowIndex, ColorTable[GetBitNumb(MyArray[7])]);
@@ -502,10 +504,10 @@ namespace XICO
                         break;
                     case 4:
                         #region 一次读8位 绘制2个点
-                        for (Int32 i = 0; i != ImageByte.Length; i++)
+                        for (var i = 0; i != ImageByte.Length; i++)
                         {
-                            Int32 High = ImageByte[i] >> 4;  //取高4位
-                            Int32 Low = ImageByte[i] - (High << 4); //取低4位
+                            var High = ImageByte[i] >> 4;  //取高4位
+                            var Low = ImageByte[i] - (High << 4); //取低4位
                             if (idx >= IconImage.Width) return;
                             IconImage.SetPixel(idx, RowIndex, ColorTable[High]);
                             idx++;
@@ -517,7 +519,7 @@ namespace XICO
                         break;
                     case 8:
                         #region 一次读8位 绘制一个点
-                        for (Int32 i = 0; i != ImageByte.Length; i++)
+                        for (var i = 0; i != ImageByte.Length; i++)
                         {
                             if (idx >= IconImage.Width) return;
                             IconImage.SetPixel(idx, RowIndex, ColorTable[ImageByte[i]]);
@@ -527,7 +529,7 @@ namespace XICO
                         break;
                     case 24:
                         #region 一次读24位 绘制一个点
-                        for (Int32 i = 0; i != ImageByte.Length / 3; i++)
+                        for (var i = 0; i != ImageByte.Length / 3; i++)
                         {
                             if (i >= IconImage.Width) return;
                             IconImage.SetPixel(i, RowIndex, Color.FromArgb(ImageByte[idx + 2], ImageByte[idx + 1], ImageByte[idx]));
@@ -537,7 +539,7 @@ namespace XICO
                         break;
                     case 32:
                         #region 一次读32位 绘制一个点
-                        for (Int32 i = 0; i != ImageByte.Length / 4; i++)
+                        for (var i = 0; i != ImageByte.Length / 4; i++)
                         {
                             if (i >= IconImage.Width) return;
 
@@ -551,11 +553,11 @@ namespace XICO
                 }
             }
 
-            private void IconMask(Bitmap IconImage, Int32 RowIndex, byte[] MaskByte)
+            private void IconMask(Bitmap IconImage, Int32 RowIndex, Byte[] MaskByte)
             {
                 var Set = new BitArray(MaskByte);
-                Int32 idx = 0;
-                for (Int32 i = Set.Count; i != 0; i--)
+                var idx = 0;
+                for (var i = Set.Count; i != 0; i--)
                 {
                     if (idx >= IconImage.Width) return;
 
@@ -565,7 +567,7 @@ namespace XICO
                 }
             }
 
-            private Int32 GetBitNumb(bool BitArray) { return BitArray ? 1 : 0; }
+            private Int32 GetBitNumb(Boolean BitArray) { return BitArray ? 1 : 0; }
         }
     }
 }
\ No newline at end of file
Added +439 -0
diff --git a/XCoder/XMessage/FrmMain.cs b/XCoder/XMessage/FrmMain.cs
new file mode 100644
index 0000000..8f16d87
--- /dev/null
+++ b/XCoder/XMessage/FrmMain.cs
@@ -0,0 +1,439 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using NewLife.Log;
+using NewLife.Messaging;
+using NewLife.Net;
+using NewLife.Reflection;
+using NewLife.Threading;
+using NewLife.Windows;
+using XCoder;
+#if !NET4
+using TaskEx = System.Threading.Tasks.Task;
+#endif
+
+namespace XMessage
+{
+    [DisplayName("消息调试工具")]
+    public partial class FrmMain : Form, IXForm
+    {
+        NetServer _Server;
+        ISocketClient _Client;
+        IPacket _Packet;
+
+        static Task<Type[]> _packets;
+        //static Task<Type[]> _factorys;
+
+        /// <summary>业务日志输出</summary>
+        ILog BizLog;
+
+        #region 窗体
+        static FrmMain()
+        {
+            //_packets = TaskEx.Run(() => typeof(IPacket).GetAllSubclasses(true).ToArray());
+            _packets = TaskEx.Run(() => typeof(IPacketFactory).GetAllSubclasses(true).ToArray());
+        }
+
+        public FrmMain()
+        {
+            InitializeComponent();
+
+            Icon = IcoHelper.GetIcon("消息");
+        }
+
+        private void FrmMain_Load(Object sender, EventArgs e)
+        {
+            var log = TextFileLog.Create(null, "Message_{0:yyyy_MM_dd}.log");
+            BizLog = txtReceive.Combine(log);
+            txtReceive.UseWinFormControl();
+
+            txtReceive.SetDefaultStyle(12);
+            txtSend.SetDefaultStyle(12);
+            numMutilSend.SetDefaultStyle(12);
+
+            gbReceive.Tag = gbReceive.Text;
+            gbSend.Tag = gbSend.Text;
+
+            var cfg = MessageConfig.Current;
+            cbMode.SelectedItem = cbMode.Items[0] + "";
+            if (!cfg.Address.IsNullOrEmpty())
+            {
+                //cbAddr.DropDownStyle = ComboBoxStyle.DropDownList;
+                cbAddr.DataSource = cfg.Address.Split(";");
+            }
+
+            // 加载封包协议
+            foreach (var item in _packets.Result)
+            {
+                cbPacket.Items.Add(item.GetDisplayName() ?? item.Name);
+            }
+            cbPacket.SelectedIndex = 0;
+
+            // 加载保存的颜色
+            UIConfig.Apply(txtReceive);
+
+            LoadConfig();
+
+            // 语音识别
+            Task.Factory.StartNew(() =>
+            {
+                var sp = SpeechRecognition.Current;
+                if (!sp.Enable) return;
+
+                sp.Register("打开", () => this.Invoke(Connect))
+                .Register("关闭", () => this.Invoke(Disconnect))
+                .Register("退出", () => Application.Exit())
+                .Register("发送", () => this.Invoke(() => btnSend_Click(null, null)));
+
+                BizLog.Info("语音识别前缀:{0} 可用命令:{1}", sp.Name, sp.GetAllKeys().Join());
+            });
+        }
+        #endregion
+
+        #region 加载/保存 配置
+        void LoadConfig()
+        {
+            var cfg = MessageConfig.Current;
+            mi显示应用日志.Checked = cfg.ShowLog;
+            mi显示网络日志.Checked = cfg.ShowSocketLog;
+            mi显示接收字符串.Checked = cfg.ShowReceiveString;
+            mi显示发送数据.Checked = cfg.ShowSend;
+            mi显示接收数据.Checked = cfg.ShowReceive;
+            mi显示统计信息.Checked = cfg.ShowStat;
+            miHexSend.Checked = cfg.HexSend;
+
+            txtSend.Text = cfg.SendContent;
+            numMutilSend.Value = cfg.SendTimes;
+            numSleep.Value = cfg.SendSleep;
+            numThreads.Value = cfg.SendUsers;
+            mi日志着色.Checked = cfg.ColorLog;
+        }
+
+        void SaveConfig()
+        {
+            var cfg = MessageConfig.Current;
+            cfg.ShowLog = mi显示应用日志.Checked;
+            cfg.ShowSocketLog = mi显示网络日志.Checked;
+            cfg.ShowReceiveString = mi显示接收字符串.Checked;
+            cfg.ShowSend = mi显示发送数据.Checked;
+            cfg.ShowReceive = mi显示接收数据.Checked;
+            cfg.ShowStat = mi显示统计信息.Checked;
+            cfg.HexSend = miHexSend.Checked;
+
+            cfg.SendContent = txtSend.Text;
+            cfg.SendTimes = (Int32)numMutilSend.Value;
+            cfg.SendSleep = (Int32)numSleep.Value;
+            cfg.SendUsers = (Int32)numThreads.Value;
+            cfg.ColorLog = mi日志着色.Checked;
+
+            cfg.Save();
+        }
+        #endregion
+
+        #region 收发数据
+        void Connect()
+        {
+            _Server = null;
+            _Client = null;
+
+            var uri = new NetUri(cbAddr.Text);
+            // 网络封包
+            var idx = cbPacket.SelectedIndex;
+            var fact = idx < 0 ? null : _packets.Result[idx].CreateInstance() as IPacketFactory;
+            _Packet = fact.Create();
+
+            var cfg = MessageConfig.Current;
+            var log = BizLog;
+
+            switch (cbMode.Text)
+            {
+                case "服务端":
+                    var svr = new NetServer();
+                    svr.Log = cfg.ShowLog ? log : Logger.Null;
+                    svr.SocketLog = cfg.ShowSocketLog ? log : Logger.Null;
+                    svr.Port = uri.Port;
+                    if (uri.IsTcp || uri.IsUdp) svr.ProtocolType = uri.Type;
+                    svr.MessageReceived += OnReceived;
+
+                    svr.LogSend = cfg.ShowSend;
+                    svr.LogReceive = cfg.ShowReceive;
+
+                    // 加大会话超时时间到1天
+                    //svr.SessionTimeout = 24 * 3600;
+
+                    svr.SessionPacket = fact;
+
+                    svr.Start();
+
+                    "正在监听{0}".F(svr.Port).SpeechTip();
+
+                    if (uri.Port == 0) uri.Port = svr.Port;
+                    _Server = svr;
+                    break;
+                case "客户端":
+                    var client = uri.CreateRemote();
+                    client.Log = cfg.ShowLog ? log : Logger.Null;
+                    client.MessageReceived += OnReceived;
+
+                    client.LogSend = cfg.ShowSend;
+                    client.LogReceive = cfg.ShowReceive;
+
+                    client.Packet = _Packet;
+
+                    client.Open();
+
+                    "已连接服务器".SpeechTip();
+
+                    if (uri.Port == 0) uri.Port = client.Port;
+                    _Client = client;
+                    break;
+                default:
+                    return;
+            }
+
+            pnlSetting.Enabled = false;
+            btnConnect.Text = "关闭";
+
+            // 添加地址
+            var addr = uri.ToString();
+            var list = cfg.Address.Split(";").ToList();
+            if (!list.Contains(addr))
+            {
+                list.Insert(0, addr);
+                cfg.Address = list.Join(";");
+            }
+
+            cfg.Save();
+
+            _timer = new TimerX(ShowStat, null, 5000, 5000);
+        }
+
+        void Disconnect()
+        {
+            if (_Client != null)
+            {
+                _Client.Dispose();
+                _Client = null;
+
+                "关闭连接".SpeechTip();
+            }
+            if (_Server != null)
+            {
+                "停止监听{0}".F(_Server.Port).SpeechTip();
+                _Server.Dispose();
+                _Server = null;
+            }
+            if (_timer != null)
+            {
+                _timer.Dispose();
+                _timer = null;
+            }
+
+            pnlSetting.Enabled = true;
+            btnConnect.Text = "打开";
+        }
+
+        TimerX _timer;
+        String _lastStat;
+        void ShowStat(Object state)
+        {
+            if (!MessageConfig.Current.ShowStat) return;
+
+            var msg = "";
+            if (_Client != null)
+                msg = _Client.GetStat();
+            else if (_Server != null)
+                msg = _Server.GetStat();
+
+            if (!msg.IsNullOrEmpty() && msg != _lastStat)
+            {
+                _lastStat = msg;
+                BizLog.Info(msg);
+            }
+        }
+
+        private void btnConnect_Click(Object sender, EventArgs e)
+        {
+            SaveConfig();
+
+            var btn = sender as Button;
+            if (btn.Text == "打开")
+                Connect();
+            else
+                Disconnect();
+        }
+
+        void OnReceived(Object sender, MessageEventArgs e)
+        {
+            var session = sender as ISocketSession;
+            if (session == null)
+            {
+                var ns = sender as INetSession;
+                if (ns == null) return;
+                session = ns.Session;
+            }
+
+            if (MessageConfig.Current.ShowReceiveString)
+            {
+                var line = e.Message.Payload.ToStr();
+                BizLog.Info(line);
+            }
+        }
+
+        Int32 _pColor = 0;
+        Int32 BytesOfReceived = 0;
+        Int32 BytesOfSent = 0;
+        Int32 lastReceive = 0;
+        Int32 lastSend = 0;
+        private void timer1_Tick(Object sender, EventArgs e)
+        {
+            //if (!pnlSetting.Enabled)
+            {
+                var rcount = BytesOfReceived;
+                var tcount = BytesOfSent;
+                if (rcount != lastReceive)
+                {
+                    gbReceive.Text = (gbReceive.Tag + "").Replace("0", rcount + "");
+                    lastReceive = rcount;
+                }
+                if (tcount != lastSend)
+                {
+                    gbSend.Text = (gbSend.Tag + "").Replace("0", tcount + "");
+                    lastSend = tcount;
+                }
+
+                var set = MessageConfig.Current;
+                if (set.ColorLog) txtReceive.ColourDefault(_pColor);
+                _pColor = txtReceive.TextLength;
+            }
+        }
+
+        private void btnSend_Click(Object sender, EventArgs e)
+        {
+            var str = txtSend.Text;
+            if (String.IsNullOrEmpty(str))
+            {
+                MessageBox.Show("发送内容不能为空!", Text);
+                txtSend.Focus();
+                return;
+            }
+
+            // 多次发送
+            var count = (Int32)numMutilSend.Value;
+            var sleep = (Int32)numSleep.Value;
+            var ths = (Int32)numThreads.Value;
+            if (count <= 0) count = 1;
+            if (sleep <= 0) sleep = 1;
+
+            SaveConfig();
+
+            var cfg = MessageConfig.Current;
+
+            // 处理换行
+            str = str.Replace("\n", "\r\n");
+            var buf = cfg.HexSend ? str.ToHex() : str.GetBytes();
+
+            // 构造消息
+            var msg = _Packet.CreateMessage(buf);
+            //buf = msg.ToArray();
+            var pk = msg.ToPacket();
+
+            if (_Client != null)
+            {
+                if (ths <= 1)
+                {
+                    _Client.SendMulti(pk, count, sleep);
+                }
+                else
+                {
+                    Parallel.For(0, ths, n =>
+                    {
+                        var client = _Client.Remote.CreateRemote();
+                        client.StatSend = _Client.StatSend;
+                        client.StatReceive = _Client.StatReceive;
+                        client.SendMulti(pk, count, sleep);
+                    });
+                }
+            }
+            else if (_Server != null)
+            {
+                buf = pk.ToArray();
+                TaskEx.Run(async () =>
+                {
+                    for (var i = 0; i < count; i++)
+                    {
+                        var cs = await _Server.SendAllAsync(buf);
+                        BizLog.Info("已向[{0}]个客户端发送[{1}]数据", cs, buf.Length);
+                        if (sleep > 0) await TaskEx.Delay(sleep);
+                    }
+                });
+            }
+        }
+        #endregion
+
+        #region 右键菜单
+        private void mi清空_Click(Object sender, EventArgs e)
+        {
+            txtReceive.Clear();
+            BytesOfReceived = 0;
+        }
+
+        private void mi清空2_Click(Object sender, EventArgs e)
+        {
+            txtSend.Clear();
+            BytesOfSent = 0;
+        }
+
+        private void mi显示应用日志_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
+
+        private void mi显示网络日志_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
+
+        private void mi显示发送数据_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
+
+        private void mi显示接收数据_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
+
+        private void mi显示统计信息_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            MessageConfig.Current.ShowStat = mi.Checked = !mi.Checked;
+        }
+
+        private void mi显示接收字符串_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            MessageConfig.Current.ShowReceiveString = mi.Checked = !mi.Checked;
+        }
+
+        private void miHex发送_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            MessageConfig.Current.HexSend = mi.Checked = !mi.Checked;
+        }
+
+        private void miCheck_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
+        #endregion
+    }
+}
\ No newline at end of file
Added +480 -0
diff --git a/XCoder/XMessage/FrmMain.designer.cs b/XCoder/XMessage/FrmMain.designer.cs
new file mode 100644
index 0000000..06b2daa
--- /dev/null
+++ b/XCoder/XMessage/FrmMain.designer.cs
@@ -0,0 +1,480 @@
+namespace XMessage
+{
+    partial class FrmMain
+    {
+        /// <summary>
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows 窗体设计器生成的代码
+
+        /// <summary>
+        /// 设计器支持所需的方法 - 不要
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.gbReceive = new System.Windows.Forms.GroupBox();
+            this.txtReceive = new System.Windows.Forms.RichTextBox();
+            this.menuReceive = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
+            this.mi显示应用日志 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示网络日志 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示接收字符串 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示发送数据 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示接收数据 = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi显示统计信息 = new System.Windows.Forms.ToolStripMenuItem();
+            this.menuSend = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.miHexSend = new System.Windows.Forms.ToolStripMenuItem();
+            this.mi清空2 = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnConnect = new System.Windows.Forms.Button();
+            this.timer1 = new System.Windows.Forms.Timer(this.components);
+            this.fontDialog1 = new System.Windows.Forms.FontDialog();
+            this.colorDialog1 = new System.Windows.Forms.ColorDialog();
+            this.label1 = new System.Windows.Forms.Label();
+            this.lbAddr = new System.Windows.Forms.Label();
+            this.cbMode = new System.Windows.Forms.ComboBox();
+            this.cbAddr = new System.Windows.Forms.ComboBox();
+            this.pnlSetting = new System.Windows.Forms.Panel();
+            this.cbPacket = new System.Windows.Forms.ComboBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.gbSend = new System.Windows.Forms.GroupBox();
+            this.numThreads = new System.Windows.Forms.NumericUpDown();
+            this.numSleep = new System.Windows.Forms.NumericUpDown();
+            this.txtSend = new System.Windows.Forms.RichTextBox();
+            this.btnSend = new System.Windows.Forms.Button();
+            this.numMutilSend = new System.Windows.Forms.NumericUpDown();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label7 = new System.Windows.Forms.Label();
+            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.mi日志着色 = new System.Windows.Forms.ToolStripMenuItem();
+            this.gbReceive.SuspendLayout();
+            this.menuReceive.SuspendLayout();
+            this.menuSend.SuspendLayout();
+            this.pnlSetting.SuspendLayout();
+            this.gbSend.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numThreads)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numSleep)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numMutilSend)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // gbReceive
+            // 
+            this.gbReceive.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbReceive.Controls.Add(this.txtReceive);
+            this.gbReceive.Location = new System.Drawing.Point(9, 43);
+            this.gbReceive.Name = "gbReceive";
+            this.gbReceive.Size = new System.Drawing.Size(652, 234);
+            this.gbReceive.TabIndex = 4;
+            this.gbReceive.TabStop = false;
+            this.gbReceive.Text = "接收区:已接收0字节";
+            // 
+            // txtReceive
+            // 
+            this.txtReceive.ContextMenuStrip = this.menuReceive;
+            this.txtReceive.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.txtReceive.HideSelection = false;
+            this.txtReceive.Location = new System.Drawing.Point(3, 17);
+            this.txtReceive.Name = "txtReceive";
+            this.txtReceive.Size = new System.Drawing.Size(646, 214);
+            this.txtReceive.TabIndex = 1;
+            this.txtReceive.Text = "";
+            // 
+            // menuReceive
+            // 
+            this.menuReceive.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStripMenuItem1,
+            this.mi日志着色,
+            this.toolStripMenuItem3,
+            this.mi显示应用日志,
+            this.mi显示网络日志,
+            this.mi显示接收字符串,
+            this.mi显示发送数据,
+            this.mi显示接收数据,
+            this.mi显示统计信息});
+            this.menuReceive.Name = "menuSend";
+            this.menuReceive.Size = new System.Drawing.Size(161, 208);
+            // 
+            // toolStripMenuItem1
+            // 
+            this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+            this.toolStripMenuItem1.Size = new System.Drawing.Size(160, 22);
+            this.toolStripMenuItem1.Text = "清空";
+            this.toolStripMenuItem1.Click += new System.EventHandler(this.mi清空_Click);
+            // 
+            // toolStripMenuItem3
+            // 
+            this.toolStripMenuItem3.Name = "toolStripMenuItem3";
+            this.toolStripMenuItem3.Size = new System.Drawing.Size(157, 6);
+            // 
+            // mi显示应用日志
+            // 
+            this.mi显示应用日志.Name = "mi显示应用日志";
+            this.mi显示应用日志.Size = new System.Drawing.Size(160, 22);
+            this.mi显示应用日志.Text = "显示应用日志";
+            this.mi显示应用日志.Click += new System.EventHandler(this.mi显示应用日志_Click);
+            // 
+            // mi显示网络日志
+            // 
+            this.mi显示网络日志.Name = "mi显示网络日志";
+            this.mi显示网络日志.Size = new System.Drawing.Size(160, 22);
+            this.mi显示网络日志.Text = "显示网络日志";
+            this.mi显示网络日志.Click += new System.EventHandler(this.mi显示网络日志_Click);
+            // 
+            // mi显示接收字符串
+            // 
+            this.mi显示接收字符串.Name = "mi显示接收字符串";
+            this.mi显示接收字符串.Size = new System.Drawing.Size(160, 22);
+            this.mi显示接收字符串.Text = "显示接收字符串";
+            this.mi显示接收字符串.Click += new System.EventHandler(this.mi显示接收字符串_Click);
+            // 
+            // mi显示发送数据
+            // 
+            this.mi显示发送数据.Name = "mi显示发送数据";
+            this.mi显示发送数据.Size = new System.Drawing.Size(160, 22);
+            this.mi显示发送数据.Text = "显示发送数据";
+            this.mi显示发送数据.Click += new System.EventHandler(this.mi显示发送数据_Click);
+            // 
+            // mi显示接收数据
+            // 
+            this.mi显示接收数据.Name = "mi显示接收数据";
+            this.mi显示接收数据.Size = new System.Drawing.Size(160, 22);
+            this.mi显示接收数据.Text = "显示接收数据";
+            this.mi显示接收数据.Click += new System.EventHandler(this.mi显示接收数据_Click);
+            // 
+            // mi显示统计信息
+            // 
+            this.mi显示统计信息.Name = "mi显示统计信息";
+            this.mi显示统计信息.Size = new System.Drawing.Size(160, 22);
+            this.mi显示统计信息.Text = "显示统计信息";
+            this.mi显示统计信息.Click += new System.EventHandler(this.mi显示统计信息_Click);
+            // 
+            // menuSend
+            // 
+            this.menuSend.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.miHexSend,
+            this.mi清空2});
+            this.menuSend.Name = "menuSend";
+            this.menuSend.Size = new System.Drawing.Size(123, 48);
+            // 
+            // miHexSend
+            // 
+            this.miHexSend.Name = "miHexSend";
+            this.miHexSend.Size = new System.Drawing.Size(122, 22);
+            this.miHexSend.Text = "Hex发送";
+            this.miHexSend.Click += new System.EventHandler(this.miHex发送_Click);
+            // 
+            // mi清空2
+            // 
+            this.mi清空2.Name = "mi清空2";
+            this.mi清空2.Size = new System.Drawing.Size(122, 22);
+            this.mi清空2.Text = "清空";
+            this.mi清空2.Click += new System.EventHandler(this.mi清空2_Click);
+            // 
+            // btnConnect
+            // 
+            this.btnConnect.Location = new System.Drawing.Point(587, 9);
+            this.btnConnect.Name = "btnConnect";
+            this.btnConnect.Size = new System.Drawing.Size(67, 29);
+            this.btnConnect.TabIndex = 3;
+            this.btnConnect.Text = "打开";
+            this.btnConnect.UseVisualStyleBackColor = true;
+            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
+            // 
+            // timer1
+            // 
+            this.timer1.Enabled = true;
+            this.timer1.Interval = 300;
+            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(7, 7);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(41, 12);
+            this.label1.TabIndex = 6;
+            this.label1.Text = "模式:";
+            // 
+            // lbAddr
+            // 
+            this.lbAddr.AutoSize = true;
+            this.lbAddr.Location = new System.Drawing.Point(147, 7);
+            this.lbAddr.Name = "lbAddr";
+            this.lbAddr.Size = new System.Drawing.Size(41, 12);
+            this.lbAddr.TabIndex = 7;
+            this.lbAddr.Text = "地址:";
+            // 
+            // cbMode
+            // 
+            this.cbMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbMode.FormattingEnabled = true;
+            this.cbMode.Items.AddRange(new object[] {
+            "服务端",
+            "客户端"});
+            this.cbMode.Location = new System.Drawing.Point(48, 3);
+            this.cbMode.Name = "cbMode";
+            this.cbMode.Size = new System.Drawing.Size(93, 20);
+            this.cbMode.TabIndex = 9;
+            // 
+            // cbAddr
+            // 
+            this.cbAddr.FormattingEnabled = true;
+            this.cbAddr.Location = new System.Drawing.Point(184, 3);
+            this.cbAddr.Name = "cbAddr";
+            this.cbAddr.Size = new System.Drawing.Size(149, 20);
+            this.cbAddr.TabIndex = 10;
+            // 
+            // pnlSetting
+            // 
+            this.pnlSetting.Controls.Add(this.cbPacket);
+            this.pnlSetting.Controls.Add(this.label3);
+            this.pnlSetting.Controls.Add(this.cbAddr);
+            this.pnlSetting.Controls.Add(this.label1);
+            this.pnlSetting.Controls.Add(this.lbAddr);
+            this.pnlSetting.Controls.Add(this.cbMode);
+            this.pnlSetting.Location = new System.Drawing.Point(9, 8);
+            this.pnlSetting.Name = "pnlSetting";
+            this.pnlSetting.Size = new System.Drawing.Size(471, 31);
+            this.pnlSetting.TabIndex = 13;
+            // 
+            // cbPacket
+            // 
+            this.cbPacket.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbPacket.FormattingEnabled = true;
+            this.cbPacket.Location = new System.Drawing.Point(375, 3);
+            this.cbPacket.Name = "cbPacket";
+            this.cbPacket.Size = new System.Drawing.Size(93, 20);
+            this.cbPacket.TabIndex = 12;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(339, 7);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(41, 12);
+            this.label3.TabIndex = 11;
+            this.label3.Text = "封包:";
+            // 
+            // gbSend
+            // 
+            this.gbSend.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbSend.Controls.Add(this.numThreads);
+            this.gbSend.Controls.Add(this.numSleep);
+            this.gbSend.Controls.Add(this.txtSend);
+            this.gbSend.Controls.Add(this.btnSend);
+            this.gbSend.Controls.Add(this.numMutilSend);
+            this.gbSend.Controls.Add(this.label2);
+            this.gbSend.Controls.Add(this.label7);
+            this.gbSend.Location = new System.Drawing.Point(9, 283);
+            this.gbSend.Name = "gbSend";
+            this.gbSend.Size = new System.Drawing.Size(652, 84);
+            this.gbSend.TabIndex = 15;
+            this.gbSend.TabStop = false;
+            this.gbSend.Text = "发送区:已发送0字节";
+            // 
+            // numThreads
+            // 
+            this.numThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.numThreads.Location = new System.Drawing.Point(593, 22);
+            this.numThreads.Maximum = new decimal(new int[] {
+            100000,
+            0,
+            0,
+            0});
+            this.numThreads.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numThreads.Name = "numThreads";
+            this.numThreads.Size = new System.Drawing.Size(52, 21);
+            this.numThreads.TabIndex = 18;
+            this.numThreads.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.toolTip1.SetToolTip(this.numThreads, "模拟多客户端发送,用于压力测试!");
+            this.numThreads.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            // 
+            // numSleep
+            // 
+            this.numSleep.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.numSleep.Location = new System.Drawing.Point(538, 54);
+            this.numSleep.Maximum = new decimal(new int[] {
+            1000000,
+            0,
+            0,
+            0});
+            this.numSleep.Name = "numSleep";
+            this.numSleep.Size = new System.Drawing.Size(52, 21);
+            this.numSleep.TabIndex = 16;
+            this.numSleep.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.numSleep.Value = new decimal(new int[] {
+            1000,
+            0,
+            0,
+            0});
+            // 
+            // txtSend
+            // 
+            this.txtSend.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtSend.ContextMenuStrip = this.menuSend;
+            this.txtSend.HideSelection = false;
+            this.txtSend.Location = new System.Drawing.Point(0, 19);
+            this.txtSend.Name = "txtSend";
+            this.txtSend.Size = new System.Drawing.Size(497, 59);
+            this.txtSend.TabIndex = 2;
+            this.txtSend.Text = "";
+            // 
+            // btnSend
+            // 
+            this.btnSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnSend.Location = new System.Drawing.Point(596, 49);
+            this.btnSend.Name = "btnSend";
+            this.btnSend.Size = new System.Drawing.Size(50, 30);
+            this.btnSend.TabIndex = 1;
+            this.btnSend.Text = "发送";
+            this.btnSend.UseVisualStyleBackColor = true;
+            this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
+            // 
+            // numMutilSend
+            // 
+            this.numMutilSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.numMutilSend.Location = new System.Drawing.Point(538, 22);
+            this.numMutilSend.Maximum = new decimal(new int[] {
+            10000,
+            0,
+            0,
+            0});
+            this.numMutilSend.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numMutilSend.Name = "numMutilSend";
+            this.numMutilSend.Size = new System.Drawing.Size(52, 21);
+            this.numMutilSend.TabIndex = 14;
+            this.numMutilSend.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.numMutilSend.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            // 
+            // label2
+            // 
+            this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(503, 58);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(41, 12);
+            this.label2.TabIndex = 17;
+            this.label2.Text = "间隔:";
+            // 
+            // label7
+            // 
+            this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(503, 26);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(41, 12);
+            this.label7.TabIndex = 15;
+            this.label7.Text = "次数:";
+            // 
+            // mi日志着色
+            // 
+            this.mi日志着色.Name = "mi日志着色";
+            this.mi日志着色.Size = new System.Drawing.Size(160, 22);
+            this.mi日志着色.Text = "日志着色";
+            this.mi日志着色.Click += new System.EventHandler(this.miCheck_Click);
+            // 
+            // FrmMain
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(667, 379);
+            this.Controls.Add(this.gbSend);
+            this.Controls.Add(this.pnlSetting);
+            this.Controls.Add(this.btnConnect);
+            this.Controls.Add(this.gbReceive);
+            this.Name = "FrmMain";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "网络调试";
+            this.Load += new System.EventHandler(this.FrmMain_Load);
+            this.gbReceive.ResumeLayout(false);
+            this.menuReceive.ResumeLayout(false);
+            this.menuSend.ResumeLayout(false);
+            this.pnlSetting.ResumeLayout(false);
+            this.pnlSetting.PerformLayout();
+            this.gbSend.ResumeLayout(false);
+            this.gbSend.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numThreads)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numSleep)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numMutilSend)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbReceive;
+        private System.Windows.Forms.Button btnConnect;
+        private System.Windows.Forms.Timer timer1;
+        private System.Windows.Forms.ContextMenuStrip menuSend;
+        private System.Windows.Forms.ToolStripMenuItem mi清空2;
+        private System.Windows.Forms.RichTextBox txtReceive;
+        private System.Windows.Forms.FontDialog fontDialog1;
+        private System.Windows.Forms.ColorDialog colorDialog1;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label lbAddr;
+        private System.Windows.Forms.ComboBox cbMode;
+        private System.Windows.Forms.ComboBox cbAddr;
+        private System.Windows.Forms.Panel pnlSetting;
+        private System.Windows.Forms.ContextMenuStrip menuReceive;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
+        private System.Windows.Forms.GroupBox gbSend;
+        private System.Windows.Forms.NumericUpDown numSleep;
+        private System.Windows.Forms.RichTextBox txtSend;
+        private System.Windows.Forms.Button btnSend;
+        private System.Windows.Forms.NumericUpDown numMutilSend;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.ToolStripMenuItem mi显示发送数据;
+        private System.Windows.Forms.ToolStripMenuItem mi显示接收数据;
+        private System.Windows.Forms.ToolStripMenuItem mi显示统计信息;
+        private System.Windows.Forms.NumericUpDown numThreads;
+        private System.Windows.Forms.ToolStripMenuItem mi显示接收字符串;
+        private System.Windows.Forms.ToolStripMenuItem mi显示应用日志;
+        private System.Windows.Forms.ToolStripMenuItem mi显示网络日志;
+        private System.Windows.Forms.ToolTip toolTip1;
+        private System.Windows.Forms.ToolStripMenuItem miHexSend;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.ComboBox cbPacket;
+        private System.Windows.Forms.ToolStripMenuItem mi日志着色;
+    }
+}
+
Added +141 -0
diff --git a/XCoder/XMessage/FrmMain.resx b/XCoder/XMessage/FrmMain.resx
new file mode 100644
index 0000000..fdafb9b
--- /dev/null
+++ b/XCoder/XMessage/FrmMain.resx
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="menuReceive.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>104, 13</value>
+  </metadata>
+  <metadata name="menuSend.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>237, 17</value>
+  </metadata>
+  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="fontDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>352, 17</value>
+  </metadata>
+  <metadata name="colorDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>474, 17</value>
+  </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>601, 17</value>
+  </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>601, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
Added +81 -0
diff --git a/XCoder/XMessage/MessageConfig.cs b/XCoder/XMessage/MessageConfig.cs
new file mode 100644
index 0000000..36df5a1
--- /dev/null
+++ b/XCoder/XMessage/MessageConfig.cs
@@ -0,0 +1,81 @@
+using System;
+using System.ComponentModel;
+using System.Text;
+using System.Xml.Serialization;
+using NewLife.Xml;
+
+namespace XMessage
+{
+    /// <summary>网络口配置</summary>
+    [XmlConfigFile("Config\\Message.config")]
+    public class MessageConfig : XmlConfig<MessageConfig>
+    {
+        /// <summary>地址</summary>
+        [Description("地址")]
+        public String Address { get; set; } = "";
+
+        /// <summary>文本编码</summary>
+        [XmlIgnore]
+        public Encoding Encoding { get; set; } = Encoding.UTF8;
+
+        /// <summary>编码</summary>
+        [Description("编码 gb2312/us-ascii/utf-8")]
+        public String WebEncoding { get { return Encoding?.WebName; } set { Encoding = Encoding.GetEncoding(value); } }
+
+        /// <summary>十六进制显示</summary>
+        [Description("十六进制显示")]
+        public Boolean HexShow { get; set; }
+
+        /// <summary>十六进制发送</summary>
+        [Description("十六进制发送")]
+        public Boolean HexSend { get; set; }
+
+        /// <summary>发送内容</summary>
+        [Description("发送内容")]
+        public String SendContent { get; set; } = "新生命开发团队,学无先后达者为师";
+
+        /// <summary>发送次数</summary>
+        [Description("发送次数")]
+        public Int32 SendTimes { get; set; } = 1;
+
+        /// <summary>发送间隔。毫秒</summary>
+        [Description("发送间隔。毫秒")]
+        public Int32 SendSleep { get; set; } = 1000;
+
+        /// <summary>发送用户数</summary>
+        [Description("发送用户数")]
+        public Int32 SendUsers { get; set; } = 1;
+
+        /// <summary>显示应用日志</summary>
+        [Description("显示应用日志")]
+        public Boolean ShowLog { get; set; } = true;
+
+        /// <summary>显示网络日志</summary>
+        [Description("显示网络日志")]
+        public Boolean ShowSocketLog { get; set; } = true;
+
+        /// <summary>显示接收字符串</summary>
+        [Description("显示接收字符串")]
+        public Boolean ShowReceiveString { get; set; } = true;
+
+        /// <summary>显示发送数据</summary>
+        [Description("显示发送数据")]
+        public Boolean ShowSend { get; set; } = true;
+
+        /// <summary>显示接收数据</summary>
+        [Description("显示接收数据")]
+        public Boolean ShowReceive { get; set; } = true;
+
+        /// <summary>显示统计信息</summary>
+        [Description("显示统计信息")]
+        public Boolean ShowStat { get; set; } = true;
+
+        /// <summary>日志着色</summary>
+        [Description("日志着色")]
+        public Boolean ColorLog { get; set; } = true;
+
+        public MessageConfig()
+        {
+        }
+    }
+}
\ No newline at end of file
Modified +191 -110
diff --git a/XCoder/XNet/FrmMain.cs b/XCoder/XNet/FrmMain.cs
index 64c01b1..ff32534 100644
--- a/XCoder/XNet/FrmMain.cs
+++ b/XCoder/XNet/FrmMain.cs
@@ -1,28 +1,34 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics;
 using System.Linq;
 using System.Net;
-using System.Net.Sockets;
-using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using NewLife;
+using NewLife.Data;
 using NewLife.Log;
 using NewLife.Net;
 using NewLife.Reflection;
 using NewLife.Threading;
 using NewLife.Windows;
 using XCoder;
+#if !NET4
+using TaskEx = System.Threading.Tasks.Task;
+#endif
 
 namespace XNet
 {
     [DisplayName("网络调试工具")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
         NetServer _Server;
         ISocketClient _Client;
-        static Task<NetServer[]> _task;
+        static Task<Dictionary<String, Type>> _task;
+
+        /// <summary>业务日志输出</summary>
+        ILog BizLog;
 
         #region 窗体
         static FrmMain()
@@ -34,11 +40,16 @@ namespace XNet
         {
             InitializeComponent();
 
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
             Icon = IcoHelper.GetIcon("网络");
         }
 
-        private void FrmMain_Load(object sender, EventArgs e)
+        private void FrmMain_Load(Object sender, EventArgs e)
         {
+            var log = TextFileLog.Create(null, "Net_{0:yyyy_MM_dd}.log");
+            BizLog = txtReceive.Combine(log);
             txtReceive.UseWinFormControl();
 
             txtReceive.SetDefaultStyle(12);
@@ -50,24 +61,25 @@ namespace XNet
 
             _task.ContinueWith(t =>
             {
-                var list = EnumHelper.GetDescriptions<WorkModes>().Select(kv => kv.Value).ToList();
+                var dic = EnumHelper.GetDescriptions<WorkModes>();
+                var list = dic.Select(kv => kv.Value).ToList();
+                //var ds = dic.ToDictionary(s => s.Value, s => s.Value);
                 foreach (var item in t.Result)
                 {
-                    list.Add(item.Name);
+                    list.Add(item.Key);
                 }
                 this.Invoke(() =>
                 {
                     cbMode.DataSource = list;
-                    //cbMode.SelectedIndex = 0;
+
+                    var cfg = NetConfig.Current;
+                    if (cfg.Mode > 0 && dic.ContainsKey((WorkModes)cfg.Mode))
+                        cbMode.SelectedItem = dic[(WorkModes)cfg.Mode];
+                    else
+                        cbMode.SelectedIndex = 0;
                 });
             });
 
-            cbAddr.DropDownStyle = ComboBoxStyle.DropDownList;
-            cbAddr.DataSource = GetIPs();
-
-            var cfg = NetConfig.Current;
-            if (cfg.Port > 0) numPort.Value = cfg.Port;
-
             // 加载保存的颜色
             UIConfig.Apply(txtReceive);
 
@@ -76,12 +88,15 @@ namespace XNet
             // 语音识别
             Task.Factory.StartNew(() =>
             {
-                SpeechRecognition.Register("打开", () => this.Invoke(Connect));
-                SpeechRecognition.Register("关闭", () => this.Invoke(Disconnect));
-                SpeechRecognition.Register("退出", () => Application.Exit());
-                SpeechRecognition.Register("发送", () => this.Invoke(() => btnSend_Click(null, null)));
+                var sp = SpeechRecognition.Current;
+                if (!sp.Enable) return;
 
-                XTrace.WriteLine("有效的语音识别命令:{0}", SpeechRecognition.GetAllKeys().Join());
+                sp.Register("打开", () => this.Invoke(Connect))
+                .Register("关闭", () => this.Invoke(Disconnect))
+                .Register("退出", () => Application.Exit())
+                .Register("发送", () => this.Invoke(() => btnSend_Click(null, null)));
+
+                BizLog.Info("语音识别前缀:{0} 可用命令:{1}", sp.Name, sp.GetAllKeys().Join());
             });
         }
         #endregion
@@ -96,11 +111,23 @@ namespace XNet
             mi显示发送数据.Checked = cfg.ShowSend;
             mi显示接收数据.Checked = cfg.ShowReceive;
             mi显示统计信息.Checked = cfg.ShowStat;
+            miHexSend.Checked = cfg.HexSend;
 
             txtSend.Text = cfg.SendContent;
             numMutilSend.Value = cfg.SendTimes;
             numSleep.Value = cfg.SendSleep;
             numThreads.Value = cfg.SendUsers;
+            mi日志着色.Checked = cfg.ColorLog;
+
+            cbLocal.DataSource = GetIPs();
+            if (!cfg.Local.IsNullOrEmpty())
+                cbLocal.SelectedItem = cfg.Local;
+            else
+                cbLocal.SelectedIndex = 0;
+
+            // 历史地址列表
+            if (!cfg.Address.IsNullOrEmpty()) cbRemote.DataSource = cfg.Address.Split(";");
+            if (cfg.Port > 0) numPort.Value = cfg.Port;
         }
 
         void SaveConfig()
@@ -112,11 +139,18 @@ namespace XNet
             cfg.ShowSend = mi显示发送数据.Checked;
             cfg.ShowReceive = mi显示接收数据.Checked;
             cfg.ShowStat = mi显示统计信息.Checked;
+            cfg.HexSend = miHexSend.Checked;
 
             cfg.SendContent = txtSend.Text;
             cfg.SendTimes = (Int32)numMutilSend.Value;
             cfg.SendSleep = (Int32)numSleep.Value;
             cfg.SendUsers = (Int32)numThreads.Value;
+            cfg.ColorLog = mi日志着色.Checked;
+
+            cfg.Local = cbLocal.Text;
+            cfg.AddAddress(cbRemote.Text);
+
+            cfg.Port = (Int32)numPort.Value;
 
             cfg.Save();
         }
@@ -128,12 +162,14 @@ namespace XNet
             _Server = null;
             _Client = null;
 
+            var mode = GetMode();
+            var local = cbLocal.Text;
+            var remote = cbRemote.Text;
             var port = (Int32)numPort.Value;
 
             var cfg = NetConfig.Current;
-            cfg.Port = port;
+            cfg.Mode = (Byte)mode;
 
-            var mode = GetMode();
             switch (mode)
             {
                 case WorkModes.UDP_TCP:
@@ -148,21 +184,15 @@ namespace XNet
                     _Server.ProtocolType = NetType.Tcp;
                     break;
                 case WorkModes.TCP_Client:
-                    var tcp = new TcpSession();
-                    _Client = tcp;
-
-                    cfg.Address = cbAddr.Text;
+                    _Client = new TcpSession();
                     break;
                 case WorkModes.UDP_Client:
-                    var udp = new UdpServer();
-                    _Client = udp;
-
-                    cfg.Address = cbAddr.Text;
+                    _Client = new UdpServer();
                     break;
                 default:
-                    if ((Int32)mode > 0)
+                    if (mode > 0)
                     {
-                        var ns = GetNetServers().Where(n => n.Name == cbMode.Text).FirstOrDefault();
+                        var ns = GetServer(cbMode.Text);
                         if (ns == null) throw new XException("未识别服务[{0}]", mode);
 
                         _Server = ns.GetType().CreateInstance() as NetServer;
@@ -172,30 +202,34 @@ namespace XNet
 
             if (_Client != null)
             {
-                _Client.Log = cfg.ShowLog ? XTrace.Log : Logger.Null;
+                _Client.Log = cfg.ShowLog ? BizLog : Logger.Null;
+                if (!local.Contains("所有本地")) _Client.Local.Host = local;
                 _Client.Received += OnReceived;
                 _Client.Remote.Port = port;
-                _Client.Remote.Host = cbAddr.Text;
+                _Client.Remote.Host = remote;
 
                 _Client.LogSend = cfg.ShowSend;
                 _Client.LogReceive = cfg.ShowReceive;
 
-                _Client.Open();
+                if (!_Client.Open()) return;
 
                 "已连接服务器".SpeechTip();
             }
             else if (_Server != null)
             {
                 if (_Server == null) _Server = new NetServer();
-                _Server.Log = cfg.ShowLog ? XTrace.Log : Logger.Null;
-                _Server.SocketLog = cfg.ShowSocketLog ? XTrace.Log : Logger.Null;
+                _Server.Log = cfg.ShowLog ? BizLog : Logger.Null;
+                _Server.SocketLog = cfg.ShowSocketLog ? BizLog : Logger.Null;
                 _Server.Port = port;
-                if (!cbAddr.Text.Contains("所有本地")) _Server.Local.Host = cbAddr.Text;
+                if (!local.Contains("所有本地")) _Server.Local.Host = local;
                 _Server.Received += OnReceived;
 
                 _Server.LogSend = cfg.ShowSend;
                 _Server.LogReceive = cfg.ShowReceive;
 
+                //// 加大会话超时时间到1天
+                //_Server.SessionTimeout = 24 * 3600;
+
                 _Server.Start();
 
                 "正在监听{0}".F(port).SpeechTip();
@@ -207,8 +241,6 @@ namespace XNet
             cfg.Save();
 
             _timer = new TimerX(ShowStat, null, 5000, 5000);
-
-            BizLog = TextFileLog.Create("NetLog");
         }
 
         void Disconnect()
@@ -237,22 +269,25 @@ namespace XNet
         }
 
         TimerX _timer;
+        String _lastStat;
         void ShowStat(Object state)
         {
             if (!NetConfig.Current.ShowStat) return;
 
-            var sb = new StringBuilder();
+            var msg = "";
             if (_Client != null)
-            {
-                XTrace.WriteLine("发送:{0} 接收:{1}", _Client.StatSend, _Client.StatReceive);
-            }
+                msg = _Client.GetStat();
             else if (_Server != null)
+                msg = _Server.GetStat();
+
+            if (!msg.IsNullOrEmpty() && msg != _lastStat)
             {
-                XTrace.WriteLine("在线:{3:n0}/{4:n0} 会话:{2} 发送:{0} 接收:{1}", _Server.StatSend, _Server.StatReceive, _Server.StatSession, _Server.SessionCount, _Server.MaxSessionCount);
+                _lastStat = msg;
+                BizLog.Info(msg);
             }
         }
 
-        private void btnConnect_Click(object sender, EventArgs e)
+        private void btnConnect_Click(Object sender, EventArgs e)
         {
             SaveConfig();
 
@@ -263,9 +298,6 @@ namespace XNet
                 Disconnect();
         }
 
-        /// <summary>业务日志输出</summary>
-        ILog BizLog;
-
         void OnReceived(Object sender, ReceivedEventArgs e)
         {
             var session = sender as ISocketSession;
@@ -279,9 +311,9 @@ namespace XNet
             if (NetConfig.Current.ShowReceiveString)
             {
                 var line = e.ToStr();
-                XTrace.WriteLine(line);
+                //XTrace.WriteLine(line);
 
-                if (BizLog != null) BizLog.Info(line);
+                BizLog.Info(line);
             }
         }
 
@@ -290,9 +322,9 @@ namespace XNet
         Int32 BytesOfSent = 0;
         Int32 lastReceive = 0;
         Int32 lastSend = 0;
-        private void timer1_Tick(object sender, EventArgs e)
+        private void timer1_Tick(Object sender, EventArgs e)
         {
-            if (!pnlSetting.Enabled)
+            //if (!pnlSetting.Enabled)
             {
                 var rcount = BytesOfReceived;
                 var tcount = BytesOfSent;
@@ -307,12 +339,13 @@ namespace XNet
                     lastSend = tcount;
                 }
 
-                if (cbColor.Checked) txtReceive.ColourDefault(_pColor);
+                var cfg = NetConfig.Current;
+                if (cfg.ColorLog) txtReceive.ColourDefault(_pColor);
                 _pColor = txtReceive.TextLength;
             }
         }
 
-        private void btnSend_Click(object sender, EventArgs e)
+        private void btnSend_Click(Object sender, EventArgs e)
         {
             var str = txtSend.Text;
             if (String.IsNullOrEmpty(str))
@@ -331,121 +364,161 @@ namespace XNet
 
             SaveConfig();
 
-            if (_Client == null)
-            {
-                XTrace.WriteLine("未连接服务端!");
-                return;
-            }
+            var cfg = NetConfig.Current;
 
             // 处理换行
             str = str.Replace("\n", "\r\n");
-            var buf = str.GetBytes();
+            var buf = cfg.HexSend ? str.ToHex() : str.GetBytes();
+            var pk = new Packet(buf);
 
-            if (ths <= 1)
-                _Client.SendAsync(buf, count, sleep);
-            else
+            if (_Client != null)
             {
-                // 多线程测试
-                //Task.Factory.StartNew(() =>
-                //{
-                //    for (int i = 0; i < ths; i++)
-                //    {
-                //        var client = _Client.Remote.CreateRemote();
-                //        client.StatSend = _Client.StatSend;
-                //        client.StatReceive = _Client.StatReceive;
-                //        //client.SendAsync(buf, count, sleep).ContinueWith(t => client.Dispose());
-                //        client.SendAsync(buf, count, sleep);
-                //    }
-                //}).LogException();
-                Parallel.For(0, ths, n =>
+                if (ths <= 1)
                 {
-                    var client = _Client.Remote.CreateRemote();
-                    client.StatSend = _Client.StatSend;
-                    client.StatReceive = _Client.StatReceive;
-                    //client.SendAsync(buf, count, sleep).ContinueWith(t => client.Dispose());
-                    client.SendAsync(buf, count, sleep);
+                    _Client.SendMulti(pk, count, sleep);
+                }
+                else
+                {
+                    // 多线程测试
+                    //Parallel.For(0, ths, n =>
+                    //{
+                    //    var client = _Client.Remote.CreateRemote();
+                    //    client.StatSend = _Client.StatSend;
+                    //    client.StatReceive = _Client.StatReceive;
+                    //    client.SendMulti(buf, count, sleep);
+                    //});
+                    var any = _Client.Local.Address.IsAny();
+                    var list = new List<ISocketClient>();
+                    for (var i = 0; i < ths; i++)
+                    {
+                        var client = _Client.Remote.CreateRemote();
+                        if (!any) client.Local.EndPoint = new IPEndPoint(_Client.Local.Address, 2000 + i);
+                        client.StatSend = _Client.StatSend;
+                        client.StatReceive = _Client.StatReceive;
+                        //client.SendMulti(buf, count, sleep);
+
+                        list.Add(client);
+                    }
+                    Parallel.For(0, ths, n =>
+                    {
+                        var client = list[n];
+                        client.SendMulti(pk, count, sleep);
+                        //try
+                        //{
+                        //    client.Open();
+                        //}
+                        //catch { }
+                    });
+                }
+            }
+            else if (_Server != null)
+            {
+                TaskEx.Run(async () =>
+                {
+                    BizLog.Info("准备向[{0}]个客户端发送[{1}]次[{2}]的数据", _Server.SessionCount, count, buf.Length);
+                    for (var i = 0; i < count && _Server != null; i++)
+                    {
+                        var sw = Stopwatch.StartNew();
+                        var cs = await _Server.SendAllAsync(buf);
+                        sw.Stop();
+                        BizLog.Info("{3}/{4} 已向[{0}]个客户端发送[{1}]数据 {2:n0}ms", cs, buf.Length, sw.ElapsedMilliseconds, i + 1, count);
+                        if (sleep > 0) await TaskEx.Delay(sleep);
+                    }
                 });
             }
         }
         #endregion
 
         #region 右键菜单
-        private void mi清空_Click(object sender, EventArgs e)
+        private void mi清空_Click(Object sender, EventArgs e)
         {
             txtReceive.Clear();
-            //spList.ClearReceive();
+            BytesOfReceived = 0;
         }
 
-        private void mi清空2_Click(object sender, EventArgs e)
+        private void mi清空2_Click(Object sender, EventArgs e)
         {
             txtSend.Clear();
-            //spList.ClearSend();
+            BytesOfSent = 0;
         }
 
-        private void mi显示应用日志_Click(object sender, EventArgs e)
+        private void mi显示应用日志_Click(Object sender, EventArgs e)
         {
             var mi = sender as ToolStripMenuItem;
             mi.Checked = !mi.Checked;
         }
 
-        private void mi显示网络日志_Click(object sender, EventArgs e)
+        private void mi显示网络日志_Click(Object sender, EventArgs e)
         {
             var mi = sender as ToolStripMenuItem;
             mi.Checked = !mi.Checked;
         }
 
-        private void mi显示发送数据_Click(object sender, EventArgs e)
+        private void mi显示发送数据_Click(Object sender, EventArgs e)
         {
             var mi = sender as ToolStripMenuItem;
             mi.Checked = !mi.Checked;
         }
 
-        private void mi显示接收数据_Click(object sender, EventArgs e)
+        private void mi显示接收数据_Click(Object sender, EventArgs e)
         {
             var mi = sender as ToolStripMenuItem;
             mi.Checked = !mi.Checked;
         }
 
-        private void mi显示统计信息_Click(object sender, EventArgs e)
+        private void mi显示统计信息_Click(Object sender, EventArgs e)
         {
             var mi = sender as ToolStripMenuItem;
             NetConfig.Current.ShowStat = mi.Checked = !mi.Checked;
         }
 
-        private void mi显示接收字符串_Click(object sender, EventArgs e)
+        private void mi显示接收字符串_Click(Object sender, EventArgs e)
         {
             var mi = sender as ToolStripMenuItem;
             NetConfig.Current.ShowReceiveString = mi.Checked = !mi.Checked;
         }
+
+        private void miHex发送_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            NetConfig.Current.HexSend = mi.Checked = !mi.Checked;
+        }
+
+        private void 查看Tcp参数ToolStripMenuItem_Click(Object sender, EventArgs e)
+        {
+            NetHelper.ShowTcpParameters();
+        }
+
+        private void 设置最大TcpToolStripMenuItem_Click(Object sender, EventArgs e)
+        {
+            NetHelper.SetTcpMax();
+        }
+
+        private void mi日志着色_Click(Object sender, EventArgs e)
+        {
+            var mi = sender as ToolStripMenuItem;
+            mi.Checked = !mi.Checked;
+        }
         #endregion
 
-        private void cbMode_SelectedIndexChanged(object sender, EventArgs e)
+        private void cbMode_SelectedIndexChanged(Object sender, EventArgs e)
         {
             var mode = GetMode();
-            if ((Int32)mode == 0) return;
+            if (mode == 0) return;
 
             switch (mode)
             {
                 case WorkModes.TCP_Client:
                 case WorkModes.UDP_Client:
-                    cbAddr.DropDownStyle = ComboBoxStyle.DropDown;
-                    cbAddr.DataSource = null;
-                    cbAddr.Items.Clear();
-                    cbAddr.Text = NetConfig.Current.Address;
                     break;
                 default:
                 case WorkModes.UDP_TCP:
                 case WorkModes.UDP_Server:
                 case WorkModes.TCP_Server:
-                    cbAddr.DropDownStyle = ComboBoxStyle.DropDownList;
-                    cbAddr.DataSource = GetIPs();
                     break;
                 case (WorkModes)0xFF:
-                    cbAddr.DropDownStyle = ComboBoxStyle.DropDownList;
-                    cbAddr.DataSource = GetIPs();
-
                     // 端口
-                    var ns = GetNetServers().Where(n => n.Name == cbMode.Text).FirstOrDefault();
+                    var ns = GetServer(cbMode.Text);
                     if (ns != null && ns.Port > 0) numPort.Value = ns.Port;
 
                     break;
@@ -455,12 +528,12 @@ namespace XNet
         WorkModes GetMode()
         {
             var mode = cbMode.Text;
-            if (String.IsNullOrEmpty(mode)) return (WorkModes)0;
+            if (String.IsNullOrEmpty(mode)) return 0;
 
             var list = EnumHelper.GetDescriptions<WorkModes>().Where(kv => kv.Value == mode).ToList();
             if (list.Count == 0) return (WorkModes)0xFF;
 
-            return (WorkModes)list[0].Key;
+            return list[0].Key;
         }
 
         static String[] GetIPs()
@@ -473,8 +546,8 @@ namespace XNet
             return list.ToArray();
         }
 
-        static NetServer[] _ns;
-        static NetServer[] GetNetServers()
+        static Dictionary<String, Type> _ns;
+        static Dictionary<String, Type> GetNetServers()
         {
             if (_ns != null) return _ns;
 
@@ -482,19 +555,27 @@ namespace XNet
             {
                 if (_ns != null) return _ns;
 
-                var list = new List<NetServer>();
+                var dic = new Dictionary<String, Type>();
                 foreach (var item in typeof(NetServer).GetAllSubclasses(true))
                 {
                     try
                     {
                         var ns = item.CreateInstance() as NetServer;
-                        if (ns != null) list.Add(ns);
+                        if (ns != null) dic.Add(item.GetDisplayName() ?? ns.Name, item);
                     }
                     catch { }
                 }
 
-                return _ns = list.ToArray();
+                return _ns = dic;
             }
         }
+
+        static NetServer GetServer(String name)
+        {
+            Type t = null;
+            if (!GetNetServers().TryGetValue(name, out t)) return null;
+
+            return t.CreateInstance() as NetServer;
+        }
     }
 }
\ No newline at end of file
Modified +104 -57
diff --git a/XCoder/XNet/FrmMain.designer.cs b/XCoder/XNet/FrmMain.designer.cs
index 7ec4e91..6630d5b 100644
--- a/XCoder/XNet/FrmMain.designer.cs
+++ b/XCoder/XNet/FrmMain.designer.cs
@@ -40,20 +40,22 @@
             this.mi显示发送数据 = new System.Windows.Forms.ToolStripMenuItem();
             this.mi显示接收数据 = new System.Windows.Forms.ToolStripMenuItem();
             this.mi显示统计信息 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
+            this.查看Tcp参数ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.设置最大TcpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.menuSend = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.miHexSend = new System.Windows.Forms.ToolStripMenuItem();
             this.mi清空2 = new System.Windows.Forms.ToolStripMenuItem();
             this.btnConnect = new System.Windows.Forms.Button();
             this.timer1 = new System.Windows.Forms.Timer(this.components);
             this.fontDialog1 = new System.Windows.Forms.FontDialog();
             this.colorDialog1 = new System.Windows.Forms.ColorDialog();
             this.label1 = new System.Windows.Forms.Label();
-            this.lbAddr = new System.Windows.Forms.Label();
-            this.label3 = new System.Windows.Forms.Label();
+            this.lbLocal = new System.Windows.Forms.Label();
             this.cbMode = new System.Windows.Forms.ComboBox();
-            this.cbAddr = new System.Windows.Forms.ComboBox();
+            this.cbLocal = new System.Windows.Forms.ComboBox();
             this.numPort = new System.Windows.Forms.NumericUpDown();
             this.pnlSetting = new System.Windows.Forms.Panel();
-            this.cbColor = new System.Windows.Forms.CheckBox();
             this.gbSend = new System.Windows.Forms.GroupBox();
             this.numThreads = new System.Windows.Forms.NumericUpDown();
             this.numSleep = new System.Windows.Forms.NumericUpDown();
@@ -63,6 +65,9 @@
             this.label2 = new System.Windows.Forms.Label();
             this.label7 = new System.Windows.Forms.Label();
             this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.mi日志着色 = new System.Windows.Forms.ToolStripMenuItem();
+            this.cbRemote = new System.Windows.Forms.ComboBox();
+            this.label4 = new System.Windows.Forms.Label();
             this.gbReceive.SuspendLayout();
             this.menuReceive.SuspendLayout();
             this.menuSend.SuspendLayout();
@@ -102,15 +107,19 @@
             // 
             this.menuReceive.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.toolStripMenuItem1,
+            this.mi日志着色,
             this.toolStripMenuItem3,
             this.mi显示应用日志,
             this.mi显示网络日志,
             this.mi显示接收字符串,
             this.mi显示发送数据,
             this.mi显示接收数据,
-            this.mi显示统计信息});
+            this.mi显示统计信息,
+            this.toolStripMenuItem4,
+            this.查看Tcp参数ToolStripMenuItem,
+            this.设置最大TcpToolStripMenuItem});
             this.menuReceive.Name = "menuSend";
-            this.menuReceive.Size = new System.Drawing.Size(161, 164);
+            this.menuReceive.Size = new System.Drawing.Size(161, 236);
             // 
             // toolStripMenuItem1
             // 
@@ -166,17 +175,44 @@
             this.mi显示统计信息.Text = "显示统计信息";
             this.mi显示统计信息.Click += new System.EventHandler(this.mi显示统计信息_Click);
             // 
+            // toolStripMenuItem4
+            // 
+            this.toolStripMenuItem4.Name = "toolStripMenuItem4";
+            this.toolStripMenuItem4.Size = new System.Drawing.Size(157, 6);
+            // 
+            // 查看Tcp参数ToolStripMenuItem
+            // 
+            this.查看Tcp参数ToolStripMenuItem.Name = "查看Tcp参数ToolStripMenuItem";
+            this.查看Tcp参数ToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
+            this.查看Tcp参数ToolStripMenuItem.Text = "查看Tcp参数";
+            this.查看Tcp参数ToolStripMenuItem.Click += new System.EventHandler(this.查看Tcp参数ToolStripMenuItem_Click);
+            // 
+            // 设置最大TcpToolStripMenuItem
+            // 
+            this.设置最大TcpToolStripMenuItem.Name = "设置最大TcpToolStripMenuItem";
+            this.设置最大TcpToolStripMenuItem.Size = new System.Drawing.Size(160, 22);
+            this.设置最大TcpToolStripMenuItem.Text = "设置最大Tcp";
+            this.设置最大TcpToolStripMenuItem.Click += new System.EventHandler(this.设置最大TcpToolStripMenuItem_Click);
+            // 
             // menuSend
             // 
             this.menuSend.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.miHexSend,
             this.mi清空2});
             this.menuSend.Name = "menuSend";
-            this.menuSend.Size = new System.Drawing.Size(101, 26);
+            this.menuSend.Size = new System.Drawing.Size(123, 48);
+            // 
+            // miHexSend
+            // 
+            this.miHexSend.Name = "miHexSend";
+            this.miHexSend.Size = new System.Drawing.Size(122, 22);
+            this.miHexSend.Text = "Hex发送";
+            this.miHexSend.Click += new System.EventHandler(this.miHex发送_Click);
             // 
             // mi清空2
             // 
             this.mi清空2.Name = "mi清空2";
-            this.mi清空2.Size = new System.Drawing.Size(100, 22);
+            this.mi清空2.Size = new System.Drawing.Size(122, 22);
             this.mi清空2.Text = "清空";
             this.mi清空2.Click += new System.EventHandler(this.mi清空2_Click);
             // 
@@ -199,51 +235,43 @@
             // label1
             // 
             this.label1.AutoSize = true;
-            this.label1.Location = new System.Drawing.Point(7, 7);
+            this.label1.Location = new System.Drawing.Point(5, 9);
             this.label1.Name = "label1";
-            this.label1.Size = new System.Drawing.Size(41, 12);
+            this.label1.Size = new System.Drawing.Size(29, 12);
             this.label1.TabIndex = 6;
-            this.label1.Text = "模式:";
-            // 
-            // lbAddr
+            this.label1.Text = "模式";
             // 
-            this.lbAddr.AutoSize = true;
-            this.lbAddr.Location = new System.Drawing.Point(147, 7);
-            this.lbAddr.Name = "lbAddr";
-            this.lbAddr.Size = new System.Drawing.Size(41, 12);
-            this.lbAddr.TabIndex = 7;
-            this.lbAddr.Text = "地址:";
+            // lbLocal
             // 
-            // label3
-            // 
-            this.label3.AutoSize = true;
-            this.label3.Location = new System.Drawing.Point(359, 7);
-            this.label3.Name = "label3";
-            this.label3.Size = new System.Drawing.Size(41, 12);
-            this.label3.TabIndex = 8;
-            this.label3.Text = "端口:";
+            this.lbLocal.AutoSize = true;
+            this.lbLocal.Location = new System.Drawing.Point(141, 9);
+            this.lbLocal.Name = "lbLocal";
+            this.lbLocal.Size = new System.Drawing.Size(29, 12);
+            this.lbLocal.TabIndex = 7;
+            this.lbLocal.Text = "本地";
             // 
             // cbMode
             // 
             this.cbMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this.cbMode.FormattingEnabled = true;
-            this.cbMode.Location = new System.Drawing.Point(48, 3);
+            this.cbMode.Location = new System.Drawing.Point(41, 5);
             this.cbMode.Name = "cbMode";
             this.cbMode.Size = new System.Drawing.Size(93, 20);
             this.cbMode.TabIndex = 9;
             this.cbMode.SelectedIndexChanged += new System.EventHandler(this.cbMode_SelectedIndexChanged);
             // 
-            // cbAddr
+            // cbLocal
             // 
-            this.cbAddr.FormattingEnabled = true;
-            this.cbAddr.Location = new System.Drawing.Point(184, 3);
-            this.cbAddr.Name = "cbAddr";
-            this.cbAddr.Size = new System.Drawing.Size(169, 20);
-            this.cbAddr.TabIndex = 10;
+            this.cbLocal.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbLocal.FormattingEnabled = true;
+            this.cbLocal.Location = new System.Drawing.Point(177, 5);
+            this.cbLocal.Name = "cbLocal";
+            this.cbLocal.Size = new System.Drawing.Size(116, 20);
+            this.cbLocal.TabIndex = 10;
             // 
             // numPort
             // 
-            this.numPort.Location = new System.Drawing.Point(403, 3);
+            this.numPort.Location = new System.Drawing.Point(512, 5);
             this.numPort.Maximum = new decimal(new int[] {
             65535,
             0,
@@ -255,38 +283,30 @@
             0,
             0});
             this.numPort.Name = "numPort";
-            this.numPort.Size = new System.Drawing.Size(61, 21);
+            this.numPort.Size = new System.Drawing.Size(51, 21);
             this.numPort.TabIndex = 11;
             this.numPort.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+            this.toolTip1.SetToolTip(this.numPort, "端口");
             this.numPort.Value = new decimal(new int[] {
-            80,
+            8080,
             0,
             0,
             0});
             // 
             // pnlSetting
             // 
+            this.pnlSetting.Controls.Add(this.cbRemote);
+            this.pnlSetting.Controls.Add(this.label4);
             this.pnlSetting.Controls.Add(this.numPort);
-            this.pnlSetting.Controls.Add(this.cbAddr);
-            this.pnlSetting.Controls.Add(this.label3);
+            this.pnlSetting.Controls.Add(this.cbLocal);
             this.pnlSetting.Controls.Add(this.label1);
-            this.pnlSetting.Controls.Add(this.lbAddr);
+            this.pnlSetting.Controls.Add(this.lbLocal);
             this.pnlSetting.Controls.Add(this.cbMode);
             this.pnlSetting.Location = new System.Drawing.Point(9, 8);
             this.pnlSetting.Name = "pnlSetting";
-            this.pnlSetting.Size = new System.Drawing.Size(471, 31);
+            this.pnlSetting.Size = new System.Drawing.Size(572, 31);
             this.pnlSetting.TabIndex = 13;
             // 
-            // cbColor
-            // 
-            this.cbColor.AutoSize = true;
-            this.cbColor.Location = new System.Drawing.Point(500, 15);
-            this.cbColor.Name = "cbColor";
-            this.cbColor.Size = new System.Drawing.Size(72, 16);
-            this.cbColor.TabIndex = 14;
-            this.cbColor.Text = "日志着色";
-            this.cbColor.UseVisualStyleBackColor = true;
-            // 
             // gbSend
             // 
             this.gbSend.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
@@ -417,13 +437,36 @@
             this.label7.TabIndex = 15;
             this.label7.Text = "次数:";
             // 
+            // mi日志着色
+            // 
+            this.mi日志着色.Name = "mi日志着色";
+            this.mi日志着色.Size = new System.Drawing.Size(160, 22);
+            this.mi日志着色.Text = "日志着色";
+            this.mi日志着色.Click += new System.EventHandler(this.mi日志着色_Click);
+            // 
+            // cbRemote
+            // 
+            this.cbRemote.FormattingEnabled = true;
+            this.cbRemote.Location = new System.Drawing.Point(336, 5);
+            this.cbRemote.Name = "cbRemote";
+            this.cbRemote.Size = new System.Drawing.Size(169, 20);
+            this.cbRemote.TabIndex = 17;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(300, 9);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(29, 12);
+            this.label4.TabIndex = 16;
+            this.label4.Text = "远程";
+            // 
             // FrmMain
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(667, 379);
             this.Controls.Add(this.gbSend);
-            this.Controls.Add(this.cbColor);
             this.Controls.Add(this.pnlSetting);
             this.Controls.Add(this.btnConnect);
             this.Controls.Add(this.gbReceive);
@@ -443,7 +486,6 @@
             ((System.ComponentModel.ISupportInitialize)(this.numSleep)).EndInit();
             ((System.ComponentModel.ISupportInitialize)(this.numMutilSend)).EndInit();
             this.ResumeLayout(false);
-            this.PerformLayout();
 
         }
 
@@ -458,16 +500,14 @@
         private System.Windows.Forms.FontDialog fontDialog1;
         private System.Windows.Forms.ColorDialog colorDialog1;
         private System.Windows.Forms.Label label1;
-        private System.Windows.Forms.Label lbAddr;
-        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label lbLocal;
         private System.Windows.Forms.ComboBox cbMode;
-        private System.Windows.Forms.ComboBox cbAddr;
+        private System.Windows.Forms.ComboBox cbLocal;
         private System.Windows.Forms.NumericUpDown numPort;
         private System.Windows.Forms.Panel pnlSetting;
         private System.Windows.Forms.ContextMenuStrip menuReceive;
         private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
         private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3;
-        private System.Windows.Forms.CheckBox cbColor;
         private System.Windows.Forms.GroupBox gbSend;
         private System.Windows.Forms.NumericUpDown numSleep;
         private System.Windows.Forms.RichTextBox txtSend;
@@ -483,6 +523,13 @@
         private System.Windows.Forms.ToolStripMenuItem mi显示应用日志;
         private System.Windows.Forms.ToolStripMenuItem mi显示网络日志;
         private System.Windows.Forms.ToolTip toolTip1;
+        private System.Windows.Forms.ToolStripMenuItem miHexSend;
+        private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
+        private System.Windows.Forms.ToolStripMenuItem 查看Tcp参数ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem 设置最大TcpToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem mi日志着色;
+        private System.Windows.Forms.ComboBox cbRemote;
+        private System.Windows.Forms.Label label4;
     }
 }
 
Modified +6 -0
diff --git a/XCoder/XNet/FrmMain.resx b/XCoder/XNet/FrmMain.resx
index 2099e7b..0ab0a11 100644
--- a/XCoder/XNet/FrmMain.resx
+++ b/XCoder/XNet/FrmMain.resx
@@ -135,4 +135,10 @@
   <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>601, 17</value>
   </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>601, 17</value>
+  </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>601, 17</value>
+  </metadata>
 </root>
\ No newline at end of file
Added +54 -0
diff --git a/XCoder/XNet/IPPacket.cs b/XCoder/XNet/IPPacket.cs
new file mode 100644
index 0000000..bf212ed
--- /dev/null
+++ b/XCoder/XNet/IPPacket.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using NewLife.Data;
+
+namespace XCoder.XNet
+{
+    /// <summary>IP包</summary>
+    public class IPPacket
+    {
+        public Byte Version;
+        public Byte Length;
+        public Byte DiffServices;
+        public UInt16 DataLength;
+        public UInt16 Identification;
+        public Byte Flag;
+        public UInt16 Excursion;
+        public Byte TTL;
+        public ProtocolType Protocol;
+        public UInt16 CheckSum;
+        public IPAddress SrcAddr;
+        public IPAddress DestAddr;
+        public Byte[] Option;
+        public Packet Data;
+
+        public IPPacket(Packet pk)
+        {
+            if (pk == null) throw new ArgumentNullException(nameof(pk));
+
+            var data = pk.ReadBytes(0, 20);
+
+            Version = (Byte)((data[0] & 0xF0) >> 4);
+            Length = (Byte)((data[0] & 0x0F) * 4);
+            DiffServices = data[1];
+            DataLength = (UInt16)((data[2] << 8) + data[3]);
+            Identification = (UInt16)((data[4] << 8) + data[5]);
+            Flag = (Byte)(data[6] >> 5);
+            Excursion = (UInt16)(((data[6] & 0x1F) << 8) + data[7]);
+            TTL = data[8];
+            Protocol = (ProtocolType)data[9];
+            CheckSum = (UInt16)((data[10] << 8) + data[11]);
+
+            SrcAddr = new IPAddress(pk.ReadBytes(12, 4));
+            DestAddr = new IPAddress(pk.ReadBytes(16, 4));
+
+            // 可选项
+            if (Length > 20) Option = pk.ReadBytes(20, Length - 20);
+
+            Data = pk.Sub(Length, DataLength);
+        }
+
+        public override String ToString() => $"{SrcAddr} => {DestAddr} [{DataLength}]";
+    }
+}
\ No newline at end of file
Added +309 -0
diff --git a/XCoder/XNet/MySqlParser.cs b/XCoder/XNet/MySqlParser.cs
new file mode 100644
index 0000000..768bf77
--- /dev/null
+++ b/XCoder/XNet/MySqlParser.cs
@@ -0,0 +1,309 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Net;
+using System.Text;
+using NewLife.Data;
+
+namespace XCoder.XNet
+{
+    #region 分析器
+    abstract class MySqlParser
+    {
+        public Action<MySqlPacket> OnParsedPacket;
+        public Action OnParsedError;
+
+        public DateTime LastTime { get; set; }
+        public IPEndPoint LastSrcEP { get; set; }
+        public IPEndPoint LastDstEP { get; set; }
+
+        public abstract void Parse(Packet pk);
+
+        //The Packet Header
+        //Bytes                 Name
+        // -----                 ----
+        // 3                     Packet Length
+        // 1                     Packet Number
+
+        // Packet Length: The length, in bytes, of the packet
+        //                that follows the Packet Header. There
+        //                may be some special values in the most
+        //                significant byte. The maximum packet 
+        //                length is (2**24 -1),about 16MB.
+
+        // Packet Number: A serial number which can be used to
+        //                ensure that all packets are present
+        //                and in order. The first packet of a
+        //                client query will have Packet Number = 0
+        //                Thus, when a new SQL statement starts, 
+        //                the packet number is re-initialised.
+
+        protected void ReadPacketHeader(Byte[] header, out Int32 packetLength, out Int32 packetNum)
+        {
+            if (header == null || header.Length != 4) throw new ArgumentException();
+
+            packetLength = header[0] + (header[1] << 8) + (header[3] << 16);
+            packetNum = header[3];
+        }
+    }
+
+    class MySqlQueryParser : MySqlParser
+    {
+        private enum ParsingState
+        {
+            Head,
+            Body
+        }
+
+        private ParsingState _state;
+        private MySqlQueryPacket _packet;
+
+        public MySqlQueryParser()
+        {
+            _state = ParsingState.Head;
+            _packet = new MySqlQueryPacket();
+        }
+
+        public override void Parse(Packet pk)
+        {
+            TryParse(pk);
+        }
+
+        private void TryParse(Packet pk)
+        {
+            if (_state == ParsingState.Head)
+            {
+                if (pk.Count >= 4)
+                {
+                    var head = pk.ReadBytes(4);
+                    ReadPacketHeader(head, out _packet.Length, out _packet.Num);
+                    _state = ParsingState.Body;
+                }
+                else
+                    return;
+            }
+
+            if (_state == ParsingState.Body)
+            {
+                if (pk.Count >= _packet.Length)
+                {
+                    var body = _packet.Body = pk.ReadBytes(_packet.Length);
+                    _packet.Command = (DBCmd)body[0];
+                    HandleParseOk();
+                }
+            }
+        }
+
+        private void HandleParseError(String msg)
+        {
+            _state = ParsingState.Head;
+            _packet = new MySqlQueryPacket();
+
+            OnParsedError?.Invoke();
+        }
+
+        private void HandleParseOk()
+        {
+            if (OnParsedPacket != null)
+            {
+                _packet.Time = LastTime;
+                _packet.SrcEP = LastSrcEP;
+                _packet.DstEP = LastDstEP;
+                OnParsedPacket(_packet);
+            }
+            _state = ParsingState.Head;
+            _packet = new MySqlQueryPacket();
+        }
+    }
+    #endregion
+
+    #region 数据包
+    enum PacketType
+    {
+        Query,
+        ResultSet,
+    }
+
+    class MySqlPacket
+    {
+        public DateTime Time { get; set; }
+        public IPEndPoint SrcEP { get; set; }
+        public IPEndPoint DstEP { get; set; }
+
+        public PacketType PacketType { get; set; }
+    }
+    #endregion
+
+    #region 结果包
+    enum ResultSetType
+    {
+        OK,
+        Error,
+        ResultSet,
+    }
+
+    class MySqlResultSetPacket : MySqlPacket
+    {
+        public ResultSetType ResultSetType { get; set; }
+
+        public MySqlResultSetPacket()
+        {
+            PacketType = PacketType.ResultSet;
+        }
+    }
+
+    class MySqlOKResultSet : MySqlResultSetPacket
+    {
+        public Int32 Length;
+        public Int32 Num;
+        public Int32 AffectRow;
+        public Int32 ServerState;
+        public String Message;
+
+        public MySqlOKResultSet()
+        {
+            ResultSetType = ResultSetType.OK;
+        }
+    }
+
+    class MySqlErrorResultSet : MySqlResultSetPacket
+    {
+        public Int32 Length;
+        public Int32 Num;
+        public Int32 ErrorNum;
+        public Int32 SqlState;
+        public String Message;
+
+        public MySqlErrorResultSet()
+        {
+            ResultSetType = ResultSetType.Error;
+        }
+    }
+
+    class MySqlDataResultSet : MySqlResultSetPacket
+    {
+        public ResultSetHeadPacket HeadPacket;
+        public List<ResultSetFieldPacket> FieldPacket;
+        public List<ResultSetRowPacket> RowPacket;
+
+        public MySqlDataResultSet()
+        {
+            ResultSetType = ResultSetType.ResultSet;
+        }
+    }
+
+    public class ResultSetHeadPacket
+    {
+        public Int32 PacketLength;
+        public Int32 PacketNum;
+        public Int32 FieldNum;
+    }
+
+    public class ResultSetFieldPacket
+    {
+        public Int32 PacketLength;
+        public Int32 PacketNum;
+    }
+
+    public class ResultSetRowPacket
+    {
+        public Int32 PacketLength;
+        public Int32 PacketNum;
+    }
+    #endregion
+
+    #region 请求包
+    class MySqlQueryPacket : MySqlPacket
+    {
+        public Int32 Length;
+        public Int32 Num;
+        public Byte[] Body;
+        public DBCmd Command;
+
+        private String _commandArgs;
+        public String CommandArgs
+        {
+            get
+            {
+                if (Command == DBCmd.QUERY && Body != null && Body.Length > 0)
+                {
+                    if (_commandArgs == null)
+                        _commandArgs = Encoding.UTF8.GetString(Body, 1, Body.Length - 1);
+                }
+
+                return _commandArgs;
+            }
+        }
+
+        public MySqlQueryPacket()
+        {
+            PacketType = PacketType.Query;
+        }
+
+        public MySqlCommandArgs ResolveCommand()
+        {
+            var args = new MySqlCommandArgs
+            {
+                CmdType = CommandType.Text
+            };
+
+            var cmd = CommandArgs;
+            if (cmd != null)
+            {
+                if (cmd.Substring(0, 4) == "CALL")
+                {
+                    args.CmdType = CommandType.StoredProcedure;
+
+                    var start = cmd.IndexOf("(");
+                    if (start > 3) args.ResolveQuery = cmd.Substring(3, start - 3);
+                }
+                else
+                {
+                    //todo replace ='xx' to ={}
+                }
+            }
+
+            return args;
+        }
+    }
+
+    class MySqlCommandArgs
+    {
+        public CommandType CmdType { get; set; }
+        public String ResolveQuery { get; set; }
+    }
+
+    enum DBCmd : Byte
+    {
+        SLEEP = 0,
+        QUIT = 1,
+        INIT_DB = 2,
+        QUERY = 3,
+        FIELD_LIST = 4,
+        CREATE_DB = 5,
+        DROP_DB = 6,
+        RELOAD = 7,
+        SHUTDOWN = 8,
+        STATISTICS = 9,
+        PROCESS_INFO = 10,
+        CONNECT = 11,
+        PROCESS_KILL = 12,
+        DEBUG = 13,
+        PING = 14,
+        TIME = 15,
+        DELAYED_INSERT = 16,
+        CHANGE_USER = 17,
+        BINLOG_DUMP = 18,
+        TABLE_DUMP = 19,
+        CONNECT_OUT = 20,
+        REGISTER_SLAVE = 21,
+        PREPARE = 22,
+        EXECUTE = 23,
+        LONG_DATA = 24,
+        CLOSE_STMT = 25,
+        RESET_STMT = 26,
+        SET_OPTION = 27,
+        FETCH = 28
+    }
+    #endregion
+}
\ No newline at end of file
Modified +44 -27
diff --git a/XCoder/XNet/NetConfig.cs b/XCoder/XNet/NetConfig.cs
index 2bf9b3c..74145af 100644
--- a/XCoder/XNet/NetConfig.cs
+++ b/XCoder/XNet/NetConfig.cs
@@ -1,6 +1,7 @@
 using System;
 using System.ComponentModel;
 using System.IO.Ports;
+using System.Linq;
 using System.Text;
 using System.Xml.Serialization;
 using NewLife.Xml;
@@ -11,9 +12,18 @@ namespace XNet
     [XmlConfigFile("Config\\Net.config")]
     public class NetConfig : XmlConfig<NetConfig>
     {
-        /// <summary>目的地址</summary>
-        [Description("目的地址")]
-        public String Address { get; set; }
+        #region 属性
+        /// <summary>模式</summary>
+        [Description("模式")]
+        public Int32 Mode { get; set; } = 1;
+
+        /// <summary>本地地址</summary>
+        [Description("本地地址")]
+        public String Local { get; set; }
+
+        /// <summary>远程地址</summary>
+        [Description("远程地址")]
+        public String Address { get; set; } = "";
 
         /// <summary>端口</summary>
         [Description("端口")]
@@ -21,7 +31,7 @@ namespace XNet
 
         /// <summary>文本编码</summary>
         [XmlIgnore]
-        public Encoding Encoding { get; set; }
+        public Encoding Encoding { get; set; } = Encoding.UTF8;
 
         /// <summary>编码</summary>
         [Description("编码 gb2312/us-ascii/utf-8")]
@@ -31,61 +41,68 @@ namespace XNet
         [Description("十六进制显示")]
         public Boolean HexShow { get; set; }
 
+        /// <summary>十六进制发送</summary>
+        [Description("十六进制发送")]
+        public Boolean HexSend { get; set; }
+
         /// <summary>发送内容</summary>
         [Description("发送内容")]
-        public String SendContent { get; set; }
+        public String SendContent { get; set; } = "新生命开发团队,学无先后达者为师";
 
         /// <summary>发送次数</summary>
         [Description("发送次数")]
-        public Int32 SendTimes { get; set; }
+        public Int32 SendTimes { get; set; } = 1;
 
         /// <summary>发送间隔。毫秒</summary>
         [Description("发送间隔。毫秒")]
-        public Int32 SendSleep { get; set; }
+        public Int32 SendSleep { get; set; } = 1000;
 
         /// <summary>发送用户数</summary>
         [Description("发送用户数")]
-        public Int32 SendUsers { get; set; }
+        public Int32 SendUsers { get; set; } = 1;
 
         /// <summary>显示应用日志</summary>
         [Description("显示应用日志")]
-        public Boolean ShowLog { get; set; }
+        public Boolean ShowLog { get; set; } = true;
 
         /// <summary>显示网络日志</summary>
         [Description("显示网络日志")]
-        public Boolean ShowSocketLog { get; set; }
+        public Boolean ShowSocketLog { get; set; } = true;
 
         /// <summary>显示接收字符串</summary>
         [Description("显示接收字符串")]
-        public Boolean ShowReceiveString { get; set; }
+        public Boolean ShowReceiveString { get; set; } = true;
 
         /// <summary>显示发送数据</summary>
         [Description("显示发送数据")]
-        public Boolean ShowSend { get; set; }
+        public Boolean ShowSend { get; set; } = true;
 
         /// <summary>显示接收数据</summary>
         [Description("显示接收数据")]
-        public Boolean ShowReceive { get; set; }
+        public Boolean ShowReceive { get; set; } = true;
 
         /// <summary>显示统计信息</summary>
         [Description("显示统计信息")]
-        public Boolean ShowStat { get; set; }
+        public Boolean ShowStat { get; set; } = true;
+
+        /// <summary>日志着色</summary>
+        [Description("日志着色")]
+        public Boolean ColorLog { get; set; } = true;
+        #endregion
 
+        #region 方法
         public NetConfig()
         {
-            Encoding = Encoding.Default;
-
-            SendContent = "新生命开发团队,学无先后达者为师";
-            SendTimes = 1;
-            SendSleep = 1000;
-            SendUsers = 1;
-
-            ShowLog = true;
-            ShowSocketLog = true;
-            ShowReceiveString = true;
-            ShowSend = true;
-            ShowReceive = true;
-            ShowStat = true;
         }
+
+        public void AddAddress(String addr)
+        {
+            var addrs = (Address + "").Split(";").Distinct().ToList();
+            addrs.Insert(0, addr);
+            addrs = addrs.Distinct().ToList();
+            while (addrs.Count > 10) addrs.RemoveAt(addrs.Count - 1);
+            Address = addrs.Join(";");
+        }
+        #endregion
     }
 }
\ No newline at end of file
Added +74 -0
diff --git a/XCoder/XNet/RawSocket.cs b/XCoder/XNet/RawSocket.cs
new file mode 100644
index 0000000..b40763a
--- /dev/null
+++ b/XCoder/XNet/RawSocket.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using NewLife.Data;
+
+namespace XCoder.XNet
+{
+    /// <summary>原始数据Socket。用于抓包</summary>
+    public class RawSocket
+    {
+        private Socket _socket;
+        private IPAddress _address;
+
+        public Action<TcpPacket> OnTcpReceive;
+
+        public Action<Byte[], Int32> OnReceive;
+
+        public RawSocket(IPAddress address)
+        {
+            _address = address;
+            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
+            _socket.Bind(new IPEndPoint(address, 0));
+        }
+
+        public Boolean Capture()
+        {
+            try
+            {
+                _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);
+                var inBytes = new Byte[] { 1, 0, 0, 0 };
+                var outBytes = new Byte[] { 0, 0, 0, 0 };
+                _socket.IOControl(IOControlCode.ReceiveAll, inBytes, outBytes);
+                if (0 != outBytes[0] + outBytes[1] + outBytes[2] + outBytes[3]) return false;
+            }
+            catch (SocketException)
+            {
+                return false;
+            }
+
+            while (_socket != null)
+            {
+                var buffer = new Byte[1500];
+
+                var count = _socket.Receive(buffer, SocketFlags.None);
+                var pk = new Packet(buffer, 0, count);
+
+                OnReceive?.Invoke(buffer, count);
+
+                if (OnTcpReceive != null)
+                {
+                    var ip = new IPPacket(pk);
+                    if (ip.Protocol == ProtocolType.Tcp)
+                    {
+                        var tcp = new TcpPacket(ip);
+                        OnTcpReceive(tcp);
+                    }
+                }
+            }
+
+            return true;
+        }
+
+        public void Stop()
+        {
+            var s = _socket;
+            if (s != null)
+            {
+                _socket = null;
+                s.Shutdown(SocketShutdown.Both);
+                s.Close();
+            }
+        }
+    }
+}
\ No newline at end of file
Added +56 -0
diff --git a/XCoder/XNet/TcpPacket.cs b/XCoder/XNet/TcpPacket.cs
new file mode 100644
index 0000000..645b202
--- /dev/null
+++ b/XCoder/XNet/TcpPacket.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Net.Sockets;
+using NewLife.Data;
+
+namespace XCoder.XNet
+{
+    /// <summary>Tcp包</summary>
+    public class TcpPacket
+    {
+        public IPPacket IPPacket;
+
+        public UInt16 SrcPort;
+        public UInt16 DestPort;
+        public UInt32 SequenceNo;
+        public UInt32 NextSeqNo;
+        public Byte HeadLength;
+        public Byte Flag;
+        public UInt16 WindowSize;
+        public UInt16 CheckSum;
+        public UInt16 UrgPtr;
+        public Byte[] Option;
+        public Packet Data;
+
+        public TcpPacket(IPPacket packet)
+        {
+            if (packet == null) throw new ArgumentNullException(nameof(packet));
+            if (packet.Protocol != ProtocolType.Tcp) throw new NotSupportedException();
+
+            IPPacket = packet;
+
+            var pk = packet.Data;
+            var data = pk.ReadBytes(0, 20);
+
+            SrcPort = (UInt16)((data[0] << 8) + data[1]);
+            DestPort = (UInt16)((data[2] << 8) + data[3]);
+
+            SequenceNo = ((UInt32)data[7] << 24) + ((UInt32)data[6] << 16) + ((UInt32)data[5] << 8) + data[4];
+            NextSeqNo = ((UInt32)data[11] << 24) + ((UInt32)data[10] << 16) + ((UInt32)data[9] << 8) + data[8];
+
+            HeadLength = (Byte)(((data[12] & 0xF0) >> 4) * 4);
+
+            // 6bit保留位
+            Flag = (Byte)(data[13] & 0x3F);
+            WindowSize = (UInt16)((data[14] << 8) + data[15]);
+            CheckSum = (UInt16)((data[16] << 8) + data[17]);
+            UrgPtr = (UInt16)((data[18] << 8) + data[19]);
+
+            // 可选项
+            if (HeadLength > 20) Option = pk.ReadBytes(20, HeadLength - 20);
+
+            Data = pk.Sub(HeadLength);
+        }
+
+        public override String ToString() => $"{IPPacket?.SrcAddr}:{SrcPort} => {IPPacket.DestAddr}:{DestPort} [{IPPacket.DataLength - HeadLength}]";
+    }
+}
\ No newline at end of file
Modified +10 -10
diff --git a/XCoder/XRegex/FileResource.cs b/XCoder/XRegex/FileResource.cs
index 384d47d..0185998 100644
--- a/XCoder/XRegex/FileResource.cs
+++ b/XCoder/XRegex/FileResource.cs
@@ -37,26 +37,26 @@ namespace XCoder.XRegex
         /// <param name="name">名称</param>
         public static void ReleaseTemplateFiles(String name)
         {
-            String path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name);
+            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name);
             if (Directory.Exists(path)) return;
 
-            String[] ss = Assembly.GetExecutingAssembly().GetManifestResourceNames();
+            var ss = Assembly.GetExecutingAssembly().GetManifestResourceNames();
             if (ss == null || ss.Length <= 0) return;
 
             // 取命名空间
-            String prefix = typeof(FileResource).FullName;
+            var prefix = typeof(FileResource).FullName;
             prefix = prefix.Substring(0, prefix.LastIndexOf("."));
             prefix += "." + name + ".";
 
             //找到资源名
-            foreach (String item in ss)
+            foreach (var item in ss)
             {
                 if (item.StartsWith(prefix))
                 {
-                    String fileName = item.Substring(prefix.Length);
+                    var fileName = item.Substring(prefix.Length);
                     fileName = fileName.Replace(".", @"\");
                     // 最后一个斜杠变回圆点
-                    Char[] cc = fileName.ToCharArray();
+                    var cc = fileName.ToCharArray();
                     cc[fileName.LastIndexOf("\\")] = '.';
                     fileName = new String(cc);
                     fileName = Path.Combine(path, fileName);
@@ -75,13 +75,13 @@ namespace XCoder.XRegex
         {
             try
             {
-                Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
+                var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
                 if (stream == null) return;
 
-                Byte[] buffer = new Byte[stream.Length];
-                Int32 count = stream.Read(buffer, 0, buffer.Length);
+                var buffer = new Byte[stream.Length];
+                var count = stream.Read(buffer, 0, buffer.Length);
 
-                String p = Path.GetDirectoryName(fileName);
+                var p = Path.GetDirectoryName(fileName);
                 if (!String.IsNullOrEmpty(p) && !Directory.Exists(p)) Directory.CreateDirectory(p);
 
                 File.WriteAllBytes(fileName, buffer);
Modified +67 -64
diff --git a/XCoder/XRegex/FrmMain.cs b/XCoder/XRegex/FrmMain.cs
index 94052fb..bfe5891 100644
--- a/XCoder/XRegex/FrmMain.cs
+++ b/XCoder/XRegex/FrmMain.cs
@@ -13,26 +13,29 @@ using XCoder.XRegex;
 namespace NewLife.XRegex
 {
     [DisplayName("正则表达式工具")]
-    public partial class FrmMain : Form
+    public partial class FrmMain : Form, IXForm
     {
         #region 窗体初始化
         public FrmMain()
         {
             InitializeComponent();
 
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
             Icon = IcoHelper.GetIcon("正则");
 
             FileResource.CheckTemplate();
         }
 
-        private void FrmMain_Shown(object sender, EventArgs e)
+        private void FrmMain_Shown(Object sender, EventArgs e)
         {
             //Text += " V" + FileVersion;
 
             GetOption();
         }
 
-        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
+        private void FrmMain_FormClosing(Object sender, FormClosingEventArgs e)
         {
             // 关闭前保存正则和内容
             Save(txtPattern.Text, "Pattern");
@@ -43,21 +46,21 @@ namespace NewLife.XRegex
         {
             if (String.IsNullOrEmpty(content)) return;
 
-            String p = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name);
+            var p = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name);
             p = Path.Combine(p, "最近");
 
             #region 预处理
             if (Directory.Exists(p))
             {
                 // 拿出所有文件
-                String[] files = Directory.GetFiles(p, "*.txt", SearchOption.TopDirectoryOnly);
+                var files = Directory.GetFiles(p, "*.txt", SearchOption.TopDirectoryOnly);
                 if (files != null && files.Length > 0)
                 {
                     // 内容比对
-                    List<String> list = new List<String>();
-                    foreach (String item in files)
+                    var list = new List<String>();
+                    foreach (var item in files)
                     {
-                        String content2 = File.ReadAllText(item);
+                        var content2 = File.ReadAllText(item);
                         if (content2 == content)
                             File.Delete(item);
                         else
@@ -71,7 +74,7 @@ namespace NewLife.XRegex
                         list.Sort();
 
                         // 删除最后的
-                        for (int i = list.Count - 1; i >= 10; i--)
+                        for (var i = list.Count - 1; i >= 10; i--)
                         {
                             File.Delete(list[i]);
                         }
@@ -83,16 +86,16 @@ namespace NewLife.XRegex
             #endregion
 
             // 写入
-            String file = String.Format("{0:yyyy-MM-dd_HHmmss}.txt", DateTime.Now);
+            var file = String.Format("{0:yyyy-MM-dd_HHmmss}.txt", DateTime.Now);
             file = Path.Combine(p, file);
             File.WriteAllText(file, content);
         }
         #endregion
 
         #region 正则匹配
-        private void radioButton1_CheckedChanged(object sender, EventArgs e)
+        private void radioButton1_CheckedChanged(Object sender, EventArgs e)
         {
-            RadioButton rb = sender as RadioButton;
+            var rb = sender as RadioButton;
             if (rb.Checked)
             {
                 button2.Text = "正则匹配";
@@ -131,14 +134,14 @@ namespace NewLife.XRegex
             RegexOptions options;
             GetReg(out pattern, out options);
 
-            Boolean isSuccess = false;
-            AutoResetEvent e = new AutoResetEvent(false);
-            Thread thread = new Thread(new ThreadStart(delegate
+            var isSuccess = false;
+            var e = new AutoResetEvent(false);
+            var thread = new Thread(new ThreadStart(delegate
             {
                 try
                 {
                     // 如果正则表达式过于复杂,创建对象时可能需要花很长时间,甚至超时
-                    Regex reg = new Regex(pattern, options);
+                    var reg = new Regex(pattern, options);
                     callback(reg);
 
                     isSuccess = true;
@@ -162,8 +165,8 @@ namespace NewLife.XRegex
             //    ShowError("执行正则表达式超时!");
             //    return;
             //}
-            Boolean b = false;
-            for (int i = 0; i < timeout / 100; i++)
+            var b = false;
+            for (var i = 0; i < timeout / 100; i++)
             {
                 if (e.WaitOne(100))
                 {
@@ -181,23 +184,23 @@ namespace NewLife.XRegex
             return isSuccess;
         }
 
-        private void button2_Click(object sender, EventArgs e)
+        private void button2_Click(Object sender, EventArgs e)
         {
             if (String.IsNullOrEmpty(txtPattern.Text)) return;
-            String content = txtContent.Text;
+            var content = txtContent.Text;
             if (String.IsNullOrEmpty(content)) return;
 
             // 是否替换
-            Boolean isReplace = !radioButton1.Checked;
-            String replacement = rtReplace.Text;
+            var isReplace = !radioButton1.Checked;
+            var replacement = rtReplace.Text;
             if (isReplace && String.IsNullOrEmpty(replacement)) return;
 
             Regex r = null;
             MatchCollection ms = null;
-            Int32 count = 0;
+            var count = 0;
 
             // 异步执行,防止超时
-            Boolean isSuccess = ProcessAsync(delegate(Regex reg)
+            var isSuccess = ProcessAsync(delegate(Regex reg)
             {
                 r = reg;
                 ms = reg.Matches(content);
@@ -214,7 +217,7 @@ namespace NewLife.XRegex
 
             lbStatus.Text = String.Format("成功{0} {1} 项!", !isReplace ? "匹配" : "替换", count);
 
-            int i = 1;
+            var i = 1;
             foreach (Match match in ms)
             {
                 var item = lvMatch.Items.Add(i.ToString());
@@ -227,31 +230,31 @@ namespace NewLife.XRegex
             if (isReplace) txtContent.Text = content;
         }
 
-        private void button5_Click(object sender, EventArgs e)
+        private void button5_Click(Object sender, EventArgs e)
         {
             if (String.IsNullOrEmpty(txtPattern.Text)) return;
-            String replacement = rtReplace.Text;
+            var replacement = rtReplace.Text;
             if (String.IsNullOrEmpty(replacement)) return;
 
             // 获取文件
-            String[] files = GetFiles();
+            var files = GetFiles();
             lbStatus.Text = String.Format("共有符合条件的文件 {0} 个!", files.Length);
 
             MatchCollection ms = null;
-            Int32 count = 0;
+            var count = 0;
 
             // 异步执行,防止超时
-            Boolean isSuccess = ProcessAsync(delegate(Regex reg)
+            var isSuccess = ProcessAsync(delegate(Regex reg)
             {
-                foreach (String item in files)
+                foreach (var item in files)
                 {
-                    String content = File.ReadAllText(item);
+                    var content = File.ReadAllText(item);
                     ms = reg.Matches(content);
                     if (ms != null) count = ms.Count;
                     // 有匹配项才替换
                     if (count > 0)
                     {
-                        String content2 = reg.Replace(content, replacement);
+                        var content2 = reg.Replace(content, replacement);
                         // 有改变才更新文件
                         if (content != content2) File.WriteAllText(item, content2);
                     }
@@ -267,18 +270,18 @@ namespace NewLife.XRegex
         #endregion
 
         #region 选择匹配项
-        private void lvMatch_SelectedIndexChanged(object sender, EventArgs e)
+        private void lvMatch_SelectedIndexChanged(Object sender, EventArgs e)
         {
             if (lvMatch.SelectedItems == null || lvMatch.SelectedItems.Count < 1) return;
 
             // 当前选择项
-            Match m = lvMatch.SelectedItems[0].Tag as Match;
+            var m = lvMatch.SelectedItems[0].Tag as Match;
             //rtContent.SelectedText = m.Value;
             txtContent.Select(m.Index, m.Length);
             txtContent.ScrollToCaret();
 
             // 分组的选择是否与当前一致
-            Match m2 = lvGroup.Tag as Match;
+            var m2 = lvGroup.Tag as Match;
             if (m2 != null && m2 == m) return;
 
             lvGroup.Tag = m;
@@ -286,7 +289,7 @@ namespace NewLife.XRegex
             lvCapture.Items.Clear();
 
             var reg = lvMatch.Tag as Regex;
-            for (int i = 0; i < m.Groups.Count; i++)
+            for (var i = 0; i < m.Groups.Count; i++)
             {
                 var g = m.Groups[i];
                 var item = lvGroup.Items.Add(i.ToString());
@@ -297,24 +300,24 @@ namespace NewLife.XRegex
             }
         }
 
-        private void lvGroup_SelectedIndexChanged(object sender, EventArgs e)
+        private void lvGroup_SelectedIndexChanged(Object sender, EventArgs e)
         {
             if (lvGroup.SelectedItems == null || lvGroup.SelectedItems.Count < 1) return;
 
             // 当前选择项
-            Group g = lvGroup.SelectedItems[0].Tag as Group;
+            var g = lvGroup.SelectedItems[0].Tag as Group;
             //rtContent.SelectedText = g.Value;
             txtContent.Select(g.Index, g.Length);
             txtContent.ScrollToCaret();
 
             // 分组的选择是否与当前一致
-            Group g2 = lvCapture.Tag as Group;
+            var g2 = lvCapture.Tag as Group;
             if (g2 != null && g2 == g) return;
 
             lvCapture.Tag = g;
             lvCapture.Items.Clear();
 
-            for (int i = 0; i < g.Captures.Count; i++)
+            for (var i = 0; i < g.Captures.Count; i++)
             {
                 var c = g.Captures[i];
                 var item = lvCapture.Items.Add(i.ToString());
@@ -324,12 +327,12 @@ namespace NewLife.XRegex
             }
         }
 
-        private void lvCapture_SelectedIndexChanged(object sender, EventArgs e)
+        private void lvCapture_SelectedIndexChanged(Object sender, EventArgs e)
         {
             if (lvCapture.SelectedItems == null || lvCapture.SelectedItems.Count < 1) return;
 
             // 当前选择项
-            Capture c = lvCapture.SelectedItems[0].Tag as Capture;
+            var c = lvCapture.SelectedItems[0].Tag as Capture;
             txtContent.SelectedText = c.Value;
             txtContent.Select(c.Index, c.Length);
             txtContent.ScrollToCaret();
@@ -352,8 +355,8 @@ namespace NewLife.XRegex
             {
                 if (String.IsNullOrEmpty(_FileVersion))
                 {
-                    Assembly asm = Assembly.GetExecutingAssembly();
-                    AssemblyFileVersionAttribute av = Attribute.GetCustomAttribute(asm, typeof(AssemblyFileVersionAttribute)) as AssemblyFileVersionAttribute;
+                    var asm = Assembly.GetExecutingAssembly();
+                    var av = Attribute.GetCustomAttribute(asm, typeof(AssemblyFileVersionAttribute)) as AssemblyFileVersionAttribute;
                     if (av != null) _FileVersion = av.Version;
                     if (String.IsNullOrEmpty(_FileVersion)) _FileVersion = "1.0";
                 }
@@ -374,18 +377,18 @@ namespace NewLife.XRegex
         #endregion
 
         #region 菜单
-        private void ptMenu_Opening(object sender, CancelEventArgs e)
+        private void ptMenu_Opening(Object sender, CancelEventArgs e)
         {
-            for (int i = ptMenu.Items.Count - 1; i >= 1; i--)
+            for (var i = ptMenu.Items.Count - 1; i >= 1; i--)
             {
                 ptMenu.Items.RemoveAt(i);
             }
             LoadMenuTree(ptMenu.Items, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Pattern"));
         }
 
-        private void txtMenu_Opening(object sender, CancelEventArgs e)
+        private void txtMenu_Opening(Object sender, CancelEventArgs e)
         {
-            for (int i = txtMenu.Items.Count - 1; i >= 1; i--)
+            for (var i = txtMenu.Items.Count - 1; i >= 1; i--)
             {
                 txtMenu.Items.RemoveAt(i);
             }
@@ -420,12 +423,12 @@ namespace NewLife.XRegex
                 }
             }
             // 遍历文件
-            String[] files = Directory.GetFiles(path, "*.txt", SearchOption.TopDirectoryOnly);
+            var files = Directory.GetFiles(path, "*.txt", SearchOption.TopDirectoryOnly);
             if (files != null && files.Length > 0)
             {
-                foreach (String item in files)
+                foreach (var item in files)
                 {
-                    ToolStripMenuItem menu = new ToolStripMenuItem(Path.GetFileNameWithoutExtension(item));
+                    var menu = new ToolStripMenuItem(Path.GetFileNameWithoutExtension(item));
                     menu.Click += MenuItem_Click;
                     menu.Tag = Path.Combine(path, item);
 
@@ -434,13 +437,13 @@ namespace NewLife.XRegex
             }
         }
 
-        private void MenuItem_Click(object sender, EventArgs e)
+        private void MenuItem_Click(Object sender, EventArgs e)
         {
-            ToolStripMenuItem menu = sender as ToolStripMenuItem;
+            var menu = sender as ToolStripMenuItem;
             if (menu == null) return;
 
             // 找文件路径
-            String file = (String)menu.Tag;
+            var file = (String)menu.Tag;
             if (String.IsNullOrEmpty(file)) return;
             if (!File.Exists(file)) return;
 
@@ -448,7 +451,7 @@ namespace NewLife.XRegex
             ToolStripItem item = menu;
             while (item.OwnerItem != null) item = item.OwnerItem;
 
-            ContextMenuStrip cms = item.Owner as ContextMenuStrip;
+            var cms = item.Owner as ContextMenuStrip;
             if (cms == null) return;
 
             TextBoxBase rt = null;
@@ -459,22 +462,22 @@ namespace NewLife.XRegex
 
             if (rt == null) return;
 
-            String content = File.ReadAllText(file);
+            var content = File.ReadAllText(file);
             rt.SelectedText = content;
         }
         #endregion
 
         #region 打开目录
-        private void button4_Click(object sender, EventArgs e)
+        private void button4_Click(Object sender, EventArgs e)
         {
-            Button btn = sender as Button;
+            var btn = sender as Button;
             GetFolder(btn);
             if (!String.IsNullOrEmpty(folderBrowserDialog1.SelectedPath)) GetFiles();
         }
 
         void GetFolder(Button btn)
         {
-            FolderBrowserDialog fb = folderBrowserDialog1;
+            var fb = folderBrowserDialog1;
 
             if (fb.ShowDialog() != DialogResult.OK) return;
             btn.Tag = fb.SelectedPath;
@@ -486,8 +489,8 @@ namespace NewLife.XRegex
         String[] GetFiles()
         {
             // 获取目录,如果没有选择,则打开选择
-            Button btn = button4;
-            String path = btn.Tag == null ? null : (String)btn.Tag;
+            var btn = button4;
+            var path = btn.Tag == null ? null : (String)btn.Tag;
             if (String.IsNullOrEmpty(path))
             {
                 GetFolder(btn);
@@ -497,7 +500,7 @@ namespace NewLife.XRegex
             if (String.IsNullOrEmpty(path) || !Directory.Exists(path)) return null;
 
             // 获取文件
-            String[] files = Directory.GetFiles(path, textBox2.Text, SearchOption.AllDirectories);
+            var files = Directory.GetFiles(path, textBox2.Text, SearchOption.AllDirectories);
             if (files == null || files.Length < 1)
             {
                 ShowError("没有符合条件的文件!");
@@ -517,7 +520,7 @@ namespace NewLife.XRegex
         #endregion
 
         #region 正则选项
-        private void checkBox1_CheckedChanged(object sender, EventArgs e)
+        private void checkBox1_CheckedChanged(Object sender, EventArgs e)
         {
             var chk = sender as CheckBox;
             if (chk == null) return;
Added +248 -0
diff --git a/XCoder/Yun/FrmMap.cs b/XCoder/Yun/FrmMap.cs
new file mode 100644
index 0000000..ed7c8a3
--- /dev/null
+++ b/XCoder/Yun/FrmMap.cs
@@ -0,0 +1,248 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using NewLife.Data;
+using NewLife.Log;
+using NewLife.Reflection;
+using NewLife.Serialization;
+using NewLife.Yun;
+
+namespace XCoder.Yun
+{
+    [DisplayName("地图接口")]
+    public partial class FrmMap : Form, IXForm
+    {
+        /// <summary>业务日志输出</summary>
+        ILog BizLog;
+
+        //IDictionary<String, Type> Maps = new Dictionary<String, Type>();
+        //IDictionary<String, String> Methods = new Dictionary<String, String>();
+
+        #region 窗体
+        public FrmMap()
+        {
+            InitializeComponent();
+
+            // 动态调节宽度高度,兼容高DPI
+            this.FixDpi();
+
+            Icon = IcoHelper.GetIcon("地图");
+        }
+
+        private void FrmMain_Load(Object sender, EventArgs e)
+        {
+            var log = TextFileLog.Create(null, "Map_{0:yyyy_MM_dd}.log");
+            BizLog = txtReceive.Combine(log);
+            txtReceive.UseWinFormControl();
+
+            txtReceive.SetDefaultStyle(12);
+
+            // 加载保存的颜色
+            UIConfig.Apply(txtReceive);
+
+            LoadConfig();
+
+            var cfg = Setting;
+
+            var cb = cbMap;
+            cb.Items.Clear();
+            cb.DisplayMember = "Name";
+            foreach (var item in typeof(IMap).GetAllSubclasses(true))
+            {
+                //var name = item.GetDisplayName() ?? item.Name;
+                //Maps[name] = item;
+                //cb.Items.Add(name);
+                cb.Items.Add(item);
+
+                if (cfg.Map == item.Name) cb.SelectedItem = item;
+            }
+            //if (cb.Items.Count > 0) cb.SelectedText = cfg.Map;
+        }
+        #endregion
+
+        #region 配置
+        MapSetting Setting;
+
+        void LoadConfig()
+        {
+            var cfg = Setting = MapSetting.Current;
+
+            txtAddress.Text = cfg.Address;
+            txtCity.Text = cfg.City;
+            txtLocation.Text = cfg.Location;
+            txtLocation2.Text = cfg.Location2;
+            chkFormatAddress.Checked = cfg.FormatAddress;
+
+            //cbMap.SelectedValue = cfg.Map;
+            //cbMethod.SelectedValue = cfg.Method;
+            //cbCoordtype.SelectedValue = cfg.Coordtype;
+        }
+
+        void SaveConfig()
+        {
+            var cfg = Setting = MapSetting.Current;
+
+            cfg.Address = txtAddress.Text;
+            cfg.City = txtCity.Text;
+            cfg.Location = txtLocation.Text;
+            cfg.Location2 = txtLocation2.Text;
+            cfg.FormatAddress = chkFormatAddress.Checked;
+
+            cfg.Map = (cbMap.SelectedItem as Type)?.Name;
+            cfg.Method = (cbMethod.SelectedItem as MethodInfo)?.Name;
+            cfg.Coordtype = cbCoordtype.SelectedItem as String;
+
+            cfg.Save();
+        }
+        #endregion
+
+        #region 收发数据
+        private void btnInvoke_Click(Object sender, EventArgs e)
+        {
+            var type = cbMap.SelectedItem as Type;
+            if (type == null) return;
+
+            var method = cbMethod.SelectedItem as MethodInfo;
+            if (method == null) return;
+
+            SaveConfig();
+            var cfg = Setting;
+
+            var map = type.CreateInstance() as NewLife.Yun.Map;
+            map.Log = XTrace.Log;
+            map.CoordType = cfg.Coordtype;
+
+            // 准备参数
+            var addr = txtAddress.Text;
+            var city = txtCity.Text;
+            var point = new GeoPoint(txtLocation.Text);
+            var point2 = new GeoPoint(txtLocation2.Text);
+
+            var mps = method.GetParameters();
+
+            Task.Factory.StartNew(async () =>
+            {
+                Object result = null;
+                //var point = new GeoPoint(cfg.Location);
+                //var point2 = new GeoPoint(cfg.Location2);
+                try
+                {
+                    var im = map as IMap;
+                    if (method.Name == nameof(im.GetGeocoderAsync) && mps.Length == 2)
+                    {
+                        result = await im.GetGeocoderAsync(addr,city);
+                    }
+                    else if (method.Name == nameof(im.GetGeocoderAsync) && mps.Length == 1)
+                    {
+                        result = await im.GetGeocoderAsync(point);
+                    }
+                    else if (method.Name == nameof(im.GetGeoAsync) && mps.Length == 3)
+                    {
+                        result = await im.GetGeoAsync(addr, city, cfg.FormatAddress);
+                    }
+                    else if (method.Name == nameof(im.GetGeoAsync) && mps.Length == 1)
+                    {
+                        result = await im.GetGeoAsync(point);
+                    }
+                    else if (method.Name == nameof(im.GetDistanceAsync))
+                    {
+                        result = await im.GetDistanceAsync(point, point2);
+                    }
+                    else if (map is BaiduMap bd && method.Name == nameof(bd.PlaceSearchAsync))
+                    {
+                        result = await bd.PlaceSearchAsync(addr, null, city, cfg.FormatAddress);
+                    }
+                    else if (map is AMap am && method.Name == nameof(am.GetAreaAsync))
+                    {
+                        result = (await am.GetAreaAsync(city))?.ToArray();
+                    }
+                    else
+                    {
+                        var ps = new Dictionary<String, Object>();
+                        if (mps.Any(k => k.Name.EqualIgnoreCase("address"))) ps["address"] = addr;
+                        if (mps.Any(k => k.Name.EqualIgnoreCase("city"))) ps["city"] = cfg.City;
+
+                        var task = map.InvokeWithParams(method, ps) as Task;
+                        await task;
+
+                        result = task.GetValue("Result");
+                    }
+                }
+                catch (Exception ex)
+                {
+                    ex = ex.GetTrue();
+                    if (ex.GetType() == typeof(Exception))
+                        XTrace.WriteLine(ex.Message);
+                    else
+                        XTrace.WriteException(ex);
+                    return;
+                }
+
+                this.Invoke(() =>
+                {
+                    pgResult.SelectedObject = result;
+
+                    if (result is GeoAddress geo)
+                        txtLocation.Text = geo.Location + "";
+                    else if (result is GeoPoint gp)
+                        txtLocation.Text = gp + "";
+                });
+
+                //XTrace.WriteLine(map.LastUrl);
+
+                var js = new JsonParser(map.LastString).Decode();
+                XTrace.WriteLine(js.ToJson(true));
+            });
+        }
+        #endregion
+
+        private void cbMap_SelectedIndexChanged(Object sender, EventArgs e)
+        {
+            //var name = cbMap.SelectedItem + "";
+            //if (!Maps.TryGetValue(name, out var type)) return;
+            var type = cbMap.SelectedItem as Type;
+            if (type == null) return;
+
+            var cfg = Setting;
+
+            var cb = cbMethod;
+            cb.Items.Clear();
+            //Methods.Clear();
+            cb.DisplayMember = "Name";
+            foreach (var item in type.GetMethods())
+            {
+                if (item.DeclaringType != type) continue;
+
+                //var name = item.Name;
+                //Methods.Add(name, name);
+
+                cb.Items.Add(item);
+                if (cfg.Method == item.Name) cb.SelectedItem = item;
+            }
+            //if (cb.Items.Count > 0) cb.SelectedIndex = 0;
+
+            cb = cbCoordtype;
+            cb.Items.Clear();
+
+            if (type.Name.Contains("Baidu"))
+            {
+                cb.Items.Add("bd09ll");
+                cb.Items.Add("bd09mc");
+            }
+            //else if (name.Contains("高德"))
+            //{
+
+            //}
+
+            cb.Items.Add("gcj02ll");
+            cb.Items.Add("wgs84ll");
+
+            //cb.SelectedIndex = 0;
+            cb.SelectedItem = cfg.Coordtype;
+        }
+    }
+}
\ No newline at end of file
Added +307 -0
diff --git a/XCoder/Yun/FrmMap.Designer.cs b/XCoder/Yun/FrmMap.Designer.cs
new file mode 100644
index 0000000..ebb3438
--- /dev/null
+++ b/XCoder/Yun/FrmMap.Designer.cs
@@ -0,0 +1,307 @@
+namespace XCoder.Yun
+{
+    partial class FrmMap
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.lbMethod = new System.Windows.Forms.Label();
+            this.label6 = new System.Windows.Forms.Label();
+            this.cbCoordtype = new System.Windows.Forms.ComboBox();
+            this.cbMethod = new System.Windows.Forms.ComboBox();
+            this.label5 = new System.Windows.Forms.Label();
+            this.label4 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.chkFormatAddress = new System.Windows.Forms.CheckBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.txtAddress = new System.Windows.Forms.TextBox();
+            this.cbMap = new System.Windows.Forms.ComboBox();
+            this.pgResult = new System.Windows.Forms.PropertyGrid();
+            this.colorDialog1 = new System.Windows.Forms.ColorDialog();
+            this.fontDialog1 = new System.Windows.Forms.FontDialog();
+            this.btnInvoke = new System.Windows.Forms.Button();
+            this.txtReceive = new System.Windows.Forms.RichTextBox();
+            this.txtCity = new System.Windows.Forms.TextBox();
+            this.gbReceive = new System.Windows.Forms.GroupBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.txtLocation = new System.Windows.Forms.TextBox();
+            this.button1 = new System.Windows.Forms.Button();
+            this.label7 = new System.Windows.Forms.Label();
+            this.txtLocation2 = new System.Windows.Forms.TextBox();
+            this.gbReceive.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // gbReceive
+            // 
+            this.gbReceive.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+            | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbReceive.Controls.Add(this.txtReceive);
+            this.gbReceive.Location = new System.Drawing.Point(2, 108);
+            this.gbReceive.Name = "gbReceive";
+            this.gbReceive.Size = new System.Drawing.Size(381, 378);
+            this.gbReceive.TabIndex = 24;
+            this.gbReceive.TabStop = false;
+            // 
+            // lbMethod
+            // 
+            this.lbMethod.AutoSize = true;
+            this.lbMethod.Location = new System.Drawing.Point(490, 16);
+            this.lbMethod.Name = "lbMethod";
+            this.lbMethod.Size = new System.Drawing.Size(53, 12);
+            this.lbMethod.TabIndex = 39;
+            this.lbMethod.Text = "方法签名";
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(155, 16);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(53, 12);
+            this.label6.TabIndex = 35;
+            this.label6.Text = "坐标系:";
+            // 
+            // cbCoordtype
+            // 
+            this.cbCoordtype.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbCoordtype.FormattingEnabled = true;
+            this.cbCoordtype.Location = new System.Drawing.Point(214, 12);
+            this.cbCoordtype.Name = "cbCoordtype";
+            this.cbCoordtype.Size = new System.Drawing.Size(77, 20);
+            this.cbCoordtype.TabIndex = 34;
+            // 
+            // cbMethod
+            // 
+            this.cbMethod.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbMethod.FormattingEnabled = true;
+            this.cbMethod.Location = new System.Drawing.Point(344, 12);
+            this.cbMethod.Name = "cbMethod";
+            this.cbMethod.Size = new System.Drawing.Size(128, 20);
+            this.cbMethod.TabIndex = 33;
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(297, 16);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(41, 12);
+            this.label5.TabIndex = 32;
+            this.label5.Text = "接口:";
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(16, 16);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(41, 12);
+            this.label4.TabIndex = 31;
+            this.label4.Text = "地图:";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(342, 48);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(41, 12);
+            this.label2.TabIndex = 30;
+            this.label2.Text = "城市:";
+            // 
+            // chkFormatAddress
+            // 
+            this.chkFormatAddress.AutoSize = true;
+            this.chkFormatAddress.Checked = true;
+            this.chkFormatAddress.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkFormatAddress.Location = new System.Drawing.Point(482, 46);
+            this.chkFormatAddress.Name = "chkFormatAddress";
+            this.chkFormatAddress.Size = new System.Drawing.Size(84, 16);
+            this.chkFormatAddress.TabIndex = 38;
+            this.chkFormatAddress.Text = "格式化地址";
+            this.chkFormatAddress.UseVisualStyleBackColor = true;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(16, 48);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(41, 12);
+            this.label1.TabIndex = 29;
+            this.label1.Text = "地址:";
+            // 
+            // txtAddress
+            // 
+            this.txtAddress.Location = new System.Drawing.Point(63, 44);
+            this.txtAddress.Name = "txtAddress";
+            this.txtAddress.Size = new System.Drawing.Size(256, 21);
+            this.txtAddress.TabIndex = 27;
+            this.txtAddress.Text = "陆家嘴银城中路501号";
+            // 
+            // cbMap
+            // 
+            this.cbMap.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbMap.FormattingEnabled = true;
+            this.cbMap.Location = new System.Drawing.Point(63, 12);
+            this.cbMap.Name = "cbMap";
+            this.cbMap.Size = new System.Drawing.Size(89, 20);
+            this.cbMap.TabIndex = 26;
+            this.cbMap.SelectedIndexChanged += new System.EventHandler(this.cbMap_SelectedIndexChanged);
+            // 
+            // pgResult
+            // 
+            this.pgResult.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.pgResult.LineColor = System.Drawing.SystemColors.ControlDark;
+            this.pgResult.Location = new System.Drawing.Point(386, 108);
+            this.pgResult.Name = "pgResult";
+            this.pgResult.PropertySort = System.Windows.Forms.PropertySort.NoSort;
+            this.pgResult.Size = new System.Drawing.Size(281, 375);
+            this.pgResult.TabIndex = 25;
+            // 
+            // btnInvoke
+            // 
+            this.btnInvoke.Location = new System.Drawing.Point(559, 8);
+            this.btnInvoke.Name = "btnInvoke";
+            this.btnInvoke.Size = new System.Drawing.Size(67, 29);
+            this.btnInvoke.TabIndex = 23;
+            this.btnInvoke.Text = "调用";
+            this.btnInvoke.UseVisualStyleBackColor = true;
+            this.btnInvoke.Click += new System.EventHandler(this.btnInvoke_Click);
+            // 
+            // txtReceive
+            // 
+            this.txtReceive.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.txtReceive.HideSelection = false;
+            this.txtReceive.Location = new System.Drawing.Point(3, 17);
+            this.txtReceive.Name = "txtReceive";
+            this.txtReceive.Size = new System.Drawing.Size(375, 358);
+            this.txtReceive.TabIndex = 22;
+            this.txtReceive.Text = "";
+            // 
+            // txtCity
+            // 
+            this.txtCity.Location = new System.Drawing.Point(392, 44);
+            this.txtCity.Name = "txtCity";
+            this.txtCity.Size = new System.Drawing.Size(75, 21);
+            this.txtCity.TabIndex = 28;
+            this.txtCity.Text = "上海";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(18, 77);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(41, 12);
+            this.label3.TabIndex = 36;
+            this.label3.Text = "坐标:";
+            // 
+            // txtLocation
+            // 
+            this.txtLocation.Location = new System.Drawing.Point(63, 73);
+            this.txtLocation.Name = "txtLocation";
+            this.txtLocation.Size = new System.Drawing.Size(211, 21);
+            this.txtLocation.TabIndex = 37;
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(0, 0);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 23);
+            this.button1.TabIndex = 0;
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(299, 77);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(65, 12);
+            this.label7.TabIndex = 39;
+            this.label7.Text = "第二坐标:";
+            // 
+            // txtLocation2
+            // 
+            this.txtLocation2.Location = new System.Drawing.Point(370, 73);
+            this.txtLocation2.Name = "txtLocation2";
+            this.txtLocation2.Size = new System.Drawing.Size(211, 21);
+            this.txtLocation2.TabIndex = 40;
+            // 
+            // FrmMap
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(670, 488);
+            this.Controls.Add(this.label7);
+            this.Controls.Add(this.txtLocation2);
+            this.Controls.Add(this.label6);
+            this.Controls.Add(this.cbCoordtype);
+            this.Controls.Add(this.cbMethod);
+            this.Controls.Add(this.label5);
+            this.Controls.Add(this.label4);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.txtCity);
+            this.Controls.Add(this.txtAddress);
+            this.Controls.Add(this.cbMap);
+            this.Controls.Add(this.pgResult);
+            this.Controls.Add(this.btnInvoke);
+            this.Controls.Add(this.gbReceive);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.txtLocation);
+            this.Controls.Add(this.chkFormatAddress);
+            this.Name = "FrmMap";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "地图接口";
+            this.Load += new System.EventHandler(this.FrmMain_Load);
+            this.gbReceive.ResumeLayout(false);
+            this.ResumeLayout(false);
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label lbMethod;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.ComboBox cbCoordtype;
+        private System.Windows.Forms.ComboBox cbMethod;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.CheckBox chkFormatAddress;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox txtAddress;
+        private System.Windows.Forms.ComboBox cbMap;
+        private System.Windows.Forms.PropertyGrid pgResult;
+        private System.Windows.Forms.ColorDialog colorDialog1;
+        private System.Windows.Forms.FontDialog fontDialog1;
+        private System.Windows.Forms.Button btnInvoke;
+        private System.Windows.Forms.RichTextBox txtReceive;
+        private System.Windows.Forms.TextBox txtCity;
+        private System.Windows.Forms.GroupBox gbReceive;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.TextBox txtLocation;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.TextBox txtLocation2;
+    }
+}
\ No newline at end of file
Added +126 -0
diff --git a/XCoder/Yun/FrmMap.resx b/XCoder/Yun/FrmMap.resx
new file mode 100644
index 0000000..6335d46
--- /dev/null
+++ b/XCoder/Yun/FrmMap.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="colorDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="fontDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>144, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
Added +48 -0
diff --git a/XCoder/Yun/MapSetting.cs b/XCoder/Yun/MapSetting.cs
new file mode 100644
index 0000000..78ee6a6
--- /dev/null
+++ b/XCoder/Yun/MapSetting.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NewLife.Xml;
+
+namespace XCoder.Yun
+{
+    [XmlConfigFile("Config\\Map.config", 15000)]
+    class MapSetting : XmlConfig<MapSetting>
+    {
+        #region 属性
+        /// <summary>接口</summary>
+        [Description("接口")]
+        public String Map { get; set; }
+
+        /// <summary>坐标系</summary>
+        [Description("坐标系")]
+        public String Coordtype { get; set; }
+
+        /// <summary>方法</summary>
+        [Description("方法")]
+        public String Method { get; set; }
+
+        /// <summary>地址</summary>
+        [Description("地址")]
+        public String Address { get; set; } = "陆家嘴银城中路501号";
+
+        /// <summary>城市</summary>
+        [Description("城市")]
+        public String City { get; set; } = "上海";
+
+        /// <summary>坐标</summary>
+        [Description("坐标")]
+        public String Location { get; set; }
+
+        /// <summary>坐标2</summary>
+        [Description("坐标2")]
+        public String Location2 { get; set; }
+
+        /// <summary>格式化地址</summary>
+        [Description("格式化地址")]
+        public Boolean FormatAddress { get; set; } = true;
+        #endregion
+    }
+}
\ No newline at end of file
Deleted +0 -1
XCoder/发布NuGet.cs
Modified +6 -0
diff --git "a/\347\240\201\347\245\236\345\267\245\345\205\267.sln" "b/\347\240\201\347\245\236\345\267\245\345\205\267.sln"
index 21c0179..fe167aa 100644
--- "a/\347\240\201\347\245\236\345\267\245\345\205\267.sln"
+++ "b/\347\240\201\347\245\236\345\267\245\345\205\267.sln"
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Others", "Others", "{32891F
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XCoder", "XCoder\XCoder.csproj", "{3EB3A5F1-F785-4672-A21D-A3117FC12129}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XCoder40", "XCoder\XCoder40.csproj", "{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -22,6 +24,10 @@ Global
 		{3EB3A5F1-F785-4672-A21D-A3117FC12129}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{3EB3A5F1-F785-4672-A21D-A3117FC12129}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{3EB3A5F1-F785-4672-A21D-A3117FC12129}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A4A7E1BD-9E53-4D60-A0E0-122E5441DDBF}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE