NewLife/XCoder

升级基础组件到最新引用
大石头 authored at 2023-08-06 20:51:27
465bcb5
Tree
1 Parent(s) 7728e41
Summary: 12 changed files with 359 additions and 147 deletions.
Modified +3 -3
Modified +1 -1
Modified +151 -86
Modified +1 -1
Modified +20 -0
Modified +13 -13
Modified +12 -27
Added +142 -0
Modified +1 -1
Modified +13 -13
Modified +0 -1
Modified +2 -1
Modified +3 -3
diff --git a/XCoder/Engine/ModelConfig.cs b/XCoder/Engine/ModelConfig.cs
index c490f1e..a12f7c4 100644
--- a/XCoder/Engine/ModelConfig.cs
+++ b/XCoder/Engine/ModelConfig.cs
@@ -121,9 +121,9 @@ namespace XCoder
         [DisplayName("调试")]
         public Boolean Debug { get; set; }
 
-        /// <summary> 字典属性</summary>
-        [DisplayName("数据字典")]
-        public SerializableDictionary<String, String> Items { get; set; } = new SerializableDictionary<String, String>();
+        ///// <summary> 字典属性</summary>
+        //[DisplayName("数据字典")]
+        //public SerializableDictionary<String, String> Items { get; set; } = new SerializableDictionary<String, String>();
         #endregion
 
         #region 加载/保存
Modified +1 -1
diff --git a/XCoder/FrmMDI.cs b/XCoder/FrmMDI.cs
index 3636f07..1c6922c 100644
--- a/XCoder/FrmMDI.cs
+++ b/XCoder/FrmMDI.cs
@@ -45,7 +45,7 @@ namespace XCoder
 
             var asm = AssemblyX.Create(Assembly.GetExecutingAssembly());
             if (set.Title.IsNullOrEmpty()) set.Title = asm.Title;
-            Text = String.Format("{2} v{0} {1:HH:mm:ss}", asm.CompileVersion, asm.Compile, set.Title);
+            Text = String.Format("{2} v{0} {1:HH:mm:ss}", asm.Version, asm.Compile, set.Title);
 
             _load.ContinueWith(t => LoadForms(t.Result));
 
Modified +151 -86
diff --git a/XCoder/Program.cs b/XCoder/Program.cs
index 974c97c..9e2907d 100644
--- a/XCoder/Program.cs
+++ b/XCoder/Program.cs
@@ -6,134 +6,199 @@ using NewLife;
 using NewLife.Log;
 using NewLife.Threading;
 using System.Threading.Tasks;
+using NewLife.Model;
+using Stardust.Services;
+using Stardust.Models;
+using System.Net.NetworkInformation;
 #if !NET4
 using Stardust;
 #endif
 
-namespace XCoder
+namespace XCoder;
+
+static class Program
 {
-    static class Program
+    /// <summary>应用程序的主入口点。</summary>
+    [STAThread]
+    static void Main()
     {
-        /// <summary>应用程序的主入口点。</summary>
-        [STAThread]
-        static void Main()
-        {
 #if NC30
-            XTrace2.UseWinForm();
-            Application.SetHighDpiMode(HighDpiMode.SystemAware);
+        XTrace2.UseWinForm();
+        Application.SetHighDpiMode(HighDpiMode.SystemAware);
 #else
-            XTrace.UseWinForm();
+        XTrace.UseWinForm();
 #endif
-            MachineInfo.RegisterAsync();
+        MachineInfo.RegisterAsync();
 
 #if !NET4
-            StartClient();
+        StartClient();
 #endif
 
-            StringHelper.EnableSpeechTip = XConfig.Current.SpeechTip;
+        StringHelper.EnableSpeechTip = XConfig.Current.SpeechTip;
 
-            if (XConfig.Current.IsNew) "学无先后达者为师,欢迎使用新生命码神工具!".SpeechTip();
+        if (XConfig.Current.IsNew) "学无先后达者为师,欢迎使用新生命码神工具!".SpeechTip();
 
-            Application.EnableVisualStyles();
-            Application.SetCompatibleTextRenderingDefault(false);
-            Application.Run(new FrmMDI());
-        }
+        Application.EnableVisualStyles();
+        Application.SetCompatibleTextRenderingDefault(false);
+        Application.Run(new FrmMDI());
+    }
 
 #if !NET4
-        static TimerX _timer;
-        static StarClient _Client;
-        //static ServiceManager _Manager;
-        private static void StartClient()
-        {
-            var set = XConfig.Current;
-            var server = set.Server;
-            if (server.IsNullOrEmpty()) return;
+    static TimerX _timer;
+    static StarClient _Client;
+    //static ServiceManager _Manager;
+    private static void StartClient()
+    {
+        var set = XConfig.Current;
+        var server = set.Server;
+        if (server.IsNullOrEmpty()) return;
 
-            XTrace.WriteLine("初始化服务端地址:{0}", server);
+        XTrace.WriteLine("初始化服务端地址:{0}", server);
 
-            var client = new StarClient(server)
+        var client = new StarClient(server)
+        {
+            Code = set.Code,
+            Secret = set.Secret,
+            ProductCode = "XCoder",
+            Log = XTrace.Log,
+        };
+
+        // 登录后保存证书
+        client.OnLogined += (s, e) =>
+        {
+            var inf = client.Info;
+            if (inf != null && !inf.Code.IsNullOrEmpty())
             {
-                Code = set.Code,
-                Secret = set.Secret,
-                Log = XTrace.Log,
-            };
+                set.Code = inf.Code;
+                set.Secret = inf.Secret;
+                set.Save();
+            }
+        };
 
-            // 登录后保存证书
-            client.OnLogined += (s, e) =>
-            {
-                var inf = client.Info;
-                if (inf != null && !inf.Code.IsNullOrEmpty())
-                {
-                    set.Code = inf.Code;
-                    set.Secret = inf.Secret;
-                    set.Save();
-                }
-            };
+        // 使用跟踪
+        client.UseTrace();
 
-            client.UseTrace();
+        Application.ApplicationExit += (s, e) => client.Logout("ApplicationExit");
 
-            Application.ApplicationExit += (s, e) => client.Logout("ApplicationExit");
+        // 可能需要多次尝试
+        _timer = new TimerX(TryConnectServer, client, 0, 5_000) { Async = true };
 
-            // 可能需要多次尝试
-            _timer = new TimerX(TryConnectServer, client, 0, 5_000) { Async = true };
+        _Client = client;
+    }
 
-            _Client = client;
+    private static async Task TryConnectServer(Object state)
+    {
+        if (!NetworkInterface.GetIsNetworkAvailable() || AgentInfo.GetIps().IsNullOrEmpty())
+        {
+            return;
         }
 
-        private static async Task TryConnectServer(Object state)
+        var client = state as StarClient;
+
+        try
         {
-            var client = state as StarClient;
-            var set = XConfig.Current;
             await client.Login();
-            await CheckUpgrade(client, set.Channel);
+            //await CheckUpgrade(client);
+        }
+        catch (Exception ex)
+        {
+            // 登录报错后,加大定时间隔,输出简单日志
+            //_timer.Period = 30_000;
+            if (_timer.Period < 30_000) _timer.Period += 5_000;
 
-            // 登录成功,销毁定时器
-            //TimerX.Current.Period = 0;
-            _timer.TryDispose();
-            _timer = null;
+            XTrace.Log?.Error(ex.Message);
+
+            return;
         }
 
-        private static String _lastVersion;
-        private static async Task CheckUpgrade(StarClient client, String channel)
-        {
-            var ug = new Stardust.Web.Upgrade { Log = XTrace.Log };
+        _timer.TryDispose();
+        _timer = new TimerX(CheckUpgrade, null, 5_000, 600_000) { Async = true };
 
-            // 检查更新
-            var ur = await client.Upgrade(channel);
-            if (ur != null && ur.Version != _lastVersion)
+        client.RegisterCommand("node/upgrade", s => _timer.SetNext(-1));
+    }
+
+    private static String _lastVersion;
+    private static async Task CheckUpgrade(Object data)
+    {
+        var client = _Client;
+        using var span = client.Tracer?.NewSpan("CheckUpgrade", new { _lastVersion });
+
+        // 运行过程中可能改变配置文件的通道
+        var set = XConfig.Current;
+        var ug = new Stardust.Web.Upgrade { Log = XTrace.Log };
+
+        // 去除多余入口文件
+        ug.Trim("XCoder");
+
+        // 检查更新
+        var ur = await client.Upgrade(set.Channel);
+        if (ur != null && ur.Version != _lastVersion)
+        {
+            client.WriteInfoEvent("Upgrade", $"准备从[{_lastVersion}]更新到[{ur.Version}],开始下载 {ur.Source}");
+            try
             {
-                ug.Url = ur.Source;
+                ug.Url = client.BuildUrl(ur.Source);
                 await ug.Download();
 
                 // 检查文件完整性
-                if (ur.FileHash.IsNullOrEmpty() || ug.CheckFileHash(ur.FileHash))
+                var checkHash = ug.CheckFileHash(ur.FileHash);
+                if (!ur.FileHash.IsNullOrEmpty() && !checkHash)
                 {
-                    // 执行更新,解压缩覆盖文件
-                    var rs = ug.Update();
-                    if (rs && !ur.Executor.IsNullOrEmpty()) ug.Run(ur.Executor);
-                    _lastVersion = ur.Version;
-
-                    // 去除多余入口文件
-                    ug.Trim("StarAgent");
-
-                    // 强制更新时,马上重启
-                    if (rs && ur.Force)
+                    client.WriteInfoEvent("Upgrade", "下载完成,哈希校验失败");
+                }
+                else
+                {
+                    client.WriteInfoEvent("Upgrade", "下载完成,准备解压文件");
+                    if (!ug.Extract())
                     {
-                        //StopWork("Upgrade");
-
-                        // 重新拉起进程
-                        var star = "XCoder.exe";
-                        XTrace.WriteLine("强制升级,拉起进程 {0} -upgrade", star.GetFullPath());
-                        Process.Start(star.GetFullPath(), "-upgrade");
-
-                        //var p = Process.GetCurrentProcess();
-                        //p.Close();
-                        //p.Kill();
-                        Application.Exit();
+                        client.WriteInfoEvent("Upgrade", "解压失败");
+                    }
+                    else
+                    {
+                        if (!ur.Preinstall.IsNullOrEmpty())
+                        {
+                            client.WriteInfoEvent("Upgrade", "执行预安装脚本");
+
+                            ug.Run(ur.Preinstall);
+                        }
+
+                        client.WriteInfoEvent("Upgrade", "解压完成,准备覆盖文件");
+
+                        // 执行更新,解压缩覆盖文件
+                        var rs = ug.Update();
+                        if (rs && !ur.Executor.IsNullOrEmpty()) ug.Run(ur.Executor);
+                        _lastVersion = ur.Version;
+
+                        // 去除多余入口文件
+                        ug.Trim("XCoder");
+
+                        // 强制更新时,马上重启
+                        if (rs && ur.Force)
+                        {
+                            // 重新拉起进程
+                            rs = ug.Run("XCoder.exe", "-run -upgrade");
+
+                            if (rs)
+                            {
+                                var pid = Process.GetCurrentProcess().Id;
+                                client.WriteInfoEvent("Upgrade", "强制更新完成,新进程已拉起,准备退出当前进程!PID=" + pid);
+
+                                ug.KillSelf();
+                            }
+                            else
+                            {
+                                client.WriteInfoEvent("Upgrade", "强制更新完成,但拉起新进程失败");
+                            }
+                        }
                     }
                 }
             }
+            catch (Exception ex)
+            {
+                XTrace.WriteException(ex);
+                client.WriteErrorEvent("Upgrade", ex.ToString());
+            }
         }
-#endif
     }
+#endif
 }
\ No newline at end of file
Modified +1 -1
diff --git a/XCoder/Protocols/Modbus.cs b/XCoder/Protocols/Modbus.cs
index b112f83..4086b37 100644
--- a/XCoder/Protocols/Modbus.cs
+++ b/XCoder/Protocols/Modbus.cs
@@ -149,7 +149,7 @@ namespace NewLife.IoT.Protocols
             if (rs == null || rs.Length <= 0) return null;
 
             // 去掉2字节地址
-            return rs.ReadBytes(2);
+            return rs.ReadBytes(2, -1);
         }
 
         /// <summary>写入保持寄存器,0x06</summary>
Modified +20 -0
diff --git a/XCoder/Windows/FrmMain.cs b/XCoder/Windows/FrmMain.cs
index 7311088..0edac97 100644
--- a/XCoder/Windows/FrmMain.cs
+++ b/XCoder/Windows/FrmMain.cs
@@ -539,6 +539,7 @@ namespace XCoder
                 //var builder = new EntityBuilder();
 
                 var cfg = Config;
+#if NET4
                 var option = new BuilderOption
                 {
                     BaseClass = cfg.BaseClass,
@@ -546,6 +547,15 @@ namespace XCoder
                     Namespace = cfg.NameSpace,
                     Output = cfg.OutputPath,
                 };
+#else
+                var option = new EntityBuilderOption
+                {
+                    BaseClass = cfg.BaseClass,
+                    ConnName = cfg.EntityConnName,
+                    Namespace = cfg.NameSpace,
+                    Output = cfg.OutputPath,
+                };
+#endif
                 var rs = EntityBuilder.BuildTables(new[] { table }, option);
 
                 MessageBox.Show("生成" + table + "成功!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
@@ -581,6 +591,7 @@ namespace XCoder
             //}
 
             var cfg = Config;
+#if NET4
             var option = new BuilderOption
             {
                 BaseClass = cfg.BaseClass,
@@ -588,6 +599,15 @@ namespace XCoder
                 Namespace = cfg.NameSpace,
                 Output = cfg.OutputPath,
             };
+#else
+            var option = new EntityBuilderOption
+            {
+                BaseClass = cfg.BaseClass,
+                ConnName = cfg.EntityConnName,
+                Namespace = cfg.NameSpace,
+                Output = cfg.OutputPath,
+            };
+#endif
             var rs = EntityBuilder.BuildTables(tables, option);
 
             sw.Stop();
Modified +13 -13
diff --git a/XCoder/XApi/FrmMain.cs b/XCoder/XApi/FrmMain.cs
index 23bd9e5..7eef74c 100644
--- a/XCoder/XApi/FrmMain.cs
+++ b/XCoder/XApi/FrmMain.cs
@@ -70,19 +70,19 @@ namespace XApi
 
             LoadConfig();
 
-            // 语音识别
-            ThreadPoolX.QueueUserWorkItem(() =>
-            {
-                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());
-            });
+            //// 语音识别
+            //ThreadPoolX.QueueUserWorkItem(() =>
+            //{
+            //    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
 
Modified +12 -27
diff --git a/XCoder/XCoder.csproj b/XCoder/XCoder.csproj
index a43b1bb..4e1ec57 100644
--- a/XCoder/XCoder.csproj
+++ b/XCoder/XCoder.csproj
@@ -15,7 +15,7 @@
     <TargetFrameworkProfile />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <DebugSymbols>true</DebugSymbols>
     <OutputPath>..\..\XCoder\</OutputPath>
     <DefineConstants>TRACE;DEBUG</DefineConstants>
@@ -73,12 +73,6 @@
     <Compile Include="Data\RedisConfig.cs" />
     <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>
@@ -147,6 +141,7 @@
       <DependentUpon>SerialPortList.cs</DependentUpon>
     </Compile>
     <Compile Include="XCom\SerialTransport.cs" />
+    <Compile Include="XICO\FileSource.cs" />
     <Compile Include="XNet\BenchHelper.cs" />
     <Compile Include="XNet\FrmIp.cs">
       <SubType>Form</SubType>
@@ -186,12 +181,6 @@
     <Compile Include="XNet\RawSocket.cs" />
     <Compile Include="XNet\RegisterUnit.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="Engine\FileSource.cs" />
     <Compile Include="Engine\XConfig.cs" />
     <Compile Include="Tools\FrmGPS.cs">
@@ -241,16 +230,12 @@
     <Compile Include="XNet\FrmMain.designer.cs">
       <DependentUpon>FrmMain.cs</DependentUpon>
     </Compile>
-    <Compile Include="Yun\MapSetting.cs" />
     <EmbeddedResource Include="Data\FrmRedis.resx">
       <DependentUpon>FrmRedis.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="Data\FrmRedisConfig.resx">
       <DependentUpon>FrmRedisConfig.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="FileEncoding\FrmMain.resx">
-      <DependentUpon>FrmMain.cs</DependentUpon>
-    </EmbeddedResource>
     <EmbeddedResource Include="FolderInfo\FrmMain.resx">
       <DependentUpon>FrmMain.cs</DependentUpon>
     </EmbeddedResource>
@@ -293,9 +278,6 @@
     <EmbeddedResource Include="XNet\FrmSsh.resx">
       <DependentUpon>FrmSsh.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="Yun\FrmMap.resx">
-      <DependentUpon>FrmMap.cs</DependentUpon>
-    </EmbeddedResource>
     <Compile Include="Windows\FrmMain.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -402,25 +384,28 @@
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="NewLife.Core">
-      <Version>8.11.2021.1204</Version>
+      <Version>10.5.2023.801</Version>
+    </PackageReference>
+    <PackageReference Include="NewLife.Map">
+      <Version>2.3.2023.806</Version>
     </PackageReference>
     <PackageReference Include="NewLife.MQTT">
-      <Version>1.0.2021.1204</Version>
+      <Version>1.4.2023.806</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Net">
-      <Version>3.6.2021.1204</Version>
+      <Version>4.3.2023.806</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Redis">
-      <Version>3.9.2021.1204</Version>
+      <Version>5.5.2023.803</Version>
     </PackageReference>
     <PackageReference Include="NewLife.Stardust">
-      <Version>1.5.2021.1204</Version>
+      <Version>2.9.2023.801</Version>
     </PackageReference>
     <PackageReference Include="NewLife.XCode">
-      <Version>10.3.2021.1204</Version>
+      <Version>11.9.2023.801</Version>
     </PackageReference>
     <PackageReference Include="SSH.NET">
-      <Version>2020.0.1</Version>
+      <Version>2020.0.2</Version>
     </PackageReference>
   </ItemGroup>
   <ItemGroup>
Added +142 -0
diff --git a/XCoder/XICO/FileSource.cs b/XCoder/XICO/FileSource.cs
new file mode 100644
index 0000000..95673c1
--- /dev/null
+++ b/XCoder/XICO/FileSource.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Web;
+
+namespace NewLife.IO
+{
+    /// <summary>文件资源</summary>
+    public static class FileSource
+    {
+        /// <summary>释放文件</summary>
+        /// <param name="asm"></param>
+        /// <param name="fileName"></param>
+        /// <param name="destFile"></param>
+        /// <param name="overWrite"></param>
+        public static void ReleaseFile(this Assembly asm, String fileName, String destFile = null, Boolean overWrite = false)
+        {
+            if (fileName.IsNullOrEmpty()) return;
+
+            if (asm == null) asm = Assembly.GetCallingAssembly();
+            var stream = GetFileResource(asm, fileName);
+            if (stream == null) throw new ArgumentException("filename", $"在程序集{asm.GetName().Name}中无法找到名为{fileName}的资源!");
+
+            if (destFile.IsNullOrEmpty()) destFile = fileName;
+            destFile = destFile.GetFullPath();
+
+            if (File.Exists(destFile) && !overWrite) return;
+
+            //var path = Path.GetDirectoryName(dest);
+            //if (!path.IsNullOrWhiteSpace() && !Directory.Exists(path)) Directory.CreateDirectory(path);
+            destFile.EnsureDirectory(true);
+            try
+            {
+                if (File.Exists(destFile)) File.Delete(destFile);
+
+                using var fs = File.Create(destFile);
+                //IOHelper.CopyTo(stream, fs);
+                stream.CopyTo(fs);
+            }
+            catch { }
+            finally { stream.Dispose(); }
+        }
+
+        /// <summary>释放文件夹</summary>
+        /// <param name="asm"></param>
+        /// <param name="prefix"></param>
+        /// <param name="dest"></param>
+        /// <param name="overWrite"></param>
+        public static void ReleaseFolder(this Assembly asm, String prefix, String dest, Boolean overWrite = false)
+        {
+            if (asm == null) asm = Assembly.GetCallingAssembly();
+            ReleaseFolder(asm, prefix, dest, overWrite, null);
+        }
+
+        /// <summary>释放文件夹</summary>
+        /// <param name="asm"></param>
+        /// <param name="prefix"></param>
+        /// <param name="dest"></param>
+        /// <param name="overWrite"></param>
+        /// <param name="filenameResolver"></param>
+        public static void ReleaseFolder(this Assembly asm, String prefix, String dest, Boolean overWrite = false, Func<String, String> filenameResolver = null)
+        {
+            if (asm == null) asm = Assembly.GetCallingAssembly();
+
+            // 找到符合条件的资源
+            var names = asm.GetManifestResourceNames();
+            if (names == null || names.Length <= 0) return;
+            IEnumerable<String> ns = null;
+            if (prefix.IsNullOrWhiteSpace())
+                ns = names.AsEnumerable();
+            else
+                ns = names.Where(e => e.StartsWithIgnoreCase(prefix));
+
+            if (String.IsNullOrEmpty(dest)) dest = ".".GetFullPath();
+            dest = dest.GetFullPath();
+
+            // 开始处理
+            foreach (var item in ns)
+            {
+                var stream = asm.GetManifestResourceStream(item);
+
+                // 计算filename
+                String filename = null;
+                // 去掉前缀
+                if (filenameResolver != null) filename = filenameResolver(item);
+
+                if (String.IsNullOrEmpty(filename))
+                {
+                    filename = item;
+                    if (!String.IsNullOrEmpty(prefix)) filename = filename[prefix.Length..];
+                    if (filename[0] == '.') filename = filename[1..];
+
+                    var ext = Path.GetExtension(item);
+                    filename = filename[..^ext.Length];
+                    filename = filename.Replace(".", @"\") + ext;
+                    filename = Path.Combine(dest, filename);
+                }
+
+                if (File.Exists(filename) && !overWrite) return;
+
+                //var path = Path.GetDirectoryName(filename);
+                //if (!path.IsNullOrWhiteSpace() && !Directory.Exists(path)) Directory.CreateDirectory(path);
+                filename.EnsureDirectory(true);
+                try
+                {
+                    if (File.Exists(filename)) File.Delete(filename);
+
+                    using var fs = File.Create(filename);
+                    //IOHelper.CopyTo(stream, fs);
+                    stream.CopyTo(fs);
+                }
+                catch { }
+                finally { stream.Dispose(); }
+            }
+        }
+
+        /// <summary>获取文件资源</summary>
+        /// <param name="asm"></param>
+        /// <param name="filename"></param>
+        /// <returns></returns>
+        public static Stream GetFileResource(this Assembly asm, String filename)
+        {
+            if (String.IsNullOrEmpty(filename)) return null;
+
+            var name = String.Empty;
+            if (asm == null) asm = Assembly.GetCallingAssembly();
+            var ss = asm.GetManifestResourceNames();
+            if (ss != null && ss.Length > 0)
+            {
+                //找到资源名
+                name = ss.FirstOrDefault(e => e == filename);
+                if (String.IsNullOrEmpty(name)) name = ss.FirstOrDefault(e => e.EqualIgnoreCase(filename));
+                if (String.IsNullOrEmpty(name)) name = ss.FirstOrDefault(e => e.EndsWith(filename));
+
+                if (!String.IsNullOrEmpty(name)) return asm.GetManifestResourceStream(name);
+            }
+            return null;
+        }
+    }
+}
\ No newline at end of file
Modified +1 -1
diff --git a/XCoder/XICO/IconFile.cs b/XCoder/XICO/IconFile.cs
index 3a6bca6..8e35d80 100644
--- a/XCoder/XICO/IconFile.cs
+++ b/XCoder/XICO/IconFile.cs
@@ -141,7 +141,7 @@ namespace XICO
             var item = new IconItem();
             // bmp要跳过14字节,还要修改高度,png不用
             ms.Position = 14;
-            item.Data = ms.ReadBytes();
+            item.Data = ms.ReadBytes(-1);
             item.Size = (UInt32)item.Data.Length;
             item.BitCount = (UInt16)bit;
 
Modified +13 -13
diff --git a/XCoder/XNet/FrmMain.cs b/XCoder/XNet/FrmMain.cs
index 71d3795..8987b24 100644
--- a/XCoder/XNet/FrmMain.cs
+++ b/XCoder/XNet/FrmMain.cs
@@ -87,19 +87,19 @@ namespace XNet
 
             LoadConfig();
 
-            // 语音识别
-            ThreadPoolX.QueueUserWorkItem(() =>
-            {
-                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());
-            });
+            //// 语音识别
+            //ThreadPoolX.QueueUserWorkItem(() =>
+            //{
+            //    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
 
Modified +0 -1
diff --git a/XCoder/XNet/FrmMqtt.cs b/XCoder/XNet/FrmMqtt.cs
index e9c5919..bdf2038 100644
--- a/XCoder/XNet/FrmMqtt.cs
+++ b/XCoder/XNet/FrmMqtt.cs
@@ -68,7 +68,6 @@ namespace XNet
                 Password = txtPass.Text,
 
                 Log = _log,
-                LogMessage = true,
             };
             client.Received += Client_Received;
             client.Connected += (s, e) => XTrace.WriteLine("连接成功");
Modified +2 -1
diff --git a/XCoder/Yun/FrmMap.cs b/XCoder/Yun/FrmMap.cs
index 4946505..dc7db2d 100644
--- a/XCoder/Yun/FrmMap.cs
+++ b/XCoder/Yun/FrmMap.cs
@@ -8,6 +8,7 @@ using System.Windows.Forms;
 using NewLife;
 using NewLife.Data;
 using NewLife.Log;
+using NewLife.Map;
 using NewLife.Reflection;
 using NewLife.Serialization;
 using NewLife.Yun;
@@ -114,7 +115,7 @@ namespace XCoder.Yun
             SaveConfig();
             var cfg = Setting;
 
-            var map = type.CreateInstance() as NewLife.Yun.Map;
+            var map = type.CreateInstance() as Map;
             map.Log = XTrace.Log;
             map.CoordType = cfg.Coordtype;