2015-11-23 30 views
1

我有应用程序,它应该在特定情况下阻止Windows关机(或者至少通知用户,他不应该关闭PC)。我正在使用Shutdown Blocking Reason API here(以及其他地方)。关闭块WPF的原因API不起作用

的事情是,我使用这个对的WinForms时,它工作得很好,只要我使用它从形式直接

ShutdownBlockReasonCreate(this.Handle, text)); 

一旦我迁移到WPF,我已将其更改为下一个方法

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

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

回答

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); 
}