C# ShutdownBlockReasonCreate-创建在注销/关闭期间显示的多个原因

C# ShutdownBlockReasonCreate-创建在注销/关闭期间显示的多个原因,c#,C#,我在我的C#应用程序中使用ShutdownBlockReasonCreate来警告用户,如果注销/关闭将影响我的应用程序中当前正在运行的方法 我有两种方法可以警告用户:“上传”方法和“下载”方法 如果用户开始长时间上传,我会用“Upload is current running”(上传当前正在运行)这样的消息设置ShutdownBlockReasonCreate 我遇到的问题是,如果用户在长时间上载运行时启动一个简单下载,也会再次调用ShutdownBlockReasonCreate,并显示类似

我在我的C#应用程序中使用ShutdownBlockReasonCreate来警告用户,如果注销/关闭将影响我的应用程序中当前正在运行的方法

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

如果用户开始长时间上传,我会用“Upload is current running”(上传当前正在运行)这样的消息设置ShutdownBlockReasonCreate

我遇到的问题是,如果用户在长时间上载运行时启动一个简单下载,也会再次调用ShutdownBlockReasonCreate,并显示类似“download is current running”的消息

这将覆盖原始的“上载当前正在运行”消息。因此,当我的下载方法完成后,我调用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();
        }

为了确保显示正确的消息,并确保在执行阻塞操作时始终显示消息(并防止关机),您需要仔细跟踪系统中发生的情况

例如,假设您可以同时运行任意数量的上载和下载。在这种情况下,您的
StopShutdown()
方法需要确定当前正在发生的操作。如果至少有一个上载,但没有下载,则将消息设置为“正在上载”。如果至少有一个下载,但没有上载,则将消息设置为“正在下载”。如果至少有一个上载,则将消息设置为“正在上载和下载”

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

通过这样做,您可以确保两个都有正确的关机方法,如果程序不在关机操作的中间,也只允许关机。


(此外,您应该记住,用户可以自由地“强制关闭”系统,即使您“阻止”了它,因此更安全的方法通常是尝试暂停您正在做的事情,然后在稍后继续。)

以确保显示正确的消息,并且始终显示消息(并防止关机)如果正在进行阻塞操作,则需要仔细跟踪系统中发生的情况

例如,假设您可以同时运行任意数量的上载和下载。在这种情况下,您的
StopShutdown()
方法需要确定当前正在发生的操作。如果至少有一个上载,但没有下载,则将消息设置为“正在上载”。如果至少有一个下载,但没有上载,则将消息设置为“正在下载”。如果至少有一个上载,则将消息设置为“正在上载和下载”

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

通过这样做,您可以确保两个都有正确的关机方法,如果程序不在关机操作的中间,也只允许关机。


(此外,您应该记住,用户可以自由地“强制关闭”系统,即使您“阻止”了它,因此更安全的方法通常是尝试暂停您正在做的事情,然后在稍后恢复。)

只需根据当前运行的内容设置消息(您需要在程序的中心位置跟踪)只有在没有零阻塞操作的情况下才能销毁原因。我试过了,但没有成功。我将启动ShutdownBlockReasonCreate(this.Handle,strMessage)时使用的同一字符串传递给ShutdownBlockReasonDestroy(this.Handle,strMessage),但它不起作用。只注册了一条消息,一旦我销毁了该消息,计算机将允许注销/关机,即使我使用不同的消息启动了另一个ShutdownBlockReasonCreate。我将发布一个更好地描述我意思的答案。这种方法不可能“不工作”:)一个进程只能产生一条消息。您正在编写的代码将永远不会被使用,用户将始终覆盖并强制关闭。只需根据当前正在运行的内容设置消息(您需要在程序的中心位置跟踪该消息),并且仅在没有零阻塞操作的情况下销毁原因。我尝试了,但没有成功。我将启动ShutdownBlockReasonCreate(this.Handle,strMessage)时使用的同一字符串传递给ShutdownBlockReasonDestroy(this.Handle,strMessage),但它不起作用。仅注册了一条消息,一旦我销毁该消息,计算机将允许注销/关机,即使我使用不同的消息启动了另一个ShutdownBlockReasonCreate。我