1

我在我的 C# 应用程序中使用 ShutdownBlockReasonCreate 来警告用户注销/关闭是否会影响我的应用程序中当前正在运行的方法。

我有两种方法可以警告用户:“上传”方法和“下载”方法。

如果用户开始长时间上传,我会设置 ShutdownBlockReasonCreate 并使用“上传当前正在运行”之类的消息。

我遇到的问题是,如果用户在长时间上传运行时开始简单下载,还会再次调用 ShutdownBlockReasonCreate 并显示“下载当前正在运行”之类的消息。

这会覆盖原来的“上传正在运行”消息。因此,当我的下载方法完成并调用 ShutdownBlockReasonDestroy 时,用户现在突然能够关闭和注销,即使上传仍在运行。

我希望能够使用我可以调用的可选参数调用 ShutdownBlockReasonCreate,这样我就可以向它发送多个字符串,说明程序为什么不允许 Windows 关闭或注销。

因此,当用户注销时,我希望它显示:

“上传正在运行”
“下载正在运行”

如果上传和下载都在运行。


有人可以修改我的代码来告诉我如何做到这一点吗?如果我可以传递除“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()方法需要确定当前正在发生的操作。如果至少有一个上传,但没有下载,则将消息设置为“上传中”。如果至少有一次下载,但没有上传,请将消息设置为“正在下载”。如果每个都至少有一个,则将消息设置为“正在上传和下载”。

在您的ResetShutdown()方法中,您需要再次检查哪些操作仍在进行中。如果没有,那么你应该销毁原因,然后isBlocked重新设置false。否则,您应该根据当前运行的内容调整isBlocked消息,并保留为true.

通过这样做,您可以确保您都拥有正确的关闭方法,并且只有在您的程序不在应该阻止关闭的操作中间时才允许关闭。

(此外,您应该记住,即使您“阻止”它,用户也可以自由“强制关闭”系统,因此更安全的方法通常是尝试暂停您正在执行的操作,然后稍后再恢复.)

于 2012-06-18T19:23:38.210 回答