#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启动的。