当前位置: 首页 > news >正文

Golang 实现Windows服务

文章目录

      • 什么是windows服务
      • 如何注册windows服务
      • 用vc++实现windows服务:
      • Golang 实现 Windows 服务

什么是windows服务

Windows 服务是主要用于服务器环境而长期运行的应用程序, 这类程序不需要有用户界面或者任何模拟输出。 任何的用户消息通常都是记录在Windows 事件日志里。Windows Service可以在操作系统启动的时候开始,一直在后台运行,当有需要时也可以手动启动,我们可以通过管理工具里面的服务进行统一管理。
当系统启动完毕后,Windows服务并不需要通过登陆页面后才能启动,即使用户注销登录也不会停止,通常不和用户产生交互。
而我们启动一般的exe文件却要先登陆Windows后才能启动它,通常还有一个用户界面,命令行或者是GUI界面,通常由用户手动启动和停止。

如何注册windows服务

手工注册Windows服务得用得到windows下cmd命令(管理员身份)
注册服务 [ServiceTest]:

sc create ServiceTest binpath="/path/to/exe"

启动服务:

sc start ServiceTest

停止服务、删除服务:

sc stop ServiceTest
sc delete ServiceTest

用vc++实现windows服务:

首先要初始化 SERVICE_TABLE_ENTRY 结构体数组,

SERVICE_TABLE_ENTRY serviceEntryTable[2];
serviceEntryTable[0].lpServiceName = L"ServiceTest";
serviceEntryTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceWorker;
serviceEntryTable[1].lpServiceName = NULL;
serviceEntryTable[1].lpServiceProc = NULL;

其中,ServiceTest 是要注册的服务的名称,ServiceWorker 是服务主工作函数。
通过调用 StartServiceCtrlDispatcher(serviceEntryTable),把调用进程的主线程转换为控制分派器,启动一个新线程运行分派表中的 ServiceWorker 函数。

然后,准备ServiceWorker函数,
ServiceWorker 服务程序的主运行函数,除了与普通函数执行任务之外,
它还需要完成一个工作:通过调用 RegisterServiceCtrlHandler向服务控制管理器注册控制函数。
并且调用 向 SCM(服务控制管理器)报告当前的状态。

SERVICE_STATUS serviceStatus;
serviceStatus.dwServiceType = SERVICE_WIN32;
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
serviceStatus.dwWin32ExitCode = 0;
serviceStatus.dwServiceSpecificExitCode = 0;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwWaitHint = 0;
serviceStatusHandle = ::RegisterServiceCtrlHandler(L"ServiceTest", ServiceCtrlHandler);

其中 ServiceCtrlHandler是控制处理函数,它接收 SCM 发来的控制命令,并且处理命令和回馈状态。

最后,准备控制处理函数 ServiceCtrlHandler
控制处理函数必须在30秒内返回,否则 SCM 会返回一个错,如果是一个比较耗时的操作,则需要另启一个线程来进行处理。

void WINAPI ServiceCtrlHandler(DWORD request)
{switch (request){case SERVICE_CONTROL_STOP:serviceRunning = false;serviceStatus.dwCurrentState = SERVICE_STOPPED;break;case SERVICE_CONTROL_SHUTDOWN:serviceRunning = false;serviceStatus.dwCurrentState = SERVICE_STOPPED;break;default:break;}SetServiceStatus(serviceStatusHandle, &serviceStatus);
}

完整示例代码
该示例实现了一个简单的windows服务程序,
每秒钟在C盘目录下打印一个数字。

#include <string>
#include <fstream>
#include <iostream>
#include <windows.h>using namespace std;bool serviceRunning = false;
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle;void WINAPI ServiceWorker(int argc, char** argv);
void WINAPI ServiceCtrlHandler(DWORD request);void ServiceLog(string str)
{fstream fout("c:/service_log.txt", ios::out | ios::app);if (!fout) {return;}fout << str << endl;
}void WINAPI ServiceWorker(int argc, char** argv)
{serviceStatus.dwServiceType = SERVICE_WIN32;serviceStatus.dwCurrentState = SERVICE_START_PENDING;serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;serviceStatus.dwWin32ExitCode = 0;serviceStatus.dwServiceSpecificExitCode = 0;serviceStatus.dwCheckPoint = 0;serviceStatus.dwWaitHint = 0;serviceStatusHandle = ::RegisterServiceCtrlHandler(L"ServiceTest", ServiceCtrlHandler);if (0 == serviceStatusHandle){ServiceLog("RegisterServiceCtrlHandler failed");return;}ServiceLog("RegisterServiceCtrlHandler success");serviceStatus.dwCurrentState = SERVICE_RUNNING;SetServiceStatus(serviceStatusHandle, &serviceStatus);// 工作内容,每隔一秒钟输出一个数字int num = 0;serviceRunning = true;while (serviceRunning){ServiceLog(to_string(num++));Sleep(1000);}ServiceLog("Service Stopped");
}void WINAPI ServiceCtrlHandler(DWORD request)
{switch (request){case SERVICE_CONTROL_STOP:serviceRunning = false;serviceStatus.dwCurrentState = SERVICE_STOPPED;break;case SERVICE_CONTROL_SHUTDOWN:serviceRunning = false;serviceStatus.dwCurrentState = SERVICE_STOPPED;break;default:break;}SetServiceStatus(serviceStatusHandle, &serviceStatus);
}void main()
{SERVICE_TABLE_ENTRY serviceEntryTable[2];serviceEntryTable[0].lpServiceName = L"ServiceTest";serviceEntryTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceWorker;serviceEntryTable[1].lpServiceName = NULL;serviceEntryTable[1].lpServiceProc = NULL;StartServiceCtrlDispatcher(serviceEntryTable);
}

Golang 实现 Windows 服务

Go语言有第三方封装好的库,可以用很少的代码实现一个Windows服务,相比C++方便了很多。

 package mainimport ("log""os""time""github.com/kardianos/service")type program struct{}func (p *program) Start(s service.Service) error {go p.run()return nil}func (p *program) run() {for {time.Sleep(time.Second)log.Println("running")}}func (p *program) Stop(s service.Service) error {return nil}func init() {f, err := os.Create("d:/gowinservice.txt")if err != nil {log.Fatal(err)}log.SetOutput(f)}func main() {svcConfig := &service.Config{Name: "GoService",DisplayName: "GoServiceDis",Description: "windows service form golang",}prg := &program{}s, err := service.New(prg, svcConfig)if err != nil {log.Fatal(err)}if len(os.Args) > 1 {if os.Args[1] == "install" {s.Install()log.Println("服务安装成功")return}if os.Args[1] == "remove" {s.Uninstall()log.Println("服务卸载成功")return}}if err = s.Run(); err != nil {log.Fatal(err)}}

http://www.taodudu.cc/news/show-4974484.html

相关文章:

  • Qt实现Windows服务程序
  • minio:安装部署并安装成windows服务
  • C# 创建Windows Service(Windows服务)程序
  • 如何创建Windows服务
  • window服务是什么?
  • Windows服务(Service)安装及启动停止方案
  • Windows 服务介绍(本地系统、网络服务、本地服务以及相关的power shell命令
  • windows服务ServiceProcess
  • Windows 服务
  • js 解析json数据实现快递包裹的查询
  • 12、 一键查快递
  • 已知顺丰快递既可以发陆运,也可以发空运;EMS只能发空运,圆通只能发陆运。 小明现在发送快递,为其设计两个方法,分别用来发空运和陆运。
  • valgrind 工具使用
  • valgrind 工具介绍和简单的使用
  • valgrind 简介(内存检查工具)
  • 工具:valgrind学习
  • Win10下CS231n assignment1 环境配置
  • cs231n assignment2 PyTorch
  • Stanford cs231n'18 课程及作业详细解读
  • CS231n第一节
  • cs231n笔记总结
  • 【实验小结】cs231n assignment1 knn 部分
  • CS231n 两层神经网络反向传播实现
  • 【深度学习】cs231n计算机视觉 CNN(卷积神经网络)
  • FreeCAD错误:没有激活的实体 解决办法
  • springboot 整合mysql clickhouse 多数据源
  • 自定义数据源 整合 Mybatis-Plus-多租户
  • 2020FME博客大赛——FME在数据整合中的应用
  • 从零开始Tableau | 2.数据整合
  • 代码分析 | 单细胞转录组数据整合详解