From ee3ba82221ba3c5f86c59f9186a0146deb6c474a Mon Sep 17 00:00:00 2001 From: wanggaofeng <15601716045@163.com> Date: Mon, 27 May 2024 12:10:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - Docs/1.2.使用准则.ipynb | 161 +++++------------- Docs/1.6.测试.ipynb | 69 ++++---- .../Utilities/DotnetCommondUtility.cs | 65 +++++++ .../Utilities/StartupUtility.cs | 53 ++++++ HttpClientStudy.UnitTest/TempTest.cs | 6 +- .../UtilitiesTest/DotnetCommondUtilityTest.cs | 51 ++++++ .../Controllers/CallApiController.cs | 4 +- .../Controllers/ManagerController.cs | 45 +++++ 9 files changed, 298 insertions(+), 157 deletions(-) create mode 100644 HttpClientStudy.Core/Utilities/DotnetCommondUtility.cs create mode 100644 HttpClientStudy.UnitTest/UtilitiesTest/DotnetCommondUtilityTest.cs create mode 100644 HttpClientStudy.WebClient/Controllers/ManagerController.cs diff --git a/.gitignore b/.gitignore index eec4af4..629e956 100644 --- a/.gitignore +++ b/.gitignore @@ -210,7 +210,6 @@ DocProject/Help/html publish/ # Publish Web Output -*.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted diff --git a/Docs/1.2.使用准则.ipynb b/Docs/1.2.使用准则.ipynb index e34edc5..d0ae590 100644 --- a/Docs/1.2.使用准则.ipynb +++ b/Docs/1.2.使用准则.ipynb @@ -17,6 +17,45 @@ "从 .NET Core 2.1 开始,SocketsHttpHandler 类提供实现,使行为在所有平台上保持一致。" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 准备工作:先执行下面单元,以启动WebApi及设置全局对象、方法及其它" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "ename": "Error", + "evalue": "(11,16): error CS0117: “StartupUtility”未包含“StartWebApiDll”的定义", + "output_type": "error", + "traceback": [ + "(11,16): error CS0117: “StartupUtility”未包含“StartWebApiDll”的定义" + ] + } + ], + "source": [ + "//Nuget包\n", + "\n", + "//全局引用\n", + "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", + "\n", + "//全局对象\n", + "global using HttpClientStudy.Core;\n", + "global using HttpClientStudy.Core.Utilities;\n", + "\n", + "//启动WebAPI项目\n", + "StartupUtility.StartWebApiDll(\"xxxxx\");" + ] + }, { "cell_type": "markdown", "metadata": { @@ -186,7 +225,8 @@ "using System.Net;\n", "using System.Net.Http;\n", "\n", - "var ips = await Dns.GetHostAddressesAsync(\"www.hao123.com\");\n", + "//注意:不能使用百度 hao123等站点,可能是大厂服务器的设置问题,会导致查不到效果\n", + "var ips = await Dns.GetHostAddressesAsync(\"soft.pwidc.cn\");\n", "string firstIp = ips.FirstOrDefault().ToString();\n", "\t\n", "foreach (var ipAddress in ips)\n", @@ -211,7 +251,7 @@ "\n", "for (var i = 0; i < 5; i++)\n", "{\n", - " _ = await client.GetAsync(\"https://www.hao123.com\");\n", + " _ = await client.GetAsync(\"https://soft.pwidc.cn\");\n", " await Task.Delay(TimeSpan.FromSeconds(2));\n", "}\n", "\n", @@ -241,9 +281,10 @@ }, "outputs": [], "source": [ + "# 如果没有查询到相关网络状态信息,PowerShell不针对出错,但.Net Interactive 会异常:Command failed: SubmitCode: #!set --value @csharp:xxxx\n", "#!set --value @csharp:firstIp --name queryIp\n", "Write-Host \"请先执行上面的单元,再执行本单元\"\n", - "Write-Host \"异常话,很可能是:未查找IP为 $queryIp 的网络状\"\n", + "Write-Host \"网络状态\"\n", "\n", "netstat -ano | findstr $queryIp" ] @@ -379,120 +420,6 @@ "source": [ "#!set --value @csharp:ips --name ips\n" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!set --value @csharp:ips --name ips\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "csharp" - }, - "polyglot_notebook": { - "kernelName": "csharp" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!set --value @csharp:ips --name ips\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!set --value @csharp:firstIp --name firstIp\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!set --value @csharp:firstIp --name firstIp\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "javascript" - }, - "polyglot_notebook": { - "kernelName": "javascript" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!set --value @csharp:firstIp --name firstIp\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "dotnet_interactive": { - "language": "pwsh" - }, - "polyglot_notebook": { - "kernelName": "pwsh" - }, - "vscode": { - "languageId": "polyglot-notebook" - } - }, - "outputs": [], - "source": [ - "#!set --value @pwsh:$sss --name $sss\n" - ] } ], "metadata": { diff --git a/Docs/1.6.测试.ipynb b/Docs/1.6.测试.ipynb index 48ee014..a26c7c1 100644 --- a/Docs/1.6.测试.ipynb +++ b/Docs/1.6.测试.ipynb @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -45,7 +45,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r\n" + ] + } + ], "source": [ "//引用项目\n", "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", @@ -64,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 8, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -76,16 +84,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "ename": "Error", - "evalue": "Command failed: SubmitCode: #启动项目 ...", - "output_type": "error", - "traceback": [ - "Command failed: SubmitCode: #启动项目 ..." - ] - } - ], + "outputs": [], "source": [ "#启动项目\n", "Start-Process -FilePath \".\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe\"" @@ -93,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 9, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -105,27 +104,7 @@ "languageId": "polyglot-notebook" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[31;1mGet-Process: \u001b[0m\n", - "\u001b[31;1m\u001b[36;1mLine |\u001b[0m\n", - "\u001b[31;1m\u001b[36;1m\u001b[36;1m 3 | \u001b[0m $WebAppProc = \u001b[36;1mGet-Process $WebAppProcName\u001b[0m\n", - "\u001b[31;1m\u001b[36;1m\u001b[36;1m\u001b[0m\u001b[36;1m\u001b[0m\u001b[36;1m | \u001b[31;1m ~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[0m\n", - "\u001b[31;1m\u001b[36;1m\u001b[36;1m\u001b[0m\u001b[36;1m\u001b[0m\u001b[36;1m\u001b[31;1m\u001b[31;1m\u001b[36;1m | \u001b[31;1mCannot find a process with the name \"HttpClientStudy.WebApp\". Verify the process name and call the cmdlet again.\u001b[0m\n" - ] - }, - { - "ename": "Error", - "evalue": "Command failed: SubmitCode: # 关闭项目进程 ...", - "output_type": "error", - "traceback": [ - "Command failed: SubmitCode: # 关闭项目进程 ..." - ] - } - ], + "outputs": [], "source": [ "# 关闭项目进程\n", "$WebAppProcName =\"HttpClientStudy.WebApp\";\n", @@ -135,6 +114,26 @@ " Stop-Process $WebAppProc.Id\n", "}" ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "dotnet_interactive": { + "language": "pwsh" + }, + "polyglot_notebook": { + "kernelName": "pwsh" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "# 新窗口启动WebApi\n", + "Start-Process -FilePath dotnet -ArgumentList \"run --project ..\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.csproj\"" + ] } ], "metadata": { diff --git a/HttpClientStudy.Core/Utilities/DotnetCommondUtility.cs b/HttpClientStudy.Core/Utilities/DotnetCommondUtility.cs new file mode 100644 index 0000000..3372b4c --- /dev/null +++ b/HttpClientStudy.Core/Utilities/DotnetCommondUtility.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HttpClientStudy.Core.Utilities +{ + /// + /// dotnet命令行工具类 + /// + public static class DotnetCommondUtility + { + /// + /// 执行dotnet命令 + /// + /// 命令 + /// 命令参数 + /// 是否等待退出 + /// 命令行输出文本 + public static string ExecuteCommand(string command, string arguments = "", bool waitForExit=false) + { + string output = ""; + + try + { + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "dotnet", + Arguments = $"{command} {arguments}", + RedirectStandardOutput = true, + StandardOutputEncoding = Encoding.UTF8, + RedirectStandardError = true, + StandardErrorEncoding = Encoding.UTF8, + RedirectStandardInput = true, + StandardInputEncoding = Encoding.UTF8, + UseShellExecute = false, + CreateNoWindow = false, + }; + + + Process process = new Process() + { + StartInfo = startInfo, + }; + + process.Start(); + + output = process.StandardOutput.ReadToEnd(); + + if (waitForExit) + { + process.WaitForExit(); + } + } + catch (Exception ex) + { + output = $"An error occurred: {ex.Message}"; + } + + return output; + } + } +} diff --git a/HttpClientStudy.Core/Utilities/StartupUtility.cs b/HttpClientStudy.Core/Utilities/StartupUtility.cs index c6ccee5..031d052 100644 --- a/HttpClientStudy.Core/Utilities/StartupUtility.cs +++ b/HttpClientStudy.Core/Utilities/StartupUtility.cs @@ -66,6 +66,59 @@ namespace HttpClientStudy.Core.Utilities } + public static void StartWebApiDll(string dllPath) + { + string projectAndMutexName = WebApiConfigManager.GetWebApiConfigOption().CurrentValue.WebAppMutexName; + + //webapi项目不在运行状态则启动webapi项目 + if (webAppIsRunningByMutex() == false) + { + //VS项目根目录 + string vsProjectPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory)!.Parent!.Parent!.Parent!.Parent!.FullName; + + Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); + + //webapi项目根项目 + string webApiProjectPath = Path.Combine(vsProjectPath, projectAndMutexName); + + //启动命令信息 + var prossInfo = new System.Diagnostics.ProcessStartInfo("dotnet", $"run --project {webApiProjectPath}") + { + UseShellExecute = true, + CreateNoWindow = false, + RedirectStandardOutput = false + }; + + //启动 + System.Diagnostics.Process.Start(prossInfo); + } + + //由进程名判断 + //bool webAppIsRunningByProcessName() + //{ + // return Process.GetProcessesByName(projectAndMutexName).ToList().Count == 0; + //} + + //由互斥锁判断 + bool webAppIsRunningByMutex() + { + bool createdResult = true; + + //创建互斥锁 + using (var mutex = new Mutex(true, projectAndMutexName, out createdResult)) + { + if (createdResult) + { + mutex.ReleaseMutex(); + } + } + + //互斥锁是否创建成功 + return !createdResult; + } + + } + /// /// 关闭webapi项目 /// diff --git a/HttpClientStudy.UnitTest/TempTest.cs b/HttpClientStudy.UnitTest/TempTest.cs index 75d743e..2aa8758 100644 --- a/HttpClientStudy.UnitTest/TempTest.cs +++ b/HttpClientStudy.UnitTest/TempTest.cs @@ -22,8 +22,8 @@ namespace HttpClientStudy.UnitTest [Fact] public async Task TestAsync() { - var ips = await Dns.GetHostAddressesAsync("www.hao123.com"); - string firstIp = ips.FirstOrDefault().ToString(); + var ips = await Dns.GetHostAddressesAsync("localhost"); + string firstIp = ips?.FirstOrDefault()?.ToString() ?? string.Empty; //自定义行为 var socketsHandler = new SocketsHttpHandler @@ -41,7 +41,7 @@ namespace HttpClientStudy.UnitTest { await Task.Delay(2000); } - await client.GetAsync("https://www.hao123.com"); + await client.GetAsync("http://localhost"); } var queryNetwork = CmdUtility.RunCmd($"netstat -ano | findstr {firstIp}"); diff --git a/HttpClientStudy.UnitTest/UtilitiesTest/DotnetCommondUtilityTest.cs b/HttpClientStudy.UnitTest/UtilitiesTest/DotnetCommondUtilityTest.cs new file mode 100644 index 0000000..f45b04a --- /dev/null +++ b/HttpClientStudy.UnitTest/UtilitiesTest/DotnetCommondUtilityTest.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using HttpClientStudy.Core.Utilities; + +namespace HttpClientStudy.UnitTest.UtilitiesTest +{ + public class DotnetCommondUtilityTest + { + private readonly ITestOutputHelper _output; + public DotnetCommondUtilityTest(ITestOutputHelper testOutput) + { + _output = testOutput; + } + + [Fact] + public void Version_Test() + { + var result = DotnetCommondUtility.ExecuteCommand("","--version"); + + _output.WriteLine(result); + } + + [Fact] + public void Info_Test() + { + var result = DotnetCommondUtility.ExecuteCommand("", "--info"); + + _output.WriteLine(result); + } + + [Fact] + public void Help_Test() + { + var result = DotnetCommondUtility.ExecuteCommand("", "--help"); + + _output.WriteLine(result); + } + + [Fact] + public void StartApp_Test() + { + var result = DotnetCommondUtility.ExecuteCommand("../../../../Docs/Publish/HttpClientStudy.WebApp/HttpClientStudy.WebApp.dll"); + + _output.WriteLine(result); + } + } +} diff --git a/HttpClientStudy.WebClient/Controllers/CallApiController.cs b/HttpClientStudy.WebClient/Controllers/CallApiController.cs index 209c95b..05fecd8 100644 --- a/HttpClientStudy.WebClient/Controllers/CallApiController.cs +++ b/HttpClientStudy.WebClient/Controllers/CallApiController.cs @@ -1,4 +1,6 @@ -using Microsoft.AspNetCore.Http; +using HttpClientStudy.Core.Utilities; + +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace HttpClientStudy.WebClient.Controllers diff --git a/HttpClientStudy.WebClient/Controllers/ManagerController.cs b/HttpClientStudy.WebClient/Controllers/ManagerController.cs new file mode 100644 index 0000000..fcd3236 --- /dev/null +++ b/HttpClientStudy.WebClient/Controllers/ManagerController.cs @@ -0,0 +1,45 @@ +using HttpClientStudy.Core.Utilities; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace HttpClientStudy.WebClient.Controllers +{ + /// + /// 管理API + /// + [Route("api/[controller]/[action]")] + [ApiController] + public class ManagerController : ControllerBase + { + private readonly ILogger _logger; + public ManagerController(ILogger logger) + { + _logger = logger; + } + + /// + /// 启动WebApi项目进程 + /// + /// + [HttpGet] + public IActionResult StartWebApi() + { + StartupUtility.StartWebApiProject(); + + return Ok("启动成功"); + } + + /// + /// 退出WebApi项目进程 + /// + /// + [HttpGet] + public IActionResult ExitWebApi() + { + StartupUtility.ExitWebApiProject(); + + return Ok("进程已退出"); + } + } +}