目标:
1、相同或不同exe在不同端口开启;
2、能被注册进服务,也能手动运行;(进服务是为了方便使用,手动运行是为了方便调试)
3、能写运行日志和错误日志;
编写过程:(此处只记录关键点,具体细节可以咨询ChatGPT)
1、不同端口开启同一个exe;
try
{
//生成进程
myProcessList = new List<Process>();
foreach (var arg in exePorts)
{
Process myProcess = new Process();
myProcess.StartInfo.FileName = arg.Value; // 替换为实际的程序路径
myProcess.StartInfo.Arguments = $" -p {arg.Key}"; // 替换为你要启动的端口号
Info_Log("Create Process. " + myProcess.StartInfo.FileName + " " + myProcess.StartInfo.Arguments);
myProcess.Start();
myProcessList.Add(myProcess);
}
}
catch (Exception ex)
{
Error_Log("Create Process Error." + ex.Message);
}
这里需要注意:
FileName是具体文件全路径:eg:c:\server.exe
Arguments的值中,在实际需要开启的端口之前需要有" -p " ;这个和我们用cmd开启某个程序是一样的;
eg: system32>server.exe -p 8080
2、注册服务:
通过批处理进行注册,命令如下:
sc create serverGuard binPath="c:\server.exe --server" start=auto
binPath里面增加了一个“--server”,这是为了在程序主函数来区分是通过服务进来的还是通过用户双击打开的,在代码中需要保持一致。
主函数代码如下:
static bool IsRunningAsService(string[] args)
{
// 检查命令行参数中是否包含特定的标识符
foreach (string arg in args)
{
if (arg.Equals("--server", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
static void Main(string[] args)
{
isService = IsRunningAsService(args);
if (isService)
{
try
{
//ServiceBase 类在 System.ServiceProcess 下
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new myServer()
};
ServiceBase.Run(ServicesToRun);
return;
}
catch (Exception ex)
{
Error_Log(ex.Message);
return;
}
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ServerGuardForm());
return;
}
}
3、日志
手动运行的界面日志和日常写日志一致;作为服务的日志因为没有主程序句柄会需要进一步考虑。
获取书写日志路径的代码如下:
//string path = System.Environment.CurrentDirectory + @"\log";//获取到的是主调程序所在目录,譬如,如果是服务则是在服务services.msc所在目录下(C:\windows\system32)
string path = AppDomain.CurrentDomain.BaseDirectory + @"\log";
//string path = Application.StartupPath + @"\log"; //Application是桌面程序句柄,服务程序没有这个句柄
这三个路径都是用于获取当前应用程序的基本目录或工作目录,但它们之间有一些异同之处。
-
AppDomain.CurrentDomain.BaseDirectory:
- 获取当前应用程序域的基本目录。
- 返回一个字符串,表示应用程序域的基本目录,通常是包含可执行文件的目录。
- 对于单个应用程序域来说,该路径在应用程序生命周期内是不变的。
- 这个路径在多应用程序域或多个入口点的应用程序中可能会有所区别。
-
System.Environment.CurrentDirectory:
- 获取或设置当前工作目录。
- 返回一个字符串,表示当前线程的工作目录。
- 工作目录是应用程序开始执行时操作系统指定的目录,通常为可执行文件所在的目录。
- 如果需要改变当前工作目录,可以使用
System.Environment.CurrentDirectory
进行设置。
-
Application.StartupPath:
- 获取启动应用程序的可执行文件的路径。
- 返回一个字符串,表示启动应用程序的可执行文件所在的目录。
- 通常用于 Windows 窗体应用程序,特别是在 WinForms 应用程序中使用较为广泛。
- 值得注意的是,这个属性在 ASP.NET 网站项目中不可用。
综上所述,这三个路径的主要区别在于作用范围和适用场景。AppDomain.CurrentDomain.BaseDirectory
表示应用程序域的基本目录,对于单个应用程序域来说是不变的;System.Environment.CurrentDirectory
表示当前线程的工作目录,可以通过设置来改变;而 Application.StartupPath
主要用于获取启动应用程序的可执行文件路径,在 WinForms 应用程序中使用较为广泛。