一个比较有挑战的问题:system用户安装我自己写的服务后,无法启动(提示:服务没有及时响应启动或控制请求)

StarCraftII 2007-12-27 10:46:31
Windows, VS2003

我自己写了一个服务,在很多的机器上通过system用户从服务器下载此服务程序,然后安装服务,再启动
现在发现有1%左右的机器服务不能启动,错误提示:服务没有及时响应启动或控制请求
而我们通过日志跟踪发现,程序执行正常,能够运行到服务的run()函数中的以下位置
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
中,启动服务的net start myserver没有返回。最后30秒超时出现上面的错误提示

syetem用户无法启动服务,然后我再用Administrator用户登陆,重新net start myserver,仍然不能启动,错误提示也一样。
这时候Administrator 用户把服务卸载,再重新安装,再net start myserver,就能正常运行。

另外,不通过net start启动,直接运行服务程序,是可以正常启动的

请高手谈谈看法
谢谢
...全文
700 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
StarCraftII 2008-01-02
  • 打赏
  • 举报
回复

//CMyTimer tTimer;
//tTimer.SetMyTimer(TIMERCYC*1000);

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);

_Module.RevokeClassObjects();
//tTimer.KillMyTimer();

我将CMyTimer的代码全部注释掉,只剩下服务的代码框架,运行也是一样的效果。
jameshooo 2007-12-29
  • 打赏
  • 举报
回复
CMyTimer是你自己插入的代码,也贴出来看看
StarCraftII 2007-12-29
  • 打赏
  • 举报
回复
void CServiceModule::LogEvent(LPCTSTR pFormat, ...)
{
TCHAR chMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[1];
va_list pArg;

va_start(pArg, pFormat);
_vstprintf(chMsg, pFormat, pArg);
va_end(pArg);

lpszStrings[0] = chMsg;

if (m_bService)
{
/* Get a handle to use with ReportEvent(). */
hEventSource = RegisterEventSource(NULL, m_szServiceName);
if (hEventSource != NULL)
{
/* Write to event log. */
ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
DeregisterEventSource(hEventSource);
}
}
else
{
// As we are not running as a service, just write the error to the console.
_putts(chMsg);
}
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Service startup and registration
inline void CServiceModule::Start()
{
SERVICE_TABLE_ENTRY st[] =
{
{ m_szServiceName, _ServiceMain },
{ NULL, NULL }
};
if (m_bService && !::StartServiceCtrlDispatcher(st))
{
m_bService = FALSE;
}

if (m_bService == FALSE)
Run();
}

inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
{
// Register the control request handler
m_status.dwCurrentState = SERVICE_START_PENDING;
m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
if (m_hServiceStatus == NULL)
{
LogEvent(_T("Handler not installed"));
return;
}
SetServiceStatus(SERVICE_START_PENDING);

m_status.dwWin32ExitCode = S_OK;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;

// When the Run function returns, the service has stopped.
Run();

SetServiceStatus(SERVICE_STOPPED);
LogEvent(_T("Service stopped"));
}

inline void CServiceModule::Handler(DWORD dwOpcode)
{
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
SetServiceStatus(SERVICE_STOP_PENDING);
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
break;
case SERVICE_CONTROL_PAUSE:
break;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
break;
default:
LogEvent(_T("Bad service request"));
}
}

void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
_Module.ServiceMain(dwArgc, lpszArgv);
}
void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
{
_Module.Handler(dwOpcode);
}

void CServiceModule::SetServiceStatus(DWORD dwState)
{
m_status.dwCurrentState = dwState;
::SetServiceStatus(m_hServiceStatus, &m_status);
}

void CServiceModule::Run()
{
_Module.dwThreadID = GetCurrentThreadId();

HRESULT hr = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
// HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

_ASSERTE(SUCCEEDED(hr));

// This provides a NULL DACL which will allow access to everyone.
CSecurityDescriptor sd;
sd.InitializeFromThreadToken();
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
_ASSERTE(SUCCEEDED(hr));

hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hr));

LogEvent(_T("Service started"));
if (m_bService)
SetServiceStatus(SERVICE_RUNNING);

CMyTimer tTimer;
tTimer.SetMyTimer(TIMERCYC*1000);

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);

_Module.RevokeClassObjects();
tTimer.KillMyTimer();
CoUninitialize();
}

/////////////////////////////////////////////////////////////////////////////
//

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
_Module.Init(ObjectMap, hInstance, IDS_SERVICENAME, &LIBID_MYSERVERLib);
_Module.m_bService = TRUE;

TCHAR szTokens[] = _T("-/");

LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
return _Module.UnregisterServer();

// Register as Local Server
if (lstrcmpi(lpszToken, _T("RegServer"))==0)
return _Module.RegisterServer(TRUE, FALSE);

// Register as Service
if (lstrcmpi(lpszToken, _T("AutoService"))==0)
return _Module.RegisterServer(TRUE, TRUE);

lpszToken = FindOneOf(lpszToken, szTokens);
}

// Are we Service or Local Server
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ);
if (lRes != ERROR_SUCCESS)
return lRes;

CRegKey key;
lRes = key.Open(keyAppID, _T("{DA5673B5-7F01-4025-AFBE-C8932C89C8D4}"), KEY_READ);

// if (lRes != ERROR_SUCCESS)
// return lRes;

TCHAR szValue[_MAX_PATH];
DWORD dwLen = _MAX_PATH;
//lRes = key.QueryValue(szValue, _T("LocalService"), &dwLen);
lRes = key.QueryStringValue(_T("LocalService"), szValue, &dwLen);

_Module.m_bService = FALSE;
if (lRes == ERROR_SUCCESS)
_Module.m_bService = TRUE;
_Module.Start();

// When we get here, the service has been stopped
return _Module.m_status.dwWin32ExitCode;
}
StarCraftII 2007-12-29
  • 打赏
  • 举报
回复
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>

#include "Timer.h"

#include <stdio.h>

CServiceModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()


LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
{
while (p1 != NULL && *p1 != NULL)
{
LPCTSTR p = p2;
while (p != NULL && *p != NULL)
{
if (*p1 == *p)
return CharNext(p1);
p = CharNext(p);
}
p1 = CharNext(p1);
}
return NULL;
}

// Although some of these functions are big they are declared inline since they are only used once

inline HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib, BOOL bService)
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
return hr;

if (IsInstalled()) {
MessageBox(NULL, _T("服务存在,请先卸载服务!"), m_szServiceName, MB_OK);
return 0;
}
// Remove any previous service since it may point to
// the incorrect file
Uninstall();

// Add service entries
UpdateRegistryFromResource(IDR_MYServer, TRUE);

// Adjust the AppID for Local Server or Service
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
if (lRes != ERROR_SUCCESS)
return lRes;

CRegKey key;
lRes = key.Open(keyAppID, _T("{DA5673B5-7F01-4025-AFBE-C8932C89C8D4}"), KEY_WRITE);
if (lRes != ERROR_SUCCESS)
return lRes;
key.DeleteValue(_T("LocalService"));

if (bService)
{
key.SetStringValue(_T("LocalService"), _T("MyServer"));
key.SetStringValue(_T("ServiceParameters"), _T("-Service"));
// Create service
Install();
}

// Add object entries
hr = CComModule::RegisterServer(bRegTypeLib);

CoUninitialize();
return hr;
}

inline HRESULT CServiceModule::UnregisterServer()
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
return hr;

// Remove service entries
UpdateRegistryFromResource(IDR_MYServer, FALSE);
// Remove service
Uninstall();
// Remove object entries
CComModule::UnregisterServer(TRUE);
CoUninitialize();
return S_OK;
}

inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID, const GUID* plibid)
{
CComModule::Init(p, h, plibid);

m_bService = TRUE;

LoadString(h, nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR));

// set up the initial service status
m_hServiceStatus = NULL;
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_status.dwCurrentState = SERVICE_STOPPED;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_status.dwWin32ExitCode = 0;
m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
}

LONG CServiceModule::Unlock()
{
LONG l = CComModule::Unlock();
if (l == 0 && !m_bService)
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
return l;
}

BOOL CServiceModule::IsInstalled()
{
BOOL bResult = FALSE;

SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

if (hSCM != NULL)
{
SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);
if (hService != NULL)
{
bResult = TRUE;
::CloseServiceHandle(hService);
}
::CloseServiceHandle(hSCM);
}
return bResult;
}

inline BOOL CServiceModule::Install()
{
if (IsInstalled())
return TRUE;

SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
return FALSE;
}

// Get the executable file path
TCHAR szFilePath[_MAX_PATH];
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);

SC_HANDLE hService = ::CreateService(
hSCM, m_szServiceName, _T("My服务"),
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);

if (hService == NULL)
{
::CloseServiceHandle(hSCM);
MessageBox(NULL, _T("Couldn't create service"), m_szServiceName, MB_OK);
return FALSE;
}

::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
return TRUE;
}

inline BOOL CServiceModule::Uninstall()
{
if (!IsInstalled())
return TRUE;

SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

if (hSCM == NULL)
{
MessageBox(NULL, _T("Couldn't open service manager"), m_szServiceName, MB_OK);
return FALSE;
}

SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE);

if (hService == NULL)
{
::CloseServiceHandle(hSCM);
MessageBox(NULL, _T("Couldn't open service"), m_szServiceName, MB_OK);
return FALSE;
}
SERVICE_STATUS status;
::ControlService(hService, SERVICE_CONTROL_STOP, &status);

BOOL bDelete = ::DeleteService(hService);
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);

if (bDelete)
return TRUE;

MessageBox(NULL, _T("Service could not be deleted"), m_szServiceName, MB_OK);
return FALSE;
}
StarCraftII 2007-12-28
  • 打赏
  • 举报
回复
因为在服务程序通过回调函数使用了定时器,SetTimer();
今天查资料好像在服务中使用SetTimer有问题。

不知有没有这个可能?
jameshooo 2007-12-28
  • 打赏
  • 举报
回复
贴ServiceCtrl的代码上来
wangzai117 2007-12-28
  • 打赏
  • 举报
回复
????????
StarCraftII 2007-12-28
  • 打赏
  • 举报
回复
测试又不是Timer的原因,把所有处理的代码删掉,就留下一个服务的框架,运行的时候,仍然会出这个错误
captain_x 2007-12-27
  • 打赏
  • 举报
回复
mark
stivenjia 2007-12-27
  • 打赏
  • 举报
回复
从理论上来说SYSTEM权限应该比Administrator权限更大并且容有Administrator所有权限
如果不是这样就出现错误了被。
或者说Administrator开启了Debug权限而SYSTEM没有开启Debug权限等等原因吧?
猜的
Chivalry 2007-12-27
  • 打赏
  • 举报
回复
bang ding,jf
jameshooo 2007-12-27
  • 打赏
  • 举报
回复
可能也需要检查ServiceCtrl函数是如何实现的
jameshooo 2007-12-27
  • 打赏
  • 举报
回复
在服务中不能使用GetMessage,这样会导致线程阻塞,应该用PeekMessage。否则,服务管理器发出的控制命令无法执行,你的服务程序也无法修改当前运行状态。
superdiablo 2007-12-27
  • 打赏
  • 举报
回复
LocalSystem在本地权限大,但是在网络上就没什么权限了。是不是你的服务要访问网络上什么东西卡住了?
evileagle 2007-12-27
  • 打赏
  • 举报
回复
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg); ?????
在初始化的时候就截获消息?当没有消息的时候就停下来不动了呗,scm以为启动超时,所以失败了

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧