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; ...
随机推荐
- [转帖]jdbc连接mysql设置session variables 参数变量
目录 两种方式 连接串设置[^1] 执行语句中设置 两种方式 url连接串中设置 执行语句中设置 连接串设置1 sessionVariables jdbc.url=jdbc:mysql://xxxx. ...
- [转帖]DOCKER默认网段和主机网段冲突解决
https://www.cnblogs.com/yinliang/p/13189334.html 一. docker默认网卡docker0 172.17.0.0可能会与主机冲突,这时候需要修改dock ...
- [转帖]k8s之PV、PVC、StorageClass详解
https://zhuanlan.zhihu.com/p/128552232 导读 上一篇写了共享存储的概述以及一个简单的案例演示.这一篇就写一下PV和PVC. PV是对底层网络共享存储的抽象,将共享 ...
- Intel 的家用CPU的后缀
Intel 也奸商 各种后缀 最开始P 表示无核显版本 现在用 F来表示了.. 略坑. 一下来源百家号: https://baijiahao.baidu.com/s?id=16276964705166 ...
- vim配置的学习与总结
摘要 有时候在linux里面操作需要使用粘贴以及其他处理. 很多发行版, 遇到 # 会自动退格, 很难受. 想着能够处理一下vim的默认设置可以好很多. 所以这里简单总结一下. 配置文件 vim的配置 ...
- C#开源免费的开发效率提升利器:DevToys开发人员的瑞士军刀!
前言 今天分享一款基于C#开源(MIT License开源协议).免费.离线.功能齐全的Windows开发者工具箱,号称开发人员的瑞士军刀,可以帮助开发者完成日常工作开发中常用功能:DevToys. ...
- 行云部署成长之路--慢SQL优化之旅 | 京东云技术团队
当项目的SQL查询慢得像蜗牛爬行时,用户的耐心也在一点点被消耗,作为研发,我们可不想看到这样的事.这篇文章将结合行云部署项目的实践经验,带你走进SQL优化的奇妙世界,一起探索如何让那些龟速的查询飞 ...
- 【介绍一个工具】图形化界面查看一个 golang 二进制文件的汇编代码
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 通常,可以通过命令行工具,来查看一个代码文件对应的汇编代码 ...
- MacBook m2 笔记本 + k8s容器环境开发笔记
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 为最近两周在 MacBook m2 + k8s 容器环境的 ...
- chaincode中使用第三方库
本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处. 在fabric的chaincode开发时,有时候需要用到第三方库提供的功能.这 ...