static SevenZip() { var p = ""; #region 附近文件 if (p.IsNullOrEmpty()) { var f = "../7z/7z.exe".GetFullPath(); if (File.Exists(f)) { p = f; } f = "7z/7z.exe".GetFullPath(); if (File.Exists(f)) { p = f; } } #endregion #region 注册表 #if __WIN__ if (p.IsNullOrEmpty()) { var reg = Registry.LocalMachine.OpenSubKey("Software\\7-Zip"); if (reg == null) { reg = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\7-Zip"); } if (reg != null) { var d = reg.GetValue("Path") + ""; var f = d.CombinePath("7z.exe"); if (File.Exists(f)) { p = f; } } } #endif #endregion #region X组件缓存 var cache = Path.GetPathRoot(".".GetFullPath()).CombinePath(@"\X\7z").GetFullPath(); if (p.IsNullOrEmpty()) { var f = cache.CombinePath("7z.exe"); if (File.Exists(f)) { p = f; } } #endregion #region 自动下载 if (p.IsNullOrEmpty()) { XTrace.WriteLine("准备下载7z扩展包"); var url = Setting.Current.PluginServer; var client = new WebClientX() { Log = XTrace.Log }; var dir = cache; var file = client.DownloadLinkAndExtract(url, "7z", dir); if (Directory.Exists(dir)) { var f = dir.CombinePath("7z.exe"); if (File.Exists(f)) { p = f; } } } #endregion if (!p.IsNullOrEmpty()) { _7z = p.GetFullPath(); } XTrace.WriteLine("7Z目录 {0}", _7z); }
public async Task <ActionResult> Sync() { //if (id.IsNullOrEmpty()) return RedirectToAction(nameof(Index)); // 读取系统配置 var ps = Parameter.FindAllByUserID(ManageProvider.User.ID); // UserID=0 && Category=Sync ps = ps.Where(e => e.Category == "Sync").ToList(); var server = ps.FirstOrDefault(e => e.Name == "Server")?.Value; var token = ps.FirstOrDefault(e => e.Name == "Token")?.Value; var models = ps.FirstOrDefault(e => e.Name == "Models")?.Value; if (server.IsNullOrEmpty()) { throw new ArgumentNullException("未配置 Sync:Server"); } if (token.IsNullOrEmpty()) { throw new ArgumentNullException("未配置 Sync:Token"); } if (models.IsNullOrEmpty()) { throw new ArgumentNullException("未配置 Sync:Models"); } var mds = models.Split(","); //// 创建实体工厂 //var etype = mds.FirstOrDefault(e => e.Replace(".", "_") == id); //var fact = etype.GetTypeEx()?.AsFactory(); //if (fact == null) throw new ArgumentNullException(nameof(id), "未找到模型 " + id); // 找到控制器,以识别动作地址 var cs = GetControllerAction(); var ctrl = cs[0].IsNullOrEmpty() ? cs[1] : $"{cs[0]}/{cs[1]}"; if (!mds.Contains(ctrl)) { throw new InvalidOperationException($"[{ctrl}]未配置为允许同步 Sync:Models"); } // 创建客户端,准备发起请求 var url = server.EnsureEnd("/") + $"{ctrl}/Json/{token}?PageSize=100000"; var http = new HttpClient { BaseAddress = new Uri(url) }; var sw = Stopwatch.StartNew(); var list = await http.InvokeAsync <TEntity[]>(HttpMethod.Get, null); sw.Stop(); var fact = Factory; XTrace.WriteLine("[{0}]共同步数据[{1:n0}]行,耗时{2:n0}ms,数据源:{3}", fact.EntityType.FullName, list.Length, sw.ElapsedMilliseconds, url); var arrType = fact.EntityType.MakeArrayType(); if (list.Length > 0) { XTrace.WriteLine("[{0}]准备覆盖写入[{1}]行数据", fact.EntityType.FullName, list.Length); using (var tran = fact.CreateTrans()) { // 清空 try { fact.Session.Truncate(); } catch (Exception ex) { XTrace.WriteException(ex); } // 插入 //ms.All(e => { e.AllChilds = new List<Menu>(); return true; }); fact.AllowInsertIdentity = true; //ms.Insert(); //var empty = typeof(List<>).MakeGenericType(fact.EntityType).CreateInstance(); foreach (IEntity entity in list) { if (entity is IEntityTree tree) { tree.AllChilds.Clear(); } entity.Insert(); } fact.AllowInsertIdentity = false; tran.Commit(); } } return(Index()); }
/// <summary>服务主函数</summary> /// <param name="args"></param> public void Main(String[] args) { //#if NETSTANDARD2_0 //MachineInfo.RegisterAsync(); //#endif // 以服务方式启动时,不写控制台日志 if (args == null) { args = Environment.GetCommandLineArgs(); } var isService = args != null && args.Length > 0 && args.Contains("-s"); if (!isService) { XTrace.UseConsole(); } if (Host == null) { if (Runtime.Windows) { Host = new WindowsService(); } else { Host = new Systemd(); } } var service = this; service.Log = XTrace.Log; // 初始化配置 var set = Setting.Current; if (set.ServiceName.IsNullOrEmpty()) { set.ServiceName = service.ServiceName; } if (set.DisplayName.IsNullOrEmpty()) { set.DisplayName = service.DisplayName; } if (set.Description.IsNullOrEmpty()) { set.Description = service.Description; } // 从程序集构造配置 var asm = AssemblyX.Entry; if (set.ServiceName.IsNullOrEmpty()) { set.ServiceName = asm.Name; } if (set.DisplayName.IsNullOrEmpty()) { set.DisplayName = asm.Title; } if (set.Description.IsNullOrEmpty()) { set.Description = asm.Description; } set.Save(); // 用配置覆盖 service.ServiceName = set.ServiceName; service.DisplayName = set.DisplayName; service.Description = set.Description; if (args.Length > 0) { #region 命令 var name = ServiceName; var cmd = args[0].ToLower(); switch (cmd) { case "-s": Host.Run(this); break; case "-i": Install(); break; case "-u": Host.Remove(name); break; case "-start": Host.Start(name); break; case "-stop": Host.Stop(name); break; case "-restart": Host.Restart(name); break; case "-run": StartLoop(); DoLoop(); StopLoop(); break; default: // 快速调用自定义菜单 if (cmd.Length == 2 && cmd[0] == '-' && _Menus.TryGetValue(cmd[1], out var menu)) { menu.Callback(); } break; } #endregion ProcessCommand(args); } else { if (!service.DisplayName.IsNullOrEmpty()) { Console.Title = service.DisplayName; } // 输出状态,菜单循环 service.ShowStatus(); service.ProcessMenu(); } if (XTrace.Log is CompositeLog compositeLog) { var log = compositeLog.Get <TextFileLog>(); log.TryDispose(); } }
/// <summary>同步或异步收到数据</summary> /// <param name="se"></param> void ProcessEvent(SocketAsyncEventArgs se) { try { if (!Active) { ReleaseRecv(se, "!Active " + se.SocketError); return; } // 判断成功失败 if (se.SocketError != SocketError.Success) { // 未被关闭Socket时,可以继续使用 if (OnReceiveError(se)) { var ex = se.GetException(); if (ex != null) { OnError("ReceiveAsync", ex); } ReleaseRecv(se, "SocketError " + se.SocketError); return; } } else { var ep = se.RemoteEndPoint as IPEndPoint ?? Remote.EndPoint; var pk = new Packet(se.Buffer, se.Offset, se.BytesTransferred); if (ProcessAsync) { // 拷贝走数据,参数要重复利用 pk = pk.Clone(); // 根据不信任用户原则,这里另外开线程执行用户逻辑 // 有些用户在处理数据时,又发送数据并等待响应 ThreadPoolX.QueueUserWorkItem(() => ProcessReceive(pk, ep)); } else { // 同步执行,直接使用数据,不需要拷贝 // 直接在IO线程调用业务逻辑 ProcessReceive(pk, ep); } } // 开始新的监听 if (Active && !Disposed) { ReceiveAsync(se, true); } else { ReleaseRecv(se, "!Active || Disposed"); } } catch (Exception ex) { XTrace.WriteException(ex); } }
public async void Queue_PublishAndConsume() { var key = "ReliableQueue_PublishAndConsume"; // 删除已有 _redis.Remove(key); var q = _redis.GetReliableQueue <MyModel>(key); // 改变有效期 q.BodyExpire = 5 * 60; var dic = new Dictionary <String, MyModel> { ["aaa"] = new MyModel { Id = 123, Name = "a123" }, ["bbb"] = new MyModel { Id = 456, Name = "b456" }, ["ccc"] = new MyModel { Id = 789, Name = "c789" }, }; // 生产 var rs = q.Publish(dic); Assert.Equal(dic.Count, rs); // 查看并干掉第二项 var v2 = _redis.Get <MyModel>("bbb"); Assert.NotNull(v2); Assert.Equal(456, v2.Id); Assert.Equal("b456", v2.Name); var ttl = _redis.GetExpire("bbb"); Assert.True(ttl.TotalSeconds <= q.BodyExpire); Assert.True(ttl.TotalSeconds >= q.BodyExpire - 2); rs = _redis.Remove("bbb"); // 消费第一项 XTrace.WriteLine("消费第一项"); var v1 = await q.ConsumeAsync(ProcessAsync, 3); Assert.NotNull(v1); Assert.Equal(123, v1.Id); // 消费第二项 XTrace.WriteLine("消费第二项"); v2 = await q.ConsumeAsync(ProcessAsync, 3); Assert.Null(v2); // 消费第三项 XTrace.WriteLine("消费第三项"); var v3 = await q.ConsumeAsync(ProcessAsync, 3); Assert.NotNull(v3); Assert.Equal(789, v3.Id); }
/// <summary>处理菜单</summary> protected virtual void ProcessMenu() { var service = this; var name = ServiceName; while (true) { //输出菜单 ShowMenu(); Console.Write("请选择操作(-x是命令行参数):"); //读取命令 var key = Console.ReadKey(); if (key.KeyChar == '0') { break; } Console.WriteLine(); Console.WriteLine(); try { switch (key.KeyChar) { case '1': //输出状态 ShowStatus(); break; case '2': if (Host.IsInstalled(name)) { Host.Remove(name); } else { Install(); } break; case '3': if (Host.IsRunning(name)) { Host.Stop(name); } else { Host.Start(name); } // 稍微等一下状态刷新 Thread.Sleep(500); break; case '4': if (Host.IsRunning(name)) { Host.Restart(name); } // 稍微等一下状态刷新 Thread.Sleep(500); break; case '5': #region 循环调试 try { Console.WriteLine("正在循环调试……"); StartWork("循环开始"); Console.WriteLine("任意键结束循环调试!"); Console.ReadKey(true); StopWork("循环停止"); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } #endregion break; case '7': if (WatchDogs.Length > 0) { CheckWatchDog(); } break; default: // 自定义菜单 if (_Menus.TryGetValue(key.KeyChar, out var menu)) { menu.Callback(); } break; } } catch (Exception ex) { XTrace.WriteException(ex); } } }
public void Queue_Batch() { var key = "ReliableQueue_batch"; // 删除已有 _redis.Remove(key); var queue = _redis.GetReliableQueue <String>(key); queue.RetryInterval = 5; // 发现回滚 var rcount = queue.RollbackAllAck(); if (rcount > 0) { XTrace.WriteLine("回滚:{0}", rcount); Assert.Equal(rcount, queue.Count); var rcount2 = _redis.Remove(key); Assert.Equal(1, rcount2); } // 取出个数 var count = queue.Count; Assert.True(queue.IsEmpty); Assert.Equal(0, count); // 添加 var vs = new[] { "1234", "abcd", "新生命团队", "ABEF" }; queue.Add(vs); // 取出来 var vs2 = queue.Take(3).ToArray(); Assert.Equal(3, vs2.Length); Assert.Equal("1234", vs2[0]); Assert.Equal("abcd", vs2[1]); Assert.Equal("新生命团队", vs2[2]); Assert.Equal(1, queue.Count); // 检查确认队列 var q2 = _redis.GetList <String>(queue.AckKey); Assert.Equal(vs2.Length, q2.Count); // 确认两个 var rs = queue.Acknowledge(vs2.Take(2).ToArray()); Assert.Equal(2, rs); Assert.Equal(1, q2.Count); // 捞出来Ack最后一个 var vs3 = queue.TakeAck(3).ToArray(); Assert.Equal(0, q2.Count); Assert.Single(vs3); Assert.Equal("新生命团队", vs3[0]); // 读取队列最后一个,但不确认,留给下一次回滚用 var vs4 = queue.Take(4).ToArray(); Assert.Single(vs4); }
void WriteLog(String format, params Object[] args) { XTrace.WriteLine(format, args); }
public static void Main(String[] args) { XTrace.UseConsole(); CreateWebHostBuilder(args).Build().Run(); }
/// <summary>写入</summary> /// <param name="writer"></param> /// <param name="value">数值</param> /// <param name="writeDefaultValueMember">是否写数值为默认值的成员。为了节省空间,默认不写。</param> public static void WriteXml(XmlWriter writer, Object value, Boolean writeDefaultValueMember = false) { var type = value.GetType(); var def = GetDefault(type); if (value is IDataColumn) { //var dc2 = def as IDataColumn; var value2 = value as IDataColumn; // 需要重新创建,因为GetDefault带有缓存 var dc2 = type.CreateInstance() as IDataColumn; dc2.DataType = value2.DataType; dc2.Length = value2.Length; def = Fix(dc2, value2); } String name = null; // 基本类型,输出为特性 foreach (var pi in type.GetProperties(true)) { if (!pi.CanWrite) { continue; } //if (pi.GetCustomAttribute<XmlIgnoreAttribute>(false) != null) continue; // 忽略ID if (pi.Name == "ID") { continue; } // IDataIndex跳过默认Name if (value is IDataIndex && pi.Name.EqualIgnoreCase("Name")) { var di = value as IDataIndex; if (di.Name.EqualIgnoreCase(ModelResolver.Current.GetName(di))) { continue; } } var code = Type.GetTypeCode(pi.PropertyType); var obj = value.GetValue(pi); // 默认值不参与序列化,节省空间 if (!writeDefaultValueMember) { var dobj = def.GetValue(pi); if (Equals(obj, dobj)) { continue; } if (code == TypeCode.String && "" + obj == "" + dobj) { continue; } } if (code == TypeCode.String) { // 如果别名与名称相同,则跳过,不区分大小写 if (pi.Name == "Name") { name = (String)obj; } else if (pi.Name == "TableName" || pi.Name == "ColumnName") { if (name.EqualIgnoreCase((String)obj)) { continue; } } } else if (code == TypeCode.Object) { var ptype = pi.PropertyType; if (ptype.IsArray || ptype.As <IEnumerable>() || obj is IEnumerable) { var sb = new StringBuilder(); var arr = obj as IEnumerable; foreach (var elm in arr) { if (sb.Length > 0) { sb.Append(","); } sb.Append(elm); } obj = sb.ToString(); } else if (pi.PropertyType == typeof(Type)) { obj = (obj as Type).Name; } else { // 其它的不支持,跳过 if (XTrace.Debug) { XTrace.WriteLine("不支持的类型[{0} {1}]!", pi.PropertyType.Name, pi.Name); } continue; } //if (item.Type == typeof(Type)) obj = (obj as Type).Name; } writer.WriteAttributeString(pi.Name, obj?.ToString()); } if (value is IDataTable) { var table = value as IDataTable; // 写入扩展属性作为特性 if (table.Properties.Count > 0) { foreach (var item in table.Properties) { writer.WriteAttributeString(item.Key, item.Value); } } } else if (value is IDataColumn) { var column = value as IDataColumn; // 写入扩展属性作为特性 if (column.Properties.Count > 0) { foreach (var item in column.Properties) { if (!item.Key.EqualIgnoreCase("DisplayName", "Precision", "Scale", "NumOfByte")) { writer.WriteAttributeString(item.Key, item.Value); } } } } }
void DetectSqlServer(Object state) { var item = (String)state; try { var dal = DAL.Create(item); if (dal.DbType != DatabaseType.SqlServer) { return; } var sw = Stopwatch.StartNew(); DataTable dt = null; // 列出所有数据库 //Boolean old = DAL.ShowSQL; //DAL.ShowSQL = false; //try //{ if (dal.Db.CreateMetaData().MetaDataCollections.Contains("Databases")) { dt = dal.Db.CreateSession().GetSchema("Databases", null); } //} //finally { DAL.ShowSQL = old; } if (dt == null) { return; } var dbprovider = dal.DbType.ToString(); var builder = new DbConnectionStringBuilder(); builder.ConnectionString = dal.ConnStr; // 统计库名 var n = 0; var names = new List <String>(); var sysdbnames = new String[] { "master", "tempdb", "model", "msdb" }; foreach (DataRow dr in dt.Rows) { var dbname = dr[0].ToString(); if (Array.IndexOf(sysdbnames, dbname) >= 0) { continue; } var connName = String.Format("{0}_{1}", item, dbname); builder["Database"] = dbname; DAL.AddConnStr(connName, builder.ToString(), null, dbprovider); n++; try { var ver = dal.Db.ServerVersion; names.Add(connName); } catch { if (DAL.ConnStrs.ContainsKey(connName)) { DAL.ConnStrs.Remove(connName); } } } sw.Stop(); XTrace.WriteLine("发现远程数据库{0}个,耗时:{1}!", n, sw.Elapsed); if (names != null && names.Count > 0) { var list = new List <String>(); foreach (var elm in DAL.ConnStrs) { if (!String.IsNullOrEmpty(elm.Value)) { list.Add(elm.Key); } } list.AddRange(names); this.Invoke(SetDatabaseList, list); } } catch { //if (item == localName) DAL.ConnStrs.Remove(localName); } }
/// <summary>数据库预热</summary> private void DBPreheat() { XTrace.WriteLine("数据库预热"); DisplayGlobal.log.Write("数据库预热"); tg_user_login_log.GetEntityByUserId(0); }
/// <summary>获取提供者工厂</summary> /// <param name="assemblyFile"></param> /// <param name="className"></param> /// <returns></returns> protected static DbProviderFactory GetProviderFactory(String assemblyFile, String className) { var name = Path.GetFileNameWithoutExtension(assemblyFile); var linkName = name; if (Runtime.Is64BitProcess) { linkName += "64"; } var ver = Environment.Version; if (ver.Major >= 4) { linkName += "Fx" + ver.Major + ver.Minor; } // 有些数据库驱动不区分x86/x64,并且逐步以Fx4为主,所以来一个默认 linkName += ";" + name; #if __CORE__ linkName = "st_" + name; #endif var type = PluginHelper.LoadPlugin(className, null, assemblyFile, linkName); // 反射实现获取数据库工厂 var file = assemblyFile; var plugin = NewLife.Setting.Current.GetPluginPath(); file = plugin.CombinePath(file); // 如果还没有,就写异常 if (type == null && !File.Exists(file)) { throw new FileNotFoundException("缺少文件" + file + "!", file); } if (type == null) { XTrace.WriteLine("驱动文件{0}无效或不适用于当前环境,准备删除后重新下载!", assemblyFile); try { File.Delete(file); } catch (UnauthorizedAccessException) { } catch (Exception ex) { XTrace.Log.Error(ex.ToString()); } type = PluginHelper.LoadPlugin(className, null, file, linkName); // 如果还没有,就写异常 if (!File.Exists(file)) { throw new FileNotFoundException("缺少文件" + file + "!", file); } } if (type == null) { return(null); } var asm = type.Assembly; if (DAL.Debug) { DAL.WriteLog("{2}驱动{0} 版本v{1}", asm.Location, asm.GetName().Version, className.TrimEnd("Client", "Factory")); } var field = type.GetFieldEx("Instance"); if (field == null) { return(Activator.CreateInstance(type) as DbProviderFactory); } return(Reflect.GetValue(null, field) as DbProviderFactory); }
/// <summary>登录成功</summary> /// <param name="client">OAuth客户端</param> /// <param name="context">服务提供者。可用于获取HttpContext成员</param> /// <param name="uc">用户链接</param> /// <param name="forceBind">强行绑定,把第三方账号强行绑定到当前已登录账号</param> /// <returns></returns> public virtual String OnLogin(OAuthClient client, IServiceProvider context, UserConnect uc, Boolean forceBind) { //// 强行绑定,把第三方账号强行绑定到当前已登录账号 //var forceBind = false; #if __CORE__ var httpContext = context.GetService <IHttpContextAccessor>().HttpContext; var req = httpContext.Request; var ip = httpContext.GetUserHost(); #else var req = context.GetService <HttpRequest>(); var httpContext = req.RequestContext.HttpContext; var ip = httpContext.GetUserHost(); #endif // 可能因为初始化顺序的问题,导致前面没能给Provider赋值 var prv = Provider; if (prv == null) { prv = Provider = ManageProvider.Provider; } // 检查绑定,新用户的uc.UserID为0 var user = prv.FindByID(uc.UserID); if (forceBind || user == null || !uc.Enable) { user = OnBind(uc, client); } try { uc.UpdateTime = DateTime.Now; uc.Save(); } catch (Exception ex) { //为了防止某些特殊数据导致的无法正常登录,把所有异常记录到日志当中。忽略错误 XTrace.WriteException(ex); } // 如果应用不支持自动注册,此时将得不到用户,跳回去登录页面 if (user == null) { return(null); } // 填充昵称等数据 Fill(client, user); if (user is IAuthUser user3) { user3.Logins++; user3.LastLogin = DateTime.Now; user3.LastLoginIP = ip; //user3.Save(); //(user3 as IEntity).Update(); } if (user is IEntity entity) { entity.Update(); } // 写日志 var log = LogProvider.Provider; log?.WriteLog(typeof(User), "SSO登录", true, $"[{user}]从[{client.Name}]的[{client.UserName ?? client.NickName}]登录", user.ID, user + ""); if (!user.Enable) { throw new InvalidOperationException($"用户[{user}]已禁用!"); } // 登录成功,保存当前用户 if (prv is ManageProvider2 prv2) { user = prv2.CheckAgent(user); } prv.Current = user; // 单点登录不要保存Cookie,让它在Session过期时请求认证中心 //prv.SaveCookie(user); var set = Setting.Current; if (set.SessionTimeout > 0) { var expire = TimeSpan.FromSeconds(set.SessionTimeout); #if __CORE__ prv.SaveCookie(user, expire, httpContext); #else prv.SaveCookie(user, expire, httpContext.ApplicationInstance.Context); #endif } return(SuccessUrl); }
public void Queue_Normal() { var key = "ReliableQueue"; // 删除已有 _redis.Remove(key); var queue = _redis.GetReliableQueue <String>(key); queue.RetryInterval = 5; // 发现回滚 var rcount = queue.RollbackAllAck(); if (rcount > 0) { XTrace.WriteLine("回滚:{0}", rcount); Assert.Equal(rcount, queue.Count); var rcount2 = _redis.Remove(key); Assert.Equal(1, rcount2); } // 取出个数 var count = queue.Count; Assert.True(queue.IsEmpty); Assert.Equal(0, count); // 添加 var vs = new[] { "1234", "abcd", "新生命团队", "ABEF" }; foreach (var item in vs) { queue.Add(item); } // 取出来 var vs2 = new[] { queue.TakeOne(), queue.TakeOne(), queue.TakeOne(), }; Assert.Equal(3, vs2.Length); Assert.Equal("1234", vs2[0]); Assert.Equal("abcd", vs2[1]); Assert.Equal("新生命团队", vs2[2]); Assert.Equal(1, queue.Count); // 检查Ack队列 var ackList = _redis.GetList <String>(queue.AckKey); Assert.Equal(vs2.Length, ackList.Count); // 确认两个,留下一个未确认消息在Ack队列 var rs = queue.Acknowledge(vs2[0]) + queue.Acknowledge(vs2[1]); Assert.Equal(2, rs); Assert.Equal(1, ackList.Count); // 捞出来Ack最后一个 var vs3 = queue.TakeAck(3).ToArray(); Assert.Equal(0, ackList.Count); Assert.Single(vs3); Assert.Equal("新生命团队", vs3[0]); // 读取队列最后一个,但不确认,留给下一次回滚用 var v4 = queue.TakeOne(); Assert.NotNull(v4); // 现在队列没有数据,再取一个 var v5 = queue.TakeOne(1); Assert.Null(v5); }
public void AssignCurrency(XTrace trace, string currency) { AssignCurrencyPrivate(trace, currency); }
public override void StopWork() { _timer?.Change(Timeout.Infinite, Timeout.Infinite); base.StopWork(); XTrace.WriteLine("守护服务已停止"); }