Windows系统软件自启动方法很多场景都需要软件在开机时自动启动,本文整理了一些不同系统下软件自启动的方式并进行了对比。(一利用“启动”文件夹点击左下角开始菜单,找到启动文
Windows系统软件自启动方法很多情况下软件都需要在启动时自动启动,本文整理并比较了几种不同系统下软件的自启动方法。
(一)利用“启动”文件夹,点击左下角的开始菜单,找到启动文件夹。 图:
右键单击文件夹以将其打开。 图:
把软件的快捷方式复制到这个文件夹里,重新启动电脑就可以了。 应用: windows7、windows10 (自动启动开关,不需要手动拖动快捷方式) )。
优点:不需要修改代码,操作简单方便,没有技术基础的人也可以自行启动软件。
缺点:要实现软件自启动,必须手动将快捷方式移动到文件夹中。 否则,软件永远都不会自动启动。
)二)使用任务计划缺省情况下,“任务计划”程序与Windows一起启动并在后台运行。 还可以通过将程序添加到计划任务文件夹并将计划任务设置为“系统启动时”或“登录时”来启用程序的自动启动。
“任务计划”也是一个特殊的系统文件夹,单击“开始”“程序”“附件”“系统工具”“任务计划”可打开该文件夹,便于查看和管理。 界面如下图所示:
单击“创建任务”(create task ),可以在创建新任务并运行该任务时设置帐户。 选择触发器后,将创建新的触发器。 在此可以设定任务的开始等条件。 单击“操作”可创建新操作,并在设置界中选择程序或脚本。 积分就可以了。
适用:双赢7、双赢10
优点:不需要修改代码,可以在创建新任务时定制,可以根据自己的需求定制任务。
缺点:相对来说制作过程比较复杂。
(三)修改注册表是启动程序隐藏的地方,注册表的[HKEY_LOCAL_MACHINE]和[HKEY_CURRENT_USER]键不同。 前者对所有用户有效,后者只对当前用户有效。 注册表中可运行的程序的自启动主要有Run键。
1 .运行键
Run键的位置是[HKEY_CURRENT_
user\software\Microsoft\windows\current version\run和[HKEY_
local _ machine\software\Microsoft\windows\current version\run ],下面的所有程序将在每次开始登录时按顺序自动运行。
2 .运行键
RunOnce是[ HKEY _ current _ user\software\Microsoft\windows
CurrentVersion\RunOnce]和[ HKEY _ local _ machine\software\Microsoft
windows\currentversion\Runonce]键与run不同,RunOnce下的程序只自动运行一次。
以Run键为中心进行说明。 要设置Run键下指定的数据,设计调用的接口通常如下:
创建指定的注册表项。 如果已经存在,请选中。 longregcreatekeyexa(HkeyHkey,LPCTSTR lpSubKey,DWORD Reserved,LPTSTR lpClass,DWORD dwOptions,REGSAM samDesired,LPsecured )
其中hKey是需要打开的主键的名称,lpSubKey是需要打开的子键的名称,Reserved是保留的,必须赋值为0。 lpClass是一个条目,它指向定义密钥类型的字符串。 空着也没关系。 使用本地和远程注册表时,可以使用此参数。 dwOptions进入参数并指定键的特殊选项。 参数可以是以下值
REG_OPTION_BACKUP_RESTORE,0x00000004L
REG_OPTION_NON_VOLATILE,0x00000000L,
REG_OPTION_VOLATILE,0x00000001L,
一般使用REG_OPTION_NON_VOLATILE。 samDesired是定义权限,lpSecurityAttributes参与并定义返回的句柄是否可以从子进程继承。 如果为NULL,则无法继承。 phkResult是返回的句柄。 lpdwDisposition是参与者,可能具有以下值REG_CREATED_NEW_KEY :0x00000001L此密钥是新创建的密钥。 REG_OPENED_EXISTING_KEY,0x00000002L此密钥是已存在的密钥。
注册表项下指定值的数据和类型longregsetvalueexa(HkeyHkey,LPCTSTR lpValueName,DWORD Reserved,DWORD dwType,CONST BYTE *lpData,lpcte
其中hKey是打开项目的句柄,lpValueName:是指向包含要设置的值的名称的字符串的指针。 如果指定的注册表项中不存在具有该值名称的值,函数会将该值添加到条目中。 Reserved:的保留值必须强制为0。 dwType:指定要存储的数据类型,而lpData:是包含要为指定值名称存储的数据的缓冲区。 cbData:指定lpData参数指向的数据
的大小,单位是字节。 删除注册表中键值
LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName);
其中hKey是一个已打开项的句柄,lpValueName:指向一个字符串的指针,该字符串包含了欲删除值的名称。
具体代码如下:
创建一个界面,按钮的槽函数中写入或删除注册表键值。
构造函数中创建键值:
{std::string lpRun = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";DWORD dwDisposition = 0;long lRet = RegCreateKeyExA(HKEY_LOCAL_MACHINE, lpRun.c_str(), 0, NULL, \ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &m_hKey, &dwDisposition);if (lRet != ERROR_SUCCESS) //失败 { qDebug() <<"RegCreateKeyExA failed!"; }}
其中m_hKey作为成员变量HKEY m_hKey,是操作注册表的句柄。
槽函数为:
{ if (m_hKey == nullptr) { return; }if (m_bAutoRun) { QString qStrAppPath = QApplication::applicationFilePath(); qStrAppPath.replace("/", "\\"); DWORD dwRet = qStrAppPath.length() * 2; // QtGuiApplication1应用程序名字(不加后缀.exe) long lRet = RegSetValueExA(m_hKey, "QtGuiApplication1", 0, REG_SZ, (PBYTE)qStrAppPath.toStdString().c_str(), dwRet); if (lRet != ERROR_SUCCESS) //失败 { qDebug() <<"RegSetValueExA failed!"; } } else { RegDeleteValueA(m_hKey, "QtGuiApplication1"); }}
点击按钮后写注册表成功,查看注册表键值如下:
适用于:win7,win10
优点:一般软件中均会有一个选项是否开启自启动,勾选与取消勾选实际上就是通过这种方式修改注册表实现的。
缺点:需要有一点编码能力。
注意:
1.我们开发的项目为了能够兼容32位系统和64位系统,一般应用程序都是32位的。在操作注册表时就涉及到32位和64位注册表的问题。64位windows系统中的注册表分为32位注册表和64位注册表项。为了防止注册表键冲突,注册表在某些键也分成了两个部分。一部分是专门给64位系统访问的,另一部分是专门给32位系统访问的。当32位程序去访问某些键值的时候,和文件转向类似,系统也会自动地把程序的访问转向到Wow6432Node下面。调用RegCreateKeyEx创建项时要samDesired要赋值权限与上KEY_WOW64_64KEY时,是在正常的路径下,即\Software\Microsoft\Windows\CurrentVersion\Run中;samDesired要赋值权限与上KEY_WOW64_32KEY时,创建项被重定向到了Wow6432Node节点中,\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run中。
经测试,在win7和win10上无论传入KEY_WOW64_64KEY还是KEY_WOW64_32KEY程序均可自启动成功。
2.上述三个接口均还有另外一个版本,名称的最后一个字母不是A而是W,而不带最后一个字母的接口是如下宏控制的:
#ifdef UNICODE#define RegCreateKeyEx RegCreateKeyExW#else#define RegCreateKeyEx RegCreateKeyExA#endif // !UNICODE
即UIcode下,如果调用RegCreateKeyEx,实际上调用的是RegCreateKeyExW,而调用该接口时必须要注意传入的参数(路径,软件名等),必须要转换成宽字符再传入,否则创建接口RegCreateKeyExW会报错87,参数错误,调用写入注册表接口RegSetValueExW会导致写入的注册表项乱码。所以在传入参数前应先利用MultiByteToWideChar接口把字符串转换为宽字符字符串。为了避免上述问题,建议直接调用末尾是A的接口。
具体代码如下:
string转成wstring的函数
void StringToWstring(std::wstring& szDst, std::string str){ std::string temp = str; int len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)temp.c_str(), -1, NULL, 0); wchar_t * wszUtf8 = new wchar_t[len + 1]; memset(wszUtf8, 0, len * 2 + 2); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)temp.c_str(), -1, (LPWSTR)wszUtf8, len); szDst = wszUtf8; std::wstring r = wszUtf8; delete[] wszUtf8;}
构造函数中创建键值
{std::string lpRun = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; std::wstring wszDest; StringToWstring(wszDest, lpRun); DWORD dwDisposition = 0; long lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wszDest.c_str(), 0, NULL, \ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &m_hKey, &dwDisposition); if (lRet != ERROR_SUCCESS) //失败 { qDebug() <<"RegCreateKeyExW failed!"; }}
槽函数为:
{ if (m_hKey == nullptr) { return; } if (m_bAutoRun) { QString qStrAppPath = QApplication::applicationFilePath(); qStrAppPath.replace("/", "\\"); std::wstring wszDest; StringToWstring(wszDest, qStrAppPath.toStdString()); DWORD dwRet = qStrAppPath.length() * 2; std::wstring wszDestName; StringToWstring(wszDestName, "QtGuiApplication1"); long lRet = RegSetValueExW(m_hKey, wszDestName.c_str(), 0, REG_SZ, (PBYTE)wszDest.c_str(), dwRet); if (lRet != ERROR_SUCCESS) //失败 { qDebug() <<"RegSetValueExW failed!"; } } else { std::wstring wszDestName; StringToWstring(wszDestName, "QtGuiApplication1"); RegDeleteValueW(m_hKey, wszDestName.c_str()); }}
图中不乱码的为转换成宽字符后再写入注册表的结果,乱码为没有转换字符串调用接口的结果。