Windows守护进程实现/设置程序图标/隐藏黑窗/获取exe所在目录/设置开机自启动

功能:实现一个windows守护进程,设置有自定义图标,启动后隐藏黑窗口,获取exe所在目录,并设置开机自启动(需要以管理员权限运行)。如果需要打包成可执行的安装包程序,见另一篇博客:https://blog.csdn.net/qq_24977505/article/details/106415058

 

隐藏控制台窗口:main函数前添加

#pragma comment(linker, "/subsystem:\"windows\"  /entry:\"mainCRTStartup\"" ) 即可。

设置自定义图标:Damon.exe设置heworld.ico图标,HelloWorld.exe没有

1、需要先自制一个ico格式图标,点开http://www.bitbug.net/ 上传图片即可做好。

2、将图标放到代码路径下,在vs项目中添加.rc文件(选中项目->右键添加->新建项->资源文件.rc->确定)。

3、到源文件目录记事本打开这个.rc文件,末尾添加 IDI_ICON1 ICON DISCARDABLE "heworld.ico" ,heworld.ico是第一步自作好的ico文件,一定要同在源文件目录下。

4、重新编译即可。

设置开机自启动代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>

// 设置黑窗隐藏
#pragma comment(linker, "/subsystem:\"windows\"  /entry:\"mainCRTStartup\"" ) 

// 需要守护的进程可执行文件,和daemon.exe放一起
#define PROCCESS_NAME "HelloWorld.exe"

char g_workPath[MAX_PATH] = { 0 };
void WriteLogFile(char *msg);

BOOL SetSelfStart()
{
    //获取程序完整名称
    char pName[MAX_PATH] = { 0 };
    GetModuleFileNameA(NULL, pName, MAX_PATH);

    HKEY hKey = NULL;
    LONG lRet = NULL;
    const char * regeditPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\";
    if (ERROR_SUCCESS != RegOpenKeyExA(HKEY_LOCAL_MACHINE, regeditPath, 0, KEY_ALL_ACCESS, &hKey))
    {
        return FALSE;
    }

    if (ERROR_SUCCESS != RegSetValueExA(hKey, "Heworld", 0, REG_SZ, (const unsigned char*)pName, strlen(pName) + sizeof(char)))
    {
        return FALSE;
    }

    RegCloseKey(hKey);
    WriteLogFile("守护进程开机自启动成功\n");
    return TRUE;
}

void GetWorkPath(char *argv)//获取exe所在目录
{
    char drive[4];
    char subdir[MAX_PATH];
    char fn[MAX_PATH];
    char exten[MAX_PATH];

    _splitpath_s(argv, drive, subdir, fn, exten);
    sprintf_s(g_workPath, "%s%s", drive, subdir);
}

int main(int argc, char *argv[])
{
    GetWorkPath(argv[0]);
    if (!SetSelfStart())
    {
        WriteLogFile("守护进程开机自启动失败\n");
    }

    STARTUPINFOA si;
    PROCESS_INFORMATION pi;
    //初始化
    ZeroMemory(&si, sizeof(si));
    si.wShowWindow = SW_HIDE;
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    //构造cmd执行守护进程的字符串
    static char fileName[MAX_PATH] = { 0 };
    snprintf(fileName, MAX_PATH, "%s%s", g_workPath, PROCCESS_NAME);

    do {
        if (!CreateProcessA(NULL, fileName, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
        {
            WriteLogFile("守护进程启动失败,程序即将退出\n");
            return -1;
        }

        WriteLogFile("守护进程成功\n");
        WaitForSingleObject(pi.hProcess, INFINITE);
        WriteLogFile("守护进程退出......\n");
        //关闭进程和句柄
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

        Sleep(2000);
    } while (true);
    return 0;
}

const char *GetNowStr()
{
    static char nowstr[64];
    time_t nowTime = 0;
    time(&nowTime);

    struct tm tmNow;
    localtime_s(&tmNow, &nowTime);
    sprintf_s(nowstr, "%02d%02d_%02d%02d%02d", tmNow.tm_mon + 1, tmNow.tm_mday,
        tmNow.tm_hour, tmNow.tm_min, tmNow.tm_sec);
    return nowstr;
}

void WriteLogFile(char *msg)
{
    static int writeLine = 0;
    static FILE* fp = NULL;
    if (fp == NULL)
    {
        char buf[1024];
        sprintf_s(buf, "%s%s", g_workPath, "daemon.log");
        fopen_s(&fp, buf, "w");
        if (fp == NULL)
        {
            printf("open log file fail\n");
            return;
        }
    }

    static char header[128];
    sprintf_s(header, "[%s]:", GetNowStr());
    fwrite(header, 1, strlen(header), fp);
    fwrite(msg, 1, strlen(msg), fp);
    fflush(fp);

    printf(msg);
    if (50000 < writeLine++)
    {
        fp = NULL;
        writeLine = 0;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章