无形桌面应用程序 - SystemEvents.SessionEnding不能一直工作

时间:2011-01-03 05:39:39

标签: c#

我的应用程序大部分时间都没有显示任何形式,当用户关闭系统时,我需要它自行关闭。

所以我创建了a question,那里的答案,SystemEvents.SessionEnding似乎有效。

起初。

这是我的Program.Main()方法:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
    #region Pre-launch stuff
    // Are we upgrading from an older version? We need to grab our old settings!
    if (Properties.Settings.Default.UpgradeSettings)
    {
        Properties.Settings.Default.Upgrade();
        Properties.Settings.Default.UpgradeSettings = false;
        Properties.Settings.Default.Save();
    }

    // Visual styles
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    #if !DEBUG
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandling.Application_ThreadException);

    // Set the unhandled exception mode to force all Windows Forms errors to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ErrorHandling.CurrentDomain_UnhandledException);
    #endif

    // Since we have no forms open we need to watch for the shutdown event; otherwise we're blocking it
    SystemEvents.SessionEnding += new SessionEndingEventHandler(SystemEvents_SessionEnding);

    // ...
    // ...
    // ...

    Application.Run();
}

方法SystemEvents_SessionEnding运行一个调用Exit()的方法,该方法依次运行:

    public static void Exit()
    {
        MessageBox.Show("test");

        try
        {
            IconHandler.SuperNotifyIcon.Dispose();
        }
        finally
        {
            Application.Exit();
        }
    }

然而,我的应用程序有时会关闭。我在那里添加的消息框没有显示出来。

我无法弄清楚这种简单,简单的执行路径如何失败。但确实如此,这对我和我的应用程序的用户来说都是一个主要的刺激因素。

有什么想法吗?想要四处游荡?


修改

根据corvuscorax的回答,我尝试添加一个表单,但它表现得很奇怪 - 起初,我在表单的代码中有这个:

        ShowInTaskbar = false;
        WindowState = FormWindowState.Minimized;
        Shown += (sender, e) => Hide();

修改了Program.Exit()方法以关闭该表单,该表单也会在FormClosing事件中运行处理代码。

结果是禁用ShowInTaskbar停止表单收到HWND_BROADCAST消息。我现在已经注释掉了这一行,但即便如此,我发现关闭阻塞正在发生。一旦我点击了我制作的按钮以显示表格并试图再次关闭,它就顺利完成了。

2 个答案:

答案 0 :(得分:1)

您的代码是否有消息泵?

您需要在应用程序的每个用户界面线程中使用消息泵,以便分派和处理针对您的应用程序的任何Windows消息。即使您从未在屏幕上显示表单,如果该线程是用户界面线程,仍然会发送其他系统消息需要调度和处理。

在典型的WinForms应用程序中,消息泵在此调用中......

Application.Run(new MyForm());

...仅在MyForm实例关闭后退出。在你的情况下,似乎你永远不会调用Application.Run方法或类似的东西。在这种情况下你不处理Windows消息。那么,当您没有显示表单时,您的处理循环是什么?

答案 1 :(得分:1)

我建议不要有任何形式。

只需执行一个普通的WinForms应用程序并将主窗体设置为隐藏,您就可以像往常一样使所有的消息处理工作。

附录

作为这样做的额外好处,您还可以在开发时免费获得控制台 - 通过不隐藏主窗体,您可以拥有简单的输出视图,模拟输入,触发按钮操作,各种有用东西。

附录2

以下是我通常创建隐形主窗体的方法。在表单构造函数中,添加:

if (!Debugger.IsAttached)
{
    // Prevent the window from showing up in the task bar AND when Alt-tabbing
    ShowInTaskbar = false;
    FormBorderStyle = FormBorderStyle.FixedToolWindow; 

    // Move it off-screen
    StartPosition = FormStartPosition.Manual;
    Location = new Point(SystemInformation.VirtualScreen.Right+10, SystemInformation.VirtualScreen.Bottom+10);
    Size = new System.Drawing.Size(1, 1);
}

这将在未在调试器中运行时隐藏窗口。