Best Practices for Handling Shutdown in Windows Vista

As a result of the above changes, how should applications handle shutdown in Windows Vista differently relative to Windows XP? The following are recommended best practices.

Applications should not block shutdown

If you take only one thing away from reading this topic, it should be this one. You will be presenting the best experience to your users if your application does not block shutdown. When users initiate shutdown, in the vast majority of cases, they have a strong desire to see shutdown succeed; they may be in a hurry to leave the office for the weekend, for example. Applications should respect this desire by not blocking shutdown if at all possible.

In many cases, applications that block shutdown can be redesigned so that they no longer need to do so. For example, applications with unsaved data at shutdown can be designed to automatically save their data and restore it when the user next starts the application, instead of blocking shutdown to ask the user what to do. Microsoft Office 2007 will do this in certain scenarios.

In other cases, there is usually a sensible default action that applications should automatically perform, instead of blocking shutdown to ask the user what to do. In many cases, this is true even if the default action could be slightly destructive. For example, if an application is in the middle of burning a CD when shutdown occurs, it should cancel the CD burn instead of blocking shutdown to ask the user what to do. Most users tend not to forget that they have a CD burn in progress, and if they shut down their computers while burning a CD, it would be sensible to assume that they intend to cancel the CD burn. This is what Windows Media Player 11 will do if the user shuts down while a CD burn is in progress.

Applications that must block shutdown should use the new shutdown reason API

In Windows XP, Microsoft recommended that if an application needed to block shutdown, it should display its own UI explaining why it needed to do so, so users would be less frustrated when shutdown failed. As discussed earlier, Windows Vista will reduce user frustration when shutdown fails even more, by displaying new UI that lists all the reasons applications have provided for blocking shutdown.

In Windows Vista, if your application must block shutdown, in addition to returning FALSE or not responding to WM_QUERYENDSESSION, it should leverage this new UI by using a simple API to provide Windows with a reason string explaining why it is blocking shutdown. This API is straightforward:

BOOL ShutdownBlockReasonCreate(HWND hWnd, LPCWSTR pwszReason);

BOOL ShutdownBlockReasonDestroy(HWND hWnd);

BOOL ShutdownBlockReasonQuery(HWND hWnd, LPWSTR pwszBuff, DWORD *pcchBuff);

Use of this API is detailed more fully later in this topic, as well as in the MSDN documentation for the individual ShutdownBlockReason() functions.

Again, note that this API does not replace the need to return FALSE (or delay responding) to WM_QUERYENDSESSION to block shutdown. Applications need to do this in addition to using the API. Applications that return TRUE to WM_QUERYENDSESSION will be closed at shutdown, regardless of whether they have used the API.

Also note that if your application has no visible top-level windows, it must use this API if it needs to successfully block shutdown. Such applications will automatically be terminated if they block shutdown without using the API.

Applications should no longer rely on always being able to block shutdown

If the user initiates a critical shutdown by clicking the "Shut down now" button from the new Windows UI discussed earlier, applications will not be allowed to block shutdown. In a critical shutdown, applications that return FALSE to WM_QUERYENDSESSION will be sent WM_ENDSESSION and closed, while those that time out in response to WM_QUERYENDSESSION will be terminated. The different procedure that is followed in a critical shutdown is summarized in Table 2 above.

In most cases, shutdown will not be critical, but applications should be prepared for the possibility of a critical shutdown. By following these recommendations, you can ensure that your application will handle critical shutdowns gracefully, without being terminated:

  1. Make sure your application is prepared to respond to WM_ENDSESSION even if it responded FALSE to WM_QUERYENDSESSION.
  2. Make sure your application responds to WM_QUERYENDSESSION as quickly as possible. If you need to do any time-consuming processing at shutdown, you should do it in response to WM_ENDSESSION. As indicated in Table 2, applications that respond TRUE to WM_QUERYENDSESSION will by default be given 30 seconds to do shutdown processing and respond to WM_ENDSESSION.
  3. If your application needs to determine whether a shutdown is critical, it can check the ENDSESSION_CRITICAL bit in the lParam parameter of WM_QUERYENDSESSION.
Using the New Shutdown Reason API

The new shutdown reason API consists of three functions:

  • BOOL ShutdownBlockReasonCreate(HWND hWnd, LPCWSTR pwszReason);
  • BOOL ShutdownBlockReasonDestroy(HWND hWnd);
  • BOOL ShutdownBlockReasonQuery(HWND hWnd, LPWSTR pwszBuff, DWORD *pcchBuff);

Again, the best practice for Windows Vista applications at shutdown is that they should never block shutdown. However, if your application must block shutdown, Microsoft recommends that you use this API. The functions are simple to use.

  1. When your application needs to block shutdown, it should call ShutdownBlockReasonCreate() to register a reason string, and pass in a handle to the window it uses to handle WM_QUERYENDSESSION.
  2. When your application no longer needs to block shutdown, it should call ShutdownBlockReasonDestroy() to unregister its reason string.
  3. If your application needs to determine what reason string it registered earlier, it should call ShutdownBlockReasonQuery() to retrieve it.

Windows will store the reason string associated with your application for the duration of the user's session. The reason string store is not persisted when the user successfully shuts down; new sessions initialize an empty reason string store.

There are three main usage models for these functions.

  1. The application knows ahead of time when it will need to block shutdown (preferred usage model)
  2. The application only knows whether it will need to block shutdown during the shutdown process
  3. The application has no visible top-level windows and needs more than 30 seconds to handle WM_ENDSESSION and perform shutdown processing

These are described in detail below.

The application knows ahead of time when it will need to block shutdown (preferred usage model)

An example of this is an application that performs a critical operation and knows that it will need to block shutdown during that operation. If that operation is performed in a single block of code within the application, then ShutdownBlockReasonCreate() should be called at the start of that block of code, and ShutdownBlockReasonDestroy() at the end. In addition, the application should return FALSE to WM_QUERYENDSESSION if the operation is in progress when WM_QUERYENDSESSION is received.

This way, the application will block shutdown and its reason for blocking shutdown will be displayed if and only if the critical operation was in progress when shutdown was initiated.

This is the preferred usage model for this API, because it has the advantage that if another application blocks shutdown before your application and the new Windows UI is displayed, your application will be listed as needing to block shutdown and its reason string will be shown. This is not true for the other usage models discussed below.

The application only knows whether it will need to block shutdown during the shutdown process

In some cases, an application can only know whether it will need to block shutdown when it is responding to WM_QUERYENDSESSION. In this case, it should call ShutdownBlockReasonCreate() within its WM_QUERYENDSESSION handler, then respond FALSE to WM_QUERYENDSESSION.

This way, the application will block shutdown and its reason for blocking shutdown will be displayed.

There are two important points to note in this usage model:

  1. It is especially important to ensure that your application unregisters its reason string by calling ShutdownBlockReasonDestroy() later, when it no longer needs to block shutdown. Otherwise, Windows may display a stale string for your application if a future shutdown is blocked, and your users may be confused.
  2. Your application will not always be presented to the user as needing to block shutdown. Specifically, if another application blocks shutdown before your application and the new Windows UI is displayed, your application will not be identified as needing to block shutdown, because it will not have been sent WM_QUERYENDSESSION yet.
The application has no visible top-level windows and needs more than 30 seconds to handle WM_ENDSESSION and perform shutdown processing

By default, applications without any visible top-level windows will be given 5 seconds to handle WM_ENDSESSION before being terminated.

If your application may need more than 5 seconds to complete its shutdown processing in response to WM_ENDSESSION, it should call ShutdownBlockReasonCreate() in its WM_QUERYENDSESSION handler, and promptly respond TRUE to WM_QUERYENDSESSION so as not to block shutdown. It should then perform all shutdown processing in its WM_ENDSESSION handler.

This way, Windows will treat your application as if it had visible top-level windows and will give it 30 seconds to handle WM_ENDSESSION.

Best Practices For Shutdown Reason Strings

When users are shutting down Windows, they are typically in a hurry and will spend just a few seconds looking at the new Windows UI listing application shutdown reasons. Because of this, it is imperative that the reason strings your application registers are easy to read and understand.

Below are examples of reason strings, as well as revisions to those strings that make them more concise and therefore easier to understand.

Less ClearClear

This application is blocking shutdown because a CD burn is in progress.

A CD burn is in progress.

A TV show recording is currently occurring.

A TV show is being recorded.

A transaction is in progress. Do not shut down.

A transaction is in progress.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧农业是一种结合了现代信息技术,包括物联网、大数据、云计算等,对农业生产过程进行智能化管理和监控的新模式。它通过各种传感器和设备采集农业生产中的关键数据,如大气、土壤和水质参数,以及生物生长状态等,实现远程诊断和精准调控。智慧农业的核心价值在于提高农业生产效率,保障食品安全,实现资源的可持续利用,并为农业产业的转型升级提供支持。 智慧农业的实现依赖于多个子系统,包括但不限于设施蔬菜精细化种植管理系统、农业技术资料库、数据采集系统、防伪防串货系统、食品安全与质量追溯系统、应急追溯系统、灾情疫情防控系统、农业工作管理系统、远程诊断系统、监控中心、环境监测系统、智能环境控制系统等。这些系统共同构成了一个综合的信息管理和服务平台,使得农业生产者能够基于数据做出更加科学的决策。 数据采集是智慧农业的基础。通过手工录入、传感器自动采集、移动端录入、条码/RFID扫描录入、拍照录入以及GPS和遥感技术等多种方式,智慧农业系统能够全面收集农业生产过程中的各种数据。这些数据不仅包括环境参数,还涵盖了生长状态、加工保存、检验检疫等环节,为农业生产提供了全面的数据支持。 智慧农业的应用前景广阔,它不仅能够提升农业生产的管理水平,还能够通过各种应用系统,如库房管理、无公害监控、物资管理、成本控制等,为农业生产者提供全面的服务。此外,智慧农业还能够支持政府监管,通过发病报告、投入品报告、死亡报告等,加强农业产品的安全管理和质量控制。 面对智慧农业的建设和发展,存在一些挑战,如投资成本高、生产过程标准化难度大、数据采集和监测的技术难题等。为了克服这些挑战,需要政府、企业和相关机构的共同努力,通过政策支持、技术创新和教育培训等手段,推动智慧农业的健康发展。智慧农业的建设需要明确建设目的,选择合适的系统模块,并制定合理的设备布署方案,以实现农业生产的智能化、精准化和高效化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值