最近写了两个程序,都可以以服务进程和窗口进程两种方式运行,由于两类程序都需要入口程序,所以很简单,只要在入口方法代码中判断进入相应分支即可,下面总结一下开发心得。
第一个程序,窗口进程和服务进程的功能一样,都查询一些数据并发送Email。窗口程序需要从快捷方式加一个参M来运行(按第二个程序的方式可以不用参数判断)。代码如下:
1 class Program
2 {
3 /// <summary>
4 /// 应用程序的主入口点。
5 /// </summary>
6 [STAThread]
7 static void Main(string[] args)
8 {
9
10 // 同一进程中可以运行多个用户服务。若要将
11 // 另一个服务添加到此进程中,请更改下行以
12 // 创建另一个服务对象。例如,
13 //
14 // ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
15 //
16 if (args.Length > 0 && (args[0].ToUpper() == "/M" || args[0].ToUpper() == "-M"))
17 {
18 Application.EnableVisualStyles();
19 Application.SetCompatibleTextRenderingDefault(false);
20 Application.Run(new MainForm());
21 }
22 else
23 {
24 ServiceBase[] ServicesToRun;
25 ServicesToRun = new ServiceBase[] { new Service1() };
26 ServiceBase.Run(ServicesToRun);
27 }
28 }
29
30
采用定时器时注意,窗口程序用System.Windows.Forms.Timer,而服务程序要用System.Threading.Timer。2 {
3 /// <summary>
4 /// 应用程序的主入口点。
5 /// </summary>
6 [STAThread]
7 static void Main(string[] args)
8 {
9
10 // 同一进程中可以运行多个用户服务。若要将
11 // 另一个服务添加到此进程中,请更改下行以
12 // 创建另一个服务对象。例如,
13 //
14 // ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
15 //
16 if (args.Length > 0 && (args[0].ToUpper() == "/M" || args[0].ToUpper() == "-M"))
17 {
18 Application.EnableVisualStyles();
19 Application.SetCompatibleTextRenderingDefault(false);
20 Application.Run(new MainForm());
21 }
22 else
23 {
24 ServiceBase[] ServicesToRun;
25 ServicesToRun = new ServiceBase[] { new Service1() };
26 ServiceBase.Run(ServicesToRun);
27 }
28 }
29
30
第二个程序,窗口进程用于设置参数,保存于App.config,服务进程用于定时运行。代码如下:
1 static class Program
2 {
3 /// <summary>
4 /// 应用程序的主入口点。
5 /// </summary>
6 static void Main(string[] args)
7 {
8 bool b = false;
9 System.ServiceProcess.ServiceController[] services;
10 services = System.ServiceProcess.ServiceController.GetServices();
11 for (int i = 0; i < services.Length; i++)
12 {
13 if (services[i].Status == System.ServiceProcess.ServiceControllerStatus.StartPending &&
14 services[i].ServiceName == "Service2")
15 {
16 b = true;
17 break;
18 }
19 }
20 if (b)
21 {
22 ServiceBase[] ServicesToRun;
23 ServicesToRun = new ServiceBase[] { new Service2() };
24 ServiceBase.Run(ServicesToRun);
25 }
26 else
27 {
28 Application.EnableVisualStyles();
29 Application.SetCompatibleTextRenderingDefault(false);
30 Application.Run(new Main());
31 }
32 }
33 }
34
2 {
3 /// <summary>
4 /// 应用程序的主入口点。
5 /// </summary>
6 static void Main(string[] args)
7 {
8 bool b = false;
9 System.ServiceProcess.ServiceController[] services;
10 services = System.ServiceProcess.ServiceController.GetServices();
11 for (int i = 0; i < services.Length; i++)
12 {
13 if (services[i].Status == System.ServiceProcess.ServiceControllerStatus.StartPending &&
14 services[i].ServiceName == "Service2")
15 {
16 b = true;
17 break;
18 }
19 }
20 if (b)
21 {
22 ServiceBase[] ServicesToRun;
23 ServicesToRun = new ServiceBase[] { new Service2() };
24 ServiceBase.Run(ServicesToRun);
25 }
26 else
27 {
28 Application.EnableVisualStyles();
29 Application.SetCompatibleTextRenderingDefault(false);
30 Application.Run(new Main());
31 }
32 }
33 }
34
将后台服务进程和窗口设置进程集成为一个程序,这种方案可以在程序中采用同一商业逻辑层代码,可以读取同一App.config设置,还可以在窗口进程中控制服务进程的启动和停止。采用入口方法进行分支,然后运行各自的代码,代码很简单,也很实用。
但还有以下两个问题,待高手指点。
1. App.config设置只在进程启动时读取一遍,更改的设置只有重启进程后才生效。
2. 服务需要用InstallUtil.exe来安装和卸载,如果能在窗口进程中安装和卸载就好了。