Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.01.2012, 06:45   #1
Tolias
Пользователь
 
Регистрация: 18.08.2010
Сообщений: 41
По умолчанию Как перехватить закрытие Windows-приложения без формы?

Я на C# создал приложение, выбрав проект WindowsForms. Но так как моя программа не должна иметь никаких окон, я удалил Form1.cs, а код своей программы поместил в функции Main() типа так:
PHP код:
static void Main()
{
     
FileSystemWatcher watcher = new FileSystemWatcher();
     
watcher.Path "C:\\";
     
watcher.NotifyFilter NotifyFilters.LastAccess;
     
watcher.Changed += new FileSystemEventHandler(OnChanged);
     
watcher.Created += new FileSystemEventHandler(OnChanged);
     
watcher.Deleted += new FileSystemEventHandler(OnChanged);
     
watcher.Renamed += new RenamedEventHandler(OnRenamed);
            
     
Application.SetCompatibleTextRenderingDefault(false);
     
Application.Run();

после Мейна идут фукнции-обработчики событий, который пишут все в текстовый файл.
Мне надо так сделать, чтобы при выключении компьютера, когда система посылает всем программам команду закрыться, чтобы в этот момент моя программа перед своим закрытием сбрасывала содержимое всех буферов файлового потока в файл (то есть, выполнялась функция Flush()), а то сейчас получается неприятная ситуация, что мое приложение виндой убивается, и все данные, что должны были записаться в файл, но остались в буфере файлового потока, так и пропадают, не записавшись в файл.

Как перехватить закрытие приложения?

P.S. Как перехвачивать закрытие приложения с формой, я знаю. Но просто в моем приложении нет формы...
Tolias вне форума Ответить с цитированием
Старый 25.01.2012, 09:42   #2
Guy
Форумчанин
 
Регистрация: 15.12.2010
Сообщений: 398
По умолчанию

Код:
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
Guy вне форума Ответить с цитированием
Старый 25.01.2012, 13:48   #3
Hollander
Участник клуба
 
Аватар для Hollander
 
Регистрация: 03.05.2007
Сообщений: 1,189
По умолчанию

Я бы сохранял после каждой записи, т.к. есть еще экстренное закрытие программы, т.е. просто убить процесс.
Hollander вне форума Ответить с цитированием
Старый 25.01.2012, 14:21   #4
Guy
Форумчанин
 
Регистрация: 15.12.2010
Сообщений: 398
По умолчанию

Правильно говорит, а закрывать поток только в Application_ApplicationExit
Guy вне форума Ответить с цитированием
Старый 26.01.2012, 02:50   #5
Tolias
Пользователь
 
Регистрация: 18.08.2010
Сообщений: 41
По умолчанию

Цитата:
Сообщение от Hollander Посмотреть сообщение
Я бы сохранял после каждой записи, т.к. есть еще экстренное закрытие программы, т.е. просто убить процесс.
После каждой записи записывать файл сильно повышает ресусоемкость приложения, так как иногда файл может очень часто записываться. Я из этой ситуации вышел по другому - сбрасывал буфер потока раз в минуту.
Но кроме этого нужно еще сбросить его перед закрытием процесса, над чем я сейчас и борюсь..
Tolias вне форума Ответить с цитированием
Старый 26.01.2012, 02:51   #6
Tolias
Пользователь
 
Регистрация: 18.08.2010
Сообщений: 41
По умолчанию

Цитата:
Сообщение от Guy Посмотреть сообщение
Код:
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
В том то и дело, что событие ApplicationExit почему то не происходит..
Я также пробовал подписываться на другие события, такие как Application.ThreadExit и AppDomain.CurrentDomain.ProcessExit , но ни то ни другое событие не происходит при закрытии приложения виндой. Уже надоело из-за этих тестов комп перезагружать... А как можно еще послать команду приложению закрыться, чтобы компьютер перезагрузками не мучать? Я для тестов написал вот такое приложение для послания команды закрыться:
PHP код:
private void buttonRun_Click(object senderEventArgs e)
{
    
processPath "F:\\Projects\\C#\\Test\\FSEvents\\FSEvents\\bin\\Debug\\FSEvents.exe";
    
this.process System.Diagnostics.Process.Start(processPath);
}
        
private 
void buttonExit_Click(object senderEventArgs e)
{
    
process.CloseMainWindow();

но оно не закрывает приложение FSEvents.exe
Если я для примера напишу в processPath "notepad.exe", то он кнопкой Run запускается и кнопкой Exit закрывается. А если FSEvents.exe написать, то открывать он его открывает, а кнопка Exit не действует на него никак =-O То есть, приложение FSEvents.exe продолжает работать.

Последний раз редактировалось Tolias; 26.01.2012 в 02:54.
Tolias вне форума Ответить с цитированием
Старый 26.01.2012, 02:55   #7
Tolias
Пользователь
 
Регистрация: 18.08.2010
Сообщений: 41
По умолчанию

Вот полный код моего приложения FSEvents. Может я где-то и накрутил, из-за того и не работает событие... Покажите пожалуйста.
PHP код:
using System;
using System.Windows.Forms;
using System.IO;

namespace 
FSEvents
{
    static class 
Program
    
{
        public static 
StreamWriter flog;
        public static 
string fileLogName "history.txt";
        public static 
string fileSettingsName "settings.ini";
        public static 
DateTime dt DateTime.Now;
        public static 
DateTime dtNow;

        
/// <summary>
        /// The main entry point for the application.
        /// </summary>
        
[STAThread]
        static 
void Main()
        {
            
flog = new StreamWriter(fileLogNametrue);
            
flog.WriteLine("{0} FS START"dt);
            
StreamReader fileSettings;
            try
            {
                
fileSettings = new StreamReader(fileSettingsName);
            }
            catch (
Exception e)
            {
                
flog.WriteLine("{0} ERROR. {1}"DateTime.Nowe.Message);
                
flog.Close();
                return;
            }

            
string nameDrives fileSettings.ReadLine(); ////
            
if (nameDrives == null)
            {
                
flog.WriteLine("{0} ERROR. File '{1}' not have drive letters"DateTime.NowfileSettingsName);
                
flog.Close();
                return;
            }
            
int numberDrives nameDrives.Length;
            
FileSystemWatcher[] fsw = new FileSystemWatcher[numberDrives];
            
//  Create a FileSystemWatcher to monitor all files on drives.
            
for (int i 0numberDrivesi++)
            {
                try
                {
                    
fsw[i] = new FileSystemWatcher(nameDrives[i] + ":\\");

                    
//  Watch for changes in LastAccess and LastWrite times, and
                    //  the renaming of files or directories. 
                    
fsw[i].NotifyFilter NotifyFilters.LastAccess NotifyFilters.LastWrite
                        
NotifyFilters.FileName NotifyFilters.DirectoryName;

                    
//  Register a handler that gets called when a 
                    //  file is created, changed, or deleted.
                    
fsw[i].Changed += new FileSystemEventHandler(OnChanged);

                    
fsw[i].Created += new FileSystemEventHandler(OnChanged);

                    
fsw[i].Deleted += new FileSystemEventHandler(OnChanged);

                    
//  Register a handler that gets called when a file is renamed.
                    
fsw[i].Renamed += new RenamedEventHandler(OnRenamed);

                    
//  Register a handler that gets called if the 
                    //  FileSystemWatcher needs to report an error.
                    
fsw[i].Error += new ErrorEventHandler(OnError);

                    
//  Begin watching.
                    
fsw[i].EnableRaisingEvents true;
                }
                catch (
Exception e)
                {
                    
flog.WriteLine("{0} ERROR. {1}"DateTime.Nowe.Message);
                }
            }
            
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
            
Application.ThreadExit += new EventHandler(Application_ApplicationExit);
            
AppDomain.CurrentDomain.ProcessExit += new EventHandler(Application_ApplicationExit);  
            
Application.SetCompatibleTextRenderingDefault(false);
            
Application.Run();
        }

        
//  This method is called when a file is created, changed, or deleted.
        
private static void OnChanged(object sourceFileSystemEventArgs e)
        {
            
//  Show that a file has been created, changed, or deleted.
            
dtNow DateTime.Now;
            
WatcherChangeTypes wct e.ChangeType;
            try
            {
                
flog.WriteLine("{2} \"{0}\" {1}"e.FullPathwct.ToString(), dtNow);
            }
            catch
            {
                return;
            }
            
ForceFlush();
        }

        
//  This method is called when a file is renamed.
        
private static void OnRenamed(object sourceRenamedEventArgs e)
        {
            
//  Show that a file has been renamed.
            
dtNow DateTime.Now;
            
WatcherChangeTypes wct e.ChangeType;
            try
            {
                
flog.WriteLine("{3} \"{0}\" {2} to \"{1}\""e.OldFullPathe.FullPathwct.ToString(), dtNow);
            }
            catch
            {
                return;
            }
            
ForceFlush();
        } 
продолжение кода в следующем посте... Пришлось разделить из-за ограмничения на форуме в 5000 символов
Tolias вне форума Ответить с цитированием
Старый 26.01.2012, 02:56   #8
Tolias
Пользователь
 
Регистрация: 18.08.2010
Сообщений: 41
По умолчанию

PHP код:
        //  This method is called when the FileSystemWatcher detects an error.
        
private static void OnError(object sourceErrorEventArgs e)
        {
            
//  Show that an error has been detected.
            
dtNow DateTime.Now;
            
flog.WriteLine("{0} The FileSystemWatcher has detected an error"dtNow);
            
//  Give more information if the error is due to an internal buffer overflow.
            
if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
            {
                
//  This can happen if Windows is reporting many file system events quickly 
                //  and internal buffer of the  FileSystemWatcher is not large enough to handle this
                //  rate of events. The InternalBufferOverflowException error informs the application
                //  that some of the file system events are being lost.
                
flog.WriteLine(("{0} The file system watcher experienced an internal buffer overflow: " e.GetException().Message), dtNow);
            }
            
ForceFlush();
        }

        private static 
void ForceFlush()
        {
            if (
dtNow.Minute != dt.Minute)
                
flog.Flush();
            
dt dtNow;
        }

        private static 
void Application_ApplicationExit(object senderEventArgs e)
        {
            
MessageBox.Show("ApplicationExit"); //for tests... delete after tests
            
flog.WriteLine("{0} FS EXIT"DateTime.Now);
            
flog.Close();
        }
    }

Tolias вне форума Ответить с цитированием
Старый 26.01.2012, 09:59   #9
Guy
Форумчанин
 
Регистрация: 15.12.2010
Сообщений: 398
По умолчанию

Может так поможет, проверить нету возможности
Код:
namespace RTCChecker
{
    class Program : Form
    {
        private delegate void VoidDelegate();
        static void Main(string[] args)
        {
            Catcher c = new Catcher();
            c.OnWindowsExit += c_OnWindowsExit;
            Thread th = new Thread(new ThreadStart((VoidDelegate)delegate
            {
                c.Show();
                c.Hide();
            }));
            th.Start();

            //Твой код
            
        }

        //При закрытии Window
        static void c_OnWindowsExit()
        {
            //Flush потоков
        }
    }

    class Catcher : Form
    {
        public delegate void VoidDelegate();
        public event VoidDelegate OnWindowsExit;
        protected override void WndProc(ref Message m)
        {
            //0x0016 - из гугля. Возможно другой сообщение но этот должно работать проверь
            if (m.Msg == 0x0016)
            {
                if (OnWindowsExit != null)
                {
                    OnWindowsExit();
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }
    }
}
Guy вне форума Ответить с цитированием
Старый 27.01.2012, 05:14   #10
Tolias
Пользователь
 
Регистрация: 18.08.2010
Сообщений: 41
По умолчанию

Guy, спасибо. Но по прежнему не срабатывает. Я кажется понял, что проблема вовсе не в моем приложении. Потому что я даже отсюда брал пример, переделал его для одной формы и если послать ему команду закрыться из другого приложения, событие ApplicationExit срабатывает и приложение сбрасывает все буферы потоков (то есть, все пучком). Но стоит мне это приложение оставить открытым и выключить компьютер, как оно просто завершается без всяких событий ApplicationExit. По ходу, как я понял, винда нагло убивает приложения, не дожидаясь их нормально выключения и рыть мне надо настройки винды, а не исходники своего приложения. Наверное я буду привязываться к другому событию - изменения питания. Оно то точно происходит при выключении, уже проверял.
Tolias вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как перехватить нажатие клавиш в Windows? JoanM Win Api 15 31.05.2013 14:42
Как перехватить событие формы (Движение) ImmortalAlexSan Общие вопросы Delphi 12 02.01.2011 11:36
как определить закрытие приложения Анастасия123456789 Помощь студентам 3 02.05.2009 16:32
как подождать о определить закрытие приложения Анастасия123456789 Общие вопросы Delphi 1 02.05.2009 16:30
Как перехватить нажатие клавиши Windows? UnD)eaD)Snake Win Api 3 16.03.2009 18:21