VC++ 开发总结回顾(一)

VC++ 开发总结回顾(一)

做过一段时间vc++,虽说我现在也经常在群里喷微软的vc++ 各种不好用和繁琐,而且我认为c++已经越来越变质了,尤其到c++ 11再也不是我认识的c++了,可是即使这样,再让我做windows 软件我还是用vc++,因为我不会.net也不会qt

我回顾一下我之前vc++经常用的东西,我一直用的是vs2015,尽管我听说vs已经出了2017而且好像支持交叉编译了。。。

vc++开发其实就像php的框架一样 一般只需要在主程序文件 和 initDialog 和 OnPaint 以及一些事件里绘制一些东西即可

1.windows 程序分为 控制台程序 和 服务程序,控制台程序 不用说 是非常常见 的,主要说一下服务程序

别人的博客地址:

https://blog.csdn.net/lincyang/article/details/6231406

1)初始化一部分全局变量

void Init();

BOOL IsInstalled();

BOOL Install();

BOOL Uninstall();

void LogEvent(LPCTSTR pszFormat, ...);

void WINAPI ServiceMain();

void WINAPI ServiceStrl(DWORD dwOpcode);

TCHAR szServiceName[] = _T("ServiceTest");

BOOL bInstall;

SERVICE_STATUS_HANDLE hServiceStatus;

SERVICE_STATUS status;

DWORD dwThreadID;

2)初始化服务句柄

void init()
{
    hEvent = CreateEvent(NULL, TRUE, FALSE,NULL);
    hServiceStatus = NULL;
    status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
    status.dwCurrentState = SERVICE_START_PENDING;
    status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    status.dwWin32ExitCode = 0;
    status.dwServiceSpecificExitCode = 0;
    status.dwCheckPoint = 0;
    status.dwWaitHint = 0;
}

3)安装和卸载服务和是否安装

是否安装过服务:

BOOL IsInstalled()
{
    BOOL bResult = FALSE;
    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    /*CString errorno;
    errorno.Format("%d", GetLastError());
    AfxMessageBox(errno);*/
    if (hSCM != NULL)
    {
        SC_HANDLE hService = ::OpenService(hSCM,szServiceName,SERVICE_QUERY_CONFIG);
        if (hService != NULL)
        {
            bResult = TRUE;
            ::CloseServiceHandle(hService);
        }
        ::CloseServiceHandle(hSCM);
    }
    else {
        AfxMessageBox("服务出现异常不能打开");
        return FALSE;
    }
    return bResult;
}

安装服务:

BOOL Install()
{
    //这里列出主要的两个函数,其它的可以在代码里找。

    if (IsInstalled())
        return TRUE;

    //打开服务控制管理器
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);


    if (hSCM == NULL)
    {
        AfxMessageBox("不能打开服务");
        return FALSE;
    }

    //创建服务
    CHAR szFilePath[MAX_PATH];
    ::GetModuleFileName(NULL, szFilePath, MAX_PATH);
    SC_HANDLE hService = ::CreateService(
        hSCM, szServiceName, szServiceName,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
        SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, "", NULL, NULL);

    CString errorno;
    errorno.Format("%d",GetLastError());
    if (errorno == "1073")
    {
        AfxMessageBox("指定的服务已经存在");
        return false;
    }
    else if(hService == NULL){
        AfxMessageBox("服务打开失败");
        return false;
    }

    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
    return TRUE;
}

卸载服务

BOOL Uninstall()
{
    //这里列出主要的两个函数,其它的可以在代码里找。

    //打开服务控制管理器
    BOOL result = FALSE;
    SC_HANDLE hSCM = ::OpenService(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM != NULL) {

        SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG);

        if (hService != NULL) {

            OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

            //打开服务
            OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);

            //停止服务
            ControlService(hService, SERVICE_CONTROL_STOP, &status);

            //删除服务
            DeleteService(hService);
            result = TRUE;
            return result;
        }
    }

    return result;
}

小结:

把握住几个核心的函数

打开服务前 必须 OpenSCManager 打开服务管理器,然后才能OpenService,创建服务的时候必须也是要先OpenSCManager 然后才能CreateService,卸载服务的几个核心函数 也是 OpenSCManager,OpenService,ControlService,DeleteService,最后就是windows 上句柄资源是十分珍贵的 我们用完了必须要及时Close 释放掉。

4)服务程序主函数ServiceMain

服务ServiceMain函数 当一个服务控制程序请求开启一个新的服务时,SCM(服务控制管理器)开启服务的同时,向控制调度器发送一个开始请求。控制调度器为服务创建一个新的线程来运行ServiceMain函数。

ServiceMain函数应该执行下面的这些任务:

1、立刻为服务调用RegisterServiceCtrlHandlerEx函数,用来注册一个处理控制请求的HandlerEx函数。RegisterServiceCtrlHandlerEx函数的返回值是一个service status handle(服务状态句柄),稍后向SCM通知当前服务状态会用到。

2、执行初始化。如果初始化的时间非常短(小于一秒),可以直接在ServiceMain函数中完成。

如果预期初始化的时间会比一秒长,调用SetServiceStatus函数,在SERVICESTATUS结构中指明等待间隔,以及当前的状态是SERVICESTART_PENDING。当初始化继续时,服务应该再调用SetServiceStatus函数来报告当前状态。多次调用SetServiceStatus函数对调试服务很有用。

3、初始化结束后,调用SetServiceStatus函数,在SERVICESTATUS结构中指明SERVICERUNNING状态。

4、执行服务的任务,或者已经没有未完成的任务,那就返回。服务状态有任何改变,都要保证调用SetServiceStatus函数来报告新的状态。

5、如果在初始化或者运行的过程中遇到错误并且清理的过程会很长,服务应该调用SetServiceStatus函数,在SERVICESTATUS结构中指定SERVICESTOPPENDING状态。一旦清理结束,在最后中止的线程中调用SetServiceStatus函数,在SERVICESTATUS结构中指定SERVICESTOPPED状态。确保向SERVICESTATUS结构里的dwServiceSpecificExitCode和dwWin32ExitCode赋值,来标志错误。

void WINAPI ServiceMain()

{

    // Register the control request handler

    status.dwCurrentState = SERVICE_START_PENDING;

    status.dwControlsAccepted = SERVICE_ACCEPT_STOP;//这个要使用,否则你不能控制



    //注册服务控制

    hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);

    if (hServiceStatus == NULL)

    {

        LogEvent(_T("Handler not installed"));

        return;

    }

    SetServiceStatus(hServiceStatus, &status);



    status.dwWin32ExitCode = S_OK;

    status.dwCheckPoint = 0;

    status.dwWaitHint = 0;

    status.dwCurrentState = SERVICE_RUNNING;

    SetServiceStatus(hServiceStatus, &status);



    //模拟服务的运行,10后自动退出。应用时将主要任务放于此即可

    int i = 0;

    while (i < 10)

    {

           Sleep(1000);

           i++;

    }

    //



    status.dwCurrentState = SERVICE_STOPPED;

    SetServiceStatus(hServiceStatus, &status);

    LogEvent(_T("Service stopped"));

}

void WINAPI ServiceStrl(DWORD dwOpcode)
{
    switch (dwOpcode)
    {
    case SERVICE_CONTROL_STOP:
        status.dwCurrentState = SERVICE_STOP_PENDING;
        SetServiceStatus(hServiceStatus, &status);
        PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);
        //::PostMessage(dlg->m_hWnd,WM_ISER_CLOSE);
        break;
    case SERVICE_CONTROL_PAUSE:
        break;
    case SERVICE_CONTROL_CONTINUE:
        break;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        break;
    default:
        LogEvent(("Bad service request"));
    }
}

2.对话框和非模态对话框(其实有的时候服务程序我任务比不上隐藏的非模态的程序)

1) 模态对话框 是非常简单的

 dlg.DoModal();

2)非模态对话框

CbigScreenDownloadDlg dlg;

m_pMainWnd = &dlg;

INT_PTR nResponse = dlg.Create(IDD_BIGSCREENDOWNLOAD_DIALOG);
dlg.ShowWindow(SW_HIDE);
dlg.RunModalLoop();

3.windows 软件开机自动运行,其实就是写入注册表

BOOL AutoBootSet()
{
    HKEY hKey;
    CString lpRun = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";

    long lRet = RegOpenKeyEx(HKEY_CURRENT_USER, lpRun, 0, KEY_ALL_ACCESS, &hKey);
    if (lRet == ERROR_SUCCESS)
    {
        CHAR pFileName[MAX_PATH];

        //获取程序自身的路径
        DWORD dwRet = GetModuleFileName(NULL, pFileName, MAX_PATH);

    /*  _tcscat_s(pFileName, "-auto");*/

        //添加一个子Key,并设置值, 下面应用程序名字(不加后缀.exe)    
        lRet = RegSetValueEx(hKey,"bigScreenRelease",0, REG_SZ, (const BYTE*)(LPCSTR)pFileName, (strlen(pFileName)));

        //关闭注册表     
        RegCloseKey(hKey);

        if (lRet != ERROR_SUCCESS)
        {
            return FALSE;
        }
        return TRUE;
    }
    return FALSE;
}

RegSetValueEx写入注册表 RegCloseKey 关闭注册表

猜你喜欢

转载自blog.csdn.net/qq_32783703/article/details/80317436
今日推荐