急急急!Svchost.exe调用的DLL服务,服务可以创建,但是启动不了。

Jo_Kael 2016-06-22 11:43:01
用svchost.exe调用一个自己写的dll服务,服务可以创建,但是启动不了,看日志,ServiceMain压根没有进去,DllMain进去了,哪个大神帮忙看下,代码如下:
#pragma  once

#ifdef SVCHOSTLIBDLLSRV
#define SvcHostSrvApi _declspec(dllexport)
#else
#define SvcHostSrvApi _declspec(dllimport)
#endif

class SvcHostSrvApi SvcHostDllSrv
{
public:
SvcHostDllSrv();
~SvcHostDllSrv();

int InstallService(char *name);
int UninstallService(char *name);
void __stdcall ServiceMain( int argc, wchar_t* argv[] );

static int ConsoleSCManager(DWORD dwState, DWORD dwExitCode, DWORD dwProgress );
static unsigned __stdcall OutPutDateTime(void *pm);

static DWORD m_dwCurrState;

private:

BOOL CreateStringReg(HKEY hRoot,char *szSubKey, unsigned long kType,char* ValueName,char *Data);
BOOL CreateDWORDReg(HKEY hRoot,char *szSubKey,char* ValueName,DWORD Data);

void CoreWork();
bool OpenCalcExe();

static bool m_bExitFlag;
static SERVICE_STATUS_HANDLE m_hSrv;
};

// SvcHostDllSrv.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"

#define SVCHOSTLIBDLLSRV

#include "SvcHostDllSrv.h"

#include "logfile.h"

CLogFile g_runLog(("Log_"));


SERVICE_STATUS_HANDLE SvcHostDllSrv::m_hSrv = NULL;
DWORD SvcHostDllSrv::m_dwCurrState = 0;
bool SvcHostDllSrv::m_bExitFlag = false;

SvcHostDllSrv::SvcHostDllSrv()
{
m_bExitFlag = false;
}

SvcHostDllSrv::~SvcHostDllSrv()
{
m_bExitFlag = true;
}

void __stdcall ServiceHandler(DWORD dwCommand)
{
switch( dwCommand )
{
case SERVICE_CONTROL_STOP:
SvcHostDllSrv::ConsoleSCManager( SERVICE_STOP_PENDING, 0, 1 );
Sleep(10);
SvcHostDllSrv::ConsoleSCManager( SERVICE_STOPPED, 0, 0 );
break;
case SERVICE_CONTROL_PAUSE:
SvcHostDllSrv::ConsoleSCManager( SERVICE_PAUSE_PENDING, 0, 1 );
SvcHostDllSrv::ConsoleSCManager( SERVICE_PAUSED, 0, 0 );
break;
case SERVICE_CONTROL_CONTINUE:
SvcHostDllSrv::ConsoleSCManager( SERVICE_CONTINUE_PENDING, 0, 1 );
SvcHostDllSrv::ConsoleSCManager( SERVICE_RUNNING, 0, 0 );
break;
case SERVICE_CONTROL_INTERROGATE:
SvcHostDllSrv::ConsoleSCManager( SvcHostDllSrv::m_dwCurrState, 0, 0 );
break;
case SERVICE_CONTROL_SHUTDOWN:
SvcHostDllSrv::ConsoleSCManager( SERVICE_STOPPED, 0, 0 );
break;
}
}

void __stdcall SvcHostDllSrv::ServiceMain(int argc, wchar_t* argv[])
{
g_runLog.Write("SvcHostDllSrv:ServiceMain Begin...\r\n");
char svcname[256];
strncpy(svcname, (char*)argv[0], sizeof svcname); // 支持unicode和ansi
wcstombs(svcname, argv[0], sizeof svcname);

m_hSrv = RegisterServiceCtrlHandler( svcname, (LPHANDLER_FUNCTION)ServiceHandler );
if( m_hSrv == NULL )
{
g_runLog.Write("SvcHostDllSrv: RegisterServiceCtrlHandler failed!\r\n");
return;
}else FreeConsole();

ConsoleSCManager( SERVICE_START_PENDING, 0, 1 );
ConsoleSCManager( SERVICE_RUNNING, 0, 0 );

// call Real Service function noew
if(argc > 1)
strncpy(svcname, (char*)argv[1], sizeof svcname),
wcstombs(svcname, argv[1], sizeof svcname);

CoreWork();

do{
Sleep(10);
}while(m_dwCurrState != SERVICE_STOP_PENDING && m_dwCurrState != SERVICE_STOPPED);

g_runLog.Write("SvcHostDllSrv:ServiceMain done\r\n");
}

int SvcHostDllSrv::InstallService(char *name)
{
HKEY hkRoot = HKEY_LOCAL_MACHINE, hkParam = 0;
SC_HANDLE hscm = NULL, hscService = NULL;

//install service
hscm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hscm == NULL)
{
g_runLog.Write("InstallService OpenSCManager Error [%d]\r\n", GetLastError());
return GetLastError();
}
char *bin = "%systemroot%\\system32\\svchost.exe -k NBA";

hscService = CreateService(
hscm, // SCManager database
name, // name of service
NULL, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_SHARE_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
bin, // services binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password

if (hscService == NULL)
{
g_runLog.Write("InstallService CreateService Error [%d]\r\n", GetLastError());
return GetLastError();
}

CloseServiceHandle(hscService);
CloseServiceHandle(hscm);

char szFilePath[MAX_PATH];
GetModuleFileName(NULL,(LPSTR)szFilePath,sizeof(szFilePath));
(_tcsrchr(szFilePath, _T('\\')))[1] = 0;
CString strPath = szFilePath ;
strPath += "SvcHostDllSrv.dll";

CreateStringReg(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost", REG_MULTI_SZ, name,"NBA\0\0");
CreateStringReg(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA", REG_EXPAND_SZ, "ImagePath", bin);
CreateStringReg(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA", REG_SZ, "DisplayName", name);
CreateStringReg(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA", REG_SZ, "Description", "");
CreateStringReg(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA", REG_SZ, "ObjectName", "LocalSystem");
CreateDWORDReg( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA", "ErrorControl", 1);
CreateDWORDReg( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA", "Start", 2);
CreateStringReg(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA\\Parameters", REG_EXPAND_SZ, "ServiceDll", (char*)(LPSTR)(LPCTSTR)strPath);

RegCloseKey(hkRoot);
RegCloseKey(hkParam);
CloseServiceHandle(hscService);
CloseServiceHandle(hscm);

g_runLog.Write("Install SvcHostDllSrv Successful!\r\n");
return 0;
}

int SvcHostDllSrv::UninstallService(char *name)
{
m_bExitFlag = true;

HKEY hKey;
SC_HANDLE hSCM = NULL, hService = NULL;
SERVICE_STATUS ServiceStatus;
//卸载服务
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(!hSCM)
{
g_runLog.Write("UninstallService CreateService Error [%d]\r\n", GetLastError());
return GetLastError();
}

hService = OpenService(hSCM, name, SERVICE_STOP | DELETE);

if(!hService)
{
g_runLog.Write("UninstallService OpenService Error [%d]\r\n", GetLastError());
//return GetLastError();
}

ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus);
DeleteService(hService);

CloseServiceHandle(hSCM);
CloseServiceHandle(hService);

long lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost", 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hKey);
if(lRet == ERROR_SUCCESS)
{
g_runLog.Write("UninstallService RegOpenKeyEx Error [%d]\r\n", GetLastError());
lRet = RegDeleteValue(hKey, name);
RegCloseKey(hKey);
}
RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA\\Parameters");
RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NBA");

g_runLog.Write("UnInstall SvcHostDllSrv Successful\r\n");
return 0;
}

void SvcHostDllSrv::CoreWork()
{
// 打开计算器
OpenCalcExe();

// 开启线程输出日期
_beginthreadex(NULL, 0, OutPutDateTime, this,0,NULL);
}

int SvcHostDllSrv::ConsoleSCManager(DWORD dwState, DWORD dwExitCode, DWORD dwProgress)
{
SERVICE_STATUS srvStatus;
srvStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
srvStatus.dwCurrentState = m_dwCurrState = dwState;
srvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
srvStatus.dwWin32ExitCode = dwExitCode;
srvStatus.dwServiceSpecificExitCode = 0;
srvStatus.dwCheckPoint = dwProgress;
srvStatus.dwWaitHint = 3000;
return SetServiceStatus( m_hSrv, &srvStatus );
}

bool SvcHostDllSrv::OpenCalcExe()
{
ShellExecute(0,"open","calc.exe","","",SW_SHOWNORMAL);
g_runLog.Write("Open Calc Success!\r\n");
return true;
}

unsigned __stdcall SvcHostDllSrv::OutPutDateTime(void *pm)
{
while (!m_bExitFlag)
{
if (m_bExitFlag)
break;
COleDateTime curTime = COleDateTime::GetCurrentTime();
CString strCurTime = curTime.Format("%Y-%m-%d %H:%M:%S");
g_runLog.Write("%s\r\n", strCurTime);
Sleep(1000);
}

return 0;
}

BOOL SvcHostDllSrv::CreateStringReg(HKEY hRoot,char *szSubKey, unsigned long kType,char* ValueName,char *Data)
{
HKEY hKey;

long lRet=RegCreateKeyEx(hRoot,szSubKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS|KEY_WOW64_64KEY,NULL,&hKey,NULL);

if (lRet!=ERROR_SUCCESS)
return false;

lRet=RegSetValueEx(hKey, ValueName, 0, kType, (BYTE*)Data,strlen(Data));

if (lRet!=ERROR_SUCCESS)
return false;

RegCloseKey(hKey);
return true;
}

BOOL SvcHostDllSrv::CreateDWORDReg(HKEY hRoot,char *szSubKey,char* ValueName,DWORD Data)
{
HKEY hKey;

long lRet=RegCreateKeyEx(hRoot,szSubKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS|KEY_WOW64_64KEY,NULL,&hKey,NULL);

if (lRet!=ERROR_SUCCESS)
return false;

DWORD dwSize=sizeof(DWORD);

lRet=RegSetValueEx(hKey,ValueName,0,REG_DWORD,(BYTE*)&Data,dwSize);

if (lRet!=ERROR_SUCCESS)
return false;

RegCloseKey(hKey);
return true;
}

// TestSrvHostDllSrv.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "SvcHostDllSrv.h"

#pragma comment(lib, "../Debug/SvcHostDllSrv.lib")

int _tmain(int argc, _TCHAR* argv[])
{
SvcHostDllSrv* shds = new SvcHostDllSrv();

shds->InstallService("NBA");

//Sleep(1000*60);

//shds->UninstallService("NBA");

if (shds)
{
delete shds;
shds = NULL;
}
return 0;
}
...全文
580 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-07-01
  • 打赏
  • 举报
回复
引用 21 楼 Jo_Kael 的回复:
@赵4老师 多谢,最后看来是系统Session问题! 总结一下: 64位系统和32位系统目录文件的差异 注册表差异 windows Vista系统前后 服务通讯,界面交互Session的问题
世上无难事,只要肯百度。
Jo_Kael 2016-06-30
  • 打赏
  • 举报
回复
@赵4老师 多谢,最后看来是系统Session问题! 总结一下: 64位系统和32位系统目录文件的差异 注册表差异 windows Vista系统前后 服务通讯,界面交互Session的问题
赵4老师 2016-06-29
  • 打赏
  • 举报
回复
以管理员身份运行cmd 在其中 先使用32位的sc和64位的sc命令卸载你的服务 再使用64位的sc命令安装你的服务 再使用64位的sc命令启动你的服务 ……
赵4老师 2016-06-29
  • 打赏
  • 举报
回复
使用64位的depends.exe查看你的exe依赖的dll,确认所有dll都是64位的。
Jo_Kael 2016-06-29
  • 打赏
  • 举报
回复
@赵4老师 完全不行,麻烦你分析下代码,看哪里有问题 系统:windows7 64位系统 sp1 编译器:VS2008 sp1
Jo_Kael 2016-06-29
  • 打赏
  • 举报
回复
@赵4老师 试过了,在64位机上,不管用64的sc还是32的sc都启动不了,显示[SC] StartService 失败 1053: 不过我在32位机上,可以启动,进入ServiceMain后,日志,还有OutPutDebugString的内容都不显示,我在里面用ShellExcute打开notepad.exe,在进程中看,打开了,但是桌面上不显示记事本 64位机上压根服务都起不起来
Jo_Kael 2016-06-24
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
[quote=引用 9 楼 Jo_Kael 的回复:] [quote=引用 8 楼 zhao4zhong1 的回复:] 属性、登录、……
属性里压根就没有登录这一项啊,4老师[/quote] 开始、运行、services.msc 在“服务”程序中列出的你的服务上点鼠标右键、在弹出的菜单中选属性、弹出“你的服务名字 的属性(本地计算机)”对话框,选“登录”选项卡,在登录身份中选此账户,输入administrator极其对应密码、确定。 试试看。[/quote] 试过了,不行的 你可以帮我看下代码哪里出错了吗,上面我贴出来了,或者你加我QQ:416764618,我发你工程,这个问题困扰我快一个礼拜了,一直没有头绪,谢谢大神了!
赵4老师 2016-06-24
  • 打赏
  • 举报
回复
C:\>sc /? 错误: 未知命令 描述: SC 是用于与 服务控制管理器和服务进行通信的命令行程序。 用法: sc <server> [command] [service name] <option1> <option2>... 选项 <server> 的格式为 "\\ServerName" 可以键入 "sc [command]" 以获得命令的进一步帮助 命令: query-----------查询服务的状态, 或 枚举服务类型的状态。 queryex---------查询服务的扩展状态, 或 枚举服务类型的状态。 start-----------启动服务。 pause-----------向服务发送 PAUSE 控制请求。 interrogate-----向服务发送 INTERROGATE 控制请求。 continue--------向服务发送 CONTINUE 控制请求。 stop------------向服务发送 STOP 请求。 config----------更改服务的配置(永久)。 description-----更改服务的描述。 failure---------更改服务失败时所进行的操作。 sidtype---------更改服务的服务 SID 类型。 qc--------------查询服务的配置信息。 qdescription----查询服务的描述。 qfailure--------查询服务失败时所进行的操作。 qsidtype--------查询服务的服务 SID 类型。 delete----------(从注册表)删除服务。 create----------创建服务(将其添加到注册表)。 control---------向服务发送控制。 sdshow----------显示服务的安全描述符。 sdset-----------设置服务的安全描述符。 showsid---------显示与 任意名称相对应的服务 SID 字符串。 GetDisplayName--获取服务的 DisplayName。 GetKeyName------获取服务的 ServiceKeyName。 EnumDepend------枚举服务的依存关系。 下列命令不要求服务名称: sc <server> <command> <option> boot------------(ok | bad) 表明是否将最后一次启动 保存为最后一次的正确启动配置 Lock------------锁定服务数据库 QueryLock-------查询 SCManager 数据库的 LockStatus 示例: sc start MyService 是否要查看 QUERY 和 QUERYEX 命令的帮助? [ y | n ]: n
赵4老师 2016-06-24
  • 打赏
  • 举报
回复
在64位Windows下。可能 C:\WINDOWS\system32\sc.exe是管64位服务的; C:\WINDOWS\syswow64\sc.exe是管32位服务的;
Jo_Kael 2016-06-24
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
[quote=引用 9 楼 Jo_Kael 的回复:] [quote=引用 8 楼 zhao4zhong1 的回复:] 属性、登录、……
属性里压根就没有登录这一项啊,4老师[/quote] 开始、运行、services.msc 在“服务”程序中列出的你的服务上点鼠标右键、在弹出的菜单中选属性、弹出“你的服务名字 的属性(本地计算机)”对话框,选“登录”选项卡,在登录身份中选此账户,输入administrator极其对应密码、确定。 试试看。[/quote] 新发现,在services.msc里找到服务,点击启动,windows7 64位机上显示1053服务没有及时响应启动,但是在windows7 32位机上显示127找不到指定的程序,查看了下注册表,一切都正常啊。。。
赵4老师 2016-06-23
  • 打赏
  • 举报
回复
严重怀疑楼主 混淆了64位和32位服务 没有设置合适的服务登录用户 防火墙、UAC、非管理员权限运行 没重启电脑 ……
赵4老师 2016-06-23
  • 打赏
  • 举报
回复
及其
赵4老师 2016-06-23
  • 打赏
  • 举报
回复
引用 9 楼 Jo_Kael 的回复:
[quote=引用 8 楼 zhao4zhong1 的回复:] 属性、登录、……
属性里压根就没有登录这一项啊,4老师[/quote] 开始、运行、services.msc 在“服务”程序中列出的你的服务上点鼠标右键、在弹出的菜单中选属性、弹出“你的服务名字 的属性(本地计算机)”对话框,选“登录”选项卡,在登录身份中选此账户,输入administrator极其对应密码、确定。 试试看。
Jo_Kael 2016-06-23
  • 打赏
  • 举报
回复
引用 8 楼 zhao4zhong1 的回复:
属性、登录、……
属性里压根就没有登录这一项啊,4老师
赵4老师 2016-06-23
  • 打赏
  • 举报
回复
属性、登录、……
Jo_Kael 2016-06-23
  • 打赏
  • 举报
回复
我的QQ:416764618,可以加我QQ,我发源码给你,帮我看看,谢谢!
Jo_Kael 2016-06-23
  • 打赏
  • 举报
回复
引用 5 楼 zhao4zhong1 的回复:
严重怀疑楼主
混淆了64位和32位服务
没有设置合适的服务登录用户
防火墙、UAC、非管理员权限运行
没重启电脑
……


1、用的64位机, 往注册表内写 KEY_ALL_ACCESS|KEY_WOW64_64KEY,是64位的
2、没有设置合适的服务登录用户,这个我看不懂
3、防火墙关闭了,UAC权限为requireAdministrator,是管理员账户在运行
4、重启电脑也试过了,不行,服务起不起来,在services.msc中右键启动服务,会提示错误1053:服务没有及时响应启动或者控制请求。

Jo_Kael 2016-06-22
  • 打赏
  • 举报
回复
@zhao4zhong1 都有日志打印的,服务的ServiceMain压根进不去,所以说只有在调用InstallService时后创建了服务,也写入注册表了。 按照资料上说的是(http://www.xfocus.net/articles/200308/601.html): 由于svchost为该组的所有服务都注册了svchost中的一个处理函数,因此每次启动任何一个服务时,服务管理器SCM都会调用FuncServiceMain() 这个函数。这个函数使用 svcTable 查询要启动的服务使用的DLL,调用DLL导出的ServiceMain()函数来启动服务,然后返回。 但是ServiceMain() svchost压根就不掉用,所以服务一直起不起来。
赵4老师 2016-06-22
  • 打赏
  • 举报
回复
用调试器(OD,WINDBG等)调试服务程序 To debug the initialization code of a service application, the debugger must be attached when the service is started. This is accomplished by creating a registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProgramName The ProgramName is the image file for the service application you are debugging. Do not specify a path. For example, the ProgramName might look like MyService.exe. Under this key create a string data value called Debugger. The value of this string should be set to the full path of the debugger that will be used. For example, c:\Debuggers\windbg.exe In addition to setting this registry key, the service application must be marked as "interactive". This allows your service to interact with the desktop, and allows the debugger window to appear on your desktop. This again requires modifying a registry key: you must bitwise-or the type entry for your service with 0x100 (this is the value for SERVICE_INTERACTIVE_PROCESS according to Winnt.h). The exact location and name of this registry entry varies. For example: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyServiceKey Finally, you need to adjust the service application timeout. Otherwise, the service application will kill the debugger within 20 seconds after starting. Adjusting the timeout involves setting an entry in the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control Under this key, create a DWORD data value called ServicesPipeTimeout. Set this entry to the amount of time in milliseconds that you want the service to wait before timing out. For example, 60,000 is one minute, while 86,400,000 is 24 hours. 设置ServicesPipeTimeout后需要重启系统才生效 Now, when the service is started, the debugger will also start. When the debugger starts, it will stop at the initial process breakpoint, before the service has begun running. This allows you to set breakpoints or otherwise configure your debugging session to let you monitor the startup of your service. Another option is to place calls to the DebugBreak function in your service from the point at which you would like to break into the debugger. (For more information, see DebugBreak in the Platform SDK documentation.) If your service is running with other services in a Service Host Process, you may need to isolate the service into its own Service Host Process.
加载更多回复(2)

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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