一个简单的Windows服务程序

56 篇文章 2 订阅
#include <iostream>
#include <Windows.h>
#include <fstream>
#include <thread>

std::ofstream ofile("D:\\runapp.txt");
WCHAR service_Name[] = L"runapp";
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hServiceStatusHandle;
HANDLE GetTokenById(int pId)
{
	HANDLE hToken;
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
	OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);	
	return hToken;
}
void WINAPI ServiceHandler(DWORD fdwControl)
{
	switch (fdwControl)
	{
	case SERVICE_CONTROL_STOP:
	case SERVICE_CONTROL_SHUTDOWN:
		ServiceStatus.dwWin32ExitCode = 0;
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		ServiceStatus.dwCheckPoint = 0;
		ServiceStatus.dwWaitHint = 0;
		ofile << "service stop." << std::endl;
		break;
	default:
		return;
	};
	if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
	{
		DWORD nError = GetLastError();
	}
}
void WINAPI service_main(int argc, char** argv)
{
	ServiceStatus.dwServiceType = SERVICE_WIN32;
	ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
	ServiceStatus.dwWin32ExitCode = 0;
	ServiceStatus.dwServiceSpecificExitCode = 0;
	ServiceStatus.dwCheckPoint = 0;
	ServiceStatus.dwCurrentState = SERVICE_RUNNING;
	ServiceStatus.dwWaitHint = 9000;
	hServiceStatusHandle = RegisterServiceCtrlHandler(service_Name, ServiceHandler);
	if (hServiceStatusHandle == 0)
	{
		DWORD nError = GetLastError();
	}

	if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
	{
		DWORD nError = GetLastError();
	}

	ofile << "service Starting" << std::endl;
	std::thread service_thread([&]() {
		for (int i = 0; i < 100; ++i)
		{
			ofile << i << std::endl;
			Sleep(1000);
			if (i == 50)
			{
				WCHAR szDesl[] = L"winsta0\\default";
				auto token = GetTokenById(9208);
				STARTUPINFO si = { sizeof(STARTUPINFO) };
				si.lpDesktop = szDesl;
				si.dwFlags = STARTF_USESHOWWINDOW;
				si.wShowWindow = SW_SHOW;
				PROCESS_INFORMATION pi;
				WCHAR szApp[] = L"notepad";
				CreateProcessAsUser(token, NULL, szApp, 0, 0, FALSE, 0, 0, 0, &si, &pi);
			}
		}
	});
	service_thread.detach();
}
int main()
{
	SERVICE_TABLE_ENTRY service_table[2];
	service_table[0].lpServiceName = service_Name;
	service_table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;
	StartServiceCtrlDispatcher(service_table);
    std::cout << "Hello World!\n"; 
}

上面直接贴了代码,方便以后参照。翻看之前的记录,也有过相关的记录,但是太复杂,不相干的代码太多。

这里的关键是CreateProcessAsUser,这个API能以某个用户的身份启动一个进程。为什么这么做,因为服务进程属于System用户,system用户不能显示UI。所以我们要把这个进程以能够显示UI的用户启动起来。

第一个参数token就是代表这个有用户的,所有的进程都归属于一个用户,比方服务进程都属于system,管理员用户启动的程序属于administrator,user用户启动的进程默认属于user。这些不通过的角色都有不同的权限,作用也就体现在进程能够操作的权限上,比如注册表,磁盘等等。

上面的例子我去的token就是我桌面进程的token,对应的就是我当前登录的用户,因为我是用administrator登录的,所以这个进程就是由administrator启动的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值