C#实现一个用于开机启动其他程序的Windows服务

时间:2022-10-22 15:40:03
今天决定写写博客,不为别的,只当自己的积累,如果与此同时能不误导他人甚至给了朋友们一些启发,那真是更好了!

程序的目的和用途:

很多开机启动程序仅仅加在启动项里面,只有登陆后才真正启动。windows服务在开机未进行用户登录前就启动了。正是利用这一点,解决一些服务器自动重启后特定软件也自动启动的问题。

1.新建一个服务项目 visual C#----windows----windows服务;

2.添加一个dataset(.xsd),用于存储启动目标的路径,日志路径等。

   在dataset可视化编辑中,添加一个datatable,包含两列 StartAppPath 和 LogFilePath。分别用于存储目标的路径、日志路径。

   *我认为利用dataset.xsd存储配置参数的优势在于可以忽略xml解析的具体过程直接使用xml文件。

     在dataset中 提供了ReadXml方法用于读取xml文件并将其转换成内存中的一张datatable表,数据很容易取出来!同样,WriteXml方法用于存储为xml格式的文件,也仅仅需要一句话而已。

3. program.cs文件 作为程序入口,代码如下:

view plaincopy to clipboardprint?
using System.Collections.Generic;  
using System.ServiceProcess;  
using System.Text;  
  
namespace WindowsServices_AutoStart  
{  
    static class Program  
    {  
        /// <summary>  
        /// 应用程序的主入口点。  
        /// </summary>  
        static void Main()  
        {  
            ServiceBase[] ServicesToRun;  
  
            // 同一进程中可以运行多个用户服务。若要将  
            // 另一个服务添加到此进程中,请更改下行以  
            // 创建另一个服务对象。例如,  
            //  
            //   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};  
            //  
            ServicesToRun = new ServiceBase[] { new WindowsServices_AutoStart() };  
  
            ServiceBase.Run(ServicesToRun);  
        }  
    }  
}  
using System.Collections.Generic;
using System.ServiceProcess;
using System.Text;

namespace WindowsServices_AutoStart
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;

            // 同一进程中可以运行多个用户服务。若要将
            // 另一个服务添加到此进程中,请更改下行以
            // 创建另一个服务对象。例如,
            //
            //   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
            //
            ServicesToRun = new ServiceBase[] { new WindowsServices_AutoStart() };

            ServiceBase.Run(ServicesToRun);
        }
    }
}

4.service.cs主文件,代码如下:

view plaincopy to clipboardprint?
using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.IO;  
using System.Diagnostics;  
using System.ServiceProcess;  
using System.Text;  
  
namespace WindowsServices_AutoStart  
{  
    public partial class WindowsServices_AutoStart : ServiceBase  
    {  
        public WindowsServices_AutoStart()  
        {  
            InitializeComponent();  
        }  
        string StartAppPath =""; //@"F:\00.exe";  
        string LogFilePath ="";// @"f:\WindowsService.txt";  
        protected override void OnStart(string[] args)  
        {  
            string exePath = System.Threading.Thread.GetDomain().BaseDirectory;  
            //  
            if (!File.Exists(exePath + @"\ServiceAppPath.xml"))  
            {  
                dsAppPath ds = new dsAppPath();  
                object[] obj=new object[2];  
                obj[0]="0";  
                obj[1]="0";  
                ds.Tables["dtAppPath"].Rows.Add(obj);  
                ds.Tables["dtAppPath"].WriteXml(exePath + @"\ServiceAppPath.xml");  
                return;  
            }  
            try  
            {  
                dsAppPath ds = new dsAppPath();  
                ds.Tables["dtAppPath"].ReadXml(exePath + @"\ServiceAppPath.xml");  
                DataTable dt = ds.Tables["dtAppPath"];  
                StartAppPath = dt.Rows[0]["StartAppPath"].ToString();  
                LogFilePath = dt.Rows[0]["LogFilePath"].ToString();  
            }  
            catch { return; }  
              
            if (File.Exists(StartAppPath))  
            {  
                try  
                {  
                    Process proc = new Process();  
                    proc.StartInfo.FileName = StartAppPath; //注意路径  
                    //proc.StartInfo.Arguments = "";  
                    proc.Start();  
                }  
                catch (System.Exception ex)  
                {  
                    //MessageBox.Show(this, "找不到帮助文件路径。文件是否被改动或删除?\n" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);  
                }  
                FileStream fs = new FileStream(LogFilePath, FileMode.OpenOrCreate, FileAccess.Write);  
                StreamWriter m_streamWriter = new StreamWriter(fs);  
                m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);  
                m_streamWriter.WriteLine("WindowsService: Service Started" + DateTime.Now.ToString() + "\n");  
                m_streamWriter.Flush();  
                m_streamWriter.Close();  
                fs.Close();  
            }  
        }  
  
        protected override void OnStop()  
        {  
            try  
            {  
                // TODO: 在此处添加代码以执行停止服务所需的关闭操作。  
                FileStream fs = new FileStream(LogFilePath, FileMode.OpenOrCreate, FileAccess.Write);  
                StreamWriter m_streamWriter = new StreamWriter(fs);  
                m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);  
                m_streamWriter.WriteLine("WindowsService: Service Stopped " + DateTime.Now.ToString() + "\n");  
                m_streamWriter.Flush();  
                m_streamWriter.Close();  
                fs.Close();  
            }  
            catch  
            {  
  
            }  
        }  
    }  
}  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;

namespace WindowsServices_AutoStart
{
    public partial class WindowsServices_AutoStart : ServiceBase
    {
        public WindowsServices_AutoStart()
        {
            InitializeComponent();
        }
        string StartAppPath =""; //@"F:\00.exe";
        string LogFilePath ="";// @"f:\WindowsService.txt";
        protected override void OnStart(string[] args)
        {
            string exePath = System.Threading.Thread.GetDomain().BaseDirectory;
            //
            if (!File.Exists(exePath + @"\ServiceAppPath.xml"))
            {
                dsAppPath ds = new dsAppPath();
                object[] obj=new object[2];
                obj[0]="0";
                obj[1]="0";
                ds.Tables["dtAppPath"].Rows.Add(obj);
                ds.Tables["dtAppPath"].WriteXml(exePath + @"\ServiceAppPath.xml");
                return;
            }
            try
            {
                dsAppPath ds = new dsAppPath();
                ds.Tables["dtAppPath"].ReadXml(exePath + @"\ServiceAppPath.xml");
                DataTable dt = ds.Tables["dtAppPath"];
                StartAppPath = dt.Rows[0]["StartAppPath"].ToString();
                LogFilePath = dt.Rows[0]["LogFilePath"].ToString();
            }
            catch { return; }
            
            if (File.Exists(StartAppPath))
            {
                try
                {
                    Process proc = new Process();
                    proc.StartInfo.FileName = StartAppPath; //注意路径
                    //proc.StartInfo.Arguments = "";
                    proc.Start();
                }
                catch (System.Exception ex)
                {
                    //MessageBox.Show(this, "找不到帮助文件路径。文件是否被改动或删除?\n" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                FileStream fs = new FileStream(LogFilePath, FileMode.OpenOrCreate, FileAccess.Write);
                StreamWriter m_streamWriter = new StreamWriter(fs);
                m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
                m_streamWriter.WriteLine("WindowsService: Service Started" + DateTime.Now.ToString() + "\n");
                m_streamWriter.Flush();
                m_streamWriter.Close();
                fs.Close();
            }
        }

        protected override void OnStop()
        {
            try
            {
                // TODO: 在此处添加代码以执行停止服务所需的关闭操作。
                FileStream fs = new FileStream(LogFilePath, FileMode.OpenOrCreate, FileAccess.Write);
                StreamWriter m_streamWriter = new StreamWriter(fs);
                m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
                m_streamWriter.WriteLine("WindowsService: Service Stopped " + DateTime.Now.ToString() + "\n");
                m_streamWriter.Flush();
                m_streamWriter.Close();
                fs.Close();
            }
            catch
            {

            }
        }
    }
}


5.启动调试,成功时也会弹出一个对话框大致意思是提示服务需要安装。

6.把Debug文件夹下面的.exe执行程序,安装为windows系统服务,安装方法网上很多介绍。我说一种常用的:

安装服务
访问项目中的已编译可执行文件所在的目录。  
用项目的输出作为参数,从命令行运行 InstallUtil.exe。在命令行中输入下列代码:  
installutil yourproject.exe
卸载服务  
用项目的输出作为参数,从命令行运行 InstallUtil.exe。  
installutil /u yourproject.exe

至此,整个服务已经编写,编译,安装完成,你可以在控制面板的管理工具的服务中,看到你编写的服务。

7.安装好了之后在系统服务列表中可以管理服务,这时要注意将服务的属性窗口----登陆----“允许于桌面交互”勾选!这样才能在启动了你要的目标程序后不单单存留于进程。在桌面上也看得到。

8.关于卸载服务,目前有两个概念:一是禁用而已;一是完全删除服务。 前者可以通过服务管理窗口直接完成。后者则需要进入注册表“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services”找到服务名称的文件夹,整个删掉,重新启动电脑后,服务消失。

9.扩展思考:经过修改代码,还可以实现:启动目标程序之前,检测进程中是否存在目标程序,存在则不再次启动