C# Windows服务开发入门

1. 介绍

        过去称为 NT 服务,允许用户创建可在其自身的 Windows 会话中长时间运行的可执行应用程序。 这些服务可在计算机启动时自动启动,可以暂停和重启,并且不显示任何用户界面。

2. 创建 Windows 服务应用

2.1 创建服务并给服务重命名

开发环境:Windows10操作系统 + vs2015开发环境

在“解决方案资源管理器”中,从“MyNewService.cs”或“MyNewService.vb”的快捷菜单中,选择“查看设计器”。

在“工具箱”中,展开“组件”,然后将“EventLog”组件拖到“Service1.cs [Design]”或“Service1.vb [Design]”标签。

在“解决方案资源管理器”中,选择“Service1.cs”或“Service1.vb”,然后从快捷菜单中选择“重命名”。 将文件重命名为“MyNewService.cs”或“MyNewService.vb”

2.2 向服务添加功能

在MyNewService设计器,右击

注意:
LocalSystem 帐户具有广泛的权限,包括能够写入事件日志。 
使用此帐户时要特别小心,因为它会增加你受到恶意软件攻击的风险。 
对于其他任务,请考虑使用 LocalService 帐户,该帐户用作本地计算机上的非特权用户,并向任意远程服务器提供匿名凭据。 
如果你尝试使用 LocalService 账户,此例子将失败,因为它需要写入事件日志的权限。
namespace MyNewService
{
    public partial class MyNewService : ServiceBase
    {
        // 写入事件日志的事件的标识符
        private int eventId = 1;

        #region /* 设置服务状态 */

        // 使用平台调用声明 SetServiceStatus 函数
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);

        // 声明 ServiceState 值和添加你将在平台调用中使用的状态结构
        public enum ServiceState
        {
            SERVICE_STOPPED = 0x00000001,
            SERVICE_START_PENDING = 0x00000002,
            SERVICE_STOP_PENDING = 0x00000003,
            SERVICE_RUNNING = 0x00000004,
            SERVICE_CONTINUE_PENDING = 0x00000005,
            SERVICE_PAUSE_PENDING = 0x00000006,
            SERVICE_PAUSED = 0x00000007,
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ServiceStatus
        {
            public int dwServiceType;
            public ServiceState dwCurrentState;
            public int dwControlsAccepted;
            public int dwWin32ExitCode;
            public int dwServiceSpecificExitCode;
            public int dwCheckPoint;
            public int dwWaitHint;
        };

        #endregion

        public MyNewService()
        {
            InitializeComponent();

            //添加自定义事件日志功能 到 Windows 服务——“事件查看器”中找到MyNewLog
            eventLog1 = new System.Diagnostics.EventLog();
            if (!System.Diagnostics.EventLog.SourceExists("MySource"))
            {
                System.Diagnostics.EventLog.CreateEventSource(
                    "MySource", "MyNewLog");
            }
            eventLog1.Source = "MySource";
            eventLog1.Log = "MyNewLog";
        }

        /// <summary>
        /// 根据用户提供的启动参数设置事件源和日志名称。 如果未提供参数,则使用默认值。
        /// </summary>
        /// <param name="args"></param>
        public MyNewService(string[] args)
        {
            InitializeComponent();

            string eventSourceName = "MySource";
            string logName = "MyNewLog";

            if (args.Length > 0)
            {
                eventSourceName = args[0];
            }

            if (args.Length > 1)
            {
                logName = args[1];
            }

            eventLog1 = new EventLog();

            if (!EventLog.SourceExists(eventSourceName))
            {
                EventLog.CreateEventSource(eventSourceName, logName);
            }

            eventLog1.Source = eventSourceName;
            eventLog1.Log = logName;
        }


        protected override void OnStart(string[] args)
        {
            // 将服务状态更新为“开始挂起”。
            ServiceStatus serviceStatus = new ServiceStatus();
            serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
            serviceStatus.dwWaitHint = 100000;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);


            // 在服务启动时向事件日志写入一个条目
            eventLog1.WriteEntry("In OnStart.");

            //# 在服务操作开始后,OnStart 方法必须返回操作系统,以便不阻止系统。
            //  所以若要设置简单的轮询机制,设置一个每分钟触发一次的Timer计时器,以此可以进行监视服务。
            //# 当然也可以使用后台工作线程来运行任务,进行轮询。
            Timer timer = new Timer();
            timer.Interval = 60000; // 60 seconds
            timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
            timer.Start();


            // 将服务状态更新为正在运行。
            serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);
        }

        public void OnTimer(object sender, ElapsedEventArgs args)
        {
            // TODO:在此处插入监控活动。
            eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId++);
        }

        protected override void OnStop()
        {
            // 将服务状态更新为“停止挂起”。
            ServiceStatus serviceStatus = new ServiceStatus();
            serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING;
            serviceStatus.dwWaitHint = 100000;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);

            // 在服务停止时向事件日志添加一个条目
            eventLog1.WriteEntry("In OnStop.");

            // 将服务状态更新为已停止。
            serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);

        }

        /// <summary>
        /// 定义服务的OnContinue操作
        /// </summary>
        protected override void OnContinue()
        {
            eventLog1.WriteEntry("In OnContinue.");
        }

        /// <summary>
        /// 定义服务的OnPause操作
        /// </summary>
        protected override void OnPause()
        {
            eventLog1.WriteEntry("In OnPause.");
        }

        /// <summary>
        /// 定义服务的OnShutdown操作
        /// </summary>
        protected override void OnShutdown()
        {
            eventLog1.WriteEntry("In OnShutdown .");
        }
    }
}
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        static void Main(string[] args)
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new MyNewService(args)
            };
            ServiceBase.Run(ServicesToRun);
        }
    }
namespace MyNewService
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }

        private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e)
        {

        }

        protected override void OnBeforeInstall(IDictionary savedState)
        {
            string parameter = "MySource1\" \"MyLogFile1";
            Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";
            base.OnBeforeInstall(savedState);
        }

    }
}

2.3 生成服务

生成解决方法

2.4 安装服务

        要安装 Windows 服务,必须在安装它的计算机上拥有管理员凭据。进入“Visual Studio 的开发人员命令提示”窗口,导航到包含项目输出的文件夹(默认情况下,它是项目的 \bin\Debug 子目录),输入命令:

installutil MyNewService.exe

2.5 启动并运行服务

2.5.1 在 Windows 中,打开“服务”桌面应用程序 

按“Windows 徽标键+R”以打开“运行”框,然后输入 services.msc 并按 Enter 或单击“确定”。

若要启动该服务,请从服务的快捷菜单中选择“启动”。

若要停止该服务,请从服务的快捷菜单中选择“停止”。

(可选)可在命令行使用“net start<服务名称>”和“net stop<服务名称>”来启动和停止服务。

2.5.2 在 Windows 中,打开“事件查看器”桌面应用

在 Windows 搜索栏中输入事件查看器,然后从搜索结果中选择“事件查看器”。

2.6 卸载服务

        使用管理员凭据,进入“Visual Studio 的开发人员命令提示”窗口,导航到包含项目输出的文件夹(默认情况下,它是项目的 \bin\Debug 子目录),输入命令:

installutil.exe /u MyNewService.exe

 

参考文章:

(1)开发 Windows 服务应用:https://docs.microsoft.com/zh-cn/dotnet/framework/windows-services/

(2)vs2015开发Windows服务:http://www.cnblogs.com/xujie/p/5695673.html

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows程序设计入门是指学习如何使用Windows操作系统中的API和工具开发应用程序的过程。以下是一些入门的步骤: 1. 学习编程语言:Windows程序可以使用多种编程语言编写,例如C++、C#、Visual Basic等。因此,学习一种编程语言是必须的。推荐优秀的编程书籍,例如《C++ Primer》、《C#入门经典》等。 2. 熟悉Windows API:Windows API是Windows操作系统提供的一组函数调用,用于访问系统资源和执行操作。学习Windows API的使用是Windows程序设计的核心。Microsoft的官方文档提供了详细的API参考和示例代码,可以帮助开发者快速上手。 3. 使用集成开发环境(IDE):IDE是一种软件工具,可以帮助开发者编写、调试和测试程序。Windows程序设计中常用的IDE有Visual Studio、Code::Blocks、Dev-C++等。 4. 编写简单的应用程序:通过编写简单的应用程序,例如控制台程序、窗口程序等,来熟悉Windows API的使用和程序开发流程。 5. 学习GUI编程:GUI(图形用户界面)是Windows程序的重要组成部分。学习如何使用Windows API或GUI库(例如MFC、WinForms、WPF等)来设计和开发GUI是Windows程序设计的重要步骤。 6. 学习调试和测试:调试和测试是程序开发不可避免的环节。学习如何使用IDE提供的调试工具和测试框架,以及如何编写测试用例和进行单元测试等,可以提高程序的质量和稳定性。 总之,Windows程序设计入门需要学习编程语言、Windows API、GUI编程以及调试和测试等方面的知识。通过不断练习和实践,可以逐渐掌握Windows程序设计的技巧和方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值