俺最多只能给300分,不够可以另加,意在解决问题:(这个问题是我几年前就遇到的问题,当时不了了之了,现在又遇到,今天特意花了一个下午研究,还是没有解决,郁闷,特请教诸位高手。
需求说起来很简单:我要创建一个windows服务,并且运行服务的用户、密码都是要指定的以下是我的主要代码:
void InstallSvr(const char* sUser, const char* sPwd)
{
SC_HANDLE hSCDB = NULL;
try
{
//open SCM
char sPath[1024];
memset(sPath, 0, sizeof(sPath));
GetModuleFileName(NULL, sPath, sizeof(sPath));
hSCDB=OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if( !hSCDB )
{
throw "Failed to open SCM in InstallSvr.";
} //create service
char strUser[64];
char strPwd[64];
strcpy(strUser, "NT AUTHORITY\\NetworkService");
strcpy(strPwd, "");
if ( strlen(sUser)>0 && strlen(sPwd)>0 )  //指定用户、密码,问题就发生在这种场合
{
strcpy(strUser, sUser);
strcpy(strPwd, sPwd);
if ( SetSrvPriOfAccount(strUser)==RTN_OK )  //为这个用户指派权限“以服务登录”
{
printf("set SeServiceLogonRight to user[%s] OK.\n", strUser);
}
}
SC_HANDLE hTemp = CreateService(hSCDB, NIK_SERVICE_NAME, NIK_SERVICE_DISPLAYNAME, 
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,
sPath, NULL, NULL, NULL, strUser, strPwd);
if( !hTemp )
{
throw "Failed to CreateService.";
}
//ChangeServiceConfig(hTemp, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
// NULL, NULL, NULL, NULL, strUser, strPwd, NULL); //无效的测试 //set  description
SERVICE_DESCRIPTION stDescription;
stDescription.lpDescription = NIK_SERVICE_DESCRIPTION;
ChangeServiceConfig2(hTemp, SERVICE_CONFIG_DESCRIPTION, &stDescription);

CloseServiceHandle(hTemp);
}
catch (const char* e1)
{
printf(e1);
}
catch (...)
{
printf("Unknown error in InstallSvr.");
}
if( hSCDB != NULL )
{
CloseServiceHandle(hSCDB);
hSCDB = NULL;
}
}问题是:服务成功创建,但是启动服务显示“1069错误(由于登录失败而无法启动服务)”
暂时我的解决方法是手工打开service控制面板,修改密码,然后确定,服务即可成功启动。
说明:程序中设置的密码肯定是正确的。代码行SetSrvPriOfAccount(strUser)是我今天增加的,目的是是指定的用户具有“以服务登录”的权限,但是问题依然存在,我又以为是系统更新的问题,重启系统之后依然不行。不管我怎么改,依然是需要手工改一下密码,服务才可以启动。郁闷。。

解决方案 »

  1.   

    CreateService最后参数给NULL试试。
      

  2.   

    你可以看一下,用Service控制面板修改密码前后,服务的注册表键下面有什么变化。
      

  3.   

    还真没遇到过这个问题。
    顺便提一个问题:为何不用默认的LocalSystem账号而改用权限更低的NetworkService账号?
      

  4.   

    >>顺便提一个问题:为何不用默认的LocalSystem账号而改用权限更低的NetworkService账号?同问,并标记,等待答案
      

  5.   

    最后加NULL是可以的,不过只是适合于用LocalSystem、NetworkService这种系统内置的帐号,或者没有密码的场合,而我现在是要指定特定的用户、密码,是客户自己建的,这是业务决定的,没办法:(最初用LocalSystem的时候发现这个用户好像不能用于网络协议上,后来改的NetworkService,不过根据现在的需求,NetworkService也不会使用,只是保留以前的代码而已,总而言之,我是希望使用程序的方法自动创建可以启动的、指定用户帐号的服务,无论用的啥招-_-注册表我大概看了下,好像没有关于密码的,不过我没有做前后比较,另外我也想用API监视,只是没有时间了只好先发个贴
      

  6.   

    刚才对比了一下我的程序创建完服务、手工重新置一下密码的注册表,前后没有变化:(
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\服务名
      

  7.   

    传入的参数 sUser 是什么?
    应该是这样的形式:  .\user
      

  8.   

    void InstallSvr(const char* sUser, const char* sPwd)

    SC_HANDLE hSCDB = NULL; 
    try 

    //open SCM
    char sPath[] = "c:\\Project1.exe";
    //memset(sPath, 0, sizeof(sPath));
    //GetModuleFileName(NULL, sPath, sizeof(sPath));
    hSCDB=OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); 
    if( !hSCDB ) 

    throw "Failed to open SCM in InstallSvr."; 
    } //create service 
    char strUser[64]; 
    char strPwd[64]; 
    strcpy(strUser, "NT AUTHORITY\\NetworkService"); 
    strcpy(strPwd, ""); 
    if ( strlen(sUser)>0 && strlen(sPwd)>0 )  //指定用户、密码,问题就发生在这种场合 

    strcpy(strUser, sUser); 
    strcpy(strPwd, sPwd); 
    //if ( SetSrvPriOfAccount(strUser)==RTN_OK )  //为这个用户指派权限“以服务登录”
    //{
    //printf("set SeServiceLogonRight to user[%s] OK.\n", strUser);
    //}} 
    SC_HANDLE hTemp = CreateService(hSCDB, "MyCnfgSvc", "MyCnfgSvc",
    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,
    sPath, NULL, NULL, NULL, strUser, strPwd);
    if( !hTemp ) 

    throw "Failed to CreateService.";

    //ChangeServiceConfig(hTemp, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 
    // NULL, NULL, NULL, NULL, strUser, strPwd, NULL); //无效的测试 //set  description 
    SERVICE_DESCRIPTION stDescription; 
    stDescription.lpDescription = "Tester";
    ChangeServiceConfig2(hTemp, SERVICE_CONFIG_DESCRIPTION, &stDescription); CloseServiceHandle(hTemp); 

    catch (const char* e1) 

    printf(e1);
    }
    catch (...)
    {
    printf("Unknown error in InstallSvr.");
    }
    if( hSCDB != NULL ) 

    CloseServiceHandle(hSCDB); 
    hSCDB = NULL; 


    InstallSvr(".\\Administrator"/*不知道楼主是不是犯了低级错误,*/,"******");
      

  9.   

    啊啊我的帐号密码是从命令行传进来的,不在代码中。lsd僵哥测试OK了?你的是什么系统?明天有空俺再test下
      

  10.   

    命令行传入,建议加个双引号,比如
    ".\Administrator" 
      

  11.   

    晕倒看来不跟进新技术,就是不行@_@俺从来没用过win2003,今天找同事要了台win2003机器测试了一下,结果如下:
    win2003下一切OK!与\转义符无关,看来应该是OS的bug奇怪为什么os sp一直都没更新这个bug吗?这个问题从win2000到xp一直都存在@_@本帖告一段落,回头有空找vista试试,谢谢各位-_-
      

  12.   

    很抱歉地告诉你,我的Winxp也没有问题,但是会提示我要求该用户配置以服务启动的权限,可能关键问题在这里。
      

  13.   

    具体做法:控制面板->管理工具->本地安全策略(设置)本地策略->用户权利指派->作为服务登录
    添加该用户
      

  14.   

    那是为何,难以理解了,我也很遗憾告诉你,我已经给用户设置以服务启动的权限了(代码中的SetSrvPriOfAccount函数),各种测试我都作过了@_@关于权限,如果你先行设置权限(无论是程序还是手动),windows就不会再要求,问题不在这里,以确认过了。
      

  15.   

    看来我需要test下你贴的代码,可是看起来一样啊#$%^#$%^#SDF@#$%WDF@#$@@R$^F#$%
      

  16.   

    test了一下你的代码,还是老问题,权限确认肯定有(另外如果没有权限,在手工修改服务时,windows是会提示的给这个用户设置了权限的),并且只要手动再修改次密码,即可成功启动。
      

  17.   

    如果代码没问题,又不是bug,也许和补丁、系统哪个配置有关,唉。。
      

  18.   

    楼主:你的SetSrvPriOfAccount函数是怎么实现的?