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;
    }
}

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