【问题标题】:Shutdown Block Reason API for WPF is not workingWPF 的关闭阻止原因 API 不起作用
【发布时间】:2015-11-23 16:46:48
【问题描述】:

我有应用程序,它应该在特定情况下阻止 Windows 关闭(或至少通知用户,他不应该关闭 PC)。我正在使用here(以及其他一些地方)提到的 Shutdown Blocking Reason API。

问题是,当我将它用于 Winforms 时,它运行良好,只要我直接从 Form 使用它

ShutdownBlockReasonCreate(this.Handle, text));

迁移到 WPF 后,我将其更改为下一种方式

ShutdownBlockReasonCreate(new WindowInteropHelper(this).Handle, text));

它是从MainWindow.xaml.cs 调用的。 问题是,它什么也没做。不会引发异常,但在 Windows 关闭时它不会执行任何操作。 那么,它是与 WPF 不兼容,还是其他什么?

【问题讨论】:

    标签: c# wpf winforms xaml shutdown


    【解决方案1】:

    如果没有可靠地重现问题的a good, minimal, complete code example,就不可能确定您的问题是什么。我确实知道这行不通的至少两个可能原因:

    1. ShutdownBlockReasonCreate() 方法调用太快。我发现如果您尝试在Window 类的构造函数中使用WindowInteropHelper,使用以这种方式检索到的HWND 来调用ShutdownBlockReasonCreate(),则不会创建阻塞原因。但是,如果您延迟对 Window 对象的 Loaded 事件的初始化,它会起作用。
    2. 您还没有回复WM_QUERYENDSESSION 消息。在 WPF 中,完成此操作的最简单方法是将处理程序添加到 SystemEvents.SessionEnding 事件。
    3. 您允许关闭窗口。自然,如果窗口不存在,则不再报告阻止关闭的原因。

    这是一个完整的代码示例,在我的机器上运行良好。也就是说,如果您尝试关闭计算机,该程序将显示在阻止关闭的活动程序列表中,并且给定的阻止原因文本显示在程序名称下方:

    XAML:

    <Window x:Class="TestSO33876255BlockShutdown.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            DataContext="{Binding RelativeSource={RelativeSource Self}}"
            Title="MainWindow" Height="350" Width="525">
    
      <StackPanel>
        <CheckBox Content="Allow window to close" IsChecked="{Binding AllowClose}"/>
      </StackPanel>
    </Window>
    

    C#:

    public partial class MainWindow : Window
    {
        public bool AllowClose { get; set; }
    
        private WindowInteropHelper _helper;
    
        public MainWindow()
        {
            InitializeComponent();
    
            Loaded += (sender, e) =>
            {
                _helper = new WindowInteropHelper(this);
                _helper.EnsureHandle();
    
                SystemEvents.SessionEnding += (s1, e1) =>
                {
                    if (e1.Reason == SessionEndReasons.SystemShutdown)
                    {
                        Dispatcher.InvokeAsync(() => MessageBox.Show("attempting to block shutdown"));
                        e1.Cancel = true;
                    }
                };
    
                if (!ShutdownBlockReasonCreate(_helper.Handle, "Testing Stack Overflow Block Reason"))
                {
                    MessageBox.Show("Failed to create shutdown-block reason. Error: "
                        + Marshal.GetExceptionForHR(Marshal.GetLastWin32Error()).Message);
                }
            };
        }
    
        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (!AllowClose)
            {
                e.Cancel = true;
                ShutdownBlockReasonDestroy(_helper.Handle);
            }
            base.OnClosing(e);
        }
    
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public extern static bool ShutdownBlockReasonCreate([In]IntPtr hWnd, [In] string pwszReason);
    
        [DllImport("user32.dll", SetLastError = true)]
        public extern static bool ShutdownBlockReasonDestroy([In]IntPtr hWnd);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多