win32 - service的创建
参考这篇教程:Simple Windows Service in C++
安装service需要在管理员权限下运行cmd,并输入下面的命令行
C:\>sc create "My Sample Service" binPath= C:\SampleService.exe
My Sample Service是service name,可以随意更改。 后面的exe程序是我们需要执行的service,代码如下。
卸载service,输入,
C:\>sc delete "My Sample Service"
代码样例:
#include <Windows.h>
#include <tchar.h>
#include <wtsapi32.h> #pragma comment(lib,"Wtsapi32.lib") SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE; HANDLE g_hChildStd_Rd = NULL;
HANDLE g_hChildStd_Wr = NULL; VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam); #define SERVICE_NAME _T("My Sample Service") int _tmain(int argc, TCHAR* argv[])
{
OutputDebugString(_T("My Sample Service: Main: Entry")); SERVICE_TABLE_ENTRY ServiceTable[] =
{
{(LPWSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
}; if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
OutputDebugString(_T("My Sample Service: Main: StartServiceCtrlDispatcher returned error"));
return GetLastError();
} OutputDebugString(_T("My Sample Service: Main: Exit"));
return 0;
} VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
HANDLE hThread;
DWORD Status = E_FAIL; OutputDebugString(_T("My Sample Service: ServiceMain: Entry")); g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); if (g_StatusHandle == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));
goto EXIT;
} // Tell the service controller we are starting
ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
} /*
* Perform tasks neccesary to start the service here
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Service Start Operations")); // Create stop event to wait on later.
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error")); g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
} // Tell the service controller we are started
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
} // Start the thread that will perform the main task of the service
hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL); OutputDebugString(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete")); // Wait until our worker thread exits effectively signaling that the service needs to stop
WaitForSingleObject(hThread, INFINITE); OutputDebugString(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled")); /*
* Perform any cleanup tasks
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Cleanup Operations")); CloseHandle(g_ServiceStopEvent); g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
} EXIT:
OutputDebugString(_T("My Sample Service: ServiceMain: Exit")); return;
} VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Entry")); switch (CtrlCode)
{
case SERVICE_CONTROL_STOP: OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SERVICE_CONTROL_STOP Request")); if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break; /*
* Perform tasks neccesary to stop the service here
*/ g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 4; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SetServiceStatus returned error"));
} // This will signal the worker thread to start shutting down
SetEvent(g_ServiceStopEvent); break; default:
break;
} OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Exit"));
} DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));
WCHAR station[] = L"Winsta0\\default";
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL; CreatePipe(&g_hChildStd_Rd, &g_hChildStd_Wr, &saAttr, 0); STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdOutput = g_hChildStd_Wr;
si.hStdError = g_hChildStd_Wr;
si.lpDesktop = station;
si.dwFlags = STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi; HANDLE hToken;
bool err = WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &hToken);
WCHAR path[] = L"D:\\child.exe";
if (CreateProcessAsUser(hToken, path, NULL, 0, 0, true, CREATE_NO_WINDOW, 0, 0, &si, &pi))
{
CloseHandle(g_hChildStd_Wr);
DWORD ret = WaitForSingleObject(pi.hProcess, 2000); //wait for the child process exit.
if (ret == 0)
{
WCHAR chBuf[100]= L"HELLO WORLD";
DWORD dwRead, dwWritten,
err = ReadFile(g_hChildStd_Rd, chBuf, 100, &dwRead, NULL);
HANDLE hFile = CreateFile(L"123.txt", // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
WriteFile(
hFile, // open file handle
chBuf, // start of data to write
100, // number of bytes to write
&dwWritten, // number of bytes that were written
NULL); // no overlapped structure
}
}
// Periodically check if the service has been requested to stop
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
{
/*
* Perform main service function here
*/ // Simulate some work by sleeping
Sleep(3000);
} OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit")); return ERROR_SUCCESS;
}
在Winsta0\default中创建子进程,在service中使用CreateProcessAsUser调用子进程。
文档参考:Window Stations
如果需要service与子进程建立通信,可以使用匿名管道,代码中已经创建了管道,我没有使用它们。
如果对匿名管道的数据传输有兴趣的,可以参考我的另外一篇文章: win32 - 匿名管道的使用
win32 - service的创建的更多相关文章
- Web Service 的创建简单编码、发布和部署
最近,老大准备将已有的C/S架构项目中的通信部分做成通用,需要将其支持WebService为以后项目向着B/S架构升级做好铺垫,为此身为屌丝的我去各种百度WebService是个什么卵玩意,然后逐渐搭 ...
- 在Salesforce中向外公布Service去创建Lead,并且用Asp.Net去调用此Service
1):在Salesforce中如何配置,向外公布此Service,请看如下链接: http://www.shellblack.com/marketing/web-to-lead/ 2):如何在Asp. ...
- Win32 SDK程序创建一些控件(简单调用InitCommonControlsEx,并指定ICC_LISTVIEW_CLASSES控件就可以了)
在Win32 SDK中创建一些控件的时候需要注意一下(具体是哪些控件请参看MSDN文档中列出来的) /* MSDN:Carries information used to load common co ...
- Win32 多线程的创建方法和基本使用
Win32多线程的创建方法主要有: (1)CreateThread() (2)_beginthread()&&_beginthreadex() (3)AfxBeginThread() ...
- SQL Server Service Broker创建单个数据库会话
概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...
- SQL Server Service Broker创建单个数据库会话(消息队列)
概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...
- Android的Service的创建与使用
Service介绍 Service是Android四大组件中与Activity最为相似的组件,它们都代表可执行的程序,区别是:Service一直在后台运行,没有用户界面.使用service要向Acti ...
- Docker Kubernetes Service 代理服务创建
Docker Kubernetes Service 代理服务创建 创建Service需要提前创建好pod容器.再创建Service时需要指定Pod标签,它会提供一个暴露端口默会分配容器内网访问的唯一 ...
- C# window service的创建
其实我也是第一次在博客园写博客,看到那些高手说自己要多动手写博客,于是乎自己也尝试尝试. 废话不多说.这几天在研究window service,通过查找各种大神写的博客,我终于成功的自己写出来了. 下 ...
- 从微信推送看Android Service的创建和销毁
启动服务是有两组参数影响服务的状态. 1.在onStartCommand(Intent intent, int flags, int startId) 接口中返回值,例如 START_STICKY; ...
随机推荐
- [转帖]被误解的CPU利用率、超线程、动态调频 —— CPU 性能之迷 Part 1
https://blog.mygraphql.com/zh/notes/hw/hyper-threading/ 引 性能测试.压力测试.业务系统性能容量评估.这 3 件事,可以认为是大部分程序员/软件 ...
- [转帖]Oracle数据库下PreparedStatementCache内存问题解决方案
https://github.com/alibaba/druid/wiki/Oracle%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8BPreparedStatementCac ...
- [转帖]Shell三剑客之awk
目录 awk简述 awk的工作过程 awk的工作原理 awk的基本格式及其内置变量 getline 文本内容匹配过滤打印 对字段进行处理打印 条件判断打印 awk的三元表达式与精准筛选用法 awk的精 ...
- [转帖]Dockerfile中CMD和ENTRYPOINT命令详解
https://www.jb51.net/article/136264.htm Dockerfile中的ENTRYPOINT指令和CMD指令都可以设置容器启动时要执行的命令,但用途是有略微不同的. ...
- [转帖]iptables规则链执行顺序
https://www.cnblogs.com/yum777/articles/8514636.html iptables 是采用规则堆栈的方式来进行过滤,当一个封包进入网卡,会先检查 Prerout ...
- [转帖]磁盘负载指标 %iowait, await, %util 的正确理解
说明 %iowait, await, %util 是用来衡量硬盘负载的三个指标, 但是这几个指标通常容易被误解, 实际上, 这三个指标单纯的高, 并不一定能说明相应的磁盘有问题或者有瓶颈, 而是需要结 ...
- Ubuntu2204设置固定IP地址
前言 Ubuntu每次升级都会修改一部分组件. 从1804开始Ubuntu开始使用netplan的方式进行网络设置. 但是不同版本的配置一直在升级与变化. 今天掉进坑里折腾了好久. 所以这边总结一下, ...
- 如何写RN样式 如何写RN组件 如何满屏 如何使用变量
app.js 文本水平居中了哈 控制文本的大小 字体颜色等 只有在文本元素上去控制哈 import React from 'react'; import {View, Text, StyleSheet ...
- Vue3中ref和toRef的区别
1. ref是复制,视图会更新 如果利用ref将某一个对象中的某一个属性值变成响应式数据 我们修改响应式数据是不会影响原始数据的; 同时视图会跟新. ref就是复制 复制是不会影响原始数据的 < ...
- vue如何获取动态添加的类
动态添加的类.你在声明周期中的mounted中是拿不到的. 是有在updata这个声明周期中才可以拿到的. 因为此时数据才跟新完成