如何在Windows服务中以当前tomcat指定用户启动动一个程序

1271人阅读
在CodeProject上看到一个Demo, 在服务中以当前用户身份启动一个程序.
跟帖的人指出了一些bug, 我整理了一下, 将跟帖人指出的bug在工程中修正.
他提供的类, 也有一个小bug, 没有被跟帖的人指出, 被我发现并修正.
这个Demo整理后, 被我用在项目中, 用起来效果还不错.
以当前登录用户的身份运行一个程序的好处:&
* 可以避免权限问题. e.g. 文件建立后, 当前用户打不开.
* 有些程序或部件运行, 是需要Windows窗口消息的, 不能直接在服务中运行.
工程下载点:&
编译环境: vs2010 vc++
&/// @todo ls 服务启动停止时, 检测服务是否已经在运行或停止的处理要加上, 提高效率.
/// 如果硬生生的启动停止服务时, 还要启动停止桌面上的程序, 在没有检测服务状态时, 要花费的时间多些.
// lsServiceForTest.cpp : Defines the entry point for the application.
#include &stdafx.h&
#include &process.h&
#include &lsServiceForTest.h&
#include &ProcessStarter.h&
#define SERVICE_VER_W L&1, 0, 0, 1&
#define PROJECT_MODIFY_TIME L&26&
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv);
SERVICE_TABLE_ENTRYW lpServiceStartTable[] =
{SERVICE_NAME_W, ServiceMain},
{NULL, NULL}
SERVICE_STATUS_HANDLE g_hServiceCtrlHandler = NULL;
SERVICE_STATUS g_ServiceS
std::wstring g_strPathNameMe = L&&;
std::wstring g_strCmdLine = L&&;
ns_base::CThreadManager g_ThreadM
VOID ServiceMainProc();
static UINT WINAPI ThreadProcWorker(void* pParam);
BOOL ThreadProcStart_Worker();
BOOL ThreadProcStop_Worker();
BOOL GetObjProgInfo(DWORD dwSessionId, OUT std::wstring& strObjPathName, OUT std::wstring& strCmdLine);
VOID ExecuteAsService();
VOID WINAPI ServiceHandler(DWORD fdwControl);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
lpCmdLine,
std::wstring strLogFilePathName = L&&;
ns_base::GetFilePathName_Me(g_strPathNameMe);
g_strCmdLine = (NULL != lpCmdLine) ? lpCmdLine : L&&;
strLogFilePathName = ns_business::GetLogPathName_lsServiceForTest().c_str();
SetLogFilePathName(strLogFilePathName.c_str());
ServiceMainProc();
VOID ServiceMainProc()
WriteLogEx(L&&& ServiceMainProc() [%s][%s][%s]&, SERVICE_NAME_W, SERVICE_VER_W, PROJECT_MODIFY_TIME);
if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-i&)
|| ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-I&))
ns_base::ServiceInstall(g_strPathNameMe.c_str(), SERVICE_NAME_W);
else if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-s&)
|| ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-S&))
ns_base::ServiceStart(SERVICE_NAME_W);
else if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-k&)
|| ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-K&))
ns_base::ServiceStop(SERVICE_NAME_W);
else if (ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-u&)
|| ns_base::StringCompare_equ(g_strCmdLine.c_str(), L&-U&))
ns_base::ServiceUnInstall(SERVICE_NAME_W);
ExecuteAsService();
WriteLogEx(L&&& ServiceMainProc() [%s][%s][%s]&, SERVICE_NAME_W, SERVICE_VER_W, PROJECT_MODIFY_TIME);
VOID ExecuteAsService()
WriteLogEx(L&&& ExecuteAsService&);
if(!ThreadProcStart_Worker())
WriteLogEx(L&ThreadProcStart_Worker failed[%d]&, GetLastError());
if(!StartServiceCtrlDispatcherW(lpServiceStartTable))
WriteLogEx(L&StartServiceCtrlDispatcher failed[%d]&, GetLastError());
WriteLogEx(L&&& ExecuteAsService&);
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
WriteLogEx(L&&& ServiceMain(%d, lpszArgv)&, dwArgc);
g_ServiceStatus.dwServiceType = SERVICE_WIN32;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_PAUSE_CONTINUE
| SERVICE_ACCEPT_SHUTDOWN
| SERVICE_ACCEPT_PARAMCHANGE
| SERVICE_ACCEPT_NETBINDCHANGE
| SERVICE_ACCEPT_HARDWAREPROFILECHANGE
| SERVICE_ACCEPT_POWEREVENT
| SERVICE_ACCEPT_SESSIONCHANGE
| SERVICE_ACCEPT_PRESHUTDOWN
| SERVICE_ACCEPT_TIMECHANGE
| SERVICE_ACCEPT_TRIGGEREVENT;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
g_hServiceCtrlHandler = RegisterServiceCtrlHandlerW(SERVICE_NAME_W, ServiceHandler);
if (NULL == g_hServiceCtrlHandler)
ns_base::NotifyFailed_RegisterServiceCtrlHandler(GetLastError(), SERVICE_NAME_W);
// Initialization complete - report running status
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(g_hServiceCtrlHandler, &g_ServiceStatus))
ns_base::NotifyFailed_SetServiceStatus(GetLastError(), SERVICE_NAME_W);
} while (0);
WriteLogEx(L&&& ServiceMain(%d, lpszArgv)&, dwArgc);
VOID WINAPI ServiceHandler(DWORD fdwControl)
int iIndex = 0;
WriteLogEx(L&&& ServiceHandler(%d)&, fdwControl);
switch(fdwControl)
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
g_ThreadManager.StopThread(TRUE, L&g_ThreadManager&);
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCurrentState
= SERVICE_STOPPED;
g_ServiceStatus.dwCheckPoint
g_ServiceStatus.dwWaitHint
// terminate all processes started by this service before shutdown
ns_business::StopAndKill_dlgNotify();
case SERVICE_CONTROL_PAUSE:
g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
case SERVICE_CONTROL_CONTINUE:
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
WriteLogEx(L&Unrecognized opcode %d\n&, fdwControl);
if (!SetServiceStatus(g_hServiceCtrlHandler,
&g_ServiceStatus))
ns_base::NotifyFailed_SetServiceStatus(GetLastError(), SERVICE_NAME_W);
WriteLogEx(L&&& ServiceHandler(%d)&, fdwControl);
static UINT WINAPI ThreadProcWorker(void* pParam)
BOOL bLog = TRUE;
DWORD dwSessionIdPrev = -1;
DWORD dwSessionId = -1;
size_t nSleepTotal = 0;
UINT uRc = S_FALSE;
std::wstring strObjPathName = L&&;
std::wstring strCmdLine = L&&;
ns_base::TAG_THREAD_MANAGER_PARAM ThreadManagerP
ns_base::TAG_THREAD_MANAGER_PARAM* pThreadManagerParam = NULL;
CProcessStarter ProcessS
WriteLogEx(L&&& lsServiceForTest ThreadProcWorker&);
if (NULL == pParam)
pThreadManagerParam = (ns_base::TAG_THREAD_MANAGER_PARAM*)pP
ThreadManagerParam.copy((ns_base::TAG_THREAD_MANAGER_PARAM*)pParam);
SAFE_DELETE(pThreadManagerParam);
if (NULL == ThreadManagerParam.pThreadManager)
while(!ThreadManagerParam.pThreadManager-&IsNeedQuitThread())
if (!ns_base::SleepContinueEx(, nSleepTotal))
/// 保证 只有在SessionId变化的时候, 才打印 FindActiveSessionId 的日志
if (!ProcessStarter.FindActiveSessionId(dwSessionId, bLog)
|| (dwSessionIdPrev == dwSessionId))
bLog = FALSE;
if (!bLog)
bLog = TRUE;
/// 用户每次切换一次桌面, 我们就启动一次子程序
dwSessionIdPrev = dwSessionId;
if (GetObjProgInfo(dwSessionId, strObjPathName, strCmdLine))
if (!ns_base::IsFileExist(strObjPathName.c_str()))
WriteLogEx(L&[error] !ns_base::IsFileExist(%s)&, strObjPathName.c_str());
/// 确保在多个SessionId的环境下, 也只有当前SessionId上运行唯一一个dlgNotify
ns_business::StopAndKill_dlgNotify();
ProcessStarter.Run(
strObjPathName.c_str(),
strCmdLine.c_str());
} while (0);
uRc = S_OK;
} while (0);
WriteLogEx(L&&& FzAppService ThreadProcWorker&);
return uRc;
BOOL ThreadProcStart_Worker()
BOOL bRc = FALSE;
ns_base::TAG_THREAD_MANAGER_PARAM* pThreadManagerParam = NULL;
if (!g_ThreadManager.IsNeedQuitThread()
&& !g_ThreadManager.IsThreadRunning())
pThreadManagerParam = new ns_base::TAG_THREAD_MANAGER_PARAM;
if (NULL == pThreadManagerParam)
pThreadManagerParam-&pThreadManager = &g_ThreadM
g_ThreadManager.SetThreadHandle(
(HANDLE)_beginthreadex(
&ThreadProcWorker,
(void*)pThreadManagerParam,
bRc = TRUE;
} while (0);
return bRc;
BOOL ThreadProcStop_Worker()
g_ThreadManager.StopThread(TRUE, L&g_ThreadManager&);
return TRUE;
BOOL GetObjProgInfo(DWORD dwSessionId, OUT std::wstring& strObjPathName, OUT std::wstring& strCmdLine)
ns_base::GetPathName_Me(strObjPathName);
strObjPathName += FILE_NAME_ObjProgI
strCmdLine = ns_base::StringFormatV(L&sessionId-%d&, dwSessionId);
return TRUE;
CProcessStarter 实现, 负责以当前用户身份启动一个程序.
#ifndef _PROCESS_STARTER_H_
#define _PROCESS_STARTER_H_
#include &stdafx.h&
class CProcessStarter
CProcessStarter();
/// 如果没有找到&已经激活的SessionId&, 说明还没有进入桌面
BOOL FindActiveSessionId(OUT DWORD& dwSessionId, BOOL bNeedLog);
BOOL Run(LPCWSTR pcProcessPathName, LPCWSTR pcCmdLine);
HANDLE GetCurrentUserToken();
std::wstring m_strProcessPathN
std::wstring m_strCmdL
#endif //_PROCESS_STARTER_H_
#include &stdafx.h&
#include &ProcessStarter.h&
#include &userenv.h&
#pragma comment(lib, &Userenv.lib&)
#include &wtsapi32.h&
#pragma comment(lib, &Wtsapi32.lib&)
CProcessStarter::CProcessStarter()
: m_strProcessPathName(L&&),
m_strCmdLine(L&&)
BOOL CProcessStarter::FindActiveSessionId(OUT DWORD& dwSessionId, BOOL bNeedLog)
BOOL bFindActiveSession = FALSE;
DWORD dwIndex = 0;
PWTS_SESSION_INFO pWtsSessionInfo = NULL;
DWORD dwCntWtsSessionInfo = 0;
if (bNeedLog)
WriteLogEx(L&&& CProcessStarter::FindActiveSessionId()&);
dwSessionId = (DWORD)(-1);
if ((!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pWtsSessionInfo, &dwCntWtsSessionInfo))
|| (NULL == pWtsSessionInfo))
if (bNeedLog)
WriteLogEx(L&break 0 CProcessStarter::FindActiveSessionId()&);
for (dwIndex = 0; dwIndex & dwCntWtsSessionI dwIndex++)
if (WTSActive == pWtsSessionInfo[dwIndex].State)
dwSessionId = pWtsSessionInfo[dwIndex].SessionId;
bFindActiveSession = TRUE;
WTSFreeMemory(pWtsSessionInfo);
if (!bFindActiveSession)
if (bNeedLog)
WriteLogEx(L&break 1 CProcessStarter::FindActiveSessionId()&);
} while (0);
if (bNeedLog)
WriteLogEx(L&&& CProcessStarter::FindActiveSessionId(), bFindActiveSession = [%s], dwSessionId = %d&,
bFindActiveSession ? L&TRUE& : L&FALSE&,
dwSessionId);
return bFindActiveS
HANDLE CProcessStarter::GetCurrentUserToken()
DWORD dwSessionId = 0;
HANDLE hCurrentToken = NULL;
HANDLE hPrimaryToken = NULL;
WriteLogEx(L&&& CProcessStarter::GetCurrentUserToken()&);
if (!FindActiveSessionId(dwSessionId, TRUE))
WriteLogEx(L&break 0 CProcessStarter::GetCurrentUserToken()&);
if (!WTSQueryUserToken(dwSessionId, &hCurrentToken)
|| (NULL == hCurrentToken))
WriteLogEx(L&break 2 CProcessStarter::GetCurrentUserToken()&);
if (!DuplicateTokenEx(hCurrentToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hPrimaryToken))
WriteLogEx(L&break 3 CProcessStarter::GetCurrentUserToken()&);
} while (0);
WriteLogEx(L&&& CProcessStarter::GetCurrentUserToken(), hCurrentToken = 0x%p, hPrimaryToken = 0x%p&,
hCurrentToken,
hPrimaryToken);
SAFE_CLOSE_HANDLE(hCurrentToken);
return hPrimaryT
BOOL CProcessStarter::Run(LPCWSTR pcProcessPathName, LPCWSTR pcCmdLine)
BOOL bRc = FALSE;
BOOL bTmp = FALSE;
HANDLE hPrimaryToken = NULL;
STARTUPINFOA StartupInfo = {0};
PROCESS_INFORMATION processInfo = {0};
std::wstring command = L&&;
LPVOID lpEnvironment = NULL;
WriteLogEx(L&&& CProcessStarter::Run&);
if ((NULL == pcProcessPathName) || (!ns_base::IsFileExist(pcProcessPathName)))
WriteLogEx(L&break 0 CProcessStarter::Run&);
this-&m_strProcessPathName = pcProcessPathN
this-&m_strCmdLine = (NULL != pcCmdLine) ? pcCmdLine : L&&;
hPrimaryToken = GetCurrentUserToken();
if (NULL == hPrimaryToken)
WriteLogEx(L&break 1 CProcessStarter::Run&);
StartupInfo.cb = sizeof(STARTUPINFO);
command = L&\&&;
command += m_strProcessPathName.c_str();
command += L&\&&;
if (m_strCmdLine.length() != 0)
command += L& &;
command += m_strCmdLine.c_str();
WriteLogEx(L&command = [%s]&, command.c_str());
if (!CreateEnvironmentBlock(&lpEnvironment, hPrimaryToken, TRUE))
WriteLogEx(L&!CreateEnvironmentBlock by hPrimaryToken&);
bTmp = CreateProcessAsUserA(
hPrimaryToken,
(LPSTR)ns_base::W2Aex(command.c_str()).c_str(),
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,
lpEnvironment, // __in_opt
LPVOID lpEnvironment,
&StartupInfo,
&processInfo);
if (NULL != lpEnvironment)
DestroyEnvironmentBlock(lpEnvironment);
WriteLogEx(L&CreateProcessAsUserA = %s&, bTmp ? L&TRUE& : L&FALSE&);
if (!bTmp)
bRc = TRUE;
} while (0);
SAFE_CLOSE_HANDLE(hPrimaryToken);
WriteLogEx(L&&& CProcessStarter::Run, bRc = [%s]&, bRc ? L&TRUE& : L&FALSE&);
return bRc;
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
(4)(12)(14)(15)(30)(15)(32)(18)(18)(18)(24)(35)(17)(17)(9)(15)(25)(26)(9)(40)(41)(54)(29)(27)(7)(9)(6)(13)(15)(7)(9)(4)(4)(6)(5)(7)(5)(5)(13)(4)(6)(9)(11)(9)(4)(8)(17)(22)(21)(26)(32)(27)(9)(8)(3)(8)(10)(6)(6)(3)(4)(2)(3)(2)(2)(4)(8)(6)(3)(7)(2)(2)(1)(21)(23)(16)(22)(29)(29)(31)(19)(10)(7)(2)(2)(10)(1)查看:1709|回复:2
win2003系统 ,一个应用程序,在计划任务中设定随系统启动而启动,以administrator远程桌面登录后,能在任务管理器的系统进程里看见(用户也是administrator),但应用程序界面无法调出,请问如何调出应用程序界面?
有高手能给解答吗?
优秀技术经理
随系统启动的任务实际上是运行在一个特殊的用户账号SYSTEM的环境中,所以你是无法看见界面,正如两个同时登录到WINDOWS的用户无法看见对方的界面是一回事。
所以将任务改成随用户登录启动,就可以看见界面了。
记得点“引用/回复” 我才能跟踪你的问题与反馈。
因为专注,所以专业。}

我要回帖

更多关于 nginx 普通用户启动 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信