diff --git a/ExecuteCommandStudy.CApp/ExecuteCommandStudy.CApp.csproj b/ExecuteCommandStudy.CApp/ExecuteCommandStudy.CApp.csproj new file mode 100644 index 0000000..fca895a --- /dev/null +++ b/ExecuteCommandStudy.CApp/ExecuteCommandStudy.CApp.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/ExecuteCommandStudy.CApp/Program.cs b/ExecuteCommandStudy.CApp/Program.cs new file mode 100644 index 0000000..d126668 --- /dev/null +++ b/ExecuteCommandStudy.CApp/Program.cs @@ -0,0 +1,10 @@ +namespace ExecuteCommandStudy.CApp +{ + internal class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello, World!"); + } + } +} diff --git a/ExecuteCommandStudy.Core/AppUtility.cs b/ExecuteCommandStudy.Core/AppUtility.cs new file mode 100644 index 0000000..c1bf68a --- /dev/null +++ b/ExecuteCommandStudy.Core/AppUtility.cs @@ -0,0 +1,62 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; + + +namespace ExecuteCommandStudy.Core +{ + /// + /// 应用工具类 + /// + public class AppUtility + { + /// + /// 获取应用运行时各种路径 + /// + /// + public static IDictionary GetApplicationPaths() + { + var pathDic = new Dictionary() + { + //当前运行的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) }, + }; + + return pathDic; + } + } +} diff --git a/ExecuteCommandStudy.Core/DotnetCommondUtility.cs b/ExecuteCommandStudy.Core/DotnetCommondUtility.cs new file mode 100644 index 0000000..4da692c --- /dev/null +++ b/ExecuteCommandStudy.Core/DotnetCommondUtility.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ExecuteCommandStudy.Core +{ + /// + /// dotnet命令行工具类 + /// + public static class DotnetCommondUtility + { + /// + /// 执行dotnet命令 + /// + /// 命令 + /// 命令参数 + /// 新窗口执行命令 + /// 命令行输出文本 + public static string ExecuteCommand(string command, string argument = "", bool newWindow = false) + { + string output = ""; + + try + { + if (newWindow) + { + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "pwsh.exe", + Arguments = $" Start-Process -FilePath 'dotnet' -ArgumentList '{command}','{argument}'", + //RedirectStandardOutput = true, + //StandardOutputEncoding = Encoding.UTF8, + //RedirectStandardError = true, + //StandardErrorEncoding = Encoding.UTF8, + //RedirectStandardInput = false, + //StandardInputEncoding = Encoding.UTF8, + UseShellExecute = true, + CreateNoWindow = false, + }; + + + Process process = new Process() + { + StartInfo = startInfo, + }; + + process.Start(); + + output = "命令已在新窗口执行!"; + } + else + { + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "dotnet", + Arguments = $"{command} {argument}", + RedirectStandardOutput = true, + StandardOutputEncoding = Encoding.UTF8, + RedirectStandardError = true, + StandardErrorEncoding = Encoding.UTF8, + //RedirectStandardInput = false, + //StandardInputEncoding = Encoding.UTF8, + + //启用内核模式时,不能重定向输出 + UseShellExecute = false, + + //不创建新窗口 + CreateNoWindow = false, + }; + + Process process = new Process() + { + StartInfo = startInfo, + }; + + //处理输出 + process.OutputDataReceived += (sender, args) => + { + if (!string.IsNullOrEmpty(args.Data)) + { + output += args.Data; + } + }; + + process.Start(); + + //开始异步读取输出 + process.BeginOutputReadLine(); + + //等待里程结束 + process.WaitForExit(); + } + } + catch (Exception ex) + { + output = $"An error occurred: {ex.Message}"; + } + + return output; + } + + /// + /// 新窗口启动WebApp项目 + /// + /// 包含全路径的WebApp项目 + /// 命令参数 + /// + public static string RunWebApp(string startFile, params string[] args) + { + string output = ""; + + try + { + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "powershell.exe", + Arguments = $"Start-Process -FilePath '{startFile}' -ArgumentList '{string.Join(" ", args)}' ", + UseShellExecute = true, + CreateNoWindow = false, + }; + + + Process process = new Process() + { + StartInfo = startInfo, + }; + + process.Start(); + + output = "已在新窗口中启动WebApp项目。如果已有实例在运行或者执行异常,则窗口会自动关闭;否则新窗口一直存在,直到手动关闭!"; + + } + catch (Exception ex) + { + output = $"An error occurred: {ex.Message}"; + } + + return output; + } + + /// + /// 停止WebAPI项目 + /// + /// 包含全路径的可执行文件 + /// + public static string SopWebApp() + { + string output = ""; + + try + { + string projectAndMutexName = "xxxxxxx"; + + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "powershell.exe", + Arguments = $"Stop-Process -Name '{projectAndMutexName}'", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + StandardOutputEncoding = Encoding.UTF8, + }; + + + Process process = new Process() + { + StartInfo = startInfo, + }; + + process.Start(); + + process.WaitForExit(); + + output = process.StandardOutput.ReadToEnd(); + + } + catch (Exception ex) + { + output = $"An error occurred: {ex.Message}"; + } + + return output; + } + } +} diff --git a/ExecuteCommandStudy.Core/ExecuteCommandStudy.Core.csproj b/ExecuteCommandStudy.Core/ExecuteCommandStudy.Core.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/ExecuteCommandStudy.Core/ExecuteCommandStudy.Core.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/ExecuteCommandStudy.Core/GlobalUsing.cs b/ExecuteCommandStudy.Core/GlobalUsing.cs new file mode 100644 index 0000000..4863fb3 --- /dev/null +++ b/ExecuteCommandStudy.Core/GlobalUsing.cs @@ -0,0 +1,4 @@ +global using System; + +global using System.Text; +global using System.Diagnostics; \ No newline at end of file diff --git a/ExecuteCommandStudy.Core/StartupUtility.cs b/ExecuteCommandStudy.Core/StartupUtility.cs new file mode 100644 index 0000000..2de8295 --- /dev/null +++ b/ExecuteCommandStudy.Core/StartupUtility.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ExecuteCommandStudy.Core +{ + /// + /// 启动工具类 + /// + public static class StartupUtility + { + /// + /// 启动webapi项目 + /// (出现webapi项目启动命令行窗口) + /// + public static void StartWebApiProject() + { + string projectAndMutexName = "xxx"; + + //webapi项目不在运行状态则启动webapi项目 + if (webAppIsRunningByMutex() == false) + { + //VS项目根目录 + string vsProjectPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory)!.Parent!.Parent!.Parent!.Parent!.FullName; + + //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项目 + /// + public static void ExitWebApiProject() + { + string projectAndMutexName = WebApiConfigManager.GetWebApiConfigOption().CurrentValue.WebAppMutexName; + + //webapi为运行状态则关闭 + if (webAppIsRunningByMutex()) + { + var webApiProcess = System.Diagnostics.Process.GetProcessesByName(projectAndMutexName); + + if (webApiProcess != null && webApiProcess.Length>0) + { + webApiProcess[0].Kill(); + } + } + + //由进程名判断 + //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; + } + } + } +} diff --git a/ExecuteCommandStudy.Core/Utils1.cs b/ExecuteCommandStudy.Core/Utils1.cs new file mode 100644 index 0000000..1282fc0 --- /dev/null +++ b/ExecuteCommandStudy.Core/Utils1.cs @@ -0,0 +1,186 @@ +namespace ExecuteCommandStudy.Core +{ + public static class Utils1 + { + static void A() + { + ProcessStartInfo startInfo = new ProcessStartInfo(); + startInfo.FileName = "cmd.exe"; + startInfo.Arguments = "/u /k dotnet exec c:\\Users\\ruyu\\Desktop\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.dll"; + startInfo.UseShellExecute = false; + startInfo.CreateNoWindow = false; + + Process.Start(startInfo); + } + + /// + /// 启动WebApi程序 + /// + /// 带相对或绝对路径的可执行文件 + /// 应用程序参数 + static string B(string exePathAndName, params string[] args) + { + string executedMessage = string.Empty; + try + { + if (!Path.IsPathRooted(exePathAndName)) + { + exePathAndName = Path.GetFullPath(exePathAndName, Environment.CurrentDirectory); + } + + if (!File.Exists(exePathAndName)) + { + executedMessage = $"可执行文件[{exePathAndName}]不存在"; + return executedMessage; + } + + ProcessStartInfo startInfo = new ProcessStartInfo(); + startInfo.FileName = exePathAndName; + startInfo.Arguments = string.Join(" ", args); + + //未知原因:只有 UseShellExecute 设置为 true 时,CreateNoWindow参数才有效,新窗口执行才实际有效。 + startInfo.UseShellExecute = true; + + //true时不创建新窗口,false才是创建新窗口 + startInfo.CreateNoWindow = false; + + //启动进程 + using (Process process = new Process() { StartInfo = startInfo }) + { + process.Start(); + } + + executedMessage = $"程序[{exePathAndName}]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!"; + } + catch (Exception ex) + { + executedMessage = $"启动程序[{exePathAndName}]出现异常:[{ex.Message}]"; + } + finally + { + + } + + return executedMessage; + } + + static void PowerShell() + { + // 创建新的进程开始信息 + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "powershell.exe", + Arguments = $"Start-Process powershell -ArgumentList '-noexit','-command','dotnet c:\\Users\\ruyu\\Desktop\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.dll'", + + UseShellExecute = false, + RedirectStandardOutput = false, + CreateNoWindow = false // 设置为false以在新窗口中打开 + }; + + try + { + // 使用启动信息创建并启动进程 + using (Process process = new Process() { StartInfo = startInfo }) + { + process.Start(); + } + } + catch (Exception e) + { + Console.WriteLine("An error occurred: " + e.Message); + } + } + + static void RunExe() + { + // PowerShell(); + + var webapiExe = "c:\\Users\\ruyu\\Desktop\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe"; + + // 创建新的进程开始信息 + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = "powershell.exe", + Arguments = $"Start-Process {webapiExe} -ArgumentList '-noexit'", + + UseShellExecute = false, + RedirectStandardOutput = false, + CreateNoWindow = false // 设置为false以在新窗口中打开 + }; + + try + { + // 使用启动信息创建并启动进程 + using (Process process = new Process() { StartInfo = startInfo }) + { + process.Start(); + } + } + catch (Exception e) + { + Console.WriteLine("An error occurred: " + e.Message); + } + } + + /// + /// 运行WebApi发布程序 + /// + /// + public static string RunWebApiExeFile(string exeFile, bool stayWindows = false, params string[] args) + { + string executedMessage = string.Empty; + try + { + if (!Path.IsPathRooted(exeFile)) + { + exeFile = Path.GetFullPath(exeFile, Environment.CurrentDirectory); + } + + if (!File.Exists(exeFile)) + { + executedMessage = $"可执行文件[{exeFile}]不存在"; + return executedMessage; + } + + string fileName = Path.GetFileNameWithoutExtension(exeFile); + + string stayWindowsArg = stayWindows ? "/k" : "/c"; + + string systemShell = "cmd.exe"; + + string webApiArgs = $"{stayWindowsArg} start \"{fileName}\" {exeFile} {string.Join(" ", args)}"; + + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = systemShell, + Arguments = webApiArgs, + + //未知原因:只有 UseShellExecute 设置为 true 时,CreateNoWindow参数才有效,新窗口执行才实际有效。 + UseShellExecute = true, + + //true时不创建新窗口,false才是创建新窗口 + CreateNoWindow = false, + }; + + + //启动进程 + using (Process process = new Process() { StartInfo = startInfo }) + { + process.Start(); + } + + executedMessage = $"程序[{exeFile}]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!"; + } + catch (Exception ex) + { + executedMessage = $"启动程序[{exeFile}]出现异常:[{ex.Message}]"; + } + finally + { + + } + + return executedMessage; + } + } +} diff --git a/ExecuteCommandStudy.Test/ExecuteCommandStudy.Test.csproj b/ExecuteCommandStudy.Test/ExecuteCommandStudy.Test.csproj new file mode 100644 index 0000000..3181b74 --- /dev/null +++ b/ExecuteCommandStudy.Test/ExecuteCommandStudy.Test.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + diff --git a/ExecuteCommandStudy.Test/UnitTest1.cs b/ExecuteCommandStudy.Test/UnitTest1.cs new file mode 100644 index 0000000..5abdffa --- /dev/null +++ b/ExecuteCommandStudy.Test/UnitTest1.cs @@ -0,0 +1,11 @@ +namespace ExecuteCommandStudy.Test +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} \ No newline at end of file diff --git a/ExecuteCommandStudy.sln b/ExecuteCommandStudy.sln new file mode 100644 index 0000000..d5e671e --- /dev/null +++ b/ExecuteCommandStudy.sln @@ -0,0 +1,36 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35013.160 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecuteCommandStudy.CApp", "ExecuteCommandStudy.CApp\ExecuteCommandStudy.CApp.csproj", "{05C727B6-7A38-476D-8D6C-62A26B7BEF3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecuteCommandStudy.Test", "ExecuteCommandStudy.Test\ExecuteCommandStudy.Test.csproj", "{DD1D2861-2D56-4279-81DA-447ADF1A3343}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecuteCommandStudy.Core", "ExecuteCommandStudy.Core\ExecuteCommandStudy.Core.csproj", "{F2AF0EC2-D892-4079-8306-D974A1757F34}" +EndProject +Global + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EC5B6915-A92D-4B38-B717-94AEBE296A64} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {05C727B6-7A38-476D-8D6C-62A26B7BEF3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05C727B6-7A38-476D-8D6C-62A26B7BEF3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05C727B6-7A38-476D-8D6C-62A26B7BEF3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05C727B6-7A38-476D-8D6C-62A26B7BEF3D}.Release|Any CPU.Build.0 = Release|Any CPU + {DD1D2861-2D56-4279-81DA-447ADF1A3343}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD1D2861-2D56-4279-81DA-447ADF1A3343}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD1D2861-2D56-4279-81DA-447ADF1A3343}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD1D2861-2D56-4279-81DA-447ADF1A3343}.Release|Any CPU.Build.0 = Release|Any CPU + {F2AF0EC2-D892-4079-8306-D974A1757F34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2AF0EC2-D892-4079-8306-D974A1757F34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2AF0EC2-D892-4079-8306-D974A1757F34}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2AF0EC2-D892-4079-8306-D974A1757F34}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal