C++语言编写windows服务

C++语言编写windows服务

1、 windows服务

通过快捷键”win+R”打开运行框,输入”services.msc”,就能够打开windows服务。鼠标右键任意一个服务,能看见以下的选项,如下图1.1所示 
图1.1图1.1 windows服务 
本文的内容讲的就是通过windows服务控制程序的启动停止等操作。

2、 DebugView调试工具

官网上是这样介绍这款软件的

DebugView is an application that lets you monitor debug output on your local system, or any computer on the network that you can reach via TCP/IP. It is capable of displaying both kernel-mode and Win32 debug output, so you don’t need a debugger to catch the debug output your applications or device drivers generate, nor do you need to modify your applications or drivers to use non-standard debug output APIs.

我们可以用这款软件来调试windows服务程序。如图2.1进行DebugView的相关设置,并在我们写的程序中使用函数”OutputDebugString”,这时当启动我们写的windows服务,DebugView就能够将程序的调试信息捕捉到,显示出来。 
图2.1图2.1 将Capture Kernel打上勾

3、 c++语言编写windows服务

c++语言的windows服务的代码如下,此程序已在win7,VS2010调试运行通过。本例的源代码来自代码来源

#include <stdio.h>

#include <Windows.h>

#define SLEEP_TIME 5000 //间隔时间

#define FILE_PATH "C:\\log.txt" //信息输出文件

bool brun=false;

SERVICE_STATUS servicestatus;

SERVICE_STATUS_HANDLE hstatus;

int WriteToLog(char* str);

void WINAPI ServiceMain(int argc, char** argv);

void WINAPI CtrlHandler(DWORD request);

int InitService();

int WriteToLog(char* str)

{

    FILE* pfile;

    fopen_s(&pfile,FILE_PATH,"a+");

    if (pfile==NULL)

    {

        return -1;

    }

    fprintf_s(pfile,"%s\n",str);

    fclose(pfile);

    return 0;

}

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("testservice", CtrlHandler);

    if (hstatus==0)
    {

        WriteToLog("RegisterServiceCtrlHandler failed");

        return;

    }

    WriteToLog("RegisterServiceCtrlHandler success");

    //向SCM 报告运行状态

    servicestatus.dwCurrentState = SERVICE_RUNNING;

    SetServiceStatus (hstatus, &servicestatus);

    //在此处添加你自己希望服务做的工作,在这里我做的工作是获得当前可用的物理和虚拟内存信息

    brun=true;

    MEMORYSTATUS memstatus;

    char str[100];

    memset(str,'\0',100);

    while (brun)
    {

        GlobalMemoryStatus(&memstatus);

        int availmb=memstatus.dwAvailPhys/1024/1024;

        sprintf_s(str,100,"available memory is %dMB",availmb);

        WriteToLog(str);

        Sleep(SLEEP_TIME);

    }

    WriteToLog("service stopped");

}

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;

        break;

    default:

        break;

    }

    SetServiceStatus (hstatus, &servicestatus);
}

void main()
{

    SERVICE_TABLE_ENTRY entrytable[2];

    entrytable[0].lpServiceName="testservice";

    entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain;

    entrytable[1].lpServiceName=NULL;

    entrytable[1].lpServiceProc=NULL;

    StartServiceCtrlDispatcher(entrytable);

}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157

我在写相关的windows服务程序的时候遇到了这样的问题,程序加载当前的路径的配置文件”./config.xml”,发现程序总是在加载文件这个地方出错,然后用函数”GetCurrentDirectory”函数获取程序当前运行的路径,并且用函数”OutputDebugString”将获取到的路径信息打印出来,获取到程序当前的运行目录是”C:\Windows\system32”,要加载程序运行的配置文件,应该使用绝对路径。在windows服务中获取程序的路径。下面两段程序都能获得程序的路径。

//代码一
string GetProgramDir()    
{     
    TCHAR exeFullPath[MAX_PATH]; // Full path  
    GetModuleFileName(NULL,exeFullPath,MAX_PATH);  
    string strPath = __TEXT("");         
    strPath = exeFullPath;    // Get full path of the file  
    int pos = strPath.find_last_of(L'\\', strPath.length());  
    return strPath.substr(0, pos);  // Return the directory without the file name  
} 
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
//代码二
void GetConfigPath()
{   
    UINT    nLen  = MAX_PATH;
    char    process[MAX_PATH] = {0};
    char    drive[_MAX_DRIVE] = {0};
    char    dir[_MAX_DIR] = {0};
    char    fname[_MAX_FNAME] = {0};
    char    ext[_MAX_EXT] = {0};
    UINT    nbaselen = 0;
    UINT    nprocesslen = 0;
    char *pChrTemp = chConfigPath;
    memset(pChrTemp,0,MAX_PATH);
    GetModuleFileName(NULL, process, MAX_PATH);
    _splitpath_s(process, drive, dir, fname, ext);
    _makepath_s(process, "", dir, "", "");
    strcat_s(pChrTemp,nLen-strlen(pChrTemp),drive);
    nbaselen = (UINT)strlen(pChrTemp);
    nprocesslen = (UINT)strlen(process);
    if((nbaselen+nprocesslen)<nLen)
    {   
        strcat_s(pChrTemp,nLen-strlen(pChrTemp),process);
        chConfigPath[strlen(chConfigPath)-1] = '\0';
    }
    /*
    while( *pChrTemp) {
        if( *pChrTemp == '\\') {
            *pChrTemp = '/';
        }
        pChrTemp ++;
    }
    */
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

4、 将程序作为windows服务

windows服务有以下命令,”win+R”后输入”cmd”,即可进行操作

输入sc create testservicename binpath= D:\test.exe (这里的D:\test.exe路径就是你的.exe程序所在的绝对路径,注意"="后面有一个空格)

输入sc start testservicename 启动服务

输入sc query 会在最底部显示你的服务当前的状态

输入sc stop testservicename 停止服务

输入sc delete testservicename删除服务,该服务将在下次重启后删除,在重启之前将不能注册同一个名字的服务。
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

下面是一个简单的startup.bat文件创建windows服务的操作

rem startup.bat 文件创建服务,这里为服务取名为testservicename,此文件放在与.exe文件同级目录下,按着"Shift"键,同时单击鼠标右键,点击"在此处打开命令窗口",然后输入此文件名"startup.bat",就能创建此服务
@echo off

rem 获取绝对路径
set "CURRENT_DIR=%~dp0"

set "EXE_NAME=testservicename.exe"

@echo %CURRENT_DIR%%EXE_NAME%

rem 创建windows服务
sc create yzUpgradeService binpath= %CURRENT_DIR%%EXE_NAME%

sc config yzUpgradeService start= AUTO 

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值