报告错误:使用StartServiceCtrlDispatcher(entrytable)时访问冲突

Sua*_*SFT 1 c sdk

当程序执行到StartServiceCtrlDispatcher()时,我的程序报告错误。

错误:ConsoleApplication33.exe中的0x74BFFF70(sechost.dll)抛出异常:0xC0000005:访问冲突读取位置0xCCCCCCCC。

我尝试了很多方法,但是失败了。我在哪里写错了。请告诉我。先感谢您。代码如下:

#include "pch.h"
#include<Windows.h>
#include<iostream>
#include<atlstr.h>
#include<fstream>
#include<tchar.h>
bool brun = false;
SERVICE_STATUS servicestatus;
SERVICE_STATUS_HANDLE hstatus;
void WriteToLog(const std::string &str)
{
    std::ofstream p("D:/log.txt", std::ios::app);
    if (!p.is_open())
        return;
    p << str << std::endl;
    p.close();
}

void WINAPI CtrlHandler(DWORD request)
{
    switch (request)
    {
    case SERVICE_CONTROL_STOP:
        brun = false;
        servicestatus.dwCurrentState = SERVICE_STOPPED;
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        brun = false;
        servicestatus.dwCurrentState = SERVICE_STOPPED;
    }
    SetServiceStatus(hstatus, &servicestatus);
}
void WINAPI ServiceMain(int argc, char **argv)
{
    servicestatus.dwServiceType = SERVICE_WIN32;
    servicestatus.dwCurrentState = SERVICE_START_PENDING;
    servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
    servicestatus.dwWin32ExitCode = 0;
    servicestatus.dwServiceSpecificExitCode = 0;
    servicestatus.dwCheckPoint = 0;
    servicestatus.dwWaitHint = 0;
    hstatus = ::RegisterServiceCtrlHandler("MyService", CtrlHandler);
    if (hstatus == 0)
    {
        WriteToLog("RegisterServiceCtrlHandler failed");
        return;
    }
    WriteToLog("RegisterServiceCtrlHandler success");
    servicestatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hstatus, &servicestatus);
    brun = true;
    MEMORYSTATUSEX memstatus;
    char str[100];
    memset(str, '\0', 100);
    while (brun)
    {
        GlobalMemoryStatusEx(&memstatus);
        SIZE_T availmb = memstatus.ullAvailPhys / 1024 / 1024;
        sprintf_s(str, 100, "available memory is %zdMB", availmb);
        WriteToLog(str);
        Sleep(2000);
    }
    WriteToLog("service stopped");
}
int _tmain(int argc, _TCHAR **argv)
{
    SERVICE_TABLE_ENTRY entrytable[1];
    CString cstr("MyService");
    entrytable[0].lpServiceName = cstr.GetBuffer();
    cstr.ReleaseBuffer();
    entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    StartServiceCtrlDispatcher(entrytable);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Jea*_*SFT 7

SERVICE_TABLE_ENTRY结构数组要求最后一个成员为NULL,我们将其称为“ Sentinel”(所有值均为NULL),它表示服务表的末尾。服务启动后,将调用StartServiceCtrlDispatcher()来通知服务控制器该服务正在执行并提供地址。StartServiceCtrlDispatcher()仅需要至少两个SERVICE_TABLE_ENTRY结构的数组。

This is why access violations occur. When your program executes to StartServiceCtrlDispatcher(entrytable), It will acess the second element ofSERVICE_TABLE_ENTRY, but your array definition has only one element, so it results in access violation.

int _tmain(int argc, _TCHAR **argv)
{
    //SERVICE_TABLE_ENTRY entrytable[] = 
    //{ 
    //  {(LPWSTR)"MyService", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
    //  {NULL, NULL}
    //};
    SERVICE_TABLE_ENTRY entrytable[2];
    CString cstr("MyService");
    entrytable[0].lpServiceName = cstr.GetBuffer();
    cstr.ReleaseBuffer();
    entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    entrytable[1].lpServiceName = NULL;
    entrytable[1].lpServiceProc = NULL;
    StartServiceCtrlDispatcher(entrytable);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)