使用VS C++ 2005使用ATL编写一个Windows服务,发现不知道如何单步调试。msdn的说法是:
如何:调试 Windows 服务应用程序
更新:2007 年 11 月
由于服务必须从服务控制管理器的上下文中运行,而不是从 Visual Studio 中运行,因此调试服务不像调试其他 Visual Studio 应用程序类型那样简单。若要调试服务,必须首先启动服务,然后将一个调试器附加到正在运行服务的进程中。然后可以使用 Visual Studio 的所有标准调试功能来调试应用程序。
我将程序编译成功后,在“管理工具”中的服务管理器中其中已经注册的服务,然后VS 2005的菜单栏“调试”——〉“附加到进程”,在可用进程列表中选择我编写的windows服务,接着在程序中设置断点,按F5开始调试,但是总是进入 不了我的那个函数。但是如果我采用写日志的方式进行调试,发现确是可以进入那个函数的。
网上的另外一个说法是:可以先不注册成服务,按普通的exe程序那样执行,就可以调试了。
但是我试过了。也不行。
我的主要代码是这样的:
#include "stdafx.h"
#include "resource.h"
#include "StartThunder.h"
#include <stdio.h>
class CStartThunderModule : public CAtlServiceModuleT< CStartThunderModule, IDS_SERVICENAME >
{
public :
DECLARE_LIBID(LIBID_StartThunderLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_STARTTHUNDER, "{B3B6CFFE-DDFE-4397-88DC-B3DBE7D68D82}")
HRESULT InitializeSecurity() throw()
{
// TODO : 调用 CoInitializeSecurity 并为服务提供适当的
// 安全设置
// 建议 - PKT 级别的身份验证、
// RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
// 以及适当的非 NULL 安全说明符。
return S_OK;
}
//HRESULT PreMessageLoop(int nShowCmd) throw();
// HRESULT PostMessageLoop() throw();
HRESULT RegisterAppId(bool bService = false) throw();
HRESULT Start(int nShowCmd) throw();
HRESULT Run(int nShowCmd = SW_HIDE)throw();
};
HRESULT CStartThunderModule::Start(int nShowCmd) throw()
{
// HRESULT hr = __super::Start(nShowCmd);
HRESULT hr = S_OK;
if (SUCCEEDED(hr))
{
// 通过注册表获取迅雷的路径
// 打开键
HKEY hKEY;
LPCTSTR Rgspath = _T("SOFTWARE\\Thunder Network\\ThunderOem\\thunder_backwnd");
LONG ret = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,Rgspath,0, KEY_READ, &hKEY);
if(ret != ERROR_SUCCESS)
{
RegCloseKey(hKEY);
return S_FALSE;
}
// 读取键值内容
DWORD dwInfoSize;
DWORD type = REG_SZ;
BYTE UserInfo[255];
/*
注意RegQueryValueEx最后一个参数是个双向参数,入参时表示的是前一个参数的缓冲区大小,出参时表示的是返回的大小。
所以最好把UserInfo的大小给dwInfoSize,防止UserInfo溢出。
*/
dwInfoSize = sizeof(UserInfo)/sizeof(BYTE);
// added end
ret = ::RegQueryValueEx(hKEY, _T("Path"), NULL, &type, UserInfo, &dwInfoSize);
if(ret!=ERROR_SUCCESS)
{
LPVOID lpMsgBuf;
DWORD dw = ::GetLastError();
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
::MessageBox(NULL,(LPCTSTR)lpMsgBuf,_T("系统错误"),MB_OK|MB_ICONSTOP);
::LocalFree(lpMsgBuf);
::RegCloseKey(hKEY);
return S_FALSE;
}
_tfopen(_T("C:\\Thunder.txt"),_T("w"));
}
return hr;
}
HRESULT CStartThunderModule::RegisterAppId(bool bService) throw()
{
HRESULT hr = S_OK;
BOOL res = __super::RegisterAppId(bService);
if (bService)
{
if (IsInstalled())
{
SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SERVICE_CHANGE_CONFIG);
SC_HANDLE hService = NULL;
if (hSCM == NULL)
hr = AtlHresultFromLastError();
else
{
hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);
if (hService != NULL)
{
TCHAR szDisplayName[128];
ZeroMemory(szDisplayName, 128);
lstrcpy(szDisplayName, _T("迅雷自动启动"));
::ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, NULL, NULL, NULL, NULL, NULL, NULL, NULL, szDisplayName);
SERVICE_DESCRIPTION Description;
TCHAR szDescription[1024];
ZeroMemory(szDescription, 1024);
ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION));
lstrcpy(szDescription, _T("XXX软件有限公司 版权所有(R) 2001-2008"));
Description.lpDescription = szDescription;
::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &Description);
::CloseServiceHandle(hService);
}
else
hr = AtlHresultFromLastError();
::CloseServiceHandle(hSCM);
}
}
}
return hr;
}
HRESULT CStartThunderModule::Run(int nShowCmd)throw()
{
HRESULT hr = S_OK;
hr = ::CoInitialize(NULL);
Start(nShowCmd);
hr = __super::PreMessageLoop(nShowCmd);
if (hr == S_OK)
{
if (m_bService)
{
//可以在这里启动线程,或者什么其他东西来做自己的工作的啦
//这里是什么都没有做了,只输出一条信息
// LogEvent(_T("widebright 的服务启动咯,呵呵 "));
SetServiceStatus(SERVICE_RUNNING);
}
//进入消息循环,不停的处理消息,可能最后分发到Handler去处理,调用了OnShutdown等函数的。
__super::RunMessageLoop();
}
if (SUCCEEDED(hr))
{
hr = PostMessageLoop();
}
//可以在适当的时候调用Uninstall函数来卸载掉服务
//__super::Uninstall();
::CoUninitialize();
return hr;
}
CStartThunderModule _AtlModule;
//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/, int nShowCmd)
{
return _AtlModule.WinMain(nShowCmd);
}
前无古人,后无来者