1

C# アプリケーションで ShutdownBlockReasonCreate を使用して、アプリケーションで現在実行中のメソッドにログオフ/シャットダウンが影響するかどうかをユーザーに警告しています。

ユーザーに警告する方法は 2 つあります。「アップロード」方法と「ダウンロード」方法です。

ユーザーが長いアップロードを開始した場合、ShutdownBlockReasonCreate に「アップロードは現在実行中です」などのメッセージを設定します。

私が抱えている問題は、長いアップロードの実行中にユーザーが単純なダウンロードを開始すると、「ダウンロードは現在実行中です」のようなメッセージで ShutdownBlockReasonCreate も再度呼び出されることです。

これにより、元の「アップロードは現在実行中です」というメッセージが上書きされます。したがって、ダウンロード メソッドが終了し、ShutdownBlockReasonDestroy を呼び出すと、アップロードがまだ実行中であっても、ユーザーは突然シャットダウンしてログオフできるようになります。

プログラムがウィンドウのシャットダウンまたはログオフを許可しない理由について複数の文字列を送信できるように、呼び出すことができるオプションのパラメーターを使用して ShutdownBlockReasonCreate を呼び出すことができるようにしたいと考えています。

したがって、ユーザーがログオフすると、次のように表示されます。

「アップロードは現在実行中です」
「ダウンロードは現在実行中です」

アップロードとダウンロードの両方が実行されている場合。


誰かが私のコードを変更して、これを行う方法を教えてもらえますか? 「this.Handle」以外のものを渡すことができる場合。多分私はこれを達成することができますが、これを行う方法がわかりません。

        //http://blogs.msdn.com/b/oldnewthing/archive/2012/06/14/10319617.aspx
        //http://bartdesmet.net/blogs/bart/archive/2006/10/25/Windows-Vista-_2D00_-ShutdownBlockReasonCreate-in-C_2300_.aspx
        [DllImport("user32.dll")]
        public extern static bool ShutdownBlockReasonCreate(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] string pwszReason);

        [DllImport("user32.dll")]
        public extern static bool ShutdownBlockReasonDestroy(IntPtr hWnd);

        private bool isBlocked = false;

        protected override void WndProc(ref Message aMessage)
        {
            const int WM_QUERYENDSESSION = 0x0011;
            const int WM_ENDSESSION = 0x0016;

            if (isBlocked && (aMessage.Msg == WM_QUERYENDSESSION || aMessage.Msg == WM_ENDSESSION))
                return;

            base.WndProc(ref aMessage);
        }

        private void StopShutdown(string strMessage)
        {
            try
            {
                //strMessage == Message to display in shutdown/logoff box
                if (ShutdownBlockReasonCreate(this.Handle, strMessage))
                {
                    isBlocked = true;
                   Console.WriteLine("++ StopShutdown successful");
                }
                else
                    Console.WriteLine("++ StopShutdown failed");

            }
            catch (Exception ext)
            {
                MessageBox.Show("++ StopShutdown Error:    " + ext.Message + " " + ext.StackTrace);
            }
        }

        private void ResetShutdown()
        {
            try
            {

                if (ShutdownBlockReasonDestroy(this.Handle))
                {
                    isBlocked = false;
                    Console.WriteLine("++ ResetShutdown successful");
                }
                else
                    Console.WriteLine("++ ResetShutdown failed");

            }
            catch (Exception ext)
            {
                MessageBox.Show("++ ResetShutdown Error:    " + ext.Message + " " + ext.StackTrace);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            StopShutdown("Upload in Progress");
            MessageBox.Show("Upload in Progress");
            ResetShutdown();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            StopShutdown("Download in Progress");
            MessageBox.Show("Download in Progress");
            ResetShutdown();
        }
4

1 に答える 1

4

正しいメッセージが表示され、ブロック操作が進行中の場合にメッセージが常に表示される (シャットダウンが防止される) ようにするには、システムで何が起きているかを注意深く追跡する必要があります。

たとえば、任意の数のアップロードとダウンロードを同時に実行できるとします。その場合、StopShutdown()メソッドは現在発生している操作を特定する必要があります。少なくとも 1 つのアップロードがあり、ダウンロードがない場合は、メッセージを「アップロード中」に設定します。少なくとも 1 つのダウンロードがあり、アップロードがない場合は、メッセージを「ダウンロード中」に設定します。それぞれに少なくとも 1 つある場合は、メッセージを「アップロードとダウンロードが進行中です」に設定します。

ResetShutdown()メソッドでは、まだ進行中の操作を再度確認する必要があります。何もない場合は、理由を破棄して、にisBlocked戻す必要がありfalseます。それ以外の場合は、現在実行中のものに基づいてメッセージを調整isBlockedし、そのままにしておく必要がありますtrue

そうすることで、両方が正しいシャットダウン方法を持っていることを確認し、シャットダウンをブロックする必要がある操作の最中にプログラムが実行されていない場合にのみシャットダウンを許可します。

(また、システムを「ブロック」したとしても、ユーザーは自由にシステムを「強制シャットダウン」できることを覚えておく必要があります。そのため、より安全な方法は、多くの場合、実行中の作業を一時停止して、後で再開することです。 .)

于 2012-06-18T19:23:38.210 に答える