2012-12-15 3 views
-1

제 코드에 나와 있습니다. 응용 프로그램이 수동으로 닫히지 않을 경우에 대비하여 세션이 끝날 때 내 app 데이터를 저장하는 것으로 win32.systemevents.sessionended 이벤트를 catch하려고 시도합니다. 시간이 전에 일하고있다 그리고 이제는 내 프로젝트가 더 이상되지 않습니다 릴 성장했다 ..? 나는 며칠 동안 무언가 의미있는 것을 찾으려고 노력했지만 아무 것도 발견하지 못했습니다. MonitorResolutionChanged와 같은 또 다른 systemevent를 잡으려고 할 때 잘 작동하지만이 것은 아닙니다. 나는 또한 mainWindow (응용 프로그램 양식 ..), 아무것도 등록하려고했는데 :-(제발 어떤 생각이 있니? 나는 모든 관련 정보가 처음부터 무효 메인까지 있어야한다고 생각하지만 당신이 필요하거나 많은 토마스 내 코드 고맙습니다 .. 더보고 싶어 : A의systemevents.sessionended가 잡히지 않았거나 해고 당하지 않았습니다.

protected override void OnShutdown() 
{ 
    //your code here 
    base.OnShutdown(); 
} 

:

여기
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

는, 종료를 들어

을 시도 OnShutdown 메서드를 재정의 수있는 일입니다 로그 오프 :

첫째, 서비스 생성자에 Microsoft.Win32.SystemEvents.SessionEnded에 이벤트 처리기를 추가 :

void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e) 
{ 
    //your code here 
} 

이것은 어떤 종단 세션을 잡을 포함한다 :

public MyService() 
{ 
    InitializeComponent; 
    Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded); 
} 

가 그런 다음 처리기를 추가 콘솔 자체 (서비스를 실행하는 콘솔).

+0

Thanx Dj Kraze, me also dj (Spejbl). 어쨌든. 귀하의 대답은 servis와 관련된 것 같지만 내 코드는 Windows.Forms 응용 프로그램입니다. 내 양식 작성자 내에서 제안한 것과 동일한 것을 시도한 적이 많습니다. InicializeComponent 호출 전에 처리기를 등록하는 차이점이 될 수 있습니까? 추측하기 전에 내가 어디에 넣었는지 확실하지 않다. 어쨌든 내 릴은 모든 창을 멈추게한다. ..? – user1906564

+0

나는'OnShutdown'이 ['ServiceBase.OnShutdown'을 가리킨다 고 생각합니다. (https://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.onshutdown (v = vs.110) .aspx). – jrh

2

확인. 그래서 여기 잡기와 해결책이 있습니다. Windows에서는 win32.systemevents.sessionended가 실행되어야하는지 또는 form.close()가 운영 체제에서 먼저 호출되는지 여부는 결정되지 않습니다. 또한 form.close()가 먼저 호출되면 양식이 닫히지 않고 닫는 프로세스가 취소 되어도 세션이 끝난 상태가 생략됩니다. 내 시스템에서이 동작은 일부 레지스트리 청소 소프트웨어를 실행 한 후에 변경되었습니다. 어쨌든 이것을 이해하면 가능한 시나리오를 모두 처리해야합니다. 우리의 요구에 맞는 어떤 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()를 오버라이드 (override)

또는 시스템에 의해, loging를 등 아래 shuting 때 또는 주 form.Closing에 대한 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(); 
       } 
      } 

그냥 메시지 펌프가 상승 할 sessionended하기 위해 runnig해야 언급하고자합니다. Application.run()이이를 수행합니다.

내 경우에는 내가 더 깊게 파고 야했다는 것을 알 수 있습니다. 앱을 숨기지 않고 리디렉션 만하면 닫을 수 있습니다. (단지 알림 아이콘에 앱을 숨기고 필요할 때 수동으로 닫습니다.) 그래서 나는 발신자가 unfortunatelly이고 예기치 않게 항상 이것 때문에 ..라고 불릴 때 어떤 상황을 지정하는 방법을 사용해야했다. 이것은 WndProc을 오버라이드하고 프로퍼티 메시지를 잡아서 수행됩니다. 윈도우 내부의 모든 것들 (예 : 디스크 삽입/제거)을들을 수 있지만 양식에만 푹 붙어서 구현이 정의되는 경우가 종종 있습니다. 다양한 값과 구조체를 비교하고 그 값과 비교합니다.다른 그는 아주 간단합니다 :

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

시스템으로 아마 항상 mainForm.close()하지만 난 전화를 시도해야 조금 더 우리가 가능한 점 하나를 생략 할 수 있습니다 생각 그것을 다시 다른 순서로 그 물건을 실행하면 나는 윈도우의 행동에 대해 확신 할 수 없어 계속 ... 또한 시스템에 반응에 대한 주로 제안 솔루션입니다 ..

이것은 누군가에게 도움이되기를 바랍니다. 프라하 tomas에서 인사드립니다

+0

옵션 2가 유용합니다. 문제가 해결되었습니다. 양식 닫기 이벤트에서 세션 별 이벤트를 병합했습니다. – Vijayaraghavan

관련 문제