请在我的代码中尝试捕获win32.systemevents.sessionended事件,以便在会话结束时保存我的应用数据以防应用程序未手动关闭..前一段时间这已经工作了,现在我让我的项目增长了一点,它不再是......?我试图找到一些有意义的东西几天但没有发现任何真正的...当我试图捕捉另一个像MonitorResolutionChanged这样的系统时,它运作良好,但这不是。我也尝试在mainWindow(app形式..)中注册,没有:-(请知道吗? 我认为所有相关信息应该在开头直到无效主要但我把它放在一起以防你需要或想要看到更多.. Thanx很多Tomas 我的代码:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using MovablePython; // my own class within this project
using Avn; //my own referenced assembly
namespace DirDist
{
class Program
{
private static string appGuid = "Cddbserviceman";
private static System.Windows.Forms.ContextMenu nIMenu;
internal static System.Windows.Forms.NotifyIcon notifyIcon1;
private static MenuItem showItem;
public static MenuItem justCDsItem;
private static MenuItem searchItem;
private static MenuItem settingsItem;
private static MenuItem quitItem;
internal static Form1 mainWindow;
private static Hotkey hk;
internal static Registration.LicenceState mode; // app mode - registered/trial/blocked/demaged ..
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid))
{
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("CDDB is already running on your machine \n (Check status bar for access ..)");
return;
}
GC.Collect();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
mode = Registration.Startup();
Program.mainWindow = new Form1();
mainWindow.Activate();
//mainWindow.Validate();
//mainWindow.Update();
mainWindow.Visible = false;
PutIcon();
//Microsoft.Win32.SystemEvents.SessionEnded += SystemEvents_SessionEnded;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);//**zkousime zda funguje pro hibernaci ..
RegisterHotKey(true);
Application.Run();
}
}
static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//MessageBox.Show("SessionEnded fired");
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
mainWindow.Close();
}
// zaregistruje globalni hotkey ctrl+shift+F Pro hledani
private static void RegisterHotKey(bool active)
{
if (!active)
{
if (hk != null) hk.Unregister();
}
else
{
if(hk ==null) hk = new Hotkey();
hk.KeyCode = Keys.F;
//hk.Windows = true;
hk.Shift = true;
hk.Control = true;
//hk.Pressed += delegate { Console.WriteLine("Windows+1 pressed!"); };
hk.Pressed += delegate { searchItemClick(new object(), new EventArgs()); };
if (hk.GetCanRegister(mainWindow)) hk.Register(mainWindow);
else ; // just do nothing
}
}
private static void PutIcon()
{
if (notifyIcon1 == null)
{
showItem = new MenuItem ("&Show interface", new System.EventHandler (showInfaceClick));
justCDsItem = new MenuItem ("&Jus'CDs",new System.EventHandler ( justCDsClick));
justCDsItem.Checked = Form1.settings.justCDs;
searchItem = new MenuItem("Search CDDB",new System.EventHandler (searchItemClick));
searchItem.Shortcut = Shortcut.CtrlShiftF;
searchItem.ShowShortcut = true;
settingsItem = new MenuItem("Settings", new System.EventHandler(settingsItemClick));
quitItem = new MenuItem("&Quit", new System.EventHandler(quitItemClick));
nIMenu = new System.Windows.Forms.ContextMenu(new MenuItem[5] { showItem, justCDsItem, searchItem,settingsItem, quitItem });
notifyIcon1 = new System.Windows.Forms.NotifyIcon();
notifyIcon1.ContextMenu = nIMenu;
notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(
//System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase ) + "Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon("Icon1.ico");
notifyIcon1.DoubleClick += new EventHandler(notifyIcon1_DoubleClick);
notifyIcon1.Visible = true;
}
}
/* private static void notifyIcon1_MouseMove(object sender, MouseEventArgs mea)
* aby to fungovalo je treba upravit contextmenu na contextmenustrip a taky ty items .. az nakonec
* je tu kolem uz rozdelana priprava ..
{
notifyIcon1.ShowBalloonTip(2000,AppName,"Active",ToolTipIcon.None);
} */
// clicks on NotificationIcon context menu ..
private static void showInfaceClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 0;
mainWindow.Show();
}
private static void justCDsClick(object sender, EventArgs e)
{
Form1.settings.justCDs = mainWindow.checkBox1.Checked = justCDsItem.Checked = !Form1.settings.justCDs;
if (mainWindow.Visible) mainWindow.Update();
}
private static void searchItemClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 1 ;
//this.Size = new Size(this.Width, SystemInformation.PrimaryMonitorSize.Height);
mainWindow.Location = new System.Drawing.Point(SystemInformation.PrimaryMonitorSize.Width - mainWindow.Width, SystemInformation.PrimaryMonitorSize.Height - mainWindow.Height);
//mainWindow.Location = new System.Drawing.Point(880, 500);
mainWindow.Show();
}
private static void settingsItemClick(object sender, EventArgs e)
{
mainWindow.tabPage3_GotFocus(new Object(), new EventArgs());
mainWindow.tabControl1.SelectedIndex = 2;
mainWindow.Show();
}
public static void quitItemClick(object sender, EventArgs e)
{
if (DialogResult.Cancel == MessageBox.Show("Really exit application and stop scanning?",Form1.AppName,MessageBoxButtons.OKCancel,MessageBoxIcon.Question)) return;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
//if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
if (Form1.settings.fileIndex) mainWindow.SaveIndex(Form1.settings.indexPath);
mainWindow.Close();
mainWindow = null;
notifyIcon1.Visible = false;
Application.Exit();
}
static void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
//throw new NotImplementedException();
//if (!mainWindow.Visible) mainWindow.WindowState = FormWindowState.Normal; else mainWindow.WindowState = FormWindowState.Minimized;
//if (!mainWindow.Visible) mainWindow.Show(); else mainWindow.Hide();
if (!mainWindow.Visible) mainWindow.Visible = true; else mainWindow.Visible = false;
}
}
}
答案 0 :(得分:2)
行。所以这是捕获和解决方案。在Windows中,不确定是否应该升级win32.systemevents.sessionended,否则将首先由操作系统调用form.close()。此外,似乎如果首先调用form.close(),则会省略sessionended,即使由于取消关闭过程而没有关闭和处理表单。在我运行一些注册表清理软件后,我的系统中此行为发生了变化无论如何理解这一点,我们必须处理两种可能的情况。 1.抓住win32.systemevents.sessionended(或sessionending)事件,更好地满足我们的需求
.
.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
Program.mainWindow = new Form1();
mainWindow.Activate();
mainWindow.Visible = false;
PutIcon();
RegisterHotKey(true);
Application.Run();
}
}
public static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
// do whatever needed and exit application ..
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
if (mainWindow != null)
{
mainWindow.Dispose();
mainWindow = null;
}
Application.Exit();
}
2。正确覆盖form.OnClosing(),因为当窗体关闭时,用户或系统在关闭,关闭等时手动关闭或者为主窗体创建hanler时调用它。关闭:
public Form1()
{
this.Closing += new CancelEventHandler(this.Form1_Closing);
InitializeComponent();
}
private void Form1_Closing(Object sender, CancelEventArgs e)
{
if (systemShutdown) Program.SystemEvents_SessionEnded(this, new Microsoft.Win32.SessionEndedEventArgs(Microsoft.Win32.SessionEndReasons.SystemShutdown));
else
{
e.Cancel = true;
this.Hide();
}
}
只是想提一下,消息泵必须运行才能使会话升级。 Application.run()完成了。
在我的情况下你可以看到我必须深入挖掘,因为我关闭重定向只是为了隐藏应用程序不要关闭它(我只是隐藏应用程序通知irea图标并在我需要时手动关闭..)因此我必须使用某种方式来指定调用此情况的原因,因为发送者不幸且意外地总是这样......? 这是通过覆盖WndProc和捕获propper消息来完成的。你可以在窗口内的所有内容(如插入/删除的光盘)中聆听,但它只挂钩到一个表单,并且实现通常不那么简单,因为你必须手动定义各种值和结构并与这些值进行比较..除此之外它非常简单:
private static int WM_QUERYENDSESSION = 0x11;
private static bool systemShutdown = false;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg==WM_QUERYENDSESSION)
{
systemShutdown = true;
}
base.WndProc(ref m);
}
这是在这里找到的: http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending.aspx
进一步思考我们可以省略第1点,因为系统可能总是尝试调用mainForm.close(),但我保留它,因为一旦它以不同的顺序再次运行那些东西,我无法确定它的行为。并且它是主要建议的解决方案,以响应系统关闭..
希望这对某人有帮助。来自布拉格tomas的问候
答案 1 :(得分:1)
这是你可以尝试的东西
对于关机,请覆盖OnShutdown方法:
protected override void OnShutdown()
{
//your code here
base.OnShutdown();
}
注销:
首先,在Service Constructor中向Microsoft.Win32.SystemEvents.SessionEnded添加一个事件处理程序:
public MyService()
{
InitializeComponent;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
}
然后添加处理程序:
void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//your code here
}
这应该捕获任何已结束的会话,包括控制台本身(运行服务的那个)。