2009-04-07 35 views
6

Ứng dụng của tôi cần chặn chế độ ngủ/ngủ đông. Tôi có mã tại chỗ, nhưng sau khi bắt được thành công thông báo WM_POWERBROADCAST, không phải PBT_APMQUERYSUSPEND hoặc PBT_APMQUERYSTANDBY đang bị bắt gặp thành công. Điều thú vị là, PBT_APMRESUMECRITICALPBT_APMRESUMEAUTOMATIC tin nhắn bị ứng dụng của tôi chặn lại.Không thể bắt giấc ngủ/treo tin nhắn (winXP)

Câu hỏi cuối cùng: có bất kỳ lý do nào khiến ứng dụng của tôi không thể nhận thông báo dự phòng/tạm dừng nhưng thành công trong việc thu thập thông báo tiếp tục không?

Điều này Q&A [stackoverflow.com] đã giúp, btw, nhưng một lần nữa, các thông báo dường như không biến nó thành ứng dụng của tôi.

Mã của tôi (w/sự kiện mã đăng nhập loại bỏ cho ngắn gọn):

 protected override void WndProc(ref System.Windows.Forms.Message m) 
    { 
     // Power status event triggered 
     if (m.Msg == (int)NativeMethods.WindowMessage.WM_POWERBROADCAST) 
     { 
      // Machine is trying to enter suspended state 
      if (m.WParam.ToInt32() == (int)NativeMethods.WindowMessage.PBT_APMQUERYSUSPEND || 
       m.WParam.ToInt32() == (int)NativeMethods.WindowMessage.PBT_APMQUERYSTANDBY) 
      { 
       // Have perms to deny this message? 
       if((m.LParam.ToInt32() & 0x1) != 0) 
       { 
        // If so, deny broadcast message 
        m.Result = new IntPtr((int)NativeMethods.WindowMessage.BROADCAST_QUERY_DENY); 
       } 
      } 
      return; // ?! 
     } 

     base.WndProc(ref m); 
    } 

Trả lời

3

Nó hoạt động ngay bây giờ, cho cả XP và Vista. Tôi tạo ra một ứng dụng winform sơ khai với các mã có liên quan (có thể được làm sạch lên, rõ ràng, nhưng nó chuyển tải điểm).

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace standbyTest 
{ 
    public partial class Form1 : Form 
    { 

     [DllImport("Kernel32.DLL", CharSet = CharSet.Auto, SetLastError = true)] 
     protected static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE state); 

     [Flags] 
     public enum EXECUTION_STATE : uint 
     { 
      ES_CONTINUOUS = 0x80000000, 
      ES_DISPLAY_REQUIRED = 2, 
      ES_SYSTEM_REQUIRED = 1, 
      ES_AWAYMODE_REQUIRED = 0x00000040 
     } 

     public Form1() 
     { 
      if(Environment.OSVersion.Version.Major > 5) 
      { 
       // vista and above: block suspend mode 
       SetThreadExecutionState(EXECUTION_STATE.ES_AWAYMODE_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS); 
      } 

      InitializeComponent(); 

      //MessageBox.Show(string.Format("version: {0}", Environment.OSVersion.Version.Major.ToString())); 

     } 

     protected override void OnClosed(EventArgs e) 
     { 
      base.OnClosed(e); 

      if(Environment.OSVersion.Version.Major > 5) 
      { 
       // Re-allow suspend mode 
       SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS); 
      } 
     } 


     protected override void WndProc(ref System.Windows.Forms.Message m) 
     { 
      // Power status event triggered 
      if(m.Msg == (int)WindowMessage.WM_POWERBROADCAST) 
      { 
       // Machine is trying to enter suspended state 
       if(m.WParam.ToInt32() == (int)WindowMessage.PBT_APMQUERYSUSPEND || 
         m.WParam.ToInt32() == (int)WindowMessage.PBT_APMQUERYSTANDBY) 
       { 
        // Have perms to deny this message? 
        if((m.LParam.ToInt32() & 0x1) != 0) 
        { 
         // If so, deny broadcast message 
         m.Result = new IntPtr((int)WindowMessage.BROADCAST_QUERY_DENY); 
        } 
       } 
       return; 
      } 

      base.WndProc(ref m); 
     } 
    } 



    internal enum WindowMessage 
    { 

     /// <summary> 
     /// Notify that machine power state is changing 
     /// </summary> 
     WM_POWERBROADCAST = 0x218, 
     /// <summary> 
     /// Message indicating that machine is trying to enter suspended state 
     /// </summary> 
     PBT_APMQUERYSUSPEND = 0x0, 
     PBT_APMQUERYSTANDBY = 0x0001, 

     /// <summary> 
     /// Message to deny broadcast query 
     /// </summary> 
     BROADCAST_QUERY_DENY = 0x424D5144 


    } 
} 
+0

Còn WPF thì sao? – Alessio

0

Bạn đang chạy trên Vista hoặc Windows Server 2008? This page nói

Do thay đổi trong Mô hình quản lý nguồn cho Windows Vista và Windows Server 2008, sự kiện PBT-APMQUERYSUSPEND không còn được gửi tới ứng dụng nữa. Thay vào đó, sự kiện BT_APMSUSPEND được phân phối ...

Đó có thể là lý do bạn không nhìn thấy nó?

+0

này là dành cho WinXP (đã không nhận để Vista/2008 chưa). Có vẻ như nó sẽ "chỉ hoạt động", nhưng không. Tôi không biết tại sao tôi lại nắm bắt thông điệp "tiếp tục" chứ không phải là thông điệp "ngủ". Ý tưởng, bất kỳ ai? – Garrett

0

Tôi đã thử cùng mã này trong ứng dụng thử nghiệm trên máy (01) của tôi & trên một máy (thử nghiệm) khác (cũng là winXP). Trên máy tính của tôi, nó tiếp tục thất bại, có nghĩa là máy đi vào giấc ngủ. Nhưng trên máy khác, nó hoạt động! Lúc đầu, tôi nghĩ rằng đây là một vấn đề chế độ gỡ lỗi vs phát hành, nhưng đó không phải là trường hợp.

Có vẻ như có điều gì đó khác biệt về máy tính của tôi, mặc dù tôi không biết nó có thể là gì.

Bí ẩn được giải quyết ... sorta.

0

Trong Vista gọi SetThreadExecutionState để thông báo cho WPM rằng hệ thống không hoạt động.

Trong Windows XP/2000:
Ứng dụng có thể trả về BROADCAST_QUERY_DENY để từ chối yêu cầu PBT_APMQUERYSUSPEND hoặc PBT_APMQUERYSUSPENDFAILED.

MSDN: Windows XP trở về trước: Hệ thống phát sự kiện PBT_APMQUERYSUSPEND để yêu cầu quyền tạm ngừng hoạt động của hệ thống. Hệ thống mong đợi mỗi ứng dụng và trình điều khiển xác định xem sự kiện được yêu cầu có xảy ra hay không và trả về TRUE nếu nó xảy ra hoặc trả về BROADCAST_QUERY_DENY nếu không. Các ứng dụng không nên từ chối yêu cầu này. Nếu một ứng dụng từ chối yêu cầu này, hệ thống sẽ phát một sự kiện PBT_APMQUERYSUSPENDFAILED. Sự kiện này thông báo cho các ứng dụng và trình điều khiển tiếp tục hoạt động như bình thường.

Ngoài ra, tôi không nghĩ rằng PBT_APMQUERYSTANDBY hoặc PBT_APMSTANDBY được hỗ trợ trong Win2K. Bạn đã cố gắng đăng nhập một cách ảm đạm khi Windows tắt để xem chúng có được gửi không?

+0

Cảm ơn các ý kiến! Tôi chưa viết mã Vista, chỉ cần XP (không lo lắng về win2k vì nó không nằm trong danh sách các hệ điều hành được hỗ trợ của chúng tôi). Bí ẩn tại thời điểm này là tại sao mã không hoạt động trên máy của tôi (nhưng DOES hoạt động trên máy thử nghiệm), nhưng tôi sẽ phải tự mình khám phá nó. =) – Garrett

+0

Vui vì bạn đã sửa nó. Xấu hổ không có chứng nhận DWOMM! http://www.codinghorror.com/blog/images/works-on-my-machine-starburst.png: oÞ – MaSuGaNa

Các vấn đề liên quan