基础文档更新

main
wanggaofeng 11 months ago
parent b1676d4ce8
commit 09eaa0336c

2
.gitignore vendored

@ -436,6 +436,8 @@ FodyWeavers.xsd
!.vscode/extensions.json
!.vscode/*.code-snippets
Docs/.vscode/*
# Local History for Visual Studio Code
.history/

@ -22,7 +22,7 @@ dotnet build ..\HttpClientStudy.sln
#!pwsh
# 可以发布整个项目,但要发布到默认目录下
dotnet publish ..\HttpClientStudy.sln
# dotnet publish ..\HttpClientStudy.sln
# 分项目发布到Docs目录下
dotnet publish ..\HttpClientStudy.Config\HttpClientStudy.Config.csproj -c Release -o .\Publish\HttpClientStudy.Config
@ -63,3 +63,67 @@ else {
$WebAppProc.Kill();
Write-Host "$WebAppProcName 进程已退出"
}
#!markdown
## 查看应用各种路径
#!csharp
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
var pathDic = new Dictionary<string, (string desc, string? path)>()
{
//当前运行的exe的完整路径包含exe文件名只用于WinForm
{"Application.ExecutablePath",("程序集基完整路径(仅WinForm)", "Application.ExecutablePath 只适用于WinForm") },
//程序的启动路径只用于WinForm
{"Application.StartupPath",("程序集启动路径(仅WinForm)", "Application.StartupPath 只适用于WinForm") },
//当前执行的exe或启动项目的路径通过AppContext
{"AppContext.BaseDirectory",("执行或启动路径", AppContext.BaseDirectory) },
//当前执行的exe的目录不包含exe名使用AppDomain
{"AppDomain.CurrentDomain.BaseDirectory",("程序集解析程序用于探测程序集的基目录", AppDomain.CurrentDomain.BaseDirectory) },
//程序安装或启动基目录 包含应用程序的目录的名称
{"AppDomain.CurrentDomain.SetupInformation.ApplicationBase",("程序安装或启动基目录", AppDomain.CurrentDomain.SetupInformation.ApplicationBase) },
//当前进程的主模块路径包含exe名
{"Process.GetCurrentProcess().MainModule.FileName",("当前进程的主模块路径", Process.GetCurrentProcess()?.MainModule?.FileName) },
//环境变量:用户当前工作目录的完整限定路径
{"Environment.CurrentDirectory",("用户当前工作目录的完整限定路径", Environment.CurrentDirectory) },
//环境变量当前exe的完整路径包含exe名通过命令行参数
{"Environment.GetCommandLineArgs()[0]",("当前exe的完整路径", Environment.GetCommandLineArgs()[0]) },
//当前工作目录的路径(可变)
{"Directory.GetCurrentDirectory",("当前工作目录的路径(可变)", Directory.GetCurrentDirectory()) },
//当前Assembly的加载路径包含dll或exe名
{"Assembly.GetExecutingAssembly().Location",("当前Assembly的加载路径", Assembly.GetExecutingAssembly().Location) },
//入口程序集的路径
{"Assembly.GetEntryAssembly().Location",("入口程序集的路径", Assembly.GetEntryAssembly()?.Location) },
//已过时当前程序集的CodeBase路径可能为file URI格式
{"Assembly.GetExecutingAssembly().CodeBase",("当前程序集的CodeBase路径", Assembly.GetExecutingAssembly()?.CodeBase) },
//已过时入口程序集的CodeBase路径可能为file URI格式
{"Assembly.GetEntryAssembly().CodeBase",("入口程序集的CodeBase路径", Assembly.GetEntryAssembly()?.CodeBase) },
};
var message = string.Empty;
foreach (var item in pathDic)
{
message += $"{item.Key} => {item.Value.path}{Environment.NewLine}";
}
Console.WriteLine(message);

@ -24,6 +24,59 @@
"## 0、准备工作先执行下面单元以启动WebApi及设置全局对象、方法及其它"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"//全局设置\n",
"#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n",
"global using System.Net;\n",
"global using System.Net.Http;\n",
"global using System.Diagnostics;\n",
"global using System.Collections;\n",
"global using System.Text;\n",
"global using System.Linq;\n",
"global using System.IO;\n",
"\n",
"global using HttpClientStudy.Core;\n",
"\n",
"var global_queryDomain=\"soft.pwidc.cn\";\n",
"var global_queryPort=80;\n",
"var global_queryBaseUrl = $\"http://{global_queryDomain}:{global_queryPort}\";\n",
"\n",
"var global_ips =Dns.GetHostAddresses(global_queryDomani);\n",
"var global_queryIp = ips.First().ToString();\n",
"var global_netstat_filter = $\"{queryIp}:{global_queryPort}\";"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"统一使用示例"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"{ //大括号: 1、作用域隔离 2、方便整体代码折叠\n",
" Console.WriteLine(global_queryDomain);\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -33,7 +86,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "pwsh"
@ -48,7 +101,7 @@
"outputs": [],
"source": [
"#启动已发布的WebApi项目\n",
"Start-Process -FilePath \"dotnet.exe\" -ArgumentList \"Publish/HttpClientStudy.WebApi/HttpClientStudy.WebApi.dll\""
"Start-Process -FilePath dotnet -ArgumentList \".\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.dll\""
]
},
{
@ -253,40 +306,31 @@
},
"outputs": [],
"source": [
"using System.Net;\n",
"using System.Net.Http;\n",
"\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",
"{\n",
" Console.WriteLine(ipAddress.MapToIPv4().ToString());\n",
"}\n",
"\n",
"//自定义行为\n",
"var socketsHandler = new SocketsHttpHandler\n",
"//测试连接寿命\n",
"{\n",
" //连接池生命周期为10分钟连接在池中保持活动时间为10分钟\n",
" PooledConnectionLifetime = TimeSpan.FromMinutes(10),\n",
" //自定义行为\n",
" var socketsHandler = new SocketsHttpHandler\n",
" {\n",
" //连接池生命周期为10分钟连接在池中保持活动时间为10分钟\n",
" PooledConnectionLifetime = TimeSpan.FromMinutes(10),\n",
"\n",
" //池化链接的空闲超时时间为5分钟: 5分钟内连接不被重用则被释放后销毁\n",
" PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),\n",
" \n",
" //每端点的最大连接数设置为10个\n",
" MaxConnectionsPerServer = 10\n",
"};\n",
" //池化链接的空闲超时时间为5分钟: 5分钟内连接不被重用则被释放后销毁\n",
" PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),\n",
" \n",
" //每端点的最大连接数设置为10个\n",
" MaxConnectionsPerServer = 10\n",
" };\n",
"\n",
"var client = new HttpClient(socketsHandler);\n",
" var client = new HttpClient(socketsHandler);\n",
"\n",
"for (var i = 0; i < 5; i++)\n",
"{\n",
" _ = await client.GetAsync(\"https://soft.pwidc.cn\");\n",
" await Task.Delay(TimeSpan.FromSeconds(2));\n",
"}\n",
" for (var i = 0; i < 5; i++)\n",
" {\n",
" _ = await client.GetAsync(global_queryBaseUrl);\n",
" await Task.Delay(TimeSpan.FromSeconds(2));\n",
" }\n",
"\n",
"Console.WriteLine(\"程序运行大约要10-20秒请在程序退出后执行下面命令行查看网络情况\");\n"
" Console.WriteLine(\"程序运行大约要10-20秒请在程序退出后执行下面命令行查看网络情况\");\n",
"}"
]
},
{
@ -312,12 +356,13 @@
},
"outputs": [],
"source": [
"# 如果没有查询到相关网络状态信息PowerShell不针对出错但.Net Interactive 会异常Command failed: SubmitCode: #!set --value @csharp:xxxx\n",
"#!set --value @csharp:firstIp --name queryIp\n",
"# 若查询不到,则异常\n",
"#!set --value @csharp:global_netstat_filter --name queryFilter\n",
"\n",
"Write-Host \"请先执行上面的单元,再执行本单元\"\n",
"Write-Host \"网络状态\"\n",
"\n",
"netstat -ano | findstr $queryIp"
"netstat -ano | findstr $queryFilter"
]
},
{
@ -344,59 +389,56 @@
},
"outputs": [],
"source": [
"using System.IO;\n",
"using System.Diagnostics;\n",
"using System.Net;\n",
"using System.Net.Http;\n",
"\n",
"var ips = await Dns.GetHostAddressesAsync(\"soft.pwidc.cn\");\n",
"string firstIp = ips.FirstOrDefault().ToString();\n",
"\t\n",
"foreach (var ipAddress in ips)\n",
"{\n",
" Console.WriteLine(ipAddress.MapToIPv4().ToString());\n",
"}\n",
"{ //\n",
" var ips = await Dns.GetHostAddressesAsync(global_queryDomain);\n",
" string firstIp = ips.FirstOrDefault().ToString();\n",
" \n",
" foreach (var ipAddress in ips)\n",
" {\n",
" Console.WriteLine(ipAddress.MapToIPv4().ToString());\n",
" }\n",
"\n",
"//自定义行为\n",
"var socketsHandler2 = new SocketsHttpHandler\n",
"{\n",
" PooledConnectionLifetime = TimeSpan.FromSeconds(1),\n",
" PooledConnectionIdleTimeout = TimeSpan.FromSeconds(1),\n",
" MaxConnectionsPerServer = 1\n",
"};\n",
" //自定义行为\n",
" var socketsHandler2 = new SocketsHttpHandler\n",
" {\n",
" PooledConnectionLifetime = TimeSpan.FromSeconds(1),\n",
" PooledConnectionIdleTimeout = TimeSpan.FromSeconds(1),\n",
" MaxConnectionsPerServer = 1\n",
" };\n",
"\n",
"var client2 = new HttpClient(socketsHandler2);\n",
" var client2 = new HttpClient(socketsHandler2);\n",
"\n",
"for (var i = 0; i < 5; i++)\n",
"{\n",
" if(i>0)\n",
" for (var i = 0; i < 5; i++)\n",
" {\n",
" await Task.Delay(TimeSpan.FromSeconds(2));\n",
" if(i>0)\n",
" {\n",
" await Task.Delay(TimeSpan.FromSeconds(2));\n",
" }\n",
" _ = await client2.GetAsync(global_queryBaseUrl);\n",
" }\n",
" _ = await client2.GetAsync(\"http://soft.pwidc.cn\");\n",
"}\n",
"\n",
"Console.WriteLine(\"程序运行大约要10-20请在程序退出后执行下面命令行查看网络情况\");\n",
" Console.WriteLine(\"程序运行大约要10-20请在程序退出后执行下面命令行查看网络情况\");\n",
"\n",
"//调用命令行,显示查看网络情况\n",
"string command = $\"netstat -ano | findstr {firstIp}\";\n",
" \n",
"// 创建一个新的ProcessStartInfo对象\n",
"ProcessStartInfo startInfo = new ProcessStartInfo(\"cmd\", $\"/c {command}\")\n",
"{\n",
" RedirectStandardOutput = true, // 重定向标准输出\n",
" UseShellExecute = false, // 不使用系统外壳程序启动\n",
" CreateNoWindow = true // 不创建新窗口\n",
"};\n",
" \n",
"// 启动进程\n",
"using (Process process = Process.Start(startInfo))\n",
"{\n",
" // 读取cmd的输出\n",
" using (StreamReader reader = process.StandardOutput)\n",
" //调用命令行,显示查看网络情况\n",
" string command = $\"netstat -ano | findstr {firstIp}\";\n",
" \n",
" // 创建一个新的ProcessStartInfo对象\n",
" ProcessStartInfo startInfo = new ProcessStartInfo(\"cmd\", $\"/c {command}\")\n",
" {\n",
" RedirectStandardOutput = true, // 重定向标准输出\n",
" UseShellExecute = false, // 不使用系统外壳程序启动\n",
" CreateNoWindow = true // 不创建新窗口\n",
" };\n",
" \n",
" // 启动进程\n",
" using (Process process = Process.Start(startInfo))\n",
" {\n",
" string stdoutLine = reader.ReadToEnd();\n",
" Console.WriteLine(stdoutLine);\n",
" // 读取cmd的输出\n",
" using (StreamReader reader = process.StandardOutput)\n",
" {\n",
" string stdoutLine = reader.ReadToEnd();\n",
" Console.WriteLine(stdoutLine);\n",
" }\n",
" }\n",
"}"
]
@ -417,8 +459,8 @@
},
"outputs": [],
"source": [
"#!set --value @csharp:firstIp --name queryIp\n",
"netstat -ano | findstr $queryIp"
"#!set --value @csharp:global_netstat_filter --name queryFilter\n",
"netstat -ano | findstr $queryFilter"
]
},
{
@ -439,50 +481,114 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"\n",
"using System.Net;\n",
"var ips = await Dns.GetHostAddressesAsync(\"www.google.com\");\n",
"\t\n",
"foreach (var ipAddress in ips)\n",
"{\n",
"\t Console.WriteLine(ipAddress.MapToIPv4().ToString());\n",
"}\n",
"\n",
"var socketsHandler = new SocketsHttpHandler\n",
"/*\n",
"\t功能将MaxConnectionsPerServer限制为2。然后启动200个任务每个任务都向同一端点发出HTTP请求。这些任务将同时运行。所有请求竞争所花费的时间将写入控制台。\n",
"\t\t 随即调用用netstat命令查看连接则根据定义的限制我们可以看到两个已建立的连接。\n",
"*/\n",
"{\n",
"\tPooledConnectionLifetime = TimeSpan.FromSeconds(60),\n",
"\tPooledConnectionIdleTimeout = TimeSpan.FromMinutes(20),\n",
"\tMaxConnectionsPerServer = 2\n",
"};\n",
"\tConsole.WriteLine(\"开始请求网络...\");\n",
"\tvar socketsHandler = new SocketsHttpHandler\n",
"\t{\n",
"\t\tPooledConnectionLifetime = TimeSpan.FromSeconds(60),\n",
"\t\tPooledConnectionIdleTimeout = TimeSpan.FromMinutes(20),\n",
"\t\tMaxConnectionsPerServer = 2\n",
"\t};\n",
"\n",
"var client = new HttpClient(socketsHandler);\n",
"\tvar client = new HttpClient(socketsHandler);\n",
"\n",
"var sw = Stopwatch.StartNew();\n",
"\tvar sw = Stopwatch.StartNew();\n",
"\n",
"var tasks = Enumerable.Range(0, 200).Select(i => client.GetAsync(\"https://www.google.com\"));\n",
"\tvar tasks = Enumerable.Range(0, 200).Select(i => client.GetAsync(global_queryBaseUrl));\n",
"\n",
"await Task.WhenAll(tasks);\n",
"\tawait Task.WhenAll(tasks);\n",
"\n",
"sw.Stop();\n",
"\t\n",
"Console.WriteLine($\"{sw.ElapsedMilliseconds}ms taken for 200 requests\");\n",
"\t\n",
"//执行查看网络状态方法"
"\tsw.Stop();\n",
"\t\t\n",
"\tConsole.WriteLine($\"共请求了200次耗时 {sw.ElapsedMilliseconds} 毫秒\");\n",
"\t\t\n",
"\t//执行查看网络状态方法\n",
"\tConsole.WriteLine(\"当前网络状态\");\n",
"\tvar message = CmdUtility.RunCmd($\"netstat -ano | findstr {global_netstat_filter}\");\n",
"\tConsole.WriteLine(message);\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "pwsh"
},
"polyglot_notebook": {
"kernelName": "pwsh"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"# 重新查询当前网络状态\n",
"#!set --value @csharp:global_netstat_filter --name queryFilter\n",
"netstat -ano | findstr $queryFilter"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"该代码将MaxConnectionsPerServer限制为2。然后启动200个任务每个任务都向同一端点发出HTTP请求。这些任务将同时运行。所有请求竞争所花费的时间将写入控制台。\n",
"如果使用netstat查看连接则根据定义的限制我们可以看到两个已建立的连接。\n",
"已建立\n"
"如果我们调整此代码以允许MaxConnectionsPerServer = 10则可以重新运行该应用程序。耗时将减少大约4倍。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"{ //MaxConnectionsPerServer 设置为10网络连接将增加到10个耗时将减少到1/4\n",
"\tConsole.WriteLine(\"开始请求网络...\");\n",
"\tvar socketsHandler = new SocketsHttpHandler\n",
"\t{\n",
"\t\tPooledConnectionLifetime = TimeSpan.FromSeconds(60),\n",
"\t\tPooledConnectionIdleTimeout = TimeSpan.FromMinutes(20),\n",
"\t\tMaxConnectionsPerServer = 10\n",
"\t};\n",
"\n",
"\tvar client = new HttpClient(socketsHandler);\n",
"\n",
"\tvar sw = Stopwatch.StartNew();\n",
"\n",
"\tvar tasks = Enumerable.Range(0, 200).Select(i => client.GetAsync(global_queryBaseUrl));\n",
"\n",
"\tawait Task.WhenAll(tasks);\n",
"\n",
"\tsw.Stop();\n",
"\t\t\n",
"\tConsole.WriteLine($\"共请求了200次耗时 {sw.ElapsedMilliseconds} 毫秒\");\n",
"\t\t\n",
"\t//执行查看网络状态方法\n",
"\tConsole.WriteLine(\"当前网络状态\");\n",
"\tvar message = CmdUtility.RunCmd($\"netstat -ano | findstr {global_netstat_filter}\");\n",
"\tConsole.WriteLine(message);\n",
"}"
]
},
{

@ -80,7 +80,7 @@
"outputs": [],
"source": [
"#启动已发布的WebApi项目\n",
"Start-Process -FilePath \"Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe\""
"Start-Process -FilePath dotnet -ArgumentList \".\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.dll\""
]
},
{
@ -131,31 +131,6 @@
" Write-Host \"$WebAppProcName 进程已退出\"\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"source": [
"var basePath = System.Environment.CurrentDirectory;\n",
"\n",
"var filePath =\"./Docs/a.txt\";\n",
" \n",
"var full = System.IO.Path.GetFullPath(filePath,basePath);\n",
"\n",
"Console.WriteLine(full);"
]
}
],
"metadata": {

@ -23,7 +23,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
@ -35,22 +35,7 @@
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"应用程序的基准目录 [AppContext.BaseDirectory] C:\\Users\\asus\\.nuget\\packages\\microsoft.dotnet-interactive\\1.0.522904\\tools\\net8.0\\any\\\n",
"程序安装当前基目录 [AppDomain.CurrentDomain.BaseDirectory] C:\\Users\\asus\\.nuget\\packages\\microsoft.dotnet-interactive\\1.0.522904\\tools\\net8.0\\any\\\n",
"程序安装或启动基目录 [AppDomain.CurrentDomain.SetupInformation.ApplicationBase] C:\\Users\\asus\\.nuget\\packages\\microsoft.dotnet-interactive\\1.0.522904\\tools\\net8.0\\any\\\n",
"进程主模块的完整路径 [Process.GetCurrentProcess().MainModule.FileName] C:\\Program Files\\dotnet\\dotnet.exe\n",
"当前工作目录 [Environment.CurrentDirectory] e:\\王高峰\\我的项目\\学习项目\\HttpClientStudy\\Docs\n",
"文件当前目录 [Directory.GetCurrentDirectory()] e:\\王高峰\\我的项目\\学习项目\\HttpClientStudy\\Docs\n",
"可执行程序集目录 [Assembly.GetExecutingAssembly().Location] \n",
"指定程序集目录 [Type.Assembly.Location] C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\8.0.5\\System.Private.CoreLib.dll\n"
]
}
],
"outputs": [],
"source": [
"// C#中,内核执行时,各种默认路径如下:\n",
"\n",
@ -62,31 +47,55 @@
"using System.Reflection;\n",
"using Microsoft.Extensions.DependencyInjection;\n",
"\n",
"//应用程序信息\n",
" var pathDic = new Dictionary<string, (string desc, string? path)>() \n",
" {\n",
" //当前运行的exe的完整路径包含exe文件名只用于WinForm\n",
" {\"Application.ExecutablePath\",(\"程序集基完整路径(仅WinForm)\", \"Application.ExecutablePath 只适用于WinForm\") },\n",
"\n",
" //程序的启动路径只用于WinForm\n",
" {\"Application.StartupPath\",(\"程序集启动路径(仅WinForm)\", \"Application.StartupPath 只适用于WinForm\") },\n",
"\n",
" //当前执行的exe或启动项目的路径通过AppContext\n",
" {\"AppContext.BaseDirectory\",(\"执行或启动路径\",AppContext.BaseDirectory) }, \n",
"\n",
" //当前执行的exe的目录不包含exe名使用AppDomain\n",
" {\"AppDomain.CurrentDomain.BaseDirectory\",(\"程序集解析程序用于探测程序集的基目录\",AppDomain.CurrentDomain.BaseDirectory) }, \n",
"\n",
" //程序安装或启动基目录 包含应用程序的目录的名称\n",
" {\"AppDomain.CurrentDomain.SetupInformation.ApplicationBase\",(\"程序安装或启动基目录\",AppDomain.CurrentDomain.SetupInformation.ApplicationBase) }, \n",
"\n",
" //当前进程的主模块路径包含exe名\n",
" {\"Process.GetCurrentProcess().MainModule.FileName\",(\"当前进程的主模块路径\",Process.GetCurrentProcess()?.MainModule?.FileName) }, \n",
"\n",
"//程序的上下文基准目录:通常是应用程序启动时的目录,也可以理解为包含可执行文件的目录\n",
"Console.WriteLine($\"应用程序的基准目录 [AppContext.BaseDirectory] {AppContext.BaseDirectory}\");\n",
" //环境变量:用户当前工作目录的完整限定路径\n",
" {\"Environment.CurrentDirectory\",(\"用户当前工作目录的完整限定路径\",Environment.CurrentDirectory) }, \n",
"\n",
"//程序安装当前基目录 \n",
"Console.WriteLine($\"程序安装当前基目录 [AppDomain.CurrentDomain.BaseDirectory] {AppDomain.CurrentDomain.BaseDirectory}\");\n",
" //环境变量当前exe的完整路径包含exe名通过命令行参数\n",
" {\"Environment.GetCommandLineArgs()[0]\",(\"当前exe的完整路径\",Environment.GetCommandLineArgs()[0]) }, \n",
"\n",
"//程序安装或启动基目录\n",
"Console.WriteLine($\"程序安装或启动基目录 [AppDomain.CurrentDomain.SetupInformation.ApplicationBase] {AppDomain.CurrentDomain.SetupInformation.ApplicationBase}\");\n",
" //当前工作目录的路径(可变)\n",
" {\"Directory.GetCurrentDirectory\",(\"当前工作目录的路径(可变)\",Directory.GetCurrentDirectory()) },\n",
" \n",
" //当前Assembly的加载路径包含dll或exe名\n",
" {\"Assembly.GetExecutingAssembly().Location\",(\"当前Assembly的加载路径\",Assembly.GetExecutingAssembly().Location) },\n",
"\n",
"//进程主模块的完整路径\n",
"Console.WriteLine($\"进程主模块的完整路径 [Process.GetCurrentProcess().MainModule.FileName] {Process.GetCurrentProcess()?.MainModule?.FileName}\");\n",
" //入口程序集的路径\n",
" {\"Assembly.GetEntryAssembly().Location\",(\"入口程序集的路径\",Assembly.GetEntryAssembly()?.Location) },\n",
"\n",
"//环境变量:当前工作目录\n",
"Console.WriteLine($\"当前工作目录 [Environment.CurrentDirectory] {Environment.CurrentDirectory}\");\n",
" //已过时当前程序集的CodeBase路径可能为file URI格式\n",
" {\"Assembly.GetExecutingAssembly().CodeBase\",(\"当前程序集的CodeBase路径\",Assembly.GetExecutingAssembly()?.CodeBase) },\n",
"\n",
"//文件当前目录:当前工作目录:不一定是启动目录\n",
"Console.WriteLine($\"文件当前目录 [Directory.GetCurrentDirectory()] {Directory.GetCurrentDirectory()}\");\n",
" //已过时入口程序集的CodeBase路径可能为file URI格式\n",
" {\"Assembly.GetEntryAssembly().CodeBase\",(\"入口程序集的CodeBase路径\",Assembly.GetEntryAssembly()?.CodeBase) },\n",
" };\n",
"\n",
"//可执行程序集目录\n",
"Console.WriteLine($\"可执行程序集目录 [Assembly.GetExecutingAssembly().Location] {Assembly.GetExecutingAssembly().Location}\");\n",
" var message = string.Empty;\n",
" foreach (var item in pathDic)\n",
" {\n",
" message += $\"{item.Key} => {item.Value.path}{Environment.NewLine}\";\n",
" }\n",
"\n",
"//指定程序集目录:可以是引用类库、指定类所在类库目录 \n",
"Console.WriteLine($\"指定程序集目录 [Type.Assembly.Location] {typeof(System.Environment).Assembly.Location}\");\n"
" Console.WriteLine(message);"
]
}
],

@ -1,15 +1 @@
Start-Process -FilePath "pwsh" -ArgumentList "-h"
Pause
# 关闭项目进程
$WebAppProcName ="HttpClientStudy.WebApp";
$WebAppProc = Get-Process $WebAppProcName -ErrorAction Ignore
if($null -eq $WebAppProc)
{
Write-Host "进程没有找到,可能已经"
}
else {
$WebAppProc.Kill();
Write-Host "$WebAppProcName 进程已退出"
}
Start-Process -FilePath "dotnet.exe" -ArgumentList ".\Publish/HttpClientStudy.WebApi/HttpClientStudy.WebApi.dll"

@ -32,38 +32,16 @@ namespace HttpClientStudy.Config
/// </summary>
public static IConfigurationBuilder AddWebApiConfiguration(this IConfigurationBuilder configuration)
{
/*
//应用程序信息
//程序的上下文基准目录:通常是应用程序启动时的目录,也可以理解为包含可执行文件的目录
Console.WriteLine($"应用程序的基准目录[AppContext.BaseDirectory] = {AppContext.BaseDirectory}");
//程序安装或启动基目录
Console.WriteLine($"程序安装或启动基目录[AppDomain.CurrentDomain.SetupInformation.ApplicationBase]{AppDomain.CurrentDomain.SetupInformation.ApplicationBase}");
//进程主模块的完整路径
Console.WriteLine($"进程主模块的完整路径[Process.GetCurrentProcess().MainModule.FileName]:{Process.GetCurrentProcess()?.MainModule?.FileName}");
//环境变量:当前工作目录
Console.WriteLine($"当前工作目录[Environment.CurrentDirectory]:{Environment.CurrentDirectory}");
//文件当前目录:当前工作目录:不一定是启动目录
Console.WriteLine($"文件当前目录[Directory.GetCurrentDirectory()]{Directory.GetCurrentDirectory()}");
//可执行程序集目录
Console.WriteLine($"可执行程序集目录[Assembly.GetExecutingAssembly().Location]:{Assembly.GetExecutingAssembly().Location}");
//指定程序集目录:可以是引用类库、指定类所在类库目录
Console.WriteLine($"指定程序集目录[Type.Assembly.Location]{typeof(WebApiConfigExtensions).Assembly.Location}");
*/
//配置文件名称
configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
configuration.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
//配置文件根目录配置项目Dll文件所在目录(被其它项目引用时引用后dll的文件所在目录)
string configDellPath = Path.GetDirectoryName(typeof(WebApiConfig).Assembly.Location) ?? Directory.GetCurrentDirectory();
configuration.SetBasePath(configDellPath);
Console.WriteLine($"配置文件根目录:{configDellPath}");
configuration.AddJsonFile($"ConfigFiles/Config.json", optional: false, reloadOnChange: true);
configuration.AddJsonFile($"ConfigFiles/Config.{System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
configuration.AddJsonFile($"ConfigFiles/Config.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true);
return configuration;
}

@ -0,0 +1,68 @@
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
namespace HttpClientStudy.Core.Utilities
{
/// <summary>
/// 应用工具类
/// </summary>
public class AppUtility
{
/// <summary>
/// 获取应用运行时各种路径
/// </summary>
/// <returns></returns>
public static IDictionary<string,(string desc,string? path)> GetApplicationPaths()
{
var pathDic = new Dictionary<string, (string desc, string? path)>()
{
//当前运行的exe的完整路径包含exe文件名只用于WinForm
{"Application.ExecutablePath",("程序集基完整路径(仅WinForm)", "Application.ExecutablePath 只适用于WinForm") },
//程序的启动路径只用于WinForm
{"Application.StartupPath",("程序集启动路径(仅WinForm)", "Application.StartupPath 只适用于WinForm") },
//当前执行的exe或启动项目的路径通过AppContext
{"AppContext.BaseDirectory",("执行或启动路径",AppContext.BaseDirectory) },
//当前执行的exe的目录不包含exe名使用AppDomain
{"AppDomain.CurrentDomain.BaseDirectory",("程序集解析程序用于探测程序集的基目录",AppDomain.CurrentDomain.BaseDirectory) },
//程序安装或启动基目录 包含应用程序的目录的名称
{"AppDomain.CurrentDomain.SetupInformation.ApplicationBase",("程序安装或启动基目录",AppDomain.CurrentDomain.SetupInformation.ApplicationBase) },
//当前进程的主模块路径包含exe名
{"Process.GetCurrentProcess().MainModule.FileName",("当前进程的主模块路径",Process.GetCurrentProcess()?.MainModule?.FileName) },
//环境变量:用户当前工作目录的完整限定路径
{"Environment.CurrentDirectory",("用户当前工作目录的完整限定路径",Environment.CurrentDirectory) },
//环境变量当前exe的完整路径包含exe名通过命令行参数
{"Environment.GetCommandLineArgs()[0]",("当前exe的完整路径",Environment.GetCommandLineArgs()[0]) },
//当前工作目录的路径(可变)
{"Directory.GetCurrentDirectory",("当前工作目录的路径(可变)",Directory.GetCurrentDirectory()) },
//当前Assembly的加载路径包含dll或exe名
{"Assembly.GetExecutingAssembly().Location",("当前Assembly的加载路径",Assembly.GetExecutingAssembly().Location) },
//入口程序集的路径
{"Assembly.GetEntryAssembly().Location",("入口程序集的路径",Assembly.GetEntryAssembly()?.Location) },
//已过时当前程序集的CodeBase路径可能为file URI格式
{"Assembly.GetExecutingAssembly().CodeBase",("当前程序集的CodeBase路径",Assembly.GetExecutingAssembly()?.CodeBase) },
//已过时入口程序集的CodeBase路径可能为file URI格式
{"Assembly.GetEntryAssembly().CodeBase",("入口程序集的CodeBase路径",Assembly.GetEntryAssembly()?.CodeBase) },
};
return pathDic;
}
}
}

@ -0,0 +1,33 @@
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 AppUtilityTest
{
private readonly ITestOutputHelper _output;
public AppUtilityTest(ITestOutputHelper testOutput)
{
_output = testOutput;
}
[Fact]
public void Test()
{
var dic = AppUtility.GetApplicationPaths();
string message = string.Empty;
foreach (var path in dic)
{
message += ($"{path.Key} : {path.Value.path}{Environment.NewLine}");
}
_output.WriteLine(message);
}
}
}

@ -37,7 +37,17 @@ namespace HttpClientStudy.WebApp
var builder = WebApplication.CreateBuilder(args);
#region 加载配置文件
var configBasePath = AppContext.BaseDirectory;
Console.WriteLine($"WebApp配置文件根目录{configBasePath}");
builder.Configuration.SetBasePath(configBasePath);
builder.Configuration.AddJsonFile("appsettings.json", false, true);
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", true, true);
builder.Configuration.AddJsonFile($"configFiles/Config.json", false, true);
#endregion
#region 向容器注册服务
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

@ -14,6 +14,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
//appsettings
"applicationUrl": "http://localhost:5189",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"

Loading…
Cancel
Save