当前位置:   article > 正文

unity应用开机自启

unity 安卓开机自启动

最近有一个项目需要设置开机自启动,没有预先为程序设定这个功能,所以部署的时候每次都要生成快捷方式,然后找自启动文件夹,搞得非常崩溃。所以决定填上这个坑,写了一段unity应用通用的开启和关闭开机自启的代码。


更新历史

  • 2017.10.15:完成初稿

写在前面

经过一晚上的研究和分析,发现设置开机自启动主要有两种主流方式和一种非主流方式,这几个方式基本能满足需求,分别是:

  1. 开始菜单启动(最常用,不需要管理员权限)

  2. 注册表启动项(需要管理员权限)

  3. Windows计划任务(需要管理员权限,unity中使用有异常)

以下代码都是即拿即用,只需绑定Button和Text即可。

开始菜单启动

开始菜单启动大概是我们最常用的一种设置开机自启的方法,具体用程序来实现也是很简单的,主要有两步:

  1. 创建快捷方式并关联程序

  2. 将快捷方式存到“开始”菜单的“启动”目录

代码如下:

  1. using System;
  2. using System.IO;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using IWshRuntimeLibrary;
  6. public class StartMenu : MonoBehaviour {
  7. public Button setupStartupButton;
  8. public Button cancelStartupButton;
  9. public Text hintText;
  10. private static string ShortcutName = "test.lnk";
  11. private void OnEnable()
  12. {
  13. isStartup();
  14. setupStartupButton.onClick.AddListener(OnSetupStartupButtonClick);
  15. cancelStartupButton.onClick.AddListener(OnCancelStartupButtonClick);
  16. }
  17. private void OnDisable()
  18. {
  19. setupStartupButton.onClick.RemoveListener(OnSetupStartupButtonClick);
  20. cancelStartupButton.onClick.RemoveListener(OnCancelStartupButtonClick);
  21. }
  22. private void OnSetupStartupButtonClick()
  23. {
  24. CreateShortcut(Environment.GetFolderPath(Environment.SpecialFolder.Startup), ShortcutName, System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
  25. isStartup();
  26. }
  27. private void OnCancelStartupButtonClick()
  28. {
  29. if (System.IO.File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + ShortcutName))
  30. System.IO.File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + ShortcutName);
  31. isStartup();
  32. }
  33. private void isStartup()
  34. {
  35. if (System.IO.File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + ShortcutName))
  36. hintText.text = "应用已开机自启";
  37. else
  38. hintText.text = "应用非开机自启";
  39. }
  40. public static bool CreateShortcut(string direstory,string shortcurName,string targetPath,string description = null,string iconLocation = null)
  41. {
  42. try
  43. {
  44. if(!Directory.Exists(direstory))
  45. {
  46. Directory.CreateDirectory(direstory);
  47. }
  48. // 添加引用com中搜索Windows Script Host Object Model, 如果在unity中使用则需下载 Interop.IWshRuntimeLibrary.dll 并放到代码同一文件夹
  49. string shortscurPath = Path.Combine(direstory, string.Format("{0}", shortcurName));
  50. IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
  51. IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shortscurPath); // 创建快捷方式对象
  52. shortcut.TargetPath = targetPath; // 指定目标路径
  53. shortcut.WorkingDirectory = Path.GetDirectoryName(targetPath); //设置起始位置
  54. shortcut.WindowStyle = 1; // 设置运行方式,默认为常规窗口
  55. shortcut.Description = description; // 设置备注
  56. shortcut.IconLocation = string.IsNullOrEmpty(iconLocation) ? targetPath : iconLocation; //设置图标路径
  57. shortcut.Save(); // 保存快捷方式
  58. return true;
  59. }
  60. catch
  61. {
  62. }
  63. return false;
  64. }
  65. }

使用开始菜单自启是非常稳的一种方法,不需要有管理员权限,但是unity中使用需要添加引用,并下载 Interop.IWshRuntimeLibrary.dll 程序集放到与本代码同一文件夹。

注册表开机启动项

这个相信是大部分同学使用的情况,简单易懂隐蔽(只是感觉很隐蔽,但是 msconfig 立马暴露),代码很简单,将启动的项目名称、文件位置添加到启动项即可。

  1. using Microsoft.Win32;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. using System;
  7. public class Regeditkey : MonoBehaviour {
  8. public Button setupStartupButton;
  9. public Button cancelStartupButton;
  10. public Text hintText;
  11. private void OnEnable()
  12. {
  13. string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
  14. //regeditkey();
  15. setupStartupButton.onClick.AddListener(OnSetupStartupButtonClick);
  16. cancelStartupButton.onClick.AddListener(OnCancelStartupButtonClick);
  17. }
  18. private void OnDisable()
  19. {
  20. setupStartupButton.onClick.RemoveListener(OnSetupStartupButtonClick);
  21. cancelStartupButton.onClick.RemoveListener(OnCancelStartupButtonClick);
  22. }
  23. private void OnSetupStartupButtonClick()
  24. {
  25. // 提示,需要更改注册表
  26. try
  27. {
  28. string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
  29. RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
  30. if(rgkRun == null)
  31. {
  32. rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
  33. }
  34. rgkRun.SetValue("dhstest", path); // 名字请自行设置
  35. }
  36. catch
  37. {
  38. Debug.Log(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
  39. }
  40. finally
  41. {
  42. regeditkey();
  43. }
  44. }
  45. private void OnCancelStartupButtonClick()
  46. {
  47. // 提示,需要更改注册表
  48. try
  49. {
  50. string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
  51. RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
  52. if (rgkRun == null)
  53. {
  54. rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
  55. }
  56. rgkRun.DeleteValue("dhstest", false);
  57. }
  58. catch
  59. {
  60. Debug.Log("error");
  61. }
  62. finally
  63. {
  64. regeditkey();
  65. }
  66. }
  67. private void regeditkey()
  68. {
  69. RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",true);
  70. if(rgkRun.GetValue("dhstest") == null)
  71. {
  72. hintText.text = "自启动为关闭";
  73. }
  74. else
  75. {
  76. hintText.text = "自启动为打开";
  77. }
  78. }
  79. }

此方法在unity中使用也稳定有效,不需要下载程序集,但是需要以管理员权限运行程序才能修改注册表。

Windows 计划任务方式启动

计划任务表有很多人都不熟悉,但是它确实有很多妙用。但是在把代码转成unity应用后发现unity开发的应用中无法使用,初步认定的原因是,Interop.TaskScheduler.dll 程序集需要设置嵌入互操作类型为 false 但是unity 开发的应用中应用的程序集并没有这个选项,所以用 unity 大概不能使用Windows计划任务管理器。

为了验证计划任务管理器是否有效,我在wpf应用上测试了一下,wpf的引用是有设置嵌入互操作类型选项的,将其改为false即可正常引用 Interop.TaskScheduler 程序集。

TaskScheduler 引用属性

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Documents;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Navigation;
  14. using System.Windows.Shapes;
  15. using TaskScheduler;
  16. namespace Task
  17. {
  18. /// <summary>
  19. /// MainWindow.xaml 的交互逻辑
  20. /// </summary>
  21. public partial class MainWindow : Window
  22. {
  23. private string TaskName = "test";
  24. public MainWindow()
  25. {
  26. InitializeComponent();
  27. isStartup();
  28. }
  29. private void OnSetupStartupButtonClick(object sender, RoutedEventArgs e)
  30. {
  31. if (!HaveTaskScheduler(TaskName))
  32. CreateTaskScheduler(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, "xtw", "Set startup");
  33. else
  34. GetTaskScheduler(TaskName).Enabled = true;
  35. isStartup();
  36. }
  37. private void OnCancelStartupButtonClick(object sender, RoutedEventArgs e)
  38. {
  39. if (HaveTaskScheduler(TaskName))
  40. GetTaskScheduler(TaskName).Enabled = false;
  41. isStartup();
  42. }
  43. private bool HaveTaskScheduler(string name)
  44. {
  45. IRegisteredTask task = GetTaskScheduler(name);
  46. if (task == null)
  47. return false;
  48. else
  49. return true;
  50. }
  51. private void isStartup()
  52. {
  53. if (HaveTaskScheduler(TaskName) && GetTaskScheduler(TaskName).Enabled)
  54. text.Content = "应用已开机自启"; // 此text是Windows 组件Label
  55. else
  56. text.Content = "应用非开机自启";
  57. }
  58. private static IRegisteredTask GetTaskScheduler(string name)
  59. {
  60. // 新建任务
  61. TaskSchedulerClass scheduler = new TaskSchedulerClass();
  62. // 连接
  63. scheduler.Connect(null, null, null, null);
  64. // 获取创建任务的目录
  65. ITaskFolder folder = scheduler.GetFolder("\\");
  66. IRegisteredTask task;
  67. try
  68. {
  69. task = folder.GetTask(name);
  70. }
  71. catch
  72. {
  73. return null;
  74. }
  75. return task;
  76. }
  77. private void CreateTaskScheduler(string file, string author, string desc)
  78. {
  79. // 新建任务
  80. TaskSchedulerClass scheduler = new TaskSchedulerClass();
  81. // 连接
  82. scheduler.Connect(null, null, null, null);
  83. // 获取创建任务的目录
  84. ITaskFolder folder = scheduler.GetFolder("\\");
  85. // 设置参数
  86. ITaskDefinition task = scheduler.NewTask(0);
  87. task.RegistrationInfo.Author = author; // 创建者
  88. task.RegistrationInfo.Description = desc; //描述
  89. // 设置触发机制 (此处是 登录后)
  90. task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
  91. // 设置动作 (此处为 exe运行程序)
  92. IExecAction action = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
  93. action.Path = file; //设置文件目录
  94. //task.Settings.ExecutionTimeLimit = "PTOS"; //运行任务时间超时停止任务吗?PTOS不开启超时
  95. task.Settings.DisallowStartIfOnBatteries = false; //只在交流电下才执行
  96. task.Settings.RunOnlyIfIdle = false; // 仅当计算机空闲下才执行
  97. IRegisteredTask regTask =
  98. folder.RegisterTaskDefinition(TaskName, task, // 此处需要设置任务的名称(name)
  99. (int)_TASK_CREATION.TASK_CREATE, null, // user
  100. null,//passward
  101. _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN,
  102. "");
  103. IRunningTask runTask = regTask.Run(null);
  104. }
  105. }
  106. }

总结

对于开发一般应用来说,开始菜单启动是最简单、有效的方法。对于开发 unity 应用来说,这也不失为是一种好方法。

参考链接

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/99493
推荐阅读
相关标签
  

闽ICP备14008679号