首页
网络资源
技术分享
云资源
分享你我
行动起来,活在当下
累计撰写
112
篇文章
累计创建
13
个标签
累计收到
0
条评论
栏目
首页
网络资源
技术分享
云资源
目 录
CONTENT
最新文章
CefSharp 滑动、输入、获取标签位置、点击等封装(支持XPath语法操作)
<pre class="brush:c#;toolbar:false"> /// <summary> /// 组装节点对象 /// </summary> /// <param name="browser"></param> /// <param name="tag"></param> /// <param name="document"></param> /// <returns></returns> public static string AssembleIframeDocument(this IBrowser browser, string tag, string document = "document") { string script = "document.evaluate(\"" + tag.Replace("\"", "'") + "\"," + document + ",null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue.contentWindow.document"; return script; } /// <summary> /// 组装节点对象 /// </summary> /// <param name="browser"></param> /// <param name="tag"></param> /// <param name="document"></param> /// <returns></returns> public static string AssembleDocument(this IBrowser browser, string tag, string document = "document") { string script = "document.evaluate(\"" + tag.Replace("\"", "'") + "\"," + document + ",null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue"; return script; } /// <summary> /// 获取元素所在位置 /// </summary> /// <param name="browser">浏览器对象</param> /// <param name="tag">标签(NodeName)</param> /// <param name="document">html文档(xpath才技持)</param> /// <returns></returns> public static BoundingClientRect GetBoundingClientRect(this IBrowser browser, string tag, string document = "document") { var isXPath = Regex.IsMatch(tag, "(^//.*)"); if (isXPath) { string script = "(function(){"; script += "var doc= document.evaluate(\"" + tag.Replace("\"", "'") + "\"," + document + ",null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;"; script += @"if(doc != null){ let bntRect = doc.getBoundingClientRect(); let result =JSON.stringify({ x: bntRect.left, y: bntRect.top,r:bntRect.right,b:bntRect.bottom }); return result; }; return null; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return null; if (response.Result == null) return null; BoundingClientRect? bc = JsonSerializer.Deserialize<BoundingClientRect>(response.Result.ToString()); return bc; } else { string script = "(function(){"; script += "var doc = document.querySelector(\"" + tag.Replace("\"", "'") + "\");"; script += @"if(doc!=null){ let bntRect = doc.getBoundingClientRect(); let result =JSON.stringify({ x: bntRect.left, y: bntRect.top,r:bntRect.right,b:bntRect.bottom }); return result; }; return null; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return null; if (response.Result == null) return null; BoundingClientRect? bc = JsonSerializer.Deserialize<BoundingClientRect>(response.Result.ToString()); return bc; } } /// <summary> /// 通过ini指定值获取坐标 /// </summary> /// <param name="browser"></param> /// <param name="key">ini配置文件<k,v> k</param> /// <param name="path">ini配置文件路径</param> /// <returns></returns> public static BoundingClientRect GetPosition(this IBrowser browser, string key, string path, string document = "document") { string tagText = INIHelper.Read("tag", key, path);//@"input[name=pass]"; tagText = string.IsNullOrWhiteSpace(tagText) ? INIHelper.Read("tagXPath", key, path) : tagText; var isLabel = browser.CheckLabel(tagText, document); if (!isLabel) return null; var bc = browser.GetBoundingClientRect(tagText, document);//获取登录按钮位置 if (bc == null) return null; return bc; } /// <summary> /// 模拟点击指定选择符DOM元素 /// </summary> /// <param name="selector">jQuery选择符</param> public static void ClickElement(this IBrowser browser, double? left, double? top, bool isFocusEvent = false) { var host = browser.GetHost(); var x = Convert.ToInt32(left) + 5; var y = Convert.ToInt32(top) + 5; host.SendMouseMoveEvent(x, y, false, CefEventFlags.None);//移动鼠标 Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);//按下鼠标左键 Thread.Sleep(50); host.SendFocusEvent(isFocusEvent); Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);//松开鼠标左键 } /// <summary> /// 全选 /// </summary> /// <param name="browser"></param> /// <param name="left"></param> /// <param name="top"></param> public static void SelectAllKeyEvent(this IBrowser browser) { KeyEvent k = new KeyEvent { WindowsKeyCode = 0x41, // A = 0x41, FocusOnEditableField = true, Modifiers = CefEventFlags.ControlDown, Type = KeyEventType.KeyDown, IsSystemKey = false }; browser.GetHost().SendKeyEvent(k); Thread.Sleep(100); k = new KeyEvent { WindowsKeyCode = 0x41, // A = 0x41, FocusOnEditableField = true, Modifiers = CefEventFlags.ControlDown, Type = KeyEventType.KeyUp, IsSystemKey = false }; browser.GetHost().SendKeyEvent(k); Thread.Sleep(100); } /// <summary> /// 向前删除 /// </summary> /// <param name="browser"></param> public static void BackSpaceKeyEvent(this IBrowser browser) { KeyEvent k = new KeyEvent { WindowsKeyCode = 0x08, // Back = 0x08, FocusOnEditableField = true, Modifiers = CefEventFlags.None, IsSystemKey = false, Type = KeyEventType.KeyDown }; browser.GetHost().SendKeyEvent(k); Thread.Sleep(100); k = new KeyEvent { WindowsKeyCode = 0x08, // Back = 0x08, FocusOnEditableField = true, Modifiers = CefEventFlags.None, IsSystemKey = false, Type = KeyEventType.KeyUp }; browser.GetHost().SendKeyEvent(k); Thread.Sleep(100); } /// <summary> /// 按下回车事件 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public static void HitEnterKeyEvent(this IBrowser browser, double? left, double? top) { KeyEvent k = new KeyEvent { WindowsKeyCode = 0x0D, // Enter FocusOnEditableField = true, IsSystemKey = false, Type = KeyEventType.KeyDown }; browser.GetHost().SendKeyEvent(k); //browser.GetHost().SendFocusEvent(); Thread.Sleep(100); k = new KeyEvent { WindowsKeyCode = 0x0D, // Enter FocusOnEditableField = true, IsSystemKey = false, Type = KeyEventType.KeyUp }; browser.GetHost().SendKeyEvent(k); Thread.Sleep(100); } /// <summary> /// 输入内容 /// </summary> /// <param name="browser"></param> /// <param name="inputString"></param> public static void Input(this IBrowser browser, string inputString) { //var inputString = "CefSharp Was Here!"; var host = browser.GetHost(); foreach (var c in inputString) { host.SendKeyEvent(new KeyEvent { WindowsKeyCode = c, Type = KeyEventType.Char }); } } /// <summary> /// 输入帐号 /// </summary> /// <param name="browser">当前浏览器</param> /// <param name="userName">用户名</param> /// <param name="x">x坐标</param> /// <param name="y">y坐标</param> public static void InputUser(this IBrowser browser, string userName, double? x, double? y) { browser.ClickElement(x, y, true); Thread.Sleep(100); browser.Input(userName);//输入帐号 Thread.Sleep(300); } /// <summary> /// 输入密码 /// </summary> /// <param name="browser"></param> /// <param name="pass"></param> /// <param name="x"></param> /// <param name="y"></param> public static void InputPass(this IBrowser browser, string pass, double? x, double? y) { browser.ClickElement(x, y, true); Thread.Sleep(100); browser.Input(pass);//输入帐号 Thread.Sleep(300); } /// <summary> /// 判断标签是否存在 /// </summary> /// <param name="browser">浏览器对象</param> /// <param name="tag">标签(NodeName)</param> /// <param name="document">html文档(xpath才技持)</param> /// <returns></returns> public static bool IsQuerySelector(this IBrowser browser, string tag, string document = "document") { var isXPath = Regex.IsMatch(tag, "(^//.*)"); if (isXPath) { string script = "(function(){"; script += "var doc= document.evaluate(\"" + tag.Replace("\"", "'") + "\","+ document + ",null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;"; script += @"if(doc == null) return null; let result =JSON.stringify({ data:true }); return result; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 if (result == null) return false; var response = result.Result; if (response.Success && response.Result == null) return false; return true; } else { string script = "(function(){"; script += "var doc = document.querySelector(\"" + tag.Replace("\"", "'") + "\");"; script += @"if(doc==null) return null; let result =JSON.stringify({ data:true }); return result; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait(); //等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return false; if (response.Result == null) return false; return true; } } /// <summary> /// 发送鼠标滚轮事件 /// </summary> /// <param name="browser">浏览器对象</param> /// <param name="left">x</param> /// <param name="top">y</param> public static void SendMouseWheel(this IBrowser browser, double? left, double? top) { var host = browser.GetHost(); var x = Convert.ToInt32(left) + 5; var y = Convert.ToInt32(top) + 5; host.SendMouseWheelEvent(Convert.ToInt32(0), Convert.ToInt32(top), x, y, CefEventFlags.None); Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);//按下鼠标左键 Thread.Sleep(50); Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);//松开鼠标左键 } /// <summary> /// 滚动到指定元素上 /// </summary> /// <param name="browser">浏览器对象</param> /// <param name="tag">标签(NodeName)</param> /// <param name="document">html文档(xpath才技持)</param> /// <returns></returns> private static bool ScrollIntoView(this IBrowser browser, string tag, string document = "document") { var isXPath = Regex.IsMatch(tag, "(^//.*)"); if (isXPath) { string script = "(function(){"; script += "var doc= document.evaluate(\"" + tag + "\","+ document + ",null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;"; script += @"if(doc != null){doc.scrollIntoView({block: 'center',behavior: 'smooth'}); return true}; return false; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return false; if (response.Result == null) return false; var bo = (bool)response.Result; return bo; } else { string script = "(function(){"; script += "var doc = document.querySelector(\"" + tag.Replace("\"", "'") + "\");"; script += @"if(doc != null){doc.scrollIntoView({block: 'center',behavior: 'smooth'}); return true}; return false; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait(); //等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return false; if (response.Result == null) return false; var bo = (bool)response.Result; return bo; } } /// <summary> /// 滚动到指定元素上 /// </summary> /// <param name="browser"></param> /// <param name="key">ini配置文件<k,v> k</param> /// <param name="path">ini配置文件路径</param> /// <param name="document"></param> /// <returns></returns> public static bool ScrollIntoView(this IBrowser browser, string key, string path, string document = "document") { string tagText = INIHelper.Read("tag", key, path); tagText = string.IsNullOrWhiteSpace(tagText) ? INIHelper.Read("tagXPath", key, path) : tagText; var isLabel = browser.CheckLabel(tagText, document); if (!isLabel) return false; var bc = browser.ScrollIntoView(tagText, document); if (bc == false) return false; return bc; } /// <summary> /// 检查标签是否存在 /// </summary> /// <param name="browser">浏览器对象</param> /// <param name="tag">标签(NodeName)</param> /// <param name="document">html文档(xpath才技持)</param> /// <returns></returns> public static bool CheckLabel(this IBrowser browser, string tag, string document = "document") { var isXPath = Regex.IsMatch(tag, "(^//.*)"); bool isTrue = false; if (isXPath) { isTrue = Policy .Handle<Exception>() .OrResult<bool>(r => r == false) .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }).Execute(() => { return browser.IsQuerySelector(tag, document); }); return isTrue; } else { isTrue = Policy .Handle<Exception>() .OrResult<bool>(r => r == false) .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }).Execute(() => { return browser.IsQuerySelector(tag); }); return isTrue; } } /// <summary> /// 检查标签是否存在 /// </summary> /// <param name="browser">浏览器对象</param> /// <param name="key">ini配置文件<k,v> k</param> /// <param name="path">ini配置文件路径</param> /// <param name="document">html文档(xpath才技持)</param> /// <returns></returns> public static bool CheckLabel(this IBrowser browser, string key, string path, string document = "document") { string tagText = INIHelper.Read("tag", key, path);//@"input[name=pass]"; tagText = string.IsNullOrWhiteSpace(tagText) ? INIHelper.Read("tagXPath", key, path) : tagText; var isXPath = Regex.IsMatch(tagText, "(^//.*)"); bool isTrue = false; if (isXPath) { isTrue = Policy .Handle<Exception>() .OrResult<bool>(r => r == false) .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }).Execute(() => { return browser.IsQuerySelector(tagText, document); }); return isTrue; } else { isTrue = Policy .Handle<Exception>() .OrResult<bool>(r => r == false) .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }).Execute(() => { return browser.IsQuerySelector(tagText); }); return isTrue; } }</pre><!--autointro--><!--90-->
2022-02-24
7
0
0
技术分享
CefSharp Dom操作封装
<p>最近在做使用CefSharp 登录各个平台自动发送文章、新闻等因此有如下封装类:</p><pre class="brush:c#;toolbar:false"> public static class DomHelper { /// <summary> /// 获取元素所在位置 /// </summary> /// <param name="browser"></param> /// <param name="tag"></param> /// <returns></returns> public static BoundingClientRect GetBoundingClientRectAsync(this IBrowser browser, string tag) { string script = "(function(){"; script += "var doc = document.querySelector('" + tag + "');"; script += @"if(doc!=null){ let bntRect = doc.getBoundingClientRect(); let result =JSON.stringify({ x: bntRect.left, y: bntRect.top,r:bntRect.right,b:bntRect.bottom }); return result; }; return null; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return null; if (response.Result == null) return null; BoundingClientRect? bc = JsonSerializer.Deserialize<BoundingClientRect>(response.Result.ToString()); return bc; } /// <summary> /// 通过xpath 语法获取坐标 /// </summary> /// <param name="browser"></param> /// <param name="tag"></param> /// <returns></returns> public static BoundingClientRect GetXPathBoundingClientRect(this IBrowser browser, string tag) { string script = "(function(){"; script += "var doc= document.evaluate(\"" + tag + "\",document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;"; script += @"if(doc != null){ let bntRect = doc.getBoundingClientRect(); let result =JSON.stringify({ x: bntRect.left, y: bntRect.top,r:bntRect.right,b:bntRect.bottom }); return result; }; return null; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 if (result == null) return null; var response = result.Result; if (response.Success && response.Result == null) return null; BoundingClientRect? bc = JsonSerializer.Deserialize<BoundingClientRect>(response.Result.ToString()); return bc; } /// <summary> /// 模拟点击指定选择符DOM元素 /// </summary> /// <param name="selector">jQuery选择符</param> public static void ClickElement(this IBrowser browser, double? left, double? top, bool isFocusEvent = false) { var host = browser.GetHost(); var x = Convert.ToInt32(left) + 5; var y = Convert.ToInt32(top) + 5; host.SendMouseMoveEvent(x, y, false, CefEventFlags.None);//移动鼠标 Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);//按下鼠标左键 Thread.Sleep(50); host.SendFocusEvent(isFocusEvent); Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);//松开鼠标左键 } /// <summary> /// 按下回车事件 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public static void HitEnter(this IBrowser browser, int x, int y) { KeyEvent k = new KeyEvent { WindowsKeyCode = 0x0D, // Enter FocusOnEditableField = true, IsSystemKey = false, Type = KeyEventType.KeyDown }; browser.GetHost().SendKeyEvent(k); //browser.GetHost().SendFocusEvent(); Thread.Sleep(100); k = new KeyEvent { WindowsKeyCode = 0x0D, // Enter FocusOnEditableField = true, IsSystemKey = false, Type = KeyEventType.KeyUp }; browser.GetHost().SendKeyEvent(k); Thread.Sleep(100); } /// <summary> /// 输入内容 /// </summary> /// <param name="browser"></param> /// <param name="inputString"></param> public static void Input(this IBrowser browser, string inputString) { //var inputString = "CefSharp Was Here!"; var host = browser.GetHost(); foreach (var c in inputString) { host.SendKeyEvent(new KeyEvent { WindowsKeyCode = c, Type = KeyEventType.Char }); } } /// <summary> /// 输入帐号 /// </summary> /// <param name="browser">当前浏览器</param> /// <param name="userName">用户名</param> /// <param name="x">x坐标</param> /// <param name="y">y坐标</param> public static void InputUser(this IBrowser browser, string userName, double? x, double? y) { browser.ClickElement(x, y, true); Thread.Sleep(100); browser.Input(userName);//输入帐号 Thread.Sleep(300); } /// <summary> /// 输入密码 /// </summary> /// <param name="browser"></param> /// <param name="pass"></param> /// <param name="x"></param> /// <param name="y"></param> public static void InputPass(this IBrowser browser, string pass, double? x, double? y) { browser.ClickElement(x, y, true); Thread.Sleep(100); browser.Input(pass);//输入帐号 Thread.Sleep(300); } /// <summary> /// 判断标签是否存在 /// </summary> /// <param name="browser"></param> /// <param name="tag"></param> public static bool IsQuerySelector(this IBrowser browser, string tag) { string script = "(function(){"; script += "var doc = document.querySelector('" + tag + "');"; script += @"if(doc==null) return null; let bntRect = doc.getBoundingClientRect(); let result =JSON.stringify({ x: bntRect.left, y: bntRect.top,r:bntRect.right,b:bntRect.bottom }); return result; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 var response = result.Result; if (response.Success && response.Result == null) return false; if (response.Result == null) return false; return true; } /// <summary> /// 通过xpath 语法判断元素是否存在 /// </summary> /// <param name="browser"></param> /// <param name="tag"></param> /// <returns></returns> public static bool IsXPathQuerySelector(this IBrowser browser, string tag) { string script = "(function(){"; script += "var doc= document.evaluate(\"" + tag + "\",document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;"; script += @"if(doc == null) return null; let bntRect = doc.getBoundingClientRect(); let result =JSON.stringify({ x: bntRect.left, y: bntRect.top,r:bntRect.right,b:bntRect.bottom }); return result; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 if (result == null) return false; var response = result.Result; if (response.Success && response.Result == null) return false; return true; } /// <summary> /// 发送鼠标滚轮事件 /// </summary> /// <param name="browser"></param> /// <param name="left"></param> /// <param name="top"></param> public static void SendMouseWheel(this IBrowser browser, double? left, double? top) { var host = browser.GetHost(); var x = Convert.ToInt32(left) + 5; var y = Convert.ToInt32(top) + 5; host.SendMouseWheelEvent(Convert.ToInt32(0), Convert.ToInt32(top), x, y, CefEventFlags.None); Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);//按下鼠标左键 Thread.Sleep(50); Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);//松开鼠标左键 } /// <summary> /// 滚动到指定元素上 /// </summary> public static bool ScrollIntoView(this IBrowser browser, string tag) { string script = "(function(){"; script += "var doc= document.evaluate(\"" + tag + "\",document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;"; script += @"if(doc != null){doc.scrollIntoView({block: 'center',behavior: 'smooth'}); return true}; return false; })()"; Task<JavascriptResponse> result = browser.EvaluateScriptAsync(script); result.Wait();//等待脚本执行完 if (result == null) return false; var response = result.Result; if (response.Success && response.Result == null) return false; var bo = (bool)response.Result; return bo; } }</pre><!--autointro--><!--89-->
2022-02-15
9
0
0
技术分享
cefsharp 模拟点击的坑
<p>网上说的基本都是:</p><pre class="brush:c#;toolbar:false"> host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);//按下鼠标左键 Thread.Sleep(50); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);//松开鼠标左键</pre><!--autointro--><!--88-->
2022-02-11
10
0
0
技术分享
c# 区分虚拟网卡 获取真实网卡信息 判断网卡有线或无线
<pre class="brush:c#;toolbar:false">public void GetPhysicsNetworkAdapterInfo() { ManagementObjectSearcher mos = new ManagementObjectSearcher(@"\\.\ROOT\StandardCimv2", "SELECT * FROM MSFT_NetAdapter WHERE Virtual=False"); ManagementObjectCollection moc = mos.Get(); foreach (ManagementObject mo in moc) { string driverDescription = mo["DriverDescription"]?.ToString(); uint interfaceType = Convert.ToUInt32(mo["InterfaceType"] ?? 0); string macAdddr = mo["PermanentAddress"]?.ToString(); Console.WriteLine("---------------------------------------"); Console.WriteLine($"DriverDescription:{driverDescription}"); Console.WriteLine($"MacAddr:{macAdddr}"); Console.WriteLine($"InterfaceType:{interfaceType}"); } }</pre><!--autointro--><!--87-->
2022-01-06
10
0
0
技术分享
.net core 内置的 System.Text.Json 序列化类型扩展支持
<p>添加以扩展:</p><pre class="brush:c#;toolbar:false">public class TextJsonConverExtension { public static void AddConverters(Microsoft.AspNetCore.Mvc.JsonOptions configure) { //添加支持string转int的操作 configure.JsonSerializerOptions.Converters.Add(new IntToStringConverter()); configure.JsonSerializerOptions.Converters.Add(new StringToStringConverter()); configure.JsonSerializerOptions.Converters.Add(new LongToStringConverter()); } } public class IntToStringConverter : JsonConverter<Int32> { public override Int32 Read(ref System.Text.Json.Utf8JsonReader reader, Type type, System.Text.Json.JsonSerializerOptions options) { if (reader.TokenType == System.Text.Json.JsonTokenType.String) { ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; if (System.Buffers.Text.Utf8Parser.TryParse(span, out Int32 number, out int bytesConsumed) && span.Length == bytesConsumed) return number; if (Int32.TryParse(reader.GetString(), out number)) return number; } return reader.GetInt32(); } public override void Write(Utf8JsonWriter writer, Int32 value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } } public class StringToStringConverter : JsonConverter<String> { public override String Read(ref System.Text.Json.Utf8JsonReader reader, Type type, System.Text.Json.JsonSerializerOptions options) { if (reader.TokenType == System.Text.Json.JsonTokenType.String) { return reader.GetString(); } else if(reader.TokenType == System.Text.Json.JsonTokenType.Number) { ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; if (System.Buffers.Text.Utf8Parser.TryParse(span, out Int32 number, out int bytesConsumed) && span.Length == bytesConsumed) return number.ToString(); if (Int32.TryParse(reader.GetString(), out number)) return number.ToString(); } return null; //return reader.GetInt32(); } public override void Write(Utf8JsonWriter writer, String value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } } public class LongToStringConverter : JsonConverter<long> { public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; if (Utf8Parser.TryParse(span, out long number, out int bytesConsumed) && span.Length == bytesConsumed) return number; if (Int64.TryParse(reader.GetString(), out number)) return number; } return reader.GetInt64(); } public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } }</pre><!--autointro--><!--86-->
2021-12-30
6
0
0
技术分享
OpenWrt实现双线接入实现负载均衡带宽叠加(测速也可以查看叠加是否成功)
<p>一、</p><p>添加两个 WAN 口,并把双线插入对应的WAN口</p><p><br/></p><p>添加WAN-1</p><p> 这里如果是用拨号上网的选择 "PPOE" 协议,然后输入宽带密码和帐号</p><p><img src="https://www.javalc.com/zb_users/upload/2021/12/202112111830304972536.png" alt="image.png" width="621" height="500" border="0" vspace="0" style="width: 621px; height: 500px;"/></p><!--autointro--><!--84-->
2021-12-11
89
0
0
技术分享
mysql bat一键安装(可手动可自动加载sql文件初始化库)
<p>简单点的:</p><pre class="brush:bash;toolbar:false">@echo off if %~dp0 == %cd%\ ( echo 请使用管理员身份执行脚本,按下回车键终止此次安装! set /p in= exit ) echo mysql5.*压缩版一键安装脚本... echo 即将开始安装... set /p password=请设置密码: if not defined password ( echo 您没有输入密码,按下回车键终止此次安装! set /p in= exit ) echo === 检查服务是否存在 SC QUERY MySQL > NUL IF ERRORLEVEL 1060 GOTO NOTEXIST GOTO EXIST :NOTEXIST ECHO 不存在MySQL服务 GOTO END :EXIST echo === 服务存在 net stop MySQL echo === 服务停止完成 sc delete MySQL If errorlevel 1 ( echo ===删除服务出错了。按下回车退出 set /p in= exit ) Else ( echo ===删除服务成功 ) GOTO END :END rem 将当前路径存储起来 set mysqlPath=%~dp0 rem 进入当前路径 cd /d %mysqlPath% rem 将配置文件名存储起来 set ini=my.ini rem 创建data文件夹 mkdir data echo ************************************************************ echo * * echo * MYSQL 系统环境变量设置 * echo * * echo ************************************************************ echo. echo === 准备设置环境变量: PATH=%%MYSQL_HOME%%bin echo. set /P EN=请确认后按 回车键 开始设置! echo. echo. rem ::如果有的话,先删除MYSQL_HOME wmic ENVIRONMENT where "name='MYSQL_HOME'" delete rem ::创建MYSQL_HOME wmic ENVIRONMENT create name="MYSQL_HOME",username="<system>",VariableValue="%mysqlPath%" ::在环境变量path中,剔除掉变量MYSQL_HOME中的字符,回显剩下的字符串 set newPath=%Path%;%%MYSQL_HOME%%\bin echo === 环境变量: PATH=%newPath% ::将返回显的字符重新赋值到path中 wmic ENVIRONMENT where "name='Path' and username='<system>'" set VariableValue="%newPath%" rem 向my.ini文件输出内容 echo [Client] >> %ini% echo. echo port = 3306 >> %ini% echo. echo [mysqld] >> %ini% echo. echo port = 3306 >> %ini% echo. echo basedir=%mysqlPath% >> %ini% echo. echo datadir=%mysqlPath%\data >> %ini% echo. echo max_connections=200 >> %ini% echo. echo character-set-server=utf8 >> %ini% echo. echo default-storage-engine=InnoDB >> %ini% echo. echo sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES >> %ini% echo. echo skip-grant-tables >> %ini% echo default_authentication_plugin=mysql_native_password >> %ini% echo. echo. echo [mysql] >> %ini% echo. echo default-character-set=utf8 >> %ini% rem 进入bin目录 cd /d %mysqlPath%\bin rem 执行mysql安装命令 start /b /wait mysqld -install rem 执行mysql初始化命令 start /b /wait mysqld --initialize --console rem 启动mysql服务 start /b /wait net start mysql rem 设置root用户密码 start /b /wait mysql -uroot -pnon -e "update mysql.user set authentication_string=PASSWORD('%password%') where user='root' and host='localhost';" rem 刷新权限 start /b /wait mysql -uroot -pnon -e "flush privileges;" rem 停止mysql服务 start /b /wait net stop mysql rem 启动mysql服务 start /b /wait net start mysql echo === 初始化数据库 set /p dataBaseName=请设置数据库名称: if not defined dataBaseName ( echo 您没有输入数据库名称,按下回车键终止此次安装! set /p in= exit ) set MYSQL_CMD= mysql -uroot -pnon rem echo %MYSQL_CMD% rem 停止mysql服务 start /b /wait net stop mysql rem 启动mysql服务 start /b /wait net start mysql echo === 创建数据库====数据库:%dataBaseName% start /b /wait %MYSQL_CMD% -e "CREATE DATABASE IF NOT EXISTS %dataBaseName% DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;"; set /p sqlfile=请输入执行sql的文件名称包括后缀: if not defined sqlfile ( echo 请没有输入执行sql的文件名称包括后缀,按下回车键终止此次安装! set /p in= exit ) echo === 执行sql脚本 echo. echo === 执行sql脚本---%sqlfile% echo. start /b /wait %MYSQL_CMD% -D%dataBaseName% < %mysqlPath%%sqlfile% @echo on echo === 执行sql脚本---setSql.sql echo. start /b /wait %MYSQL_CMD% -D%dataBaseName% < %mysqlPath%setSql.sql @echo off rem 停止mysql服务 start /b /wait net stop mysql rem 进入根目录 cd /d %mysqlPath% rem 清空my.ini文件 CD. > %ini% rem 向my.ini文件输出内容 echo [Client] >> %ini% echo. echo port = 3306 >> %ini% echo. echo [mysqld] >> %ini% echo. echo port = 3306 >> %ini% echo. echo basedir=%mysqlPath% >> %ini% echo. echo datadir=%mysqlPath%\data >> %ini% echo. echo max_connections=200 >> %ini% echo. echo character-set-server=utf8 >> %ini% echo. echo default-storage-engine=InnoDB >> %ini% echo. echo sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES >> %ini% echo default_authentication_plugin=mysql_native_password >> %ini% echo. echo. echo [mysql] >> %ini% echo. echo default-character-set=utf8 >> %ini% rem 启动mysql服务 start /b /wait net start mysql echo 安装完成 pause >nul</pre><!--autointro--><!--83-->
2021-12-03
13
0
0
技术分享
C# HttpWebRequest 多网卡指定IP下载
<pre class="brush:c#;toolbar:false">/// <summary> /// 获取指定网卡IP /// </summary> /// <param name="servicePoint"></param> /// <param name="remoteEndPoint"></param> /// <param name="retryCount"></param> /// <returns></returns> public IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount) { if (!string.IsNullOrWhiteSpace(_configuration.IP)) { IPAddress address = IPAddress.Parse(_configuration.IP); return new IPEndPoint(address, 0); } return new IPEndPoint(IPAddress.Any, 0); } public static void Main() { HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://MyServer"); request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); }</pre><!--autointro--><!--82-->
2021-11-29
9
0
0
技术分享
vue3 + ts+vite+electron使用tinymce富文本框
<p>新建TEditor.vue组件</p><pre class="brush:js;toolbar:false"># index.vue <template> <div class="tinymce-box"> <Editor v-model="contentValue" :init="initOptions" :disabled="disabled" @onClick="onClick" /> </div> </template> <script lang="ts"> //引入tinymce编辑器 import Editor from '@tinymce/tinymce-vue'; // 引入富文本编辑器主题的js和css // import 'tinymce/skins/content/default/content.css' //引入方式引入node_modules里的tinymce相关文件文件 import tinymce from 'tinymce/tinymce'; //tinymce默认hidden,不引入则不显示编辑器 import 'tinymce/themes/silver'; //编辑器主题,不引入则报错 import 'tinymce/icons/default'; //引入编辑器图标icon,不引入则不显示对应图标 // 引入编辑器插件 import 'tinymce/plugins/advlist'; //高级列表 import 'tinymce/plugins/anchor'; //锚点 import 'tinymce/plugins/autolink'; //自动链接 import 'tinymce/plugins/autoresize'; //编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效 import 'tinymce/plugins/autosave'; //自动存稿 import 'tinymce/plugins/charmap'; //特殊字符 import 'tinymce/plugins/code'; //编辑源码 import 'tinymce/plugins/codesample'; //代码示例 import 'tinymce/plugins/directionality'; //文字方向 import 'tinymce/plugins/emoticons'; //表情 import 'tinymce/plugins/fullpage'; //文档属性 import 'tinymce/plugins/fullscreen'; //全屏 import 'tinymce/plugins/help'; //帮助 import 'tinymce/plugins/hr'; //水平分割线 import 'tinymce/plugins/image'; //插入编辑图片 import 'tinymce/plugins/importcss'; //引入css import 'tinymce/plugins/insertdatetime'; //插入日期时间 import 'tinymce/plugins/link'; //超链接 import 'tinymce/plugins/lists'; //列表插件 import 'tinymce/plugins/media'; //插入编辑媒体 import 'tinymce/plugins/nonbreaking'; //插入不间断空格 import 'tinymce/plugins/pagebreak'; //插入分页符 import 'tinymce/plugins/paste'; //粘贴插件 import 'tinymce/plugins/preview'; //预览 import 'tinymce/plugins/print'; //打印 import 'tinymce/plugins/quickbars'; //快速工具栏 import 'tinymce/plugins/save'; //保存 import 'tinymce/plugins/searchreplace'; //查找替换 // import 'tinymce/plugins/spellchecker' //拼写检查,暂未加入汉化,不建议使用 import 'tinymce/plugins/tabfocus'; //切入切出,按tab键切出编辑器,切入页面其他输入框中 import 'tinymce/plugins/table'; //表格 import 'tinymce/plugins/template'; //内容模板 import 'tinymce/plugins/textcolor'; //文字颜色 import 'tinymce/plugins/textpattern'; //快速排版 import 'tinymce/plugins/toc'; //目录生成器 import 'tinymce/plugins/visualblocks'; //显示元素范围 import 'tinymce/plugins/visualchars'; //显示不可见字符 import 'tinymce/plugins/wordcount'; //字数统计 // import '../../public/tinymce/axupimgs' //多图上传 import { defineComponent, reactive, toRefs, watch, ref, onMounted } from 'vue'; export default defineComponent({ components: { Editor, }, props: { value: { type: String, default: '', }, disabled: { type: Boolean, default: false, }, plugins: { type: [String, Array], default: 'print preview searchreplace autolink directionality emoticons visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave ', }, toolbar: { type: [String, Array], default: 'fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \ styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \ table image media charmap emoticons hr pagebreak insertdatetime print preview | code selectall | indent2em lineheight formatpainter axupimgs', }, }, setup(props, { expose, emit }) { const state = reactive({ contentValue: props.value, }); const initOptions = ref({ emoticons_database_url: './/tinymce/emoticons/js/emojis.js', //更改表情插件路径 language_url: './/tinymce/langs/zh_CN.js', //引入语言包文件 language: 'zh_CN', //语言类型 skin_url: './/tinymce/skins/ui/oxide', //皮肤:浅色 // skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色 plugins: props.plugins, //插件配置 toolbar: props.toolbar, //工具栏配置,设为false则隐藏 // menubar: 'file edit', //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单” fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', //字体大小 font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;', height: 300, //注:引入autoresize插件时,此属性失效 min_heigth: 200, placeholder: '在这里输入文字...', branding: false, //tiny技术支持信息是否显示 resize: false, //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号 // statusbar: false, //最下方的元素路径和字数统计那一栏是否显示 elementpath: false, //元素路径是否显示 // content_style: 'img {max-width:100%;}', //直接自定义可编辑区域的css样式 content_css: './/tinymce/tinycontent.css', //以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入 // images_upload_url: '/demo/upimg.php', //后端处理程序的url // images_upload_base_path: '/demo', //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php // 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片, // 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler images_upload_handler: (blobInfo: any, success: any, failure: any) => { const img = 'data:image/jpeg;base64,' + blobInfo.base64(); success(img); }, }); const methods = reactive({ onClick(e: any) { emit('onClick', e, tinymce); }, // 可以添加一些自己的自定义事件,如清空内容 clear() { state.contentValue = ''; }, }); onMounted(() => { tinymce.init({}); }); watch( () => props.value, (newValue) => { state.contentValue = newValue; } ); watch( () => state.contentValue, (newValue) => { emit('input', newValue); } ); expose({ ...toRefs(state) }); return { initOptions, ...toRefs(state), ...toRefs(methods), }; }, }); </script> <style lang="scss"> .tinymce-box { z-index: 2; } </style></pre><!--autointro--><!--81-->
2021-11-21
11
0
0
技术分享
VUE3 语法糖(script setup)+ts 使用
<p>VUE3官方网站:<a href="https://v3.cn.vuejs.org/guide/introduction.html" target="_blank" rel="noopener">点击访问</a><br/></p><p>VUE3的生命周期和VUE2的区别:<a href="https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html" target="_self" rel="noopener">点击访问</a><br/></p><p>下面通过两组件和一个辅助文件说明:<br/></p><!--autointro--><!--80-->
2021-11-21
12
0
0
技术分享
1
2
3
4
5
...
12