ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【C++】【实用类库】C++开机自启方案

2022-01-14 18:57:59  阅读:168  来源: 互联网

标签:类库 std full string buffer C++ 自启 path name


模仿网易云切歌时候MAC的通知界面,需要用到开机自启的功能。但是只有写入的方法,没找到加入其他方法做成一整个类的。所以花了些时间把这功能包装成一个类了。

MediaState软件项目地址:https://gitee.com/txwh-media-state

对这个类进行一些说明:

  • 类中的每一个方法都可以单独拿来使用,不受类中定义的变量影响

    构造函数除外

  • 类中的部分方法我已经标明了参考的网址,如果想要进行学习的话可以去详细学习

  • 类中部分方法有这比较详细的注释,供大家参考

  • 构造函数中"MediaStateT"是我的项目名称。项目地址如上

核心代码讲解:

  1. 这里其实就是通过GetMouleFileName来获取当前程序运行的地址
std::string get_programme_path() {
    TCHAR buffer[512] = {0};
    GetModuleFileName(nullptr, buffer, sizeof(buffer));
    //TCHAR转string
    //参考:https://www.cnblogs.com/staring-hxs/archive/2013/01/24/2874690.html
    UINT len = wcslen(buffer)*2;
    char *buf = (char *)malloc(len);
    UINT i = wcstombs(buf,buffer,len);
    std::string full_path = buf;
    return full_path;
}
  1. 获取到当前程序运行的地址之后,加上程序的名称就可添加到自启动注册表了,对于不需要管理员权限的程序来讲,我们需要注册到HKEY_CURRENT_USER下的
    SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run这个路径当中,不然会提示需要管理员权限
    对于以上的函数实现:

    这里用到的stringToPCWSTR函数下面的全部代码有些,这里为了讲述明白不再赘述

   bool tart_with_system(const std::string &name, const std::string &full_path) {
       if (name_w == NULL){
           //string转LPCWSTR
           stringToLPCWSTR(name, name_w);
           std::cout << "hello";
           stringToLPCWSTR(full_path, path_w);
       }
   
       //打开启动项
       if (RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS){
           //判断注册表项目是否存在
           TCHAR strDir[MAX_PATH] = {};
           DWORD nLength = MAX_PATH;
           // If the function succeeds, the return value is ERROR_SUCCESS.
           // 函数解释:https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetvaluea
           long result = RegGetValue(hkey, nullptr, name_w, RRF_RT_REG_SZ, 0, strDir, &nLength);
   
           //注册表已经存在
           if (result != ERROR_SUCCESS) {
               //添加一个Key
               RegSetValueEx(hkey, name_w, 0, REG_SZ, (LPBYTE)path_w,
                             (strlen(full_path.c_str()) + 1) * sizeof(TCHAR));
               //关闭注册表
               RegCloseKey(hkey);
               return true;
           }else{
               std::cout << "StartWithSystem: Have been created!" << std::endl;
               return false;
           }
       }
       else{
           std::cout << "StartWithSystem: Can`t open the Reg!" << std::endl;
           return false;
       }
   }
  1. 然后就是对于状态的检测,其实上面的代码已经状态检测的代码了,这里不在赘述,下面的源代码部分会有具体方法实现

  2. 最后就是删除注册表代码的实现:

    这里只需要知道程序的名称就可以了

   bool remove_sws(const std::string &name) {
       if (name_w == NULL){
           //string转LPCWSTR
           stringToLPCWSTR(name, name_w);
       }
       if (RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS){
           RegDeleteValue(hkey, name_w);
           RegCloseKey(hkey);
           return true;
       }else{
           return false;
       }
   }

全部代码实现(可直接复制使用):

代码虽然看起来比较长,但不难。好多都是注释和为了代码阅读的缩进

这个【实用类库】系列到时候应该会整一个Gitee仓库存放。慢慢完善。

可以关注我的Gitee:踏雪无痕 (TaXue_TianXing) - Gitee.com

StartWithSystem.h

//
// Created by Txwh on 2022/1/12.
//
#include <windows.h>
#include <iostream>
#include <stringapiset.h>

class StartWithSystem {
private:
    HKEY hkey;

public:
    std::string programme_full_path;

    //PCWCHAR 是 WCHAR的指针,这里是为了防止内存泄露而不用new
    //所以选择新建非指针变量
    WCHAR name_w[512];
    WCHAR path_w[512];

public:
    StartWithSystem();

    /**
     * @brief: string 转 LPCWSTR
     * @param: 被转换string
     * @param: 存储WCHAR的变量
     * @note:  PCWCHAR是WCHAR的指针
     *  **/
    void stringToLPCWSTR(const std::string &converse_str, PCWCHAR out);

    /**
     * @brief: 获取当前程序运行的绝对路径
     * @return: 返回绝对路径
     * **/
    std::string get_programme_path();

    /**
     * @brief: 添加开机自启项目
     * @param: 开机项目的名称
     * @param: 开机项目的绝对路径
     **/
    bool start_with_system(const std::string &name, const std::string &full_path);

    /**
     * @brief: 检测给定程序名称是否在注册表中
     * @param: 开机项目名称
     * @param: 开机项目的绝对路径
     **/
    bool sws_statue(const std::string &name, const std::string &full_path);

    /**
     * @brief: 移除开机自启项
     * @param: 开机项目的名称
     * **/
    bool remove_sws(const std::string &name);

    /**
     * @brief: 用来设置当前工作目录,解决自动启动导致的工作目录不对的问题
     * @param: 开机项目的绝对路径
    **/
     void SetWorkDirectory(std::string & full_path);
};

StartWithSystem.cpp

//
// Created by Txwh on 2022/1/12.
//

#include "StartWithSystem.h"

StartWithSystem::StartWithSystem() {
    hkey = NULL;
    programme_full_path = get_programme_path();
    //string转LPCWSTR
    stringToLPCWSTR("MediaStateT", name_w);
    stringToLPCWSTR(programme_full_path, path_w);
    SetWorkDirectory(programme_full_path);
}

std::string StartWithSystem::get_programme_path() {
    TCHAR buffer[512] = {0};
    GetModuleFileName(nullptr, buffer, sizeof(buffer));
    //TCHAR转string
    //参考:https://www.cnblogs.com/staring-hxs/archive/2013/01/24/2874690.html
    UINT len = wcslen(buffer)*2;
    char *buf = (char *)malloc(len);
    UINT i = wcstombs(buf,buffer,len);
    std::string full_path = buf;
    return full_path;
}

void StartWithSystem::stringToLPCWSTR(const std::string &converse_str, PCWCHAR out) {
    // 参考:https://blog.csdn.net/wangshubo1989/article/details/50274103
    wchar_t * buffer = new wchar_t[converse_str.size()+1];
    MultiByteToWideChar(CP_ACP, 0, converse_str.c_str(),
                        converse_str.size(), buffer,
                        converse_str.size() * sizeof(wchar_t));
    buffer[converse_str.size()] = 0;
    //宽字符一个字体两个字节
    memcpy((void *)out, (void *)buffer, (converse_str.size()+1)*sizeof(wchar_t));
    delete [] buffer;
}

bool StartWithSystem::start_with_system(const std::string &name, const std::string &full_path) {
    if (name_w == NULL){
        //string转LPCWSTR
        stringToLPCWSTR(name, name_w);
        std::cout << "hello";
        stringToLPCWSTR(full_path, path_w);
    }

    //打开启动项
    if (RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS){
        //判断注册表项目是否存在
        TCHAR strDir[MAX_PATH] = {};
        DWORD nLength = MAX_PATH;
        // If the function succeeds, the return value is ERROR_SUCCESS.
        // 函数解释:https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetvaluea
        long result = RegGetValue(hkey, nullptr, name_w, RRF_RT_REG_SZ, 0, strDir, &nLength);

        //注册表已经存在
        if (result != ERROR_SUCCESS) {
            //添加一个Key
            RegSetValueEx(hkey, name_w, 0, REG_SZ, (LPBYTE)path_w,
                          (strlen(full_path.c_str()) + 1) * sizeof(TCHAR));
            //关闭注册表
            RegCloseKey(hkey);
            return true;
        }else{
            std::cout << "StartWithSystem: Have been created!" << std::endl;
            return false;
        }
    }
    else{
        std::cout << "StartWithSystem: Can`t open the Reg!" << std::endl;
        return false;
    }
}

bool StartWithSystem::sws_statue(const std::string &name, const std::string &full_path) {

    if (name_w == NULL){
        //string转LPCWSTR
        stringToLPCWSTR(name, name_w);
        stringToLPCWSTR(full_path, path_w);
    }

    if (RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                     0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS){

        //判断注册表项目是否存在
        TCHAR strDir[MAX_PATH] = {};
        DWORD nLength = MAX_PATH;
        // If the function succeeds, the return value is ERROR_SUCCESS.
        long result = RegGetValue(hkey, nullptr, name_w, RRF_RT_REG_SZ, 0, strDir, &nLength);

        //注册表已经存在
        if (result != ERROR_SUCCESS) {
            return false;
        }else{
            return true;
        }
    }
    else{
        std::cout << "StartWithSystem: Can`t open the Reg!" << std::endl;
        return false;
    }
}

bool StartWithSystem::remove_sws(const std::string &name) {
    if (name_w == NULL){
        //string转LPCWSTR
        stringToLPCWSTR(name, name_w);
    }
    if (RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS){
        RegDeleteValue(hkey, name_w);
        RegCloseKey(hkey);
        return true;
    }else{
        return false;
    }
}

void StartWithSystem::SetWorkDirectory(std::string & full_path) {
    //参考:https://www.cxyzjd.com/article/qq_42987442/108831931
    std::string workpath_c = full_path;
    //删除最后的xxx.exe
    std::string work_path = workpath_c.substr(0, workpath_c.find_last_of('\\'));
    //设置工作目录
    SetCurrentDirectoryA(work_path.c_str());
}

标签:类库,std,full,string,buffer,C++,自启,path,name
来源: https://blog.csdn.net/qq_38844263/article/details/122500337

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有