Эта статья гласит:
Если приложение должно блокировать возможное отключение системы, оно может вызвать функцию ShutdownBlockReasonCreate.Вызывающая сторона предоставляет строку причины, которая будет отображаться пользователю.
И в документации ShutdownBlockReasonCreate это четко указывает, что диалоговое окно со строкой причины будет отображаться дляпользователь при попытке выключения:
Указывает, что система не может быть выключена, и задает строку причины, которая будет отображаться пользователю, если выключение системы инициируется
Ипоявление этого диалогового окна подтверждается в этом обсуждении:
Пользователь может нажать «Все равно выключить».Кроме того, система предполагает «все равно отключиться», если пользователь не предпринимает никаких действий в течение некоторого количества секунд.
Однако после того, как я позвоню ShutdownBlockReasonCreate , передавая дескриптор главного окнатекущее приложение, гарантирующее, что функция выполнена успешно, и двойное заверение, вызывая функцию ShutdownBlockReasonQuery для получения строки причины, это не мешает пользователю завершить работу системы, и диалоговое окно не отображается.
Почему это не влияет на мою систему? И как мне решить эту проблему?.
Я работаю в Windows 10 x64 с учетной записью администратора (встроенной) икод, который я использую, взят из этого GitHub репозитория:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Vanara.PInvoke;
using static Vanara.PInvoke.User32;
namespace Vanara.Windows.Forms.Forms
{
/// <summary>Used to define a set of operations within which any shutdown request will be met with a reason why this application is blocking it.</summary>
/// <remarks>This is to be used in either a 'using' statement or for the life of the application.
/// <para>To use for the life of the form, define a class field:
public class PreventShutdownContext : IDisposable
{
private HandleRef href;
/// <summary>Initializes a new instance of the <see cref="PreventShutdownContext"/> class.</summary>
/// <param name="window">The <see cref="Form"/> or <see cref="Control"/> that contains a valid window handle.</param>
/// <param name="reason">The reason the application must block system shutdown. Because users are typically in a hurry when shutting down the system, they may spend only a few seconds looking at the shutdown reasons that are displayed by the system. Therefore, it is important that your reason strings are short and clear.</param>
public PreventShutdownContext(Control window, string reason)
{
href = new HandleRef(window, window.Handle);
Reason = reason;
}
/// <summary>The reason the application must block system shutdown. Because users are typically in a hurry when shutting down the system, they may spend only a few seconds looking at the shutdown reasons that are displayed by the system. Therefore, it is important that your reason strings are short and clear.</summary>
/// <value>The reason string.</value>
public string Reason
{
get
{
if (!ShutdownBlockReasonQuery(href.Handle, out var reason))
Win32Error.ThrowLastError();
return reason;
}
set
{
if (value == null) value = string.Empty;
if (ShutdownBlockReasonQuery(href.Handle, out var _))
ShutdownBlockReasonDestroy(href.Handle);
if (!ShutdownBlockReasonCreate(href.Handle, value))
Win32Error.ThrowLastError();
}
}
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose()
{
ShutdownBlockReasonDestroy(href.Handle);
}
}
}
...
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShutdownBlockReasonCreate(HWND hWnd, [MarshalAs(UnmanagedType.LPWStr)] string reason);
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShutdownBlockReasonQuery(HWND hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, ref uint pcchBuff);
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShutdownBlockReasonDestroy(HWND hWnd);
При таком использовании:
using (new PreventShutdownContext(this, "This app is super busy right now."))
{
// Do something that can't be interrupted...
}
Я попробовал код как есть, с его определениями P / Invoke, а также с небольшой модификацией кода, в котором я использую IntPtr структуру для дескрипторов окон вместо этого пользовательского * 1046Структура * HWND и передача ей дескриптора главного окна приложения, как я указал в комментарии выше.