Window服务是啥,这里就不废话了,如何用在哪里用也不废话了,这里我这篇文章只是详述了我在vs2012中创建window服务的经过,希望对你有所帮助。

另外:我在编写服务过程中参考了 Professional C# 2012 and   .NET 4.5

第一步,创建一个解决方案名称MonitoringFish

  不废话,你肯定会,会的直接去下一步。如果真的不会请继续看

  

第二步添加服务用的类库项目Sensor

并添加类文件QuoteException.cs和SensorFish.cs

  这两个类的功能并不重要,主要是给服务类用的,你也可以写自己的类文件,或者干脆不要,直接在服务类里边写逻辑代码

  QuoteException.cs代码如下:

  

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace Sensor
  7. {
  8. /// <summary>
  9. /// 自定义异常
  10. /// </summary>
  11. [Serializable]
  12. class QuoteException : Exception
  13. {
  14. public QuoteException() { }
  15. public QuoteException(string message) : base(message) { }
  16. public QuoteException(string message, Exception inner) : base(message, inner) { }
  17. protected QuoteException(
  18. System.Runtime.Serialization.SerializationInfo info,
  19. System.Runtime.Serialization.StreamingContext context)
  20. : base(info, context) { }
  21. }
  22. }

  SensorFish.cs代码如下:

  

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Threading.Tasks;
  9. using System.Diagnostics.Contracts;
  10. using System.Diagnostics;
  11.  
  12. namespace Sensor
  13. {
  14. /// <summary>
  15. /// 传感器监测
  16. /// </summary>
  17. public class SensorFish
  18. {
  19.  
  20. private TcpListener listener;
  21. private int port;//端口号
  22. private string filename;
  23. private List<string> quotes;
  24. private Random random;
  25. private Task listenerTask;
  26.  
  27. /// <summary>
  28. /// 传感器控制类
  29. /// </summary>
  30. public SensorFish()
  31. : this("quotes.txt")
  32. {
  33.  
  34. }
  35.  
  36. /// <summary>
  37. /// 传感器控制类
  38. /// </summary>
  39. /// <param name="fileName"></param>
  40. public SensorFish(string fileName)
  41. : this(fileName, )
  42. {
  43.  
  44. }
  45.  
  46. /// <summary>
  47. /// 传感器控制类
  48. /// </summary>
  49. /// <param name="fileName"></param>
  50. /// <param name="port"></param>
  51. public SensorFish(string fileName, int port)
  52. {
  53. //Contract.Requires<ArgumentNullException>(fileName != null);
  54. //Contract.Requires<ArgumentException>(port >= IPEndPoint.MinPort && port <= IPEndPoint.MaxPort);
  55. this.filename = fileName;
  56. this.port = port;
  57. }
  58.  
  59. protected void ReadQuotes()
  60. {
  61. try
  62. {
  63. quotes = File.ReadAllLines(filename).ToList();
  64. if (quotes.Count == )
  65. {
  66. throw new QuoteException("quotes file is empty");
  67. }
  68. random = new Random();
  69. }
  70. catch (IOException ex)
  71. {
  72. throw new QuoteException("I/O Error", ex);
  73. }
  74. }
  75.  
  76. protected string GetRandomQuoteOfTheDay()
  77. {
  78. int index = random.Next(, quotes.Count);
  79. return quotes[index];
  80. }
  81.  
  82. /// <summary>
  83. /// 开启服务
  84. /// </summary>
  85. public void Start()
  86. {
  87. ReadQuotes(); //读取文件
  88. listenerTask = Task.Factory.StartNew(Listener, TaskCreationOptions.LongRunning);//异步方法调用
  89. }
  90.  
  91. private void Listener()
  92. {
  93. try
  94. {
  95. IPAddress ipAddress = IPAddress.Any;//提供一个ip地址,只是服务器应侦听所有网络接口上的客户端活动。此字段为只读
  96. listener = new TcpListener(ipAddress, port);//指定在本地的IP地址和端口号上侦听是否有传入的连接尝试
  97. listener.Start();//开始侦听传入的连接请求
  98. while (true)
  99. {
  100. Socket clientSocket = listener.AcceptSocket();//接受关起的连接请求
  101. string message = GetRandomQuoteOfTheDay();
  102. var encoder = new UnicodeEncoding();
  103. byte[] buffer = encoder.GetBytes(message);
  104. clientSocket.Send(buffer, buffer.Length, );//将指定的字节数发送到已连接的Socket
  105. clientSocket.Close();//关闭Socket,并释放所有的关联的资源
  106. }
  107. }
  108. catch (SocketException ex)
  109. {
  110. Trace.TraceError(string.Format("QuoteServer {0}", ex.Message));
  111. throw new QuoteException("socket error", ex);
  112. }
  113. }
  114.  
  115. /// <summary>
  116. /// 停止服务
  117. /// </summary>
  118. public void Stop()
  119. {
  120. listener.Stop();//关闭侦听
  121. }
  122.  
  123. /// <summary>
  124. /// 暂定服务
  125. /// </summary>
  126. public void Suspend()
  127. {
  128. listener.Stop();
  129. }
  130.  
  131. /// <summary>
  132. /// 重新开始服务
  133. /// </summary>
  134. public void Resume()
  135. {
  136. Start();
  137. }
  138.  
  139. /// <summary>
  140. /// 重启
  141. /// </summary>
  142. public void RefreshSensor()
  143. {
  144. ReadQuotes();
  145. }
  146. }
  147. }

  

第三步添加控制台应用程序SensorServiceTest

  这里要说下为什么添加这个控制台程序了。

  因为在开发过程中要对Sensor项目进行调试,为了方便用 SensorServiceTest承载这个类库,作为服务使用。在第四步的程序中将会调用这个服务,以便验证Sensor中的各个类功能是否正常。

  

  直接主函数中加入代码,如下:

  

  1. /// <summary>
  2. /// 服务测试程序
  3. /// </summary>
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8.  
  9. var qs = new SensorFish("Quotes.txt", );
  10. qs.Start();
  11. Console.WriteLine("Hit return to exit");
  12. Console.ReadLine();
  13. qs.Stop();
  14. }
  15. }

第四步添加wpf应用程序项目ServiceTestClicent

  用于配合第三步创建服务测试Sensor项目,请注意配置项目属性页的【设置】选项卡的键值如下图所示

  

  这个项目中我创建了一个MainWindow.xaml文件和QuoteInformation.cs类用于客户端程序的调用,当然在创建wpf项目时候自动生成了app.config(非必须)和App.xaml(必须)

  xaml文件代码如下:

  

  1. <Window x:Class="ServiceTestClicent.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="MainWindow" Height="" Width="">
  5. <Grid>
  6. <Grid.RowDefinitions>
  7. <RowDefinition Height="*" MinHeight=""></RowDefinition>
  8. <RowDefinition Height="3*"></RowDefinition>
  9. </Grid.RowDefinitions>
  10.  
  11. <Button Margin="" VerticalAlignment="Stretch" Grid.Row="" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}"
  12. IsEnabled="{Binding EnableRequset}" Click="OnGetQuote" >Get Quote</Button>
  13. <TextBlock Margin="" Grid.Row="" TextWrapping="Wrap" Text="{Binding Quote}" />
  14. </Grid>
  15. </Window>

  

  1. using System;
  2. using System.Net.Sockets;
  3. using System.Text;
  4. using System.Windows;
  5. using System.Windows.Input;
  6.  
  7. namespace ServiceTestClicent
  8. {
  9. /// <summary>
  10. /// MainWindow.xaml 的交互逻辑
  11. /// </summary>
  12. public partial class MainWindow : Window
  13. {
  14. private QuoteInformation quoteInfo = new QuoteInformation();
  15. public MainWindow()
  16. {
  17. InitializeComponent();
  18. this.DataContext = quoteInfo;
  19. }
  20.  
  21. private async void OnGetQuote(object sender, RoutedEventArgs e)
  22. {
  23. const int bufferSize = ;
  24. Cursor currentCursor = this.Cursor; //代表用于鼠标指针的图像
  25. quoteInfo.EnableRequest = false;
  26.  
  27. string serverName = Properties.Settings.Default.ServerName; //url
  28. int port = Properties.Settings.Default.PortNumber;//端口
  29. var client = new TcpClient();//
  30. NetworkStream stream = null;
  31. try
  32. {
  33. await client.ConnectAsync(serverName, port);
  34. stream = client.GetStream();
  35. byte[] buffer = new Byte[bufferSize];
  36. int received = await stream.ReadAsync(buffer, , bufferSize);
  37. if (received <= )
  38. {
  39. return;
  40. }
  41.  
  42. quoteInfo.Quote = Encoding.Unicode.GetString(buffer).Trim('\0');
  43.  
  44. }
  45. catch (SocketException ex)
  46. {
  47. MessageBox.Show(ex.Message, "Error Quote of the day", MessageBoxButton.OK, MessageBoxImage.Error);
  48. }
  49. finally
  50. {
  51. if (stream != null)
  52. {
  53. stream.Close();
  54. }
  55.  
  56. if (client.Connected)
  57. {
  58. client.Close();
  59. }
  60. this.Cursor = currentCursor;
  61. quoteInfo.EnableRequest = true;
  62. }
  63.  
  64. }
  65. }
  66.  
  67. }

  QuoteInformation.cs类代码如下

  

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Runtime.CompilerServices;
  6. using System.Text;
  7.  
  8. namespace ServiceTestClicent
  9. {
  10. class QuoteInformation : INotifyPropertyChanged
  11. {
  12. public QuoteInformation()
  13. {
  14. EnableRequest = true;
  15. }
  16. private string quote;
  17. public string Quote
  18. {
  19. get
  20. {
  21. return quote;
  22. }
  23. internal set
  24. {
  25. SetProperty(ref quote, value);
  26. }
  27. }
  28.  
  29. private bool enableRequest;
  30. public bool EnableRequest
  31. {
  32. get
  33. {
  34. return enableRequest;
  35. }
  36. internal set
  37. {
  38. SetProperty(ref enableRequest, value);
  39. }
  40. }
  41.  
  42. private void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
  43. {
  44. if (!EqualityComparer<T>.Default.Equals(field, value))
  45. {
  46. field = value;
  47. var handler = PropertyChanged;
  48. if (handler != null)
  49. {
  50. handler(this, new PropertyChangedEventArgs(propertyName));
  51. }
  52. }
  53. }
  54.  
  55. public event PropertyChangedEventHandler PropertyChanged;
  56. }
  57. }

  在项目SensorServiceTestClient和ServiceTestClicent上右键-生成后打开在各自项目中的Debug文件夹下找到exe可执行文件,并先启动SensorServiceTestClient.exe然后启动ServiceTestClicent.exe

  启动ServiceTestClicent.exe如下图所示,表示各个程序功能正常

  

  经过测试功能正常,就可以真正的编写windows服务了

第五步添加服务项目SensorFishService

  添加一个服务类FisheryMonitoring.cs

  

  在空白处点击一下,以便选中该选项卡,然后打开属性窗口看到下图所示

  

  

  (Name)对应的是服务类的名称

  AutoLog指定把启动和停止服务的事件自动写到事件日志中

  CanPauseAndContinue、CanShutdown和CanStop指定服务可以处理暂停、继续、关闭和停止服务的请求

  ServiceName是写到注册表中的服务的名称,使用这个名称可以控制服务

  CanHandleSessionChangeEvent确定服务是否能处理终端服务器会话中的改变事件

  CanHandlePowerEvent选项对运行在笔记本电脑或移动设备上的服务有效。如果启用这个选项,服务就可以响应低电源事件,并响应的改变服务的行为。电源事件包括电量低、电源状态改变(因为A/C电源之间的切换)开关和改为断电

  设置好各个属性后,在服务类的选项卡上右键,选择【添加安装程序】

  

  

  

  选中 ServiceProcessInstaller1打开属性选项卡

  

  设置一下 Account,如果将他的值设置为User那么在安装服务的时候就要指定一个具体的账户,只有这个账户可以使用这个服务,其他的不详,请查阅其他资料

  选中serviceInstaller1并打开属性选项卡

  

  设置一下各个属性,各位看官请自行对照属性的作用,下图是系统服务中的截图

  

  

  值得注意的是 ServiceName必须和上文中提到的ServiceName相同,别问我为什么

  至此重点的部分介绍完毕

当然,大头的部分还在后边,请各位看官注意

第六步在SensorFishService项目中添加类Program.cs

  这个必须的,因为承载了程序入口,所以名字不能变,代码如下

  1. static class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5.  
  6. ServiceBase[] ServicesToRun;
  7. ServicesToRun = new ServiceBase[]{
  8. new FisheryMonitoring()
  9. };
  10.  
  11. //服务响应
  12. ServiceBase.Run(ServicesToRun);
  13. // ServiceBase.Run(new FisheryMonitoring());
  14. }
  15. }

至此整个windows服务编写已经完成,下一篇笔者将介绍安装和卸载服务的过程

注:请各位看客自行设置项目之间的引用和项目上的程序集的引用,很简单的

附源码:http://files.cnblogs.com/netqq/Fishery.zip

window服务的安装请参考文章 http://www.cnblogs.com/netqq/p/4218147.html

C#编写window服务,一步一步(1)的更多相关文章

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

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

  2. Android 从硬件到应用程序:一步一步爬上去 6 -- 我写的APP测试框架层硬件服务(终点)

    创Android Applicationproject:采用Eclipse的Android插入ADT创Androidproject,project名字Gpio,创建完成后,project文件夹pack ...

  3. 通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定

    如果说Actor是dapr有状态服务的内部体现的话,那绑定应该是dapr对serverless这部分的体现了.我们可以通过绑定极大的扩展应用的能力,甚至未来会成为serverless的基础.最开始接触 ...

  4. 通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容

    上一篇我们讲到了dapr提供的bindings,通过绑定可以让我们的程序轻装上阵,在极端情况下几乎不需要集成任何sdk,仅需要通过httpclient+text.json即可完成对外部组件的调用,这样 ...

  5. 《Pro Express.js》学习笔记——Express服务启动常规七步

    Express服务启动常规七步 1.       引用模块 var express=require('express'), compression=require('compression'), bo ...

  6. 一步一步教你编写与搭建自动化测试框架——python篇

    [本文出自天外归云的博客园] 这两天用python写了一个自动化测试框架,取名为Auty.准备用来做Web方面的接口测试,以下为Auty框架一步一步的搭建过程——

  7. WCF 一步一步 发布 WCF服务 到 IIS (图)

    WCF 一步一步 发布 WCF服务 到 IIS (图) 使用VS自带的WCFSVCHost(WCF服务主机)发布WCF服务,时刻开发人员测试使用. 下面我们来看一下如何在IIS中部发布一个WCF服务. ...

  8. 通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布

    之前的章节我们介绍了如何通过dapr发起一个服务调用,相信看过前几章的小伙伴已经对dapr有一个基本的了解了,今天我们来聊一聊dapr的另外一个功能--订阅发布 目录:一.通过Dapr实现一个简单的基 ...

  9. 通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr

    目录:一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实现一个简单的基于.net的微服务电商系统(二)--通讯框架讲解 三.通过Dapr实现一个简单的基于.net的微服务电 ...

随机推荐

  1. 遇到的Exception/error及解决办法记录汇总

    一.java.net.SocketException 1.java.net.SocketException:Connection reset 首先,如果一端的Socket被关闭(或主动关闭,或因为异常 ...

  2. JS原型链

    JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...

  3. Web系统性能测试术语简介

    并发用户 并发一般分为两种情况.一种是严格意义上的并发,即所有的用户在同一时刻做同一件事情或者操作.这种操作一般指做同一类型的业务,比如在信用卡审批业务中,一定数目的用户在同一时刻对已经完成的审批业务 ...

  4. python注释、脚本参数、字节码

    python注释.脚本参数.字节码 --道心 python安装 1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python27 3. ...

  5. 如何利用报表工具FineReport实现报表列的动态展示

    相信动态列的实现困扰了很多人,大数据量,多字段的加载将会非常耗时,数据又做不到真正的动态灵活.现有的方式都是通过变向的隐藏等方式来实现. 那该如何解决呢?这里分享帆软报表设计器FineReport的实 ...

  6. (转)Java中的static关键字解析

    转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...

  7. 【C】.h头文件的重复包含问题

    .h头文件存在的意义就是封装,可以方便多个.c源文件使用,但要防止.h头文件被同一个.c源文件多次包含. 例如, io.h文件 #ifndef _IO_H_ #define _IO_H_ #defin ...

  8. L1-006. 连续因子

    https://www.patest.cn/contests/gplt/L1-006 题目地址 在上面 一个正整数N的因子中可能存在若干连续的数字.例如630可以分解为3*5*6*7,其中5.6.7就 ...

  9. 谈c++ pb_ds库(一)rope大法好

    参考资料 1)官方说明 支持 sorry,cena不支持rope 声明 1)头文件 #include<ext/rope> 2)调用命名空间 using namespace __gnu_cx ...

  10. 控制反转(IOC)

    对于很多大中型项目为了实现解耦都用到了控制反转. 常用的控制反转有unity,autoface,spring.Net 使用它们的目的归根结底就一个:避免了直接new一个对象. 今天抽时间将三种控制反转 ...