开机自启动是一个常用需求,本文探讨之..
windows平台
修改注册表: 不推荐
- 有些杀软拦截
- 启动时机较早(当然是启动后),可能有些COM之类的接口调用会失败
使用计划任务自启动: 不推荐
- 不利于编程
- 可设置性最高(甚至不用登陆windows就可以运行)
使用快捷方式启动: 推荐
下面只介绍在方法三的编程
3.1 简单启动
使用QStandardPaths + QFile::link 可以完成该目的
需要注意的是在XP和非XP系统的快捷方式路径不同(分别为Startup和启动)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| void runWithWindows(bool autoRun, QString exeName, QString linkName) { #ifdef Q_OS_WIN QString startUpPath = QString("%1/%2") .arg(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)) .arg("Startup");
QDir dir; if(!dir.exists(startUpPath)){ startUpPath = QString("%1/%2") .arg(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)) .arg("启动"); }
QString linkFull = QString("%1/%2.lnk") .arg(startUpPath) .arg(linkName);
if(autoRun){ if(QFile::symLinkTarget(linkFull) != exeName){ QFile::link(exeName, linkFull); } } else{ if(QFile::exists(linkFull)){ QFile::remove(linkFull); } } #else
#endif }
|
3.2 带参数的启动
上面的方式可用于简单的开机自启,但是如果需要创建带参数的快捷方式就鸡鸡了,查看Qt的源代码qfsfileengine_win.cpp中的bool QFSFileEngine::link(const QString &newName)函数, 发现官方偷懒了没办法自己动手吧…
在pro文件中添加
win32{
LIBS += -lole32
LIBS += -luuid
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #ifdef Q_OS_WIN32 #include <windows.h> #include <shlobj.h> #include <shobjidl.h> #endif
#ifdef Q_OS_WIN32 bool CreateFileShortcut(const QString &linkFullName, const QString &arguments, const QString &workDir, const QString &exeName) { QString startUpPath = QString("%1/%2") .arg(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)) .arg("Startup");
QDir dir; if(!dir.exists(startUpPath)){ startUpPath = QString("%1/%2") .arg(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)) .arg("启动"); }
QString linkFull = QString("%1/%2.lnk") .arg(startUpPath) .arg(exeName);
#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if !defined(QT_NO_LIBRARY) bool ret = false;
QString linkName = linkFullName; QString pathDir = workDir; IShellLink *psl; bool neededCoInit = false;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
if (hres == CO_E_NOTINITIALIZED) { neededCoInit = true; CoInitialize(NULL); hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); }
if (SUCCEEDED(hres)) { hres = psl->SetPath((wchar_t *)linkName.replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); if (SUCCEEDED(hres)) { hres = psl->SetWorkingDirectory((wchar_t *)pathDir.replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); if (SUCCEEDED(hres)) { if(!arguments.isEmpty()){ psl->SetArguments((wchar_t *)arguments.utf16()); }
IPersistFile *ppf; hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); if (SUCCEEDED(hres)) {
hres = ppf->Save((wchar_t*)linkFull.utf16(), TRUE); if (SUCCEEDED(hres)) ret = true; ppf->Release(); } } } psl->Release(); } if (!ret) qDebug() << "create link error";
if (neededCoInit) CoUninitialize();
return ret; #else Q_UNUSED(newName); return false; #endif #elif defined(Q_OS_WINCE) && !defined(QT_NO_WINCE_SHELLSDK) QString linkName = newName; linkName.replace(QLatin1Char('/'), QLatin1Char('\\')); if (!linkName.endsWith(QLatin1String(".lnk"))) linkName += QLatin1String(".lnk"); QString orgName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')); orgName.prepend(QLatin1Char('"')); orgName.append(QLatin1Char('"')); bool ret = SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16())); if (!ret) setError(QFile::RenameError, qt_error_string()); return ret; #else Q_UNUSED(newName); Q_UNIMPLEMENTED(); return false; #endif } #endif
|
Linux平台
这个和windows平台类似(参考了ubuntu下的Stacer软件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| void StartUp::setup(bool autoRun, QString path, QString linkName, QString icon) { QString autostartPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation).append("/autostart"); QFileInfo fi(autostartPath);
if (fi.isDir()) { autostartPath.append("/"); }
if (! QDir(autostartPath).exists()) { QDir().mkdir(autostartPath); }
QString exePath = QString("%1%2.desktop").arg(autostartPath).arg(linkName); if(autoRun){ QFile f(exePath);
if(f.open(QIODevice::WriteOnly)){ f.write("[Desktop Entry]\n"); f.write(QString("Name=%1\n").arg(linkName).toUtf8()); f.write(QString("Comment=%1 Linux Version\n").arg(linkName).toUtf8()); f.write(QString("GenericName=%1\n").arg(linkName).toUtf8()); f.write(QString("Terminal=false\n").toUtf8()); f.write(QString("Type=Application\n").toUtf8()); f.write(QString("Exec=%1.sh\n").arg(path).toUtf8()); f.write(QString("MimeType=text/plain;\n").toUtf8()); f.write(QString("Icon=%1\n").arg(icon).toUtf8()); f.write(QString("StartupNotify=true\n").toUtf8()); f.write(QString("Actions=Run;").toUtf8()); f.close(); }
QString desktopPath = QString("%1/%2.desktop") .arg(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)) .arg(linkName);
QFile::copy(exePath, desktopPath); } else{ QFile::remove(exePath); }
}
|