功能:實現一個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;
}
}