c#写windows服务

 

序言

前段时间做一个数据迁移项目,刚开始用B/S架构做的项目,但B/S要寄存在IIs中,而IIs又不稳定因素,如果重启IIs就要打开页面才能运行项目。有不便之处,就改用Windows服务实现。这篇就总结下,windows服务的编写,调试,安装卸载。

Windows服务介绍

Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这使服务非常适合在服务器上使用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。本文就向大家介绍如何运用Visual C#来一步一步创建一个文件监视的Windows服务程序,然后介绍如何安装、测试和调试该Windows服务程序。

创建Windows服务

创建好项目之后 --- >> 双击 Service1.cs  ---- >>  出现一个设计界面   ---->> 右键界面  --- >> 弹出对话框选择添加安装程序

上面一系列操作完成后,就可以对windows服务名称描述以及启动方式等进行修改。

[RunInstaller(true)]

    public class Installer1 : System.Configuration.Install.Installer
{ /// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
private System.ServiceProcess.ServiceProcessInstaller spInstaller;
private System.ServiceProcess.ServiceInstaller sInstaller; public Installer1()
{
// 该调用是设计器所必需的。
InitializeComponent();
// TODO: 在 InitComponent 调用后添加任何初始化
} #region Component Designer generated code
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
// 创建ServiceProcessInstaller对象和ServiceInstaller对象
this.spInstaller = new System.ServiceProcess.ServiceProcessInstaller();
this.sInstaller = new System.ServiceProcess.ServiceInstaller(); // 设定ServiceProcessInstaller对象的帐号、用户名和密码等信息
this.spInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.spInstaller.Username = null;
this.spInstaller.Password = null; // 设定服务名称
this.sInstaller.ServiceName = "PmsDataUpdateService";
//服务描述
this.sInstaller.Description = "hi longhao !"; // 设定服务的启动方式
this.sInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic; this.Installers.AddRange(
new System.Configuration.Install.Installer[] { this.spInstaller, this.sInstaller });
} #endregion }

修改好后回头,写入自己想要的操作。Service1.cs出现设计界面,双击设计界面进入cs代码页。可以重写这些方法。

  protected override void OnStart(string[] args)
{
//服务开启执行代码
}
protected override void OnStop()
{
//服务结束执行代码
}
protected override void OnPause()
{
//服务暂停执行代码
base.OnPause();
}
protected override void OnContinue()
{
//服务恢复执行代码
base.OnContinue();
}
protected override void OnShutdown()
{
//系统即将关闭执行代码
base.OnShutdown();
}

除此之外还有一个Program.cs文件:打开看下。

使得一个Windows服务程序能够正常运行,我们需要像创建一般应用程序那样为它创建一个程序的入口点。在Windows服务程序中,我们也是在Main()函数中完成这个操作的。首先我们在Main()函数中创建一个Windows服务的实例,该实例应该是ServiceBase类的某个子类的对象,然后我们调用由基类ServiceBase类定义的一个Run()方法。然而Run()方法并不就开始了Windows服务程序,我们必须通过前面提到的服务控制管理器调用特定的控制功能来完成Windows服务程序的启动,也就是要等到该对象的OnStart()方法被调用时服务才真正开始运行。如果你想在一个Windows服务程序中同时启动多个服务,那么只要在Main()函数中定义多个ServiceBae类的子类的实例对象就可以了,方法就是创建一个ServiceBase类的数组对象,使得其中的每个对象对应于某个我们已预先定义好的服务。

 /// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1(),
new Service2()
};
ServiceBase.Run(ServicesToRun);
}

如果你在你需要的函数里面写过你需要的方法后,点运行则不可运行。

安装卸载windows服务

1、安装需要用,这个小玩意可以在网上下载到的。

2、把他放到你编写好的服务程序/bin/Debug文件夹下。

3、打开

4、用命令读到你服务.exe文件夹下。

5、运行 installutil.exe

6、安装服务命令: installutil  yourservices.exe

7、卸载服务命令: installutil  /u  yourservices.exe

注意的是:安装跟卸载需要保证程序是一样的,没有变更过的,要不会提示卸载不干净。也就是在已安装过服务的时候,不要在vs中修改你的程序。

调试windows服务

保证你的服务已安装成功,且处于启动模式。

点调试--->> 附加到进程

即可。

注意的是:

打开任务管理器:结束进程。


ASP.NET实现WEB站点的后台定时任务

在ASP.net的WEB开发中经常会碰到这样的一个问题:即用户操作响应慢的情况。这时候就可以用后台定时任务来提前实现,并且将结果存放好或分解成响应快的任务。

可以采用Asp.net的定时处理方式,直接在WEB服务器层来进行处理。

关于C#中timer类,在C#里关于定时器类就有3个,分别是System.Windows.Forms,System.Timers.Timer和System.Threading.Timer.在这里我们主要使用System.Threading.Timer,因为它是一个使用回调方法的计时器,而且由线程池线程服务,简单且对资源要求不高。

public class ScheduledTask
    {
        private static readonly ScheduledTask _ScheduledTask = null;
        private System.Threading.Timer UpdateTimer = null;
        private int Interval = 1 * 60000;//间隔时间,这里设置为15分钟
        private int _IsRunning;//上一个时间间隔触发的任务是否运行完成

static ScheduledTask()
        {
            _ScheduledTask = new ScheduledTask();
        }

public static ScheduledTask Instance()
        {
            return _ScheduledTask;
        }

/// <summary>
        /// timer启动
        /// </summary>
        public void Start()
        {
            if (UpdateTimer == null)
            {
                UpdateTimer = new System.Threading.Timer(new TimerCallback(UpdateTimerCallback), null, Interval, Interval);
            }
        }

/// <summary>
        /// 时钟callback事件
        /// </summary>
        /// <param name="sender"></param>
        private void UpdateTimerCallback(object sender)
        {
            if (Interlocked.Exchange(ref _IsRunning, 1) == 0)
            {
                try
                {
                    //要处理后台任务
                }
                catch (Exception ex)
                {

}
                finally
                {
                    Interlocked.Exchange(ref _IsRunning, 0);
                }
            }
        }

/// <summary>
        ///timer停止
        /// </summary>
        public void Stop()
        {
            if (UpdateTimer != null)
            {
                UpdateTimer.Dispose();
                UpdateTimer = null;
            }
        }

}

建议在Application_Start中调用这个类,具体调用方法如下

public class Global : System.Web.HttpApplication
    {

protected void Application_Start(object sender, EventArgs e)
        {
            ScheduledTask.Instance().Start();
        }

protected void Application_End(object sender, EventArgs e)
        {
            ScheduledTask.Instance().Stop();
        }
    }

其中_IsRunning是一个标志,它代表上一个时间间隔触发的任务是否运行完成。因为,如果我们执行的任务时间很长,就可能造成上一个时间段触发的任务还没有执行完成,下一个任务又开始了,这样就会造成重入的问题。为了解决这个问题,我们用_IsRunning作为一个标志,表示上次的任务是否完成了,如果完成了,我们就执行新的任务,如果没完成就跳过这次的任务继续执行上次的任务。

所以在程序中,我使用了Interlocked.Exchange这个方法。该方法的作用是保证多线程下给对象赋值的安全性。因为在多线程下,我们直接给_IsRunning赋值是不安全的,所以在这种情况下Interlocked.Exchange就派上了用场


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace clockDemo
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
} protected override void OnStart(string[] args)
{
ScheduledTask.Instance().Start();
} protected override void OnStop()
{
ScheduledTask.Instance().Stop();
} } public class ScheduledTask
{
private static readonly ScheduledTask _ScheduledTask = null;
private System.Threading.Timer UpdateTimer = null;
private int Interval = 1 * 10000;//间隔时间,这里设置为15分钟
private int _IsRunning;//上一个时间间隔触发的任务是否运行完成 static ScheduledTask()
{
_ScheduledTask = new ScheduledTask();
} public static ScheduledTask Instance()
{
return _ScheduledTask;
} /// <summary>
/// timer启动
/// </summary>
public void Start()
{
if (UpdateTimer == null)
{
UpdateTimer = new System.Threading.Timer(new TimerCallback(UpdateTimerCallback), null, Interval, Interval);
}
} /// <summary>
/// 时钟callback事件
/// </summary>
/// <param name="sender"></param>
private void UpdateTimerCallback(object sender)
{
if (Interlocked.Exchange(ref _IsRunning, 1) == 0)
{
try
{
File.ReadAllText("c:\\a.txt");
File.AppendText("c:\\a.txt");
}
catch (Exception ex)
{ }
finally
{
Interlocked.Exchange(ref _IsRunning, 0);
}
}
} /// <summary>
///timer停止
/// </summary>
public void Stop()
{
if (UpdateTimer != null)
{
UpdateTimer.Dispose();
UpdateTimer = null;
}
} }
}

  

window 服务的更多相关文章

  1. C#编写window服务,一步一步(1)

    Window服务是啥,这里就不废话了,如何用在哪里用也不废话了,这里我这篇文章只是详述了我在vs2012中创建window服务的经过,希望对你有所帮助. 另外:我在编写服务过程中参考了 Profess ...

  2. WPF Window 服务安装

    一.安装服务 1.已管理员的身份启动CMD 2.输入 cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 回车 3.输入 InstallUtil.exe ...

  3. Window服务初级教程以及log4net配置文件初始化

    Window服务初级教程:http://www.jb51.net/article/48987.htm 另外,配置log4net这个日志功能的时候需要初始化,不然会报没有初始化的错误,而且初始化的节点应 ...

  4. C# 编写Window服务基础(一)

    一.Windows服务介绍: Windows服务以前被称作NT服务,是一些运行在Windows NT.Windows 2000和Windows XP等操作系统下用户环境以外的程序.在以前,编写Wind ...

  5. C# 编写短信发送Window服务

    我们做项目过程中,一般都会有发送短信的需求.最常见的就是户注册或者登录时发送短信验证码.不同类型的短信发送,我们都可以放到到一张短信表中,然后通过一个定时的作业去执行短信发送.而定时作业的执行,我们就 ...

  6. 自定义Window 服务

    自定义window 服务 开发到使用的流程: 1.完成对应的代码之后(代码在底下),右键MyService.cs 添加安装程序 2.添加window服务安装程序打开Service1.cs[设计]页面, ...

  7. window服务创建

    第一步:创建服务 第二步:在Service1.cs视图中 右键 选择”添加安装程序” 这里要注意几个细节 设置上面的属性 这两个分别有属性,具体网上查使用方式 3 实例代码编写 主要下面几个方法 pr ...

  8. C#在window服务配置Log4Net.dll

    1.使用背景: C#window服务下添加一个日志记录程序集(Log4Net.dll) 2.添加和使用步骤如下: 一.下载并引入Log4Net.dll程序集到项目中 下载地址:http://loggi ...

  9. 创建一个MongoDB数据库再到配置成Window服务再设置用户名密码

    1.安装MongoDB数据在官网下载安装 然后在C盘找到C:\Program Files\MongoDB\Server\4.0\bin这个可执行目录 使用cmd进入到这: 2.在C盘根目录创建一个名为 ...

  10. Window服务项目脚手架

    本人最近工作用到window服务程序,于是尝试分享下经验,开源了一个window服务脚手架项目,把window服务程序必不可少的组件集成进去,如日志组件log4net,window服务挂在后台,用日志 ...

随机推荐

  1. MySQL主从数据库的安装

    安装环境 操作系统 :CentOS 6.5 数据库版本:MySQL 5.6.27 主机A:192.168.1.1 (Master) 主机B:192.168.1.2 (Slave) 1 2 3 4 这里 ...

  2. 插件开发-滑条(slide)开发

    自己一直很喜欢开发组件,只是OPP学的不是很精,自己在项目中用别人的框架进行项目开发,难免受制于人,也许这就是个人实际项目需求和框架提供的多少有点不符,引导我自己尝试开发一些自己常用的组件,话不多说, ...

  3. Javascript的闭包及其使用技巧实例

    Javascript的闭包及其使用技巧实例 一.闭包的基本概念 闭包(Closure)是一个引用了自由变量的函数,记录了该函数在定义时的scope chain.又称词法闭包(Lexical Closu ...

  4. linux中Centos7搭建lnmp环境

    1.安装yum yum update 2.安装nginx源: yum localinstall http://nginx.org/packages/centos/7/noarch/RPMS/nginx ...

  5. 「ZJOI2015」地震后的幻想乡

    /* 难度最低的解法 钦定一个边集S作为前S小如果这个边集假如第|S|小这条边时加入时S恰好联通, 那么我们就能够算出他的贡献了 恰好联通 = 加了这条边之前不连通方案数 - 加了这条边之后不连通方案 ...

  6. 微信小程序开发warning: Now you can provide attr "wx:key" for a "wx:for" to improve performance

    用微信官方的模板发现突然报了这个warning,检查原因: 官方解释: wx:key 如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 <i ...

  7. 【Jmeter自学】Jmeter里的指标

    聚合报告 Average:平均响应时间(毫秒ms) Median:中值时间,N个数据从小到大排列,第N/2个数 9x%Line:N个数据从小到大排列,第9x%N个数.所有数据中9x%的响应时间都小于9 ...

  8. concurrent.futures模块 -----进程池 ---线程池 ---回调

    concurrent.futures模块提供了高度封装的异步调用接口,它内部有关的两个池 ThreadPoolExecutor:线程池,提供异步调用,其基础就是老版的Pool ProcessPoolE ...

  9. nginx, supervisor, celery

      资料: supervisor和nginx使用 1 .supervisor 管理进程工具 2 .nginx 反向代理, 负载均衡 安装nginx $ sudo apt-get update $ su ...

  10. 【Python】python3 正则爬取网页输出中文乱码解决

    爬取网页时候print输出的时候有中文输出乱码 例如: \\xe4\\xb8\\xad\\xe5\\x8d\\x8e\\xe4\\xb9\\xa6\\xe5\\xb1\\x80 #爬取https:// ...