编写服务程序所遇到的问题

1.How to Create a Windows NT/ Windows 2000 Service翻译描述

网址:

http://blog.csdn.net/delphiwcdj/article/details/4581671

1.VS2008 CLR 建立WINDOWS服务程序 调用外部EXE文件

网址:

https://social.msdn.microsoft.com/Forums/vstudio/zh-CN/1876f300-16e5-49d6-b79e-b2c37e8806b8/vs2008-clr-windows-exe?forum=visualstudio2012zhcn

2.開發AP無法在Vista跟Win7正常執行

网址:

https://social.msdn.microsoft.com/Forums/zh-TW/ea1e7af2-919a-4480-a830-d2a111698c16/apvistawin7

3.服务程序中无法调用外部exe

1>穿透Session 0 隔离

网址:

http://www.cnblogs.com/gnielee/archive/2010/04/07/session0-isolation-part1.html

描述: 系统服务的Sesion 0隔离

http://tech.sina.com.cn/s/2009-09-24/07561078945.shtml

解决:

1>取得系统的Token句柄

2>根据此句柄调用CreateProcessAsUser函数来创建进程,此时创建的进程是运行在session 1.

网址:http://bbs.csdn.net/topics/390431360

通过CREATEPROCESSASUSER创建的进程,虽然任务管理器查看已经是用户权限了,但是里面执行的结果却是SYSTEM权限的,环境变量什么的都是SYSTEM的。

4.CreateProcessAsUser无法将创建的新进程前置

网址:

http://www.jscto.net/html/32840.html

如果你是用服务以已登录用户的名义创建的notepad进程的话:

你的服务和notepad属于不同的会话,属于不同的桌面,因此EnumWindows(findwindow)等局限于当前桌面的函数自然是查不到窗口的。

创建进程并置顶是有条件的:条件列表:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.

解决: CreateProcessAsUser创建一个临时的exe,再用这个exe来调用想要运行的程序,则可以实现新进程前置。

5.将基于MFC的对话框应用程序修改为服务程序

网址:

http://blog.csdn.net/delphiwcdj/article/details/4585680

未做验证。

6.

1. 有人说为什么自己不重写一个外部的exe,可以避免调用?
这个我也想过,如果重写外部exe那么简单的话,说都不愿意去调用。我这个主要是因为需要调用到一些底层的驱动,外部exe把这些都写好了,所以直接调用很方便。当然可以自己写的,我也试过,需要调用一些dll动态库,但是一些函数的调用却返回错误,查了原因,还是因为session的问题。

2. 关于“勾选允许与桌面互动”选项
最开始大部分时间浪费在这里。关于调用外部exe的方式有很多种,然后很多人建议说要勾选“允许与桌面互动”,我勾选了却和原来一样。然后我就以为是我调用外部exe的方式不对,搜索各种调用外部exe的方法,最后发现,即使可以,也是弹出一个消息框,可以在另外一个桌面上显示外部exe的窗口,不是我所想要的。
网上的很多东西都是比较老了,这些代码以及方法应该都是针对xp以及以前的系统,对于vista和win7就无效了,最开始不知道,浪费了很多时间。

3. 服务隔离
这里要感谢“gomoku”,你的回答让我知道了我错在哪里了,但是你的回答也不完全正确。我仔细阅读了微软的document,发现虽然默认情况下,服务是运行在session 0下的,与普通的应用程序不在一个session,所以不能互动,但是我们可以利用函数“CreateProcessAsUser”来创建应用程序session下的进程,从而调用外部exe。拨开云雾见日出。走到这一步,问题就明朗,方向也明确了。
这里重发一下链接,以后遇到同样问题的可以参考:http://msdn.microsoft.com/zh-cn/library/windows/hardware/gg463353.aspx

4. 如何利用用createProcessAsUser呢?
看了这个函数的介绍,在网上也有很多例子,大部分是说,需要知道当前用户的用户名和密码,但是这对于个人测试用还可以,如果你作为一个软件release给客户显然不行。网上有高人给出一个解决方法,就是得到一些系统进程的进程token,比如winlog.exe,explorer.exe,然后利用这些进程的token来创建自己的进程。有位高人给出了源码,现在找不到那个链接了,于是自己写了篇文章,把那位大哥的源码贴出来了,如果需要可以参考。http://blog.csdn.net/nonths/article/details/8833854

关于session,我觉得作为一个程序员,还是有必要深入了解下的。

6. 令牌写法,未验证

DWORD WINAPI TimeServiceThread(LPVOID)
{
while (!g_Stop)
{
Sleep(5000);

// 为了显示更加复杂的用户界面,我们需要从Session 0创建
// 一个进程,但是这个进程是运行在用户环境下。
// 我们可以使用CreateProcessAsUser实现这一功能。

BOOL bSuccess = FALSE;
STARTUPINFO si = {0};
// 进程信息
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);

// 获得当前Session ID
DWORD dwSessionID = WTSGetActiveConsoleSessionId();

HANDLE hToken = NULL;
// 获得当前Session的用户令牌
if (WTSQueryUserToken(dwSessionID, &hToken) == FALSE)
{
goto Cleanup;
}

// 复制令牌
HANDLE hDuplicatedToken = NULL;
if (DuplicateTokenEx(hToken,
MAXIMUM_ALLOWED, NULL,
SecurityIdentification, TokenPrimary,
&hDuplicatedToken) == FALSE)
{
goto Cleanup;
}

// 创建用户Session环境
LPVOID lpEnvironment = NULL;
if (CreateEnvironmentBlock(&lpEnvironment,
hDuplicatedToken, FALSE) == FALSE)
{
goto Cleanup;
}

// 获得复杂界面的名字,也就是获得可执行文件的路径
WCHAR lpszClientPath[MAX_PATH];
if (GetModuleFileName(NULL, lpszClientPath, MAX_PATH) == 0)
{
goto Cleanup;
}
PathRemoveFileSpec(lpszClientPath);
wcscat_s(lpszClientPath,
sizeof(lpszClientPath)/sizeof(WCHAR),
L"\TimeServiceClient.exe");

// 在复制的用户Session下执行应用程序,创建进程。
// 通过这个进程,就可以显示各种复杂的用户界面了
if (CreateProcessAsUser(hDuplicatedToken,
lpszClientPath, NULL, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
lpEnvironment, NULL, &si, &pi) == FALSE)
{
goto Cleanup;
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
bSuccess = TRUE;

// 清理工作

Cleanup:
if (!bSuccess)
{
ShowMessage(L"无法创建复杂UI", L"错误");
}

if (hToken != NULL)
CloseHandle(hToken);
if (hDuplicatedToken != NULL)
CloseHandle(hDuplicatedToken);
if (lpEnvironment != NULL)
DestroyEnvironmentBlock(lpEnvironment);
}

return 0;
}

7.GetTokenByName 与 CreateProcessAsUser 写法,已验证可行

BOOL GetTokenByName(HANDLE *hToken,LPSTR lpName)
{
if(!lpName){
return FALSE;
}

HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
PROCESSENTRY32 pe32 = {0};

hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);

pe32.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(hProcessSnap, &pe32))
{
do
{
if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE,pe32.th32ProcessID);
bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,hToken);
CloseHandle (hProcessSnap);
return (bRet);
}
}
while (Process32Next(hProcessSnap, &pe32));
bRet = TRUE;
}
else
bRet = FALSE;

CloseHandle (hProcessSnap);
return (bRet);
}

BOOL RunProcess()
{
TCHAR awExecuteFile[512];
HANDLE hToken;
if(!GetTokenByName(&hToken,"EXPLORER.EXE"))
{
return FALSE;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");
GetSystemDirectory(awExecuteFile, 512);
strcat(awExecuteFile, "\\spool\\drivers\\w32x86\\3\\GLP_AP.exe ");

BOOL bResult = CreateProcessAsUser(
hToken,
awExecuteFile,
NULL,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&pi);

CloseHandle(hToken);
if(bResult)
{
OutputDebugString("CreateProcessAsUser ok!\r\n");
}
else
{
OutputDebugString("CreateProcessAsUser false!\r\n");
}
return bResult;
}

时间: 2024-10-07 18:16:23

编写服务程序所遇到的问题的相关文章

DELPHI编写服务程序总结

一.服务程序和桌面程序的区别 Windows 2000/XP/2003等支持一种叫做“系统服务程序”的进程,系统服务和桌面程序的区别是:系统服务不用登陆系统即可运行:系统服务是运行在System Idle Process/System/smss/winlogon/services下的,而桌面程序是运行在Explorer下的:系统服务拥有更高的权限,系统服务拥有Sytem的权限,而桌面程序只有Administrator权限:在Delphi中系统服务是对桌面程序进行了再一次的封装,既系统服务继承于桌

C编写服务程序详细步骤

1.简介 Windows 服务被设计用于需要在后台运行的应用程序以及实现没有用户交互的任务.为了学习这种控制台应用程序的基础知识,C(不是C++)是最佳选择.C++面向对象的方法固然方便,但由于用类对底层 Win32 函数调用进行了封装,它不利于学习服务程序的基本知识. 服务是一个运行在后台并实现勿需用户交互的任务的控制台程序.Windows NT/2000/XP 操作系统提供为服务程序提供专门的支持. 2.步骤 2.1 主函数和全局定义 包含所需的头文件.要调用 Win32 函数(window

C编写服务程序

一.问题 1.[SC] OpenSCManager 失败 5:拒绝访问. 以管理员身份运行2.net start test发生系统错误 2.系统找不到指定的文件. 1)查看exe文件的路径是否正确?最好使用全路径.若修改服务路径可执行:sc delete 服务名,sc create 服务名 binPath= ""进行重新安装3.net start serverProgram服务没有响应控制功能.或者提示:错误1053:服务没有及时响应启动或控制请求. 原因:运行作为服务的应用程序不是按

BCB 编写服务程序的一个注意事项

  BCB编写服务,install报错的一个问题 今天编写了一个服务,最后INSTALL 的时候报错,如图: 经过近1小时的比较(俺过去写例子),居然无意中设置了一个属性                     查看BCB 的帮助.ServiceStartName 从文档大意,可知道,就是用与启动服务的名字.当时没看懂,查了msdn   当我看到Account终于明白了,原来指的是启动服务的账户(叫什么ServiceStartName? 叫ServiceStartAccount 不好?) 说白了

windows下服务程序相关(别人提供的5种封装使用)

作者: daodaoliang 版本: V 0.0.1 日期: 2017年11月25日 1. Windows Service 编程实现 在windows平台下面编写 服务程序 免不了要去查看微软的开发者文档,相关的介绍在这里, 多了也就不在罗嗦了,如果你嫌弃直接用他们的API的话,可以使用别人已经封装好的,比如: 参考代码 连接 参考代码001 https://github.com/magicsih/WindowsService 参考代码002 https://github.com/Olster

java RMI入门指南

感觉这篇文章不错,直接转了 RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体如今它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方式之中的一个.事实上它能够被看作是RPC的Java版本号.可是传统RPC并不能非常好地应用于分布式对象系统.而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信.实现远程对象之间的无缝远程调用. RMI眼下使用Java远程消息交换协议JRMP

STM32中断控制的流程

对于 STM32 讲(还是以Timer2例),外部中断通道位置 28(35 号优先级)是给外部设备 TIME2 的,但 TIME2本身能够引起中断的中断源或事件有好多个,比如更新事件(上溢/下溢) .输入捕获.输出匹配.DMA 申请等.所有TIME2 的中断事件都是通过一个 TIME2 的中断通道向 STM32 内核提出中断申请,那么 STM32 中如何处理和控制 TIME2 和它众多的.不同的.中断申请呢? 1.因为cortex_m3 内核对于每一个外部中断通道都有相应的控制字和控制位,用于单

Java接口技术

1.RMI技术 1.1 RMI技术介绍 RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一.其实它可以被看作是RPC的Java版本.但是传统RPC并不能很好地应用于分布式对象系统.而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用. RMI目前使用Java远程消息交换协议JRMP

Windows RPC

转载 Windows RPC Demo实现 本文参考并整理以下相关文章 1. <远程过程调用> -百度百科 2. <RPC 编程> -http://www.ibm.com/developerworks/cn/aix/library/au-rpc_programming/ 3. <微软官方参考教程> -http://blog.csdn.net/swanabin/article/details/18766209 1 概念 RPC:全称是“远程过程调用协议(Remote Pr