使用VS创建windows服务项目:
![](https://i-blog.csdnimg.cn/blog_migrate/1f5b89347b7ea7cace630ec8e8c348c8.png)
创建好项目 会出现一个设计界面 右键弹出对话框 选择添加安装程序
![](https://i-blog.csdnimg.cn/blog_migrate/c295781da892a470ec5db11e84ddfdd0.png)
名字什么的自己可以改:
![](https://i-blog.csdnimg.cn/blog_migrate/45efd36c3db601fb79496cbc6f180987.png)
项目目录:
![](https://i-blog.csdnimg.cn/blog_migrate/8d4eeb61f4eef6bbe0c147cb4d981564.png)
打开项目中的ProjectInstaller.Designer.cs 修改windows服务名称描述以及启动方式等:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
partial
class
ProjectInstaller
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private
System.ComponentModel.IContainer components =
null
;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected
override
void
Dispose(
bool
disposing)
{
if
(disposing && (components !=
null
))
{
components.Dispose();
}
base
.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private
void
InitializeComponent()
{
components =
new
System.ComponentModel.Container();
this
.spInstaller =
new
System.ServiceProcess.ServiceProcessInstaller();
this
.sInstaller =
new
System.ServiceProcess.ServiceInstaller();
this
.spInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this
.spInstaller.Username =
null
;
this
.spInstaller.Password =
null
;
this
.sInstaller.ServiceName =
"CallApiExeTask"
;
this
.sInstaller.Description =
"定时调用api接口,获取任务后操作数据库"
;
this
.sInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
this
.Installers.AddRange(
new
System.Configuration.Install.Installer[] {
this
.spInstaller,
this
.sInstaller});
}
#endregion
private
System.ServiceProcess.ServiceProcessInstaller spInstaller;
private
System.ServiceProcess.ServiceInstaller sInstaller;
}
|
打开Service1 写入想要执行的操作等:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
public
partial
class
Service1 : ServiceBase
{
System.Timers.Timer timer1;
public
Service1()
{
InitializeComponent();
}
protected
override
void
OnStart(
string
[] args)
{
timer1 =
new
System.Timers.Timer();
timer1.Interval = 3000;
timer1.Elapsed +=
new
System.Timers.ElapsedEventHandler(timer1_Elapsed);
timer1.Enabled =
true
;
}
/// <summary>
/// 定时器 调用的方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private
void
timer1_Elapsed(
object
sender, System.Timers.ElapsedEventArgs e)
{
var
client =
new
HttpClient();
client.BaseAddress =
new
Uri(
"http://192.168.10.239:9000/"
);//接口url
string
data = client.GetStringAsync(
"ZyTest"
).Result;
}
protected
override
void
OnStop()
{
this
.timer1.Enabled =
false
;
}
protected
override
void
OnPause()
{
base
.OnPause();
}
protected
override
void
OnContinue()
{
base
.OnContinue();
}
protected
override
void
OnShutdown()
{
base
.OnShutdown();
}
}
|
Program.cs中可以设置主方法调用的service服务:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static
class
Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static
void
Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun =
new
ServiceBase[]
{
new
Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
|
生成解决方案,以上就完成了windows服务的编写
下面需要把服务安装到服务器或者pc上:
首先在网上下载一个installutil.exe文件(百度直接搜索可以下载) 放到...\bin\Debug文件夹下:
用管理员身份打开命令提示符:
![](https://i-blog.csdnimg.cn/blog_migrate/201e4ee555dc5a173b93c5e888465727.png)
输入 cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 回车
如果你的程序是2.0的framework则需要输入 cd C:\Windows\Microsoft.NET\Framework\v2.0.50727
![](https://i-blog.csdnimg.cn/blog_migrate/0e2f053a3b4e1f3380304ac2ef2c0eeb.png)
输入 InstallUtil.exe D:\work\windows服务\WinService4ExeApi\WinService4ExeApi\bin\Debug\WinService4ExeApi.exe 回车 完成安装
说明: D:\work\windows服务\WinService4ExeApi\WinService4ExeApi\bin\Debug\WinService4ExeApi.exe表示项目生成的exe文件位置(也可以把debug文件夹单独copy到其他地方重命名)
![](https://i-blog.csdnimg.cn/blog_migrate/41cff2bd99eefec679d81fcacf066132.png)
安装完成后:打开服务就可以看到了
![](https://i-blog.csdnimg.cn/blog_migrate/2c61656183e6cc0600cb63e604f7b9f7.png)
如果需要卸载此服务:打开cmd 直接输入 sc delete CallApiExeTask便可 CallApiExeTask为你的服务名称
![](https://i-blog.csdnimg.cn/blog_migrate/2492fa34173ee1b8614562528a4fc6b5.png)
ps: 如果你的windows服务程序修改了 需要更新成新版本 不用卸载服务再安装 只需先停掉该服务 然后把文件夹内的文件替换为新的文件 重新启动该服务即可
原文地址:https://www.cnblogs.com/Alex-zqzy/p/7243572.html
----------------------------------------------------------------------------------------------------------------------------------------------
开篇语
因工作内容需要做一个windows服务,此前并没有相关经验,所以做了一个demo来跑跑这个梗(高手跳过,需要的来踩)~
效果如下:打开服务,可以找到我们新增的一个windows服务,这个demo是定时向一个txt文件输出一句话
![](https://i-blog.csdnimg.cn/blog_migrate/95085f6778f960caefba6e0ae0265f32.png)
生成的以日期命名的txt文件
![](https://i-blog.csdnimg.cn/blog_migrate/58301866a5bbb5b5a930e271a80be45e.png)
打开文件结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/fb9ec424690157dfb3ea23f5c22ab6fa.png)
全过程梳理
本文将只粗略简单的介绍一下windows服务是如何开发和安装的
一、创建windows服务
如图新建一个Windows服务
![](https://i-blog.csdnimg.cn/blog_migrate/acc8f1dbdaae92542cc99b7aaa9d9456.png)
进入程序如图
![](https://i-blog.csdnimg.cn/blog_migrate/dec5d2d4ffa26ec9878c9e776821e5e7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b87b65dac6d74cf4491c08ff416fe0c8.png)
空白服务如下
1 public partial class Service1 : ServiceBase
2 {
3 System.Threading.Timer recordTimer;
4
5
6 public Service1()
7 {
8 InitializeComponent();
9 }
10
11
12 protected override void OnStart(string[] args)
13 {
14 }
15
16
17 protected override void OnStop()
18 {
19 }
20 }
只要在OnStart里完成你的功能代码即可。本例中我们做一个定时向本地文件写记录的功能。
创建一个类,用户写文件
1 /// <summary>
2 /// 保存至本地文件
3 /// </summary>
4 /// <param name="ETMID"></param>
5 /// <param name="content"></param>
6 public static void SaveRecord(string content)
7 {
8 if (string.IsNullOrEmpty(content))
9 {
10 return;
11 }
12 FileStream fileStream = null;
13 StreamWriter streamWriter = null;
14 try
15 {
16 string path = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, string.Format("{0:yyyyMMdd}", DateTime.Now));
17
18
19 using (fileStream = new FileStream(path, FileMode.Append, FileAccess.Write))
20 {
21 using (streamWriter = new StreamWriter(fileStream))
22 {
23 streamWriter.Write(content);
24
25
26 if (streamWriter != null)
27 {
28 streamWriter.Close();
29 }
30 }
31
32 if (fileStream != null)
33 {
34 fileStream.Close();
35 }
36 }
37 }
38 catch { }
39 }
如图那么在Service1中调用
1 public partial class Service1 : ServiceBase
2 {
3 System.Threading.Timer recordTimer;
4 public Service1()
5 {
6 InitializeComponent();
7 }
8
9 protected override void OnStart(string[] args)
10 {
11 IntialSaveRecord();
12 }
13 /// <summary>
14 /// 定时检查,并执行方法
15 /// </summary>
16 /// <param name="source"></param>
17 /// <param name="e"></param>
18 private void IntialSaveRecord()
19 {
20 TimerCallback timerCallback = new TimerCallback(CallbackTask);
21
22 AutoResetEvent autoEvent = new AutoResetEvent(false);
23 recordTimer = new System.Threading.Timer(timerCallback, autoEvent, 0, 10000);//其中参数10000表示延时执行服务的时间间隔,毫秒为单位
24 }
25 //方法
26 private void CallbackTask(Object stateInfo)
27 {
28 Show_Java.SaveRecord(string.Format(@"当前记录时间:{0},状况:程序运行正常!", DateTime.Now));
29 }
30
31 protected override void OnStop()
32 {
33 if (recordTimer != null)
34 {
35 recordTimer.Dispose();
36 }
37 }
38 }
安装程序
这样服务算是写的差不多了,下面添加一个安装程序,用于安装服务。
如图,在service1页面空白处右键-添加安装程序
![](https://i-blog.csdnimg.cn/blog_migrate/751b2173cb32470ae0a96a5afb21e7e0.png)
添加一个安装程序,如图,添加完成后
![](https://i-blog.csdnimg.cn/blog_migrate/3d7d1277b9516f0c761d869d9e482f59.png)
设置相应的属性,给serviceInstaller1设置属性,主要是描述信息。如图,
![](https://i-blog.csdnimg.cn/blog_migrate/9059e839bb166159786a4a4df7d02bb8.png)
给serviceProcessInstaller1设置,主要是account。一般选localsystem,如图
![](https://i-blog.csdnimg.cn/blog_migrate/969e41e1f1ce60015f3fe6efea9a45a6.png)
这样服务已经写好了。那么如何添加到windows服务里面去呢。这里推荐一种简单实用的方法(也可以通过代码来安装,这里就不做过多讲解了)
安装服务
上面写好的服务,最终生成的是一个exe文件。如图,
![](https://i-blog.csdnimg.cn/blog_migrate/f63053f51b95adeacc0db5b6167a6b9d.png)
安装程序安装时需要用到这个exe的路径,所以方便起见,将这个生成的exe文件拷贝至安装程序的运行目录下。(这里我将exe拷贝到D盘shows文件夹下面)
![](https://i-blog.csdnimg.cn/blog_migrate/3f7b2f1901979f7babc12c5694623dc5.png)
用管理员权限打开cmd窗口
![](https://i-blog.csdnimg.cn/blog_migrate/d4d280559ea6b5d2cf2e296d89a71245.png)
然后分别执行
@SET FrameworkDir=%WINDIR%\Microsoft.NET\Framework
@SET FrameworkVersion=v2.0.50727
@SET PATH=%FrameworkDir%\%FrameworkVersion%;%WINDIR%\System32;%PATH%;
InstallUtil.exe D:\路径\程序名称.exe //安装服务
InstallUtil.exe /u D:\路径\程序名称.exe //卸载服务(程序安装好了,如果想要修改,需要先卸载该服务,再次执行安装)
![](https://i-blog.csdnimg.cn/blog_migrate/40b87ddb58577820526119fe715706c1.png)
运行后若无错误,效果应该如下
![](https://i-blog.csdnimg.cn/blog_migrate/d949a3c9b774223d06d6ded8cdaf0819.png)
运行完后在服务中查看,如图:
![](https://i-blog.csdnimg.cn/blog_migrate/da7edb80c45ec75ff33ee6bec50bbd4d.png)
再在安装目录下看记录的文件(因为我们设置项目的时候选的是手动,此时要记住启动该服务,程序才会定时执行)
![](https://i-blog.csdnimg.cn/blog_migrate/11139a99b938b5a3266460198344aead.png)
![](https://i-blog.csdnimg.cn/blog_migrate/01ef3031891caf0cb6411311423eb0d3.png)
这样,一个windows服务算是安装成功了。(方法多种多样,希望各位多提宝贵意见,不胜感激~)
原文地址:https://www.cnblogs.com/zhangxiaoyong/p/5920678.html
——————————————————————————————————————————————
基于0起步来创建一个服务,做到简单的记录时间日志功能,其具体招行方法可自行添加。
1.创建服务
![](https://i-blog.csdnimg.cn/blog_migrate/6cce4b33311851816ddc6db8596cf478.png)
2.删除默认服务文件
![](https://i-blog.csdnimg.cn/blog_migrate/e1993cc17baf396c9eedc3634b202bcd.png)
3.添加自己的服务文件
![](https://i-blog.csdnimg.cn/blog_migrate/ccdcc1e4f73b5fe8e3a7735707cbc394.png)
4.更改启动项目
![](https://i-blog.csdnimg.cn/blog_migrate/6760cb95a0c7d35321a34a8b31b4bf4e.png)
5. 引用 using System.Timers;并添加FileClass类
![](https://i-blog.csdnimg.cn/blog_migrate/faf3f6b50257b5072cdf684d12dbe319.png)
FileClass类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace TerminalTrance
{
public class FileClass
{
//创建文件夹
//参数:path 文件夹路径
public bool CreateFolder(string path)
{
try
{
if (Directory.Exists(path))
{
return true;
}
if (!Directory.Exists(path.Substring(0, path.LastIndexOf("\\"))))
{ //若路径中无“\”则表示路径错误
return false;
}
else
{
//创建文件夹
DirectoryInfo dirInfo = Directory.CreateDirectory(path);
return true;
}
}
catch (Exception ex)
{
return false;
}
}
//创建文件
//参数:path 文件路径
public void CreateFile(string path)
{
try
{
if (CreateFolder(path.Substring(0, path.LastIndexOf("\\"))))
{
if (!File.Exists(path))
{
FileStream fs = File.Create(path);
fs.Close();
}
}
}
catch (Exception ex)
{
return;
}
}
//删除文件
//参数:path 文件夹路径
public void DeleteFile(string path)
{
try
{
if (!File.Exists(path))
{
return;
}
else
{
File.Delete(path);
}
}
catch (Exception ex)
{
return;
}
}
//写文件
//参数:path 文件夹路径 、content要写的内容
public void WriteFile(string path, string content)
{
try
{
if (!File.Exists(path))
{
CreateFile(path);
}
FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(content);
sw.Close();
}
catch (Exception ex)
{
return;
}
}
/// <summary>
/// 将即时日志保存入日志文件
/// </summary>
public void WriteLogFile(string directoryPath, string content)
{
if (!Directory.Exists(directoryPath))
{
CreateFolder(directoryPath);
}
try
{
//写入新的文件
string filePath = directoryPath + "\\" + DateTime.Now.Date.ToString("yyyyMMdd") + ".log";
FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(content);
sw.Close();
fs.Close();
}
catch (Exception ex)
{
}
}
}
}
6. 添加上步中需要的InitService()方法
/// <summary>
/// 初始化服务参数
/// </summary>
private void InitService()
{
base.CanShutdown = true;
base.CanStop = true;
base.CanPauseAndContinue = true;
this.ServiceName = MainService.serviceName;
this.AutoLog = false;//为了使用自定义日志,必须将 AutoLog 设置为 false
tim = new System.Timers.Timer();
tim.Elapsed += new ElapsedEventHandler(tim_Elapsed);
tim.Interval = 5000;
tim.AutoReset = true;
}
7. 解决System不包含windows属性问题,引用程序集。
![](https://i-blog.csdnimg.cn/blog_migrate/957f9d6b2d9d7307ce27817cdae7a819.png)
8.添加上面引用 的 tim_Elapsed 定时方法
private void tim_Elapsed(object sender, EventArgs e)
{
StartThread();
}
/// <summary>
/// 开始任务
/// </summary>
private void StartThread()
{
MessageAdd(serviceName + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
/// <summary>
/// 日志记录
/// </summary>
/// <param name="serviceName">内容</param>
public void MessageAdd(string str)
{
try
{
fileclass.WriteLogFile(logPath, str);//写入记录日志
}
catch
{
}
}
9.此时生成解决方案是成功的
10.在OnStart等中写入自己的方法,这里用日志记录
protected override void OnStart(string[] args)
{
try
{
this.tim.Enabled = true;
this.tim.Start();
}
catch (Exception ex)
{
MessageAdd("OnStart错误:" + ex.Message);
}
MessageAdd(serviceName + "已成功启动!");
}
protected override void OnStop()
{
try
{
this.tim.Stop();
}
catch (Exception ex)
{
MessageAdd("OnStop错误:" + ex.Message);
}
MessageAdd(serviceName + "已停止!");
}
protected override void OnContinue()
{
this.tim.Start();
base.OnContinue();
}
protected override void OnPause()
{
this.tim.Stop();
base.OnPause();
}
11.给服务添加安装程序。右键鼠标单击MainService.cs[设计]*选项卡选项“添加安装程序”。
![](https://i-blog.csdnimg.cn/blog_migrate/e0afa7d1c4cee0bcf5f44e4a939e1c25.png)
12.可以看见项目中多了如下文件和组件,serviceProcessInstaller1、serviceInstaller1是自动生成的
![](https://i-blog.csdnimg.cn/blog_migrate/74551de56b8867bdc2d3112e4248cb46.png)
13.设置组件serviceInstaller1的主要属性,StartType: AutoMatic自动启动;ServiceName: 服务系统标识,在cmd命令中执行sr start/stop/query等等命令时候使用,用来唯一标识一个Window服务
![](https://i-blog.csdnimg.cn/blog_migrate/88296d457de133c1ee681033ea9b88b2.png)
14.设置组件serviceProcessInstaller1的主要属性,Accout:账户类型,LocalSystem本地系统服务;
![](https://i-blog.csdnimg.cn/blog_migrate/024dae7c95f93a9fcd13c9f30f9e4060.png)
15.设置服务安装后“允许和桌面进行交互”,
需要在ProjectInstaller.cs中添加如下代码。
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
namespace TerminalTrance
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
protected override void OnAfterInstall(IDictionary savedState)
{
try
{
base.OnAfterInstall(savedState);
// 允许服务桌面交互
System.Management.ManagementObject myService = new System.Management.ManagementObject(string.Format("Win32_Service.Name='{0}'", this.serviceInstaller1.ServiceName));
System.Management.ManagementBaseObject changeMethod = myService.GetMethodParameters("Change");
changeMethod["DesktopInteract"] = true;
System.Management.ManagementBaseObject OutParam = myService.InvokeMethod("Change", changeMethod, null);
}
catch (Exception ex)
{
}
}
}
}
16.Windows服务的安装和卸载
代码写完后,编译通过后,就可以安装、卸载、调试服务了。
在执行安装或卸载服务前,我有把服务需要的相关文件,复制到C:\Service\下面或其他路径。一旦安装完成后,此目录不能变更,否则不能卸载该服务和服务运行会报错。
安装、卸载很简单,只要在VS命令行导航到,服务程序的路径。然后运行以下命令就OK了。
打开如图:
![](https://i-blog.csdnimg.cn/blog_migrate/7e384456870ca0c14eed2ba26af5707e.png)
安装服务:installutil C:\Service\TerminalTrance.exe
卸载服务:installutil /u C:\Service\TerminalTrance.exe
调试的话,只能先安装启动服务,然后将该服务附加到进程,就可以调试了。安装好服务后,就可以在win7服务管理里面,管理刚刚启动的服务了。
安装成功后可在服务中看到
![](https://i-blog.csdnimg.cn/blog_migrate/d4021141eada9a88e750e35df5342e19.png)
在服务程序中可以看到添加的服务
![](https://i-blog.csdnimg.cn/blog_migrate/00a367e1250225b9844f436eebc1a272.png)
可以看到程序的日志记录
![](https://i-blog.csdnimg.cn/blog_migrate/479b9e222c3c72cd5213e130b3aa9bc1.png)
另外一个方法是生成安装exe程序
1.解决方案右键=》新建项目=》选择安装程序
![](https://i-blog.csdnimg.cn/blog_migrate/f4670209bd4611cf90ebbaa8048c5e92.png)
2.安装项目右键=》添加=》项目输出,选择主项目
![](https://i-blog.csdnimg.cn/blog_migrate/81e8781927343fc4dd1469b351344d10.png)
3.安装项目右键=》视图=》自定义操作
4.自定义操作=》安装右键=》选择主输出
![](https://i-blog.csdnimg.cn/blog_migrate/c7f7683964df418df19953168d0fdc97.png)
5.卸载右键=》选择主输出
6.若有文件需要添加到安装后的文件夹中=》点击应用程序文件夹=》添加=》文件,选择文件。安装后就会生成指定文件。
![](https://i-blog.csdnimg.cn/blog_migrate/38c07802a5e3d0126f60398b70994786.png)
7.生成程序,完成,Setup文件夹中找到exe安装文件执行就 OK了。卸载也是执行此exe,按提示下一步就OK
原文地址:
http://www.cnblogs.com/zhangs1986/p/3502026.html