C++读取注册表时使用服务失败但在控制台中同样成功

Posted

技术标签:

【中文标题】C++读取注册表时使用服务失败但在控制台中同样成功【英文标题】:C++ Reading Registry When using Service fails but the same succeds in Console 【发布时间】:2014-12-03 15:05:10 【问题描述】:

程序一启动,我就必须读取一些注册表值。如果代码是从命令提示符编译和运行的,则代码确实可以正常工作并提供我寻求的注册表值。但如果我创建服务并使用以下代码将 exe 附加到服务:

sc create someservice start=auto binpath= "PATH to EXE of Code"

并运行服务我没有得到想要的值。我附上了完整的代码。我也记录了每一步的结果。

#include <Windows.h>
#include <iostream>
#include <string>

SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hStatus; 

int WriteToLog(const char *);
std::string GetLPInstalledPath();

std::string GetLPInstalledPath()
    
        HKEY hKey;
        char buf[255];
        DWORD dwType;
        DWORD dwBufSize = sizeof(buf);
        std::string ss="";
        const char* subkey = "Software\\\\Logpoint\\\\InstalledPath";
        WriteToLog(" Inside GetLPInstalledPath") ;
        if( RegOpenKey(HKEY_CURRENT_USER,subkey,&hKey) == ERROR_SUCCESS)
        
            WriteToLog("Opened the Registry Key");
        dwType = REG_SZ;
        if( RegQueryValueEx(hKey,"path",0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
        
        ss = buf;       
        WriteToLog(ss.c_str());
        
        else
        
        WriteToLog(" Cound not find the value");

                   
        RegCloseKey(hKey);
        
        else
        
            WriteToLog(" Cannot Open the Installed Registry Path");

        

        return ss;
    

int WriteToLog(const char* str)

    //const char *logfile = "D:\\ubuntu_share\\lpa\\lpa_c\\build_win\\src\\lpa\\sample.txt";
    FILE* log;
    log = fopen("C:\\lpa\\sample.txt", "a+");
    if (log == NULL)
        return -1;
    fprintf(log, "%s\n", str);
    fclose(log);
    return 0;


int Run()

    WriteToLog("Run");
    WriteToLog("entering infinite loop of main thread ");
    while(1);
    WriteToLog("end of main thread ");
    return 0;


void ControlHandler(DWORD request) 
 
    //LOG4CPLUS_INFO(root,  "ControlHandler: Entry";
    switch(request) 
     
        case SERVICE_CONTROL_STOP: 
            //WriteToLog("Monitoring stopped.");
            WriteToLog( "ControlHandler: SERVICE_CONTROL_STOP Request");
            ServiceStatus.dwWin32ExitCode = 0; 
            ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
            if(SetServiceStatus (hStatus, &ServiceStatus)==FALSE)
            
                WriteToLog("ServiceCtrlHandler: SetServiceStatus returned error");
            
            return; 

        case SERVICE_CONTROL_SHUTDOWN: 
           // WriteToLog("Monitoring shutdown.");
            WriteToLog("ControlHandler: SERVICE_CONTROL_SHUTDOWN Request");
            ServiceStatus.dwWin32ExitCode = 0; 
            ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
            if(SetServiceStatus (hStatus, &ServiceStatus) == FALSE)
            
                WriteToLog("ServiceCtrlHandler: SetServiceStatus returned error");
            
            return; 

        case SERVICE_CONTROL_INTERROGATE:
            return;
        default:
            WriteToLog("ServiceCtrlHandler");
            break;
     

    // Report current status
    SetServiceStatus (hStatus,  &ServiceStatus);
    WriteToLog("ServiceCtrlHandler: Exit");
    return; 
 

void ServiceMain(int argc, char** argv) 
 
    //WriteToLog("at ServiceMain");
    WriteToLog("ServiceMain");
    int error; 

    ServiceStatus.dwServiceType        = SERVICE_WIN32; 
    ServiceStatus.dwCurrentState       = SERVICE_START_PENDING; 
    ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    ServiceStatus.dwWin32ExitCode      = 0; 
    ServiceStatus.dwServiceSpecificExitCode = 0; 
    ServiceStatus.dwCheckPoint         = 0; 
    ServiceStatus.dwWaitHint           = 0; 

    hStatus = RegisterServiceCtrlHandler(
        "MemoryStatus", 
        (LPHANDLER_FUNCTION)ControlHandler); 
    if (hStatus == NULL) 
     
        // Registering Control Handler failed
        WriteToLog("ServiceMain: RegisterServiceCtrlHandler returned error");
        return; 
      

    // We report the running status to SCM. 
    ServiceStatus.dwCurrentState = SERVICE_RUNNING; 
    if(SetServiceStatus (hStatus, &ServiceStatus)==FALSE)
    
        WriteToLog("ServiceMain: SetServiceStatus returned error");
    

    WriteToLog("ServiceMain: Performing Service Start Operations");
    Run();
    WriteToLog("ServiceMain: Performing Cleanup Operations");
    ServiceStatus.dwControlsAccepted = 0;
    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCheckPoint = 3;

    if (SetServiceStatus (hStatus, &ServiceStatus) == FALSE)
    
        WriteToLog("ServiceMain: SetServiceStatus returned error");
    
    WriteToLog("ServiceMain: Exit");
    return; 



int StartLpaService()


    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = "MemoryStatus";
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;
    // Start the control dispatcher thread for our service
    if(StartServiceCtrlDispatcher(ServiceTable)  == FALSE)
    
        WriteToLog("StartLpaService: StartServiceCtrlDispatcher returned error");
        return GetLastError ();
    
    WriteToLog("Main: Exit");
    return 0;


int main(int argc, char **argv)
 
    std::string pa = GetLPInstalledPath();
#ifdef SERVICE_DEBUG
    WriteToLog("SERVICE_DEBUG");
    Sleep(15000);
#endif
    StartLpaService();
    return 0;

我面临的问题是,如果程序的服务启动,没有写入注册表值,而是直接从命令提示符运行给出值。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

您正在查看HKCU,即当前用户的注册表配置单元。因此,对于您所描述的内容,最合理的解释只是该服务在不同的用户下运行。即服务在交互式用户以外的用户帐户下运行。

【讨论】:

我如何知道在哪个用户帐户下运行服务?那么我应该写HKCU以外的值吗? @SarvagyaPant:您在创建服务时配置用户。通常的解决方案是HKLM 嗯,这取决于我认为的问题。您可以尝试从 HKLM 阅读,但大概您从 HKCU 阅读,因为那是您想要的信息所在的地方。所以,问问自己,你想阅读的信息在哪里? 也是默认方式服务被创建为LocalSystem。这是否意味着我必须使用 HKLM? 你必须记住,我们不知道这个注册表项是什么,你为什么期望它存在,你会用它做什么等等。请记住,我们只是回答提出的问题。你问为什么服务看不到密钥。我试图回答这个问题。现在,如果所有相关方都使用 HKLM,那么密钥将被共享。模 32/64 位注册表重定向。你几乎肯定不希望你的服务是LocalSystem。这是不好的做法。

以上是关于C++读取注册表时使用服务失败但在控制台中同样成功的主要内容,如果未能解决你的问题,请参考以下文章

DirectX9 CreateDevice 在 C 中失败,但在 C++ 中成功

SSIS 在本地运行但在服务器上失败

设计注册成功,登录失败

windows services 读取注册表配置文件一般在哪个目录

使用LDAP登录模块进行Teiid VDB数据虚拟化的身份验证失败

使用 Makefile 编译失败但在命令行中成功