Windows写入注册表自启动键值对消失:

  Windows程序将程序路径写入注册表自启动时,有时可能会遇到写入成功但是注册表依然空白的问题。并且随意的字符串可以正常写入,但是写入程序路径时键与值会直接消失。

问题描述:

  最初写MFC时遇到过上述情况,最后通过写入RunOnce,并在Run下写入一个标记的键值绕过了必须通过Run自启动,但是每次启动都会检索一下Run的标记键值对,来判断是否重新写入一次RunOnce,费力且不直接。
  后来在写Qt时,刚开始通过Qt提供的方法可以直接写入Run,但是后来也出了与MFC同样的问题,最后通过各种尝试发现,在写入普通字符串时,可直接写入,当写入启动程序路径时,先创建一个值为""的键,最后再将该键设置为实际值。使用这种方法可以解决Run写入空白的问题。

原因分析:

  后来偶然发现如果已经有键值对时再次写入,值会更新并且键值对会保留,但是使用程序删除再添加时有时会添加不上,基本随缘,所以猜测是不是再Run写入启动程序路径时是不是先需要一个特定的键值对。

解决方案:

  先在Run下创建一个值为""的键,最后再将该键设置为实际值。使用这种方法可以解决Run写入空白的问题。

//参    数:(int) 参数int 0为取消自启动,1为设置自启动,2为查询自启动,自启动返回true,不是自启动返回false
bool tool::OperationAutoStart(int operation)
{
	//程序名称
	QString appName = QApplication::applicationName();
	// 程序路径
	QString application_path = QApplication::applicationFilePath();
	tool::PathConvert(application_path);

	application_path = "\"" + application_path + "\" auto";
	QSettings reg(
		"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",
		QSettings::NativeFormat);
	// 如果此键不存在,则返回的是空字符串
	QString val = reg.value(appName).toString();
	switch (operation) {
		//取消自启动
	case 0:
		//移除键
		reg.remove(appName);
		break;

	case 1:
		//设置自启动
		if (val != application_path) {
			//写入随意的字符串都能写入,但唯独自启动的程序路径写入自动成空,加入这个先添加空的值得解决了
			reg.setValue(appName, "\"\"");
			//设置键
			reg.setValue(appName, application_path);
		}
		break;

	case 2:
		//查询自启动
		if (val.compare(application_path) == 0) {
			reg.deleteLater();
			return true;
		}
		else {
			reg.deleteLater();
			return false;
		}
		break;
	default:
		reg.deleteLater();
		return false;
	}
	return false;
}

  个人猜测不同版本的系统,对写入注册表自启动的机制可能会有所不同。MFC或者Windows系统的api写入遇到这种问题时,解决方法应该一致,个人并未再次测试。