2016-09-05 4 views
1

ソフトウェアの実行中にWindowsがシャットダウンするのを防ぐために、私たちのシステム用に小さなツールを作ろうとしています。それを独立させるために、私はthis情報を使ってシャットダウンを防止する別のアプリケーションを作った。Delphi - トレイアプリケーションからWindowsがシャットダウンするのを防ぐ

ただし、アプリケーションをトレイに最小化すると、Windowsは単にアプリケーションを終了して正常にシャットダウンします。フォームが表示されている場合(つまり、Form.OnCreateイベントからApplication.Minimizeコールにコメントする)、正常にシャットダウンすることはありません。

MainWindowフックを使用してライブを維持する方法や、アプリをトレイに隠してシステムのシャットダウンを防止する方法がありますか?

ありがとうございました。

現在のコード:

unit Main; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, TlHelp32, dateutils, Vcl.AppEvnts, Vcl.ExtCtrls; 

type 
    TForm1 = class(TForm) 
    TrayIcon1: TTrayIcon; 
    ApplicationEvents1: TApplicationEvents; 
    procedure FormCreate(Sender: TObject); 
    function HookEndSession(var Message: TMessage): Boolean; 
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession) ; 
     message WM_QueryEndSession; 
    procedure ApplicationEvents1Minimize(Sender: TObject); 
    procedure ApplicationEvents1Restore(Sender: TObject); 
    procedure TrayIcon1DblClick(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var Form1: TForm1; 
var Mutex : THandle; 

implementation 

{$R *.dfm} 



procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession); 
begin 
    Msg.Result := 0; 
end; 

function TForm1.HookEndSession(var Message: TMessage): Boolean; 
begin 
    result := false; 
    if Message.Msg = WM_ENDSESSION then begin 
    Message.Result := 0; 
    result := true; 
    end; 
end; 


procedure TForm1.TrayIcon1DblClick(Sender: TObject); 
begin 
    WindowState := wsNormal; 
    Application.Terminate; 
end; 

procedure TForm1.ApplicationEvents1Minimize(Sender: TObject); 
begin 
    Hide(); 
    WindowState := wsMinimized; 
    TrayIcon1.Visible := True; 
end; 

procedure TForm1.ApplicationEvents1Restore(Sender: TObject); 
begin 
    Application.Minimize; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Mutex := CreateMutex(nil, True, 'preventWinShutdown'); 
    if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then 
    Application.Terminate; 

    Application.HookMainWindow(HookEndSession); 

    TrayIcon1.Hint := 'Windows Shutdown prevented.'; 
    //Application.Minimize; 
end; 


end. 

答えて

4

は私が手元にXE3を持っていませんが、XE7に、TCustomTrayIcon.WindowProcは、明示的にログオフ/シャットダウンを進めるために、Windowsに信号(TRUEに相当)1を返すことでWM_QUERYENDSESSIONを処理します/再開シーケンス。 あなたはそれを上書きすることができます。より完全なソリューションについては

type 
    TTrayIcon = class(Vcl.ExtCtrls.TTrayIcon) 
    protected 
    procedure WindowProc(var Message: TMessage); override; 
    end; 

procedure TTrayIcon.WindowProc(var Message: TMessage); 
begin 
    case Message.Msg of 
    WM_QUERYENDSESSION: 
     Message.Result := 0; 
    else 
     inherited WindowProc(Message); 
    end; 
end; 

は、あなたが別のユニットで新しいクラスを作成し、TCustomTrayIconと再出版プロパティとあなたはTTrayIconが行うよう、公開したいイベントから継承し、インストールIDE内のコンポーネントを使用して、プロジェクト内で使用します。

上記の例は、あなたのTForm1の前に単に宣言してすぐにこのユニットでのみ使用できるインターポーザークラスを持つ簡単なものです。

3

Ondrejはソリューションの半分にすぎないと述べました。

Vista以降では、ShutdownBlockReasonCreate()を使用する必要があります。これは、以下の注意事項をお使いの場合には特に重要です:アプリケーションの場合は、シャットダウンをブロックする必要があります

Application Shutdown Changes in Windows Vista

アプリケーションは、Windows XPでは、新たなシャットダウン理由API

を使用する必要があり、Microsoftがあることをお勧めしますなぜシャットダウンをブロックする必要があるのか​​を説明する独自のUIを表示する必要があるため、シャットダウンが失敗したときにユーザーが不満を感じることはありません。先に説明したように、Windows Vistaでは、シャットダウンがさらに失敗したときのユーザーの不満は、アプリケーションがブロックシャットダウンに提供したすべての理由を示す新しいUIを表示することで軽減されます。

Windows Vistaでは、アプリケーションがシャットダウンをブロックする必要がある場合は、FALSEを返すか、WM_QUERYENDSESSIONに応答しないだけでなく、簡単なAPIを使用してWindowsに理由を説明するストリングシャットダウン。このAPIは簡単です:このAPIの

BOOL ShutdownBlockReasonCreate(HWND hWnd, LPCWSTR pwszReason);

BOOL ShutdownBlockReasonDestroy(HWND hWnd);

BOOL ShutdownBlockReasonQuery(HWND hWnd, LPWSTR pwszBuff, DWORD *pcchBuff);

使用して、個々のShutdownBlockReasonのためのMSDNドキュメント内だけでなく、このトピックの後半で詳しく詳述されています()機能。

このAPIは、シャットダウンをブロックするためにWM_QUERYENDSESSIONにFALSE(または応答遅延)を返す必要性に代わるものではありません。アプリケーションは、APIを使用することに加えてこれを行う必要があります。 WM_QUERYENDSESSIONにTRUEを返すアプリケーションは、APIを使用しているかどうかにかかわらず、シャットダウン時に閉じられます。

アプリケーションに表示可能なトップレベルウィンドウがない場合、シャットダウンを正常にブロックする必要がある場合は、このAPIを使用する必要があります。このようなアプリケーションは、APIを使用せずにシャットダウンをブロックすると、自動的に終了します。

関連する問題