把程序设为开机启动,有三种方式:

(1). 把程序增加到注册表的开机运行项,

系统: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

用户: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

需要注意32位程序在64位系统运行,操作注册表被重定向的问题.

(2). 增加执行程序的快捷方式到系统开机启动目录,Windows自动启动放入该文件夹的所有快捷方式

注意WIN7个XP启动目录不一样

WIN7: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

XP:   C:\Documents and Settings\Administrator\「开始」菜单\程序\启动

(3). 把程序设置成服务,通常只把监控进程,守护进程设置成服务


下面介绍方法(1)的实现:

// 设置开机启动
void SetProcAutoRun(const char* szProcFullName/* = ""*/)
{
	BOOL bWOW64 = IsWow64Proc();
	PVOID oldValue = NULL;

	//关闭
	if (bWOW64)
	{
		//关闭WOW64重定向(在导注册表时很重要,避免文件被写到Wow6432Node)
		typedef BOOL(WINAPI *LPFN_Wow64DisableWow64FsRedirection)(PVOID *OldValue);
		LPFN_Wow64DisableWow64FsRedirection fnWow64DisableWow64FsRedirection = NULL;

		fnWow64DisableWow64FsRedirection = (LPFN_Wow64DisableWow64FsRedirection)GetProcAddress(
			GetModuleHandle(TEXT("kernel32")), "Wow64DisableWow64FsRedirection");

		if (fnWow64DisableWow64FsRedirection != NULL)
		{
			fnWow64DisableWow64FsRedirection(&oldValue);
		}
	}

	//修改注册表值
	if (AddRegisterRun(szProcFullName))
	{
		OutputDebugString("Set auto run mode success.");
	}

	if (bWOW64)
	{
		//恢复WOW64重定向
		typedef	BOOL(WINAPI *LPFN_Wow64RevertWow64FsRedirection)(PVOID OlValue);
		LPFN_Wow64RevertWow64FsRedirection fnWow64RevertWow64FsRedirection = NULL;
		fnWow64RevertWow64FsRedirection = (LPFN_Wow64RevertWow64FsRedirection)GetProcAddress(
			GetModuleHandle(TEXT("kernel32")), "Wow64RevertWow64FsRedirection");

		if (fnWow64RevertWow64FsRedirection != NULL)
		{
			fnWow64RevertWow64FsRedirection(oldValue);
		}
	}
}


//修改注册表值
//szProcFullName为进程的全路径文件名
//szProcName为不包含路径的执行文件名
bool AddRegisterRun(const char* szProcFullName)
{
	//打开子键(注册表键不区分大小写)
	HKEY hSubKey = NULL;
	HKEY hKey = HKEY_CURRENT_USER;
	const char* szSubKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
	LONG lRet = RegOpenKeyEx(hKey, szSubKey, 0, KEY_ALL_ACCESS, &hSubKey);
	if (lRet != ERROR_SUCCESS)
	{
		return false;
	}

	//查询键值
	DWORD dwType = 0;
	DWORD dwLen = MAX_PATH;
	UCHAR szData[MAX_PATH] = { 0 };
	const char* szQueryKey = szProcName;
	lRet = RegQueryValueEx(hSubKey, szQueryKey, NULL, &dwType, szData, &dwLen);
	if (lRet != ERROR_SUCCESS)
	{
		//创建子键
		lRet = RegSetValueEx(hSubKey, szQueryKey, NULL, REG_SZ, (const BYTE*)szProcFullName, strlen(szProcFullName));
		if (lRet != ERROR_SUCCESS)
		{
			RegCloseKey(hSubKey);
			return false;
		}
	}
	else  //子健存在时,再校验值是否匹配(应为程序绝对路径)
	{
		//键值不相等时需要修改
		if (0 != _stricmp(szProcFullName, (char*)szData))
		{
			//修改键值
			lRet = RegSetValueEx(hSubKey, szQueryKey, NULL, dwType, (const BYTE*)szProcFullName, strlen(szProcFullName));
			if (lRet != ERROR_SUCCESS)
			{
				RegCloseKey(hSubKey);
				return false;
			}
		}
	}

	RegCloseKey(hSubKey);

	return true;
}