当前位置: 首页 > news >正文

在操作系统重启后恢复应用程序的工作状态

Windows 10 创意者更新之后,默认开启了重启后恢复应用程序状态的功能。这是自 Vista 以来就提供的功能——Restart Manager。


应用程序实现这一功能只需要调用 RegisterApplicationRestart 即可。传入两个参数:

  1. 重启后使用的命令行参数(例如当前正在打开的文件,以及正在阅读或编辑的位置)
  2. 决定是否进行重启的限制标记(任何时候都能重启还是在某些条件下关掉重启功能)

我封装了以下这个函数的调用并将其放到 GitHub 上:sharing-demo/ApplicationRestartManager.cs at master · walterlv/sharing-demo。

调用代码如下:

if (ApplicationRestartManager.IsRestartManagerSupported)
{
    ApplicationRestartManager.RegisterApplicationRestart(
        currentOpeningFile,
        ApplicationRestartFlags.None);
}

:封装的 ApplicationRestartManager

using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using System.Windows;
using Jetbrains.Annotations;

namespace Walterlv.Win32
{
    /// <summary>
    /// 为应用程序提供重启后恢复状态的功能。
    /// </summary>
    public class ApplicationRestartManager
    {
        /// <summary>
        /// 获取一个值,该值指示当前操作系统环境是否支持 Restart Manager 功能。
        /// Restart Manager 是 Windows Vista 新增的功能。在 Windows 10 秋季创意者更新之后,默认开启了 EWX_RESTARTAPPS。
        /// </summary>
        public static bool IsSupported => IsSupportedLazy.Value;

        /// <summary>
        /// 向操作系统的 Restart Manager 注册应用终止后的重启方式。
        /// </summary>
        /// <param name="pwsCommandLine">
        /// 应用程序的重启时应该使用的参数,允许为 null,表示不带参数。
        /// 请注意:如果命令行参数中的某一个参数包含空格,请加上引号。
        /// </param>
        /// <param name="dwFlags">为应用程序的重启行为添加限制,默认没有限制。</param>
        /// <returns></returns>
        public static bool RegisterApplicationRestart(
            [CanBeNull] string pwsCommandLine,
            ApplicationRestartFlags dwFlags = ApplicationRestartFlags.None)
        {
            return 0 == RegisterApplicationRestart(pwsCommandLine, (int) dwFlags);
        }

        /// <summary>
        /// Windows Vista 及以上才开启 Restart Manager。
        /// </summary>
        [ContractPublicPropertyName(nameof(IsSupported))]
        private static readonly Lazy<bool> IsSupportedLazy =
            new Lazy<bool>(() => Environment.OSVersion.Version >= new Version(6, 0));

        /// <summary>
        /// Registers the active instance of an application for restart.
        /// See also: [RegisterApplicationRestart function (Windows)](https://msdn.microsoft.com/en-us/library/windows/desktop/aa373347)
        /// </summary>
        /// <param name="pwzCommandline">
        /// A pointer to a Unicode string that specifies the command-line arguments for the application when it is restarted. The maximum size of the command line that you can specify is RESTART_MAX_CMD_LINE characters. Do not include the name of the executable in the command line; this function adds it for you.
        /// If this parameter is NULL or an empty string, the previously registered command line is removed. If the argument contains spaces, use quotes around the argument.
        /// </param>
        /// <param name="dwFlags">
        /// This parameter can be 0 or one or more of the following values:
        /// - 1: Do not restart the process if it terminates due to an unhandled exception.
        /// - 2: Do not restart the process if it terminates due to the application not responding.
        /// - 4: Do not restart the process if it terminates due to the installation of an update.
        /// - 8: Do not restart the process if the computer is restarted as the result of an update.
        /// </param>
        /// <returns>
        /// This function returns S_OK on success or one of the following error codes.
        /// - E_FAIL: Internal error.
        /// - E_INVALIDARG: The specified command line is too long.
        /// </returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint RegisterApplicationRestart(string pwzCommandline, int dwFlags);
    }

    /// <summary>
    /// 表示重启时的限制标记。
    /// </summary>
    [Flags]
    public enum ApplicationRestartFlags
    {
        /// <summary>
        /// 没有重启限制。如果仅指定 <see cref="None"/>,那么操作系统在可以重启应用程序的时候都会重启应用。
        /// </summary>
        None = 0,

        /// <summary>
        /// 指定此时不重启:因未处理的异常而导致进程停止工作。
        /// </summary>
        RestartNoCrash = 1,

        /// <summary>
        /// 指定此时不重启:因应用程序无响应而导致进程停止工作。
        /// </summary>
        RestartNoHang = 2,

        /// <summary>
        /// 指定此时不重启:因应用安装更新导致进程关闭。
        /// </summary>
        RestartNoPatch = 4,

        /// <summary>
        /// 指定此时不重启:因操作系统安装更新后重启导致进程关闭。
        /// </summary>
        RestartNoReboot = 8
    }
}

参考资料

  • 为何win10 1709(秋季创意更新) 重启会自动恢复一些程序为重启以前的工作状态? - 蒋晟的回答 - 知乎
  • RegisterApplicationRestart function (Windows)
  • pinvoke.net: RegisterApplicationRestart (kernel32)
  • Restart Manager Support For Windows Application - CodeProject
  • c# - Restart a crashed program with RegisterApplicationRestart without user prompt - Stack Overflow
  • Vista Application Crash Recovery in C# - CodeProject
  • c# - Restart a crashed program with RegisterApplicationRestart without user prompt - Stack Overflow

相关文章:

  • 生成代码,从 T 到 T1, T2, Tn —— 自动生成多个类型的泛型
  • 应该抛出什么异常?不应该抛出什么异常?(.NET/C#)
  • 关闭模态窗口后,父窗口居然跑到了其他窗口的后面
  • 语义耦合(Semantic Coupling)
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • 在 Windows 安装期间将 MBR 磁盘转换为 GPT 磁盘
  • 解决大于 4GB 的 Windows 10 镜像在 UEFI 模式下的安装问题
  • 为什么 UEFI 方式启动的 U 盘必须使用 FAT32 文件系统?
  • 不再为命名而苦恼!使用 MSTestEnhancer 单元测试扩展,写契约就够了
  • Windows 10 自带那么多图标,去哪里找呢?
  • 如何删除 Windows 10 系统生成的 WindowsApps 文件夹
  • 命令“xxx.exe xxx”已退出,代码为 n。这些错误是什么意思?
  • 将 async/await 异步代码转换为安全的不会死锁的同步代码
  • 屏幕上那个灰色带有数字的框是什么?看着好难受!
  • Roslyn 入门:使用 Roslyn 静态分析现有项目中的代码
  • [PHP内核探索]PHP中的哈希表
  • 【前端学习】-粗谈选择器
  • 【知识碎片】第三方登录弹窗效果
  • 2017 年终总结 —— 在路上
  • cookie和session
  • HashMap剖析之内部结构
  • HTTP请求重发
  • javascript 哈希表
  • JavaScript实现分页效果
  • Java读取Properties文件的六种方法
  • Just for fun——迅速写完快速排序
  • maya建模与骨骼动画快速实现人工鱼
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 分类模型——Logistics Regression
  • 复杂数据处理
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 山寨一个 Promise
  • 我看到的前端
  • 新手搭建网站的主要流程
  • 一个SAP顾问在美国的这些年
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • 如何在招聘中考核.NET架构师
  • 数据可视化之下发图实践
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #在 README.md 中生成项目目录结构
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (4)Elastix图像配准:3D图像
  • (9)目标检测_SSD的原理
  • (LeetCode 49)Anagrams
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (转)nsfocus-绿盟科技笔试题目
  • (转)关于pipe()的详细解析
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转)原始图像数据和PDF中的图像数据
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .net core Swagger 过滤部分Api
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .NET的数据绑定