安装 Windows 服务 C++
Posted
技术标签:
【中文标题】安装 Windows 服务 C++【英文标题】:Install Windows Service C++ 【发布时间】:2014-03-20 22:26:32 【问题描述】:我有以下功能来安装我的 windows c++ 服务并使用了很多年。最近,我通过一些代码更改将其转换为 unicode。该代码仍然适用于多字节代码,并创建运行时检查失败 #2 - 围绕变量“MyKey”的堆栈因 unicode 而损坏。我认为调用RegSetValueEx可能有问题,但找不到原因。欢迎任何建议。函数调用结束时抛出错误。
static TCHAR* NTSERVICE=_T("MyService");
static TCHAR* svcname=_T("My Service");
void InstallService(char *exename)
SC_HANDLE myService, scm;
HKEY MyKey;
TRACE ("Installing service...");
scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if (!scm)
TRACE ("Failed to open Service Control Manager! (Error code = %d)", GetLastError());
return;
DWORD Disposition = 0;
TCHAR modname[256];
GetModuleFileName(NULL, (LPTSTR)modname, sizeof(modname)/sizeof(TCHAR));
myService = CreateService(scm,
(LPCTSTR)NTSERVICE, //Internal service name
(LPCTSTR)svcname, //Show name
SERVICE_ALL_ACCESS, //We want full control
SERVICE_WIN32_OWN_PROCESS, //Let's not mess it up for somebody else..
SERVICE_AUTO_START, //The service requires manual start
SERVICE_ERROR_NORMAL, //Normal handling when error in startup
(LPCTSTR)modname, //Binary file
0, 0, 0, 0, 0); //Misc :)
if (!myService)
TRACE (_T("Failed to create the %s service! (Error code =%d)"), NTSERVICE , GetLastError());
CloseServiceHandle(scm);
return;
TCHAR keyname[300];
_tcscpy_s(keyname,sizeof(keyname),_T("SYSTEM\\CurrentControlSet\\Services\\"));
_tcscat_s(keyname,300, NTSERVICE);
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
(LPCTSTR)keyname,
NULL, //Reserved
NULL, //Class
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, //Security attributes :)
&MyKey,
&Disposition)
!= ERROR_SUCCESS)
TRACE(_T("Failed to open registry key!"));
return;
TCHAR buffer[1024];
int size = strlen(exename);
MultiByteToWideChar(CP_ACP, 0, (char*)exename, size, buffer, size*2);
buffer[size] = _T('\0');
if (RegSetValueEx(MyKey, _T("Exename"), NULL, REG_SZ, (const BYTE*)buffer,
(size + 1) * sizeof(TCHAR)) != ERROR_SUCCESS)
TRACE(_T("Failed to write binary executable name to registry!"));
// printf("Failed to write binary executable name to registry!");
RegCloseKey(MyKey);
return;
RegCloseKey(MyKey);
TRACE(_T("Service successfully installed."));
printf("Service successfully installed.");
CloseServiceHandle(myService);
CloseServiceHandle(scm);
【问题讨论】:
我把这个函数放在一个对话框中并运行它。它给出 0xC0000005:访问冲突执行位置 0xFEFEFEFE。 【参考方案1】:GetModuleFileName(NULL, (LPTSTR)modname, sizeof(modname));
_tcscpy_s(keyname,sizeof(keyname),_T("SYSTEM\\CurrentControlSet\\Services\\"));
sizeof
返回字节大小。因为TCHAR
是wchar_t
定义了UNICODE,所以字节数是字符数的两倍。
使用
GetModuleFileName(NULL, (LPTSTR)modname, _countof(modname));
_tcscpy_s(keyname,_countof(keyname),_T("SYSTEM\\CurrentControlSet\\Services\\"));
或
GetModuleFileName(NULL, (LPTSTR)modname, sizeof(modname)/sizeof(TCHAR));
_tcscpy_s(keyname,sizeof(keyname)/sizeof(TCHAR),_T("SYSTEM\\CurrentControlSet\\Services\\"));
改为。
【讨论】:
我更正了上面的代码。问题依然存在。 痕迹显示什么?除了函数退出时的错误之外,一切正常吗?我不太了解 CString。您是否尝试过另一种从 char 转换为 TCHAR 的方法? 我做了一些改变。 CString temp(exename); TCHAR 缓冲区[1024]; _tcscpy_s(缓冲区, temp.GetBuffer()); int 大小 = _tcslen(缓冲区);缓冲区[大小] = _T('\0'); if (RegSetValueEx(MyKey, _T("Exename"), NULL, REG_SZ, (const BYTE*)buffer, (size + 1) * sizeof(TCHAR)) != ERROR_SUCCESS) 代码在调试模式下看起来不错。函数执行后给出0xC0000005:访问冲突执行位置0xFEFEFEFE。 0xFEFEFEFE 是放置在已删除内存中的签名。如果注释掉CString,错误仍然存在吗? 我更新了代码。我删除了 CString 转换,错误仍然存在。但是,如果我删除所有 reg 更改,错误就消失了。【参考方案2】:试试这个:
static const LPTSTR NTSERVICE = TEXT("MyService");
static const LPTSTR svcname = TEXT("My Service");
void InstallService(char *exename)
SC_HANDLE myService, scm;
HKEY MyKey;
TRACE (_T("Installing service..."));
scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if (!scm)
TRACE (_T("Failed to open Service Control Manager! (Error code = %d)"), GetLastError());
return;
TCHAR modname[MAX_PATH+1] = 0;
GetModuleFileName(NULL, modname, MAX_PATH);
myService = CreateService(scm,
NTSERVICE, //Internal service name
svcname, //Show name
SERVICE_ALL_ACCESS, //We want full control
SERVICE_WIN32_OWN_PROCESS, //Let's not mess it up for somebody else..
SERVICE_AUTO_START, //The service requires manual start
SERVICE_ERROR_NORMAL, //Normal handling when error in startup
modname, //Binary file
0, 0, 0, 0, 0); //Misc :)
if (!myService)
TRACE (_T("Failed to create the %s service! (Error code =%d)"), NTSERVICE, GetLastError());
CloseServiceHandle(scm);
return;
TCHAR keyname[300];
_tcscpy_s(keyname, 300, _T("SYSTEM\\CurrentControlSet\\Services\\"));
_tcscat_s(keyname, 300, NTSERVICE);
DWORD Disposition = 0;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
keyname,
NULL, //Reserved
NULL, //Class
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, //Security attributes :)
&MyKey,
&Disposition) != ERROR_SUCCESS)
TRACE(_T("Failed to open registry key!"));
CloseServiceHandle(myService);
CloseServiceHandle(scm);
return;
TCHAR buffer[MAX_PATH+1] = 0;
#ifdef UNICODE
int len = MultiByteToWideChar(CP_ACP, 0, exename, strlen(exename), buffer, MAX_PATH);
#else
strcpy_s(buffer, MAX_PATH, exename);
int len = strlen(buffer);
#endif
buffer[len] = 0;
if (RegSetValueEx(MyKey,
TEXT("Exename"),
NULL,
REG_SZ,
(const BYTE*)buffer,
(len + 1) * sizeof(TCHAR)) != ERROR_SUCCESS)
TRACE(_T("Failed to write binary executable name to registry!"));
RegCloseKey(MyKey);
CloseServiceHandle(myService);
CloseServiceHandle(scm);
return;
RegCloseKey(MyKey);
CloseServiceHandle(myService);
CloseServiceHandle(scm);
TRACE(_T("Service successfully installed."));
printf("Service successfully installed.");
【讨论】:
以上是关于安装 Windows 服务 C++的主要内容,如果未能解决你的问题,请参考以下文章