参考这篇教程: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的创建的更多相关文章

  1. Web Service 的创建简单编码、发布和部署

    最近,老大准备将已有的C/S架构项目中的通信部分做成通用,需要将其支持WebService为以后项目向着B/S架构升级做好铺垫,为此身为屌丝的我去各种百度WebService是个什么卵玩意,然后逐渐搭 ...

  2. 在Salesforce中向外公布Service去创建Lead,并且用Asp.Net去调用此Service

    1):在Salesforce中如何配置,向外公布此Service,请看如下链接: http://www.shellblack.com/marketing/web-to-lead/ 2):如何在Asp. ...

  3. Win32 SDK程序创建一些控件(简单调用InitCommonControlsEx,并指定ICC_LISTVIEW_CLASSES控件就可以了)

    在Win32 SDK中创建一些控件的时候需要注意一下(具体是哪些控件请参看MSDN文档中列出来的) /* MSDN:Carries information used to load common co ...

  4. Win32 多线程的创建方法和基本使用

    Win32多线程的创建方法主要有: (1)CreateThread() (2)_beginthread()&&_beginthreadex() (3)AfxBeginThread() ...

  5. SQL Server Service Broker创建单个数据库会话

    概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...

  6. SQL Server Service Broker创建单个数据库会话(消息队列)

    概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...

  7. Android的Service的创建与使用

    Service介绍 Service是Android四大组件中与Activity最为相似的组件,它们都代表可执行的程序,区别是:Service一直在后台运行,没有用户界面.使用service要向Acti ...

  8. Docker Kubernetes Service 代理服务创建

    Docker Kubernetes  Service 代理服务创建 创建Service需要提前创建好pod容器.再创建Service时需要指定Pod标签,它会提供一个暴露端口默会分配容器内网访问的唯一 ...

  9. C# window service的创建

    其实我也是第一次在博客园写博客,看到那些高手说自己要多动手写博客,于是乎自己也尝试尝试. 废话不多说.这几天在研究window service,通过查找各种大神写的博客,我终于成功的自己写出来了. 下 ...

  10. 从微信推送看Android Service的创建和销毁

    启动服务是有两组参数影响服务的状态. 1.在onStartCommand(Intent intent, int flags, int startId) 接口中返回值,例如 START_STICKY;  ...

随机推荐

  1. [转帖]Always-on Profiling for Production Systems

    https://0x.tools/ 0x.tools (GitHub) is a set of open-source utilities for analyzing application perf ...

  2. 申威3231_SPECJVM2008的测试结果与信创服务器对比验证

    申威3231_SPECJVM2008的测试结果与信创服务器对比验证 背景 周六找同事将在公司里的机器进行了开机. 然后验证了config.guess和config.sub 的确是可以通过复制/usr ...

  3. [转帖]Nginx(3):上手Nginx,从配置文件开始

    https://cloud.tencent.com/developer/article/1886147?areaSource=&traceId=   其实吧,我配置 tcp 负载均衡的时候也就 ...

  4. jmaps

    #!/bin/bash # # jmaps - creates java /tmp/perf-PID.map symbol maps for all java processes. # # This ...

  5. date的命令使用.

    date命令的使用 1.直接用date命令显示日期时间 在命令行中输入date然后回车,显示结果"Wed Aug 7 08:58:07 CST 2019".这是系统根据设定的时区显 ...

  6. dispaly结合背景图片会提升加载性能

    1.display的常见现象 我们很多人都知道,display可以让元素实现隐藏或者显示. 或者让行级元素变成块级元素. 对它的认识也是比较准确的. 如果一个元素使用了display:none; 那么 ...

  7. 【代码分享】使用 avx2 + 查表法,优化凯撒加密

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 接上一篇:[代码分享]使用 avx512 + 查表法,优化 ...

  8. 在K8S中,Pod创建过程包括什么?

    在Kubernetes(K8s)中,Pod的创建过程通常包括以下步骤: 提交Pod定义: 用户通过kubectl命令行工具或者调用API Server接口,提交一个包含Pod配置信息的YAML或JSO ...

  9. U盘制作linux启动盘

    1.前期准备 使用 U 盘安装 Linux 系统,需要准备以下工具:    ·大容量的U盘(安装 CentOS 6.x 系统,U 盘容量至少 8 G): ·UltraISO 工具,用来制作 U 盘启动 ...

  10. Vue基础系统文章06---导入和导出

    一.导入和导出 如果想要在一个Js文件中用另一个js文件的代码 1.将js文件中的变量和函数导出 let a = "aaaa" function show() { console. ...