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

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

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

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

  

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

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

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

  QuoteException.cs代码如下:

  

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Sensor
{
/// <summary>
/// 自定义异常
/// </summary>
[Serializable]
class QuoteException : Exception
{
public QuoteException() { }
public QuoteException(string message) : base(message) { }
public QuoteException(string message, Exception inner) : base(message, inner) { }
protected QuoteException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
}

  SensorFish.cs代码如下:

  

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Diagnostics.Contracts;
using System.Diagnostics; namespace Sensor
{
/// <summary>
/// 传感器监测
/// </summary>
public class SensorFish
{ private TcpListener listener;
private int port;//端口号
private string filename;
private List<string> quotes;
private Random random;
private Task listenerTask; /// <summary>
/// 传感器控制类
/// </summary>
public SensorFish()
: this("quotes.txt")
{ } /// <summary>
/// 传感器控制类
/// </summary>
/// <param name="fileName"></param>
public SensorFish(string fileName)
: this(fileName, )
{ } /// <summary>
/// 传感器控制类
/// </summary>
/// <param name="fileName"></param>
/// <param name="port"></param>
public SensorFish(string fileName, int port)
{
//Contract.Requires<ArgumentNullException>(fileName != null);
//Contract.Requires<ArgumentException>(port >= IPEndPoint.MinPort && port <= IPEndPoint.MaxPort);
this.filename = fileName;
this.port = port;
} protected void ReadQuotes()
{
try
{
quotes = File.ReadAllLines(filename).ToList();
if (quotes.Count == )
{
throw new QuoteException("quotes file is empty");
}
random = new Random();
}
catch (IOException ex)
{
throw new QuoteException("I/O Error", ex);
}
} protected string GetRandomQuoteOfTheDay()
{
int index = random.Next(, quotes.Count);
return quotes[index];
} /// <summary>
/// 开启服务
/// </summary>
public void Start()
{
ReadQuotes(); //读取文件
listenerTask = Task.Factory.StartNew(Listener, TaskCreationOptions.LongRunning);//异步方法调用
} private void Listener()
{
try
{
IPAddress ipAddress = IPAddress.Any;//提供一个ip地址,只是服务器应侦听所有网络接口上的客户端活动。此字段为只读
listener = new TcpListener(ipAddress, port);//指定在本地的IP地址和端口号上侦听是否有传入的连接尝试
listener.Start();//开始侦听传入的连接请求
while (true)
{
Socket clientSocket = listener.AcceptSocket();//接受关起的连接请求
string message = GetRandomQuoteOfTheDay();
var encoder = new UnicodeEncoding();
byte[] buffer = encoder.GetBytes(message);
clientSocket.Send(buffer, buffer.Length, );//将指定的字节数发送到已连接的Socket
clientSocket.Close();//关闭Socket,并释放所有的关联的资源
}
}
catch (SocketException ex)
{
Trace.TraceError(string.Format("QuoteServer {0}", ex.Message));
throw new QuoteException("socket error", ex);
}
} /// <summary>
/// 停止服务
/// </summary>
public void Stop()
{
listener.Stop();//关闭侦听
} /// <summary>
/// 暂定服务
/// </summary>
public void Suspend()
{
listener.Stop();
} /// <summary>
/// 重新开始服务
/// </summary>
public void Resume()
{
Start();
} /// <summary>
/// 重启
/// </summary>
public void RefreshSensor()
{
ReadQuotes();
}
}
}

  

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

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

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

  

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

  

     /// <summary>
/// 服务测试程序
/// </summary>
class Program
{
static void Main(string[] args)
{ var qs = new SensorFish("Quotes.txt", );
qs.Start();
Console.WriteLine("Hit return to exit");
Console.ReadLine();
qs.Stop();
}
}

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

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

  

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

  xaml文件代码如下:

  

 <Window x:Class="ServiceTestClicent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="" Width="">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight=""></RowDefinition>
<RowDefinition Height="3*"></RowDefinition>
</Grid.RowDefinitions> <Button Margin="" VerticalAlignment="Stretch" Grid.Row="" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}"
IsEnabled="{Binding EnableRequset}" Click="OnGetQuote" >Get Quote</Button>
<TextBlock Margin="" Grid.Row="" TextWrapping="Wrap" Text="{Binding Quote}" />
</Grid>
</Window>

  

 using System;
using System.Net.Sockets;
using System.Text;
using System.Windows;
using System.Windows.Input; namespace ServiceTestClicent
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private QuoteInformation quoteInfo = new QuoteInformation();
public MainWindow()
{
InitializeComponent();
this.DataContext = quoteInfo;
} private async void OnGetQuote(object sender, RoutedEventArgs e)
{
const int bufferSize = ;
Cursor currentCursor = this.Cursor; //代表用于鼠标指针的图像
quoteInfo.EnableRequest = false; string serverName = Properties.Settings.Default.ServerName; //url
int port = Properties.Settings.Default.PortNumber;//端口
var client = new TcpClient();//
NetworkStream stream = null;
try
{
await client.ConnectAsync(serverName, port);
stream = client.GetStream();
byte[] buffer = new Byte[bufferSize];
int received = await stream.ReadAsync(buffer, , bufferSize);
if (received <= )
{
return;
} quoteInfo.Quote = Encoding.Unicode.GetString(buffer).Trim('\0'); }
catch (SocketException ex)
{
MessageBox.Show(ex.Message, "Error Quote of the day", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (stream != null)
{
stream.Close();
} if (client.Connected)
{
client.Close();
}
this.Cursor = currentCursor;
quoteInfo.EnableRequest = true;
} }
} }

  QuoteInformation.cs类代码如下

  

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text; namespace ServiceTestClicent
{
class QuoteInformation : INotifyPropertyChanged
{
public QuoteInformation()
{
EnableRequest = true;
}
private string quote;
public string Quote
{
get
{
return quote;
}
internal set
{
SetProperty(ref quote, value);
}
} private bool enableRequest;
public bool EnableRequest
{
get
{
return enableRequest;
}
internal set
{
SetProperty(ref enableRequest, value);
}
} private void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
} public event PropertyChangedEventHandler PropertyChanged;
}
}

  在项目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

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

 static class Program
{
static void Main(string[] args)
{ ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]{
new FisheryMonitoring()
}; //服务响应
ServiceBase.Run(ServicesToRun);
// ServiceBase.Run(new FisheryMonitoring());
}
}

至此整个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. JavaScript(八)——复习一(重要内容基本包含在内)

    一.常用对话框 1.alert(""):警告对话框,作用是弹出一个警告对话框 2.confirm(""):确定对话框,弹出一个带确定和取消按钮的对话框——确定返 ...

  2. linux 做gw(nat)详细配置

                          linux 做企业网关gw(nat)详细配置   最近因为公司的路由器老化导致上网时断时续,上半小时网就断一次网,为此我头疼不已,本着为公司节约成本的宗旨, ...

  3. SQL 中的 AND OR

    AND 和 OR 运算符用于基于一个以上的条件对记录进行过滤. AND 和 OR 运算符 AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来. 如果第一个条件和第二个条件都成立,则 ...

  4. java程序设计之循环链表

    照例来说点废话,愿自己生一颗温柔细腻的心,这样女朋友也许一个眼神,一个微笑,我就知道如何做,可惜内心与外表一样粗糙,这一生有幸认识她,愿天下有情人终成眷属. 循环链表,顾名思义循环就好了,所以建一个线 ...

  5. PAT 1049. 数列的片段和(20)

    给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列{0.1, 0.2, 0.3, 0.4},我们有(0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1 ...

  6. CORS详解

    介绍 由于同源策略的缘故,以往我们跨域请求,会使用诸如JSON-P(不安全)或者代理(设置代理和维护繁琐)的方式.而跨源资源共享(Cross-Origin Resource Sharing)是一个W3 ...

  7. [LeetCode] Perfect Rectangle 完美矩形

    Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover o ...

  8. 华为5G空口新技术(2015年)

    2015-03-24 长江后浪推前浪,4G建设方兴未艾,业界关于5G的讨论已如火如荼.对于每一代移动通信,空口技术都相当于王冠上的明珠. 在月初的世界移动通信大会上,华为发布了面向5G的新空口,并展出 ...

  9. 齐夫定律, Zipf's law,Zipfian distribution

    齐夫定律(英语:Zipf's law,IPA英语发音:/ˈzɪf/)是由哈佛大学的语言学家乔治·金斯利·齐夫(George Kingsley Zipf)于1949年发表的实验定律. 它可以表述为: 在 ...

  10. C# 提交网页请求时出现如下错误: System.Net.WebException: 操作超时

    原因一: 连接超时时间 Timeout 以及写入Post数据超时时间 ReadWriteTimeout 设置得太短,一般要设置大于6000ms. 原因二: Expect100Continue 属性的值 ...