Best Practices for Handling Shutdown in Windows Vista

本文详细介绍了在Windows Vista系统下,应用程序在处理关机操作时的一系列最佳实践,包括避免阻塞关机、使用新的关机原因API等,确保用户在关机过程中获得最佳体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值