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("进程已退出");
+ }
+ }
+}