WPF app.xaml 退出事件不起作用
WPF app.xaml exit event not working
我不是专业的 wpf 用户所以我来这里是为了向你寻求帮助。
我想在应用程序退出但没有任何反应时更新一些数据库值。这是我的 app.xaml 代码:
<Application x:Class="pcAdmin.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:pcAdmin"
Startup="Application_Startup" Exit="Application_Exit"
>
<Application.Resources>
</Application.Resources>
</Application>
这里是 Application_Exit 方法背后的代码:
private void Application_Exit(object sender, ExitEventArgs e)
{
//just for verification
System.Windows.Forms.MessageBox.Show("apps is shutting down");
//updating DB
conDB = new MySQLConnect(this.connexion_string);
conDB.connectDB();
conDB.updateStatus("OFF", IP.mac);
conDB.disconnect();
pw.requestStop();
}
注意:- application_exit 中的所有函数都没有错误,因为它们在程序的其他部分工作正常。
- 应用程序没有 window,所以我不能使用 windows_closing 或 windows_closed 事件(但用它们尝试过并且代码有效)
我将非常感谢你的帮助。谢谢
这里是app.xaml后面代码的完整代码
public partial class App : System.Windows.Application
{
private string pData;
private string pDataPath;
private NotifyIcon nIcon;
private string connexion_string;
private string host;
private string user;
private string pwd;
private string base_sql;
private InfoPC IP;
private MySQLConnect conDB;
private IPChangeDetect ipc;
private ProcessWorker pw;
private Programme programme;
private Service services;
private List<Svc> sc;
private AV antivirus;
private Processor processor;
private void Application_Startup(object sender, StartupEventArgs e)
{
this.pData = "%ALLUSERSPROFILE%";
this.pDataPath = Environment.ExpandEnvironmentVariables(pData);
//chargement de l'icon dans la barre de tâche
nIcon = new NotifyIcon();
this.nIcon.Icon = new Icon(@"D:\sav Jerrys\pro\getInfo2.0\pcAdmin\pcAdmin\logo.ico");
nIcon.Visible = true;
nIcon.BalloonTipText = "Gathering PC info";
nIcon.BalloonTipTitle = "AEthernam";
nIcon.ShowBalloonTip(5000);
//mise à jour de l'application
getUpdated();
//obtention des paramètres de connexion à la base de donnée
recupParam();
//connexion à la base de donnée et envoi des information pendant le chargement de pcAdmin
connexion_string = "Server=" + this.host + ";Uid=" + this.user + ";password=" + this.pwd + ";database=" + this.base_sql + ";port=3306";
this.IP = new InfoPC();
IP.find_info();
conDB = new MySQLConnect(connexion_string, IP.mac, IP.ip, IP.domaine, IP.nom);
conDB.connectDB();
conDB.sendData();
//detection du changement d'ip après le chargement du logiciel
ipc = new IPChangeDetect(conDB);
ipc.detectIPChange();
conDB.disconnect();
//THread for listing process
pw = new ProcessWorker(connexion_string, IP.mac, pDataPath + @"\AEthernam\proc.bin");
Thread processThread = new Thread(pw.processWorker);
processThread.IsBackground = true;
processThread.Start();
while (!processThread.IsAlive) ;
//récupération de la liste des programmes
recupProg();
//récupération des services
recupService();
//récupération AV
recupAV();
//Recup info processeur
recupProcInfo();
//TODO:Recup info disque dur physique
recupPhyDiskInfo();
//TODO:Recup info partition
recupLogDiskInfo();
//TODO:Recup info Mémoire
recupMemoryInfo();
}
private void getUpdated()
{
// StreamWriter sw = new StreamWriter(pDataPath + "\AEthernam\aethernam.log");
Version appsVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
UpdateChecker upChecker = new UpdateChecker(appsVersion.ToString());
upChecker.checkUpdate();
//try
//{
// sw.WriteLine(upChecker.getLog);
//}
//catch(Exception ex)
//{
// this.log = "erreur ajout log dans le fichier log:\t" + ex.Message;
//}
}
private void recupParam()
{
try
{
StreamReader sr = new StreamReader(pDataPath + "\AEthernam\aethernam.cfg");
string ligne = sr.ReadLine();
this.host = ligne;
ligne = sr.ReadLine();
this.user = ligne;
ligne = sr.ReadLine();
this.pwd = ligne;
ligne = sr.ReadLine();
this.base_sql = ligne;
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
private void recupProg()
{
programme = new Programme();
List<prog> liste_programe = programme.recupProg();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
List<prog> list_pro = programme.deserialize(pDataPath + @"\AEthernam\prog.bin");
if (list_pro.Count != liste_programe.Count)
{
//mise à jour de la base des programmes
conDB.update_Prog(IP.mac, liste_programe);
conDB.disconnect();
programme.serialize(list_pro, pDataPath + @"\AEthernam\prog.bin");
}
}
else
{
conDB.sendProg(liste_programe);
conDB.disconnect();
programme.serialize(liste_programe, pDataPath + @"\AEthernam\prog.bin");
}
}
private void recupService()
{
this.services = new Service();
sc = services.getSvc();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (System.IO.File.Exists(pDataPath + @"\AEthernam\svc.bin"))
{
List<Svc> svcs = services.deserialize(pDataPath + @"\AEthernam\svc.bin");
if (svcs.Count != sc.Count)
{
//Mise à jour de la base des sevices
conDB.updateService(IP.mac, svcs);
conDB.disconnect();
services.serialize(svcs, pDataPath + @"\AEthernam\svc.bin");
}
}
else
{
//insertion des services dans la base
conDB.sendService(sc);
conDB.disconnect();
services.serialize(sc, pDataPath + @"\AEthernam\svc.bin");
}
}
private void recupAV()
{
List<AV> listAv = new List<AV>();
FindAv avInstallé = new FindAv();
ManagementObjectCollection avs = avInstallé.AvInstalled();
foreach (ManagementObject mo in avs)
{
antivirus = new AV();
antivirus.nom = mo["DisplayName"].ToString();
antivirus.etat = avInstallé.findState(mo["productState"].ToString());
listAv.Add(antivirus);
}
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
foreach (AV av in listAv)
{
conDB.sendAV(av);
conDB.disconnect();
}
}
else
{
conDB.updateAV(IP.mac, listAv);
conDB.disconnect();
}
}
private void recupMemoryInfo()
{
List<Ram> liste_ram = new List<Ram>();
liste_ram = new RamInfo().getRams();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendRam(liste_ram);
conDB.disconnect();
}
else
{
conDB.updateRam(IP.mac, liste_ram);
conDB.disconnect();
}
}
private void recupPhyDiskInfo()
{
List<DisquePhysique> liste_pdisk = new List<DisquePhysique>();
liste_pdisk = new PhysicalDiskInfo().getPDisk();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendPhydisque(liste_pdisk);
conDB.disconnect();
}
else
{
conDB.updatePhydisque(IP.mac, liste_pdisk);
conDB.disconnect();
}
}
private void recupLogDiskInfo()
{
List<LogicalDisk> liste_ldisk = new List<LogicalDisk>();
liste_ldisk = new LogicalDiskInfo().getPartition();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendLdisque(liste_ldisk);
conDB.disconnect();
}
else
{
conDB.updateLdisque(IP.mac, liste_ldisk);
conDB.disconnect();
}
}
private void recupProcInfo()
{
processor = new Processor();
ProcessorInfo pInfo = new ProcessorInfo();
processor = pInfo.getInfo();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendProcessor(processor);
conDB.disconnect();
}
else
{
conDB.updateProcessor(IP.mac, processor);
conDB.disconnect();
}
}
private void Application_Exit(object sender, ExitEventArgs e)
{
System.Windows.Forms.MessageBox.Show("apps is shutting down");
conDB = new MySQLConnect(this.connexion_string);
conDB.connectDB();
conDB.updateStatus("OFF", IP.mac);
conDB.disconnect();
pw.requestStop();
}
}
我感觉问题与您的线程有关。如果它是 foreground thread,它不允许应用程序退出,直到它是 运行。并且由于您试图在 Exit_Application 方法中停止它,所以这永远不会发生。
尝试在创建线程的地方设置。
pw.IsBackground = true;
如果您使用 new Thread() 创建它,它始终默认为前台线程。
更新:
由于应用程序是从任务管理器中关闭的,所以进程会被 windows 杀死,并且无法在关闭前执行某些代码。检查此 answer 以获取涉及 DB 的解决方法。
或者您至少需要一些 UI 或托盘图标,这将允许您在单击某些按钮时优雅地关闭应用程序。
要优雅地关闭应用程序,您可以使用之前的建议:
Application.Current.Shutdown();
只需执行以下操作:
private void Application_Startup(object sender, StartupEventArgs e)
{
//your current code
Application.Current.Shutdown();
}
这应该触发应用程序的 Exit 方法和 运行 application_exit();
中的代码
谢谢大家的回答和帮助,我会将@3615 的回答作为我可以接受的解决方案。我会找到一些方法来查看用户是否终止了进程,然后相应地更新我的数据库
我不是专业的 wpf 用户所以我来这里是为了向你寻求帮助。 我想在应用程序退出但没有任何反应时更新一些数据库值。这是我的 app.xaml 代码:
<Application x:Class="pcAdmin.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:pcAdmin"
Startup="Application_Startup" Exit="Application_Exit"
>
<Application.Resources>
</Application.Resources>
</Application>
这里是 Application_Exit 方法背后的代码:
private void Application_Exit(object sender, ExitEventArgs e)
{
//just for verification
System.Windows.Forms.MessageBox.Show("apps is shutting down");
//updating DB
conDB = new MySQLConnect(this.connexion_string);
conDB.connectDB();
conDB.updateStatus("OFF", IP.mac);
conDB.disconnect();
pw.requestStop();
}
注意:- application_exit 中的所有函数都没有错误,因为它们在程序的其他部分工作正常。 - 应用程序没有 window,所以我不能使用 windows_closing 或 windows_closed 事件(但用它们尝试过并且代码有效) 我将非常感谢你的帮助。谢谢
这里是app.xaml后面代码的完整代码
public partial class App : System.Windows.Application
{
private string pData;
private string pDataPath;
private NotifyIcon nIcon;
private string connexion_string;
private string host;
private string user;
private string pwd;
private string base_sql;
private InfoPC IP;
private MySQLConnect conDB;
private IPChangeDetect ipc;
private ProcessWorker pw;
private Programme programme;
private Service services;
private List<Svc> sc;
private AV antivirus;
private Processor processor;
private void Application_Startup(object sender, StartupEventArgs e)
{
this.pData = "%ALLUSERSPROFILE%";
this.pDataPath = Environment.ExpandEnvironmentVariables(pData);
//chargement de l'icon dans la barre de tâche
nIcon = new NotifyIcon();
this.nIcon.Icon = new Icon(@"D:\sav Jerrys\pro\getInfo2.0\pcAdmin\pcAdmin\logo.ico");
nIcon.Visible = true;
nIcon.BalloonTipText = "Gathering PC info";
nIcon.BalloonTipTitle = "AEthernam";
nIcon.ShowBalloonTip(5000);
//mise à jour de l'application
getUpdated();
//obtention des paramètres de connexion à la base de donnée
recupParam();
//connexion à la base de donnée et envoi des information pendant le chargement de pcAdmin
connexion_string = "Server=" + this.host + ";Uid=" + this.user + ";password=" + this.pwd + ";database=" + this.base_sql + ";port=3306";
this.IP = new InfoPC();
IP.find_info();
conDB = new MySQLConnect(connexion_string, IP.mac, IP.ip, IP.domaine, IP.nom);
conDB.connectDB();
conDB.sendData();
//detection du changement d'ip après le chargement du logiciel
ipc = new IPChangeDetect(conDB);
ipc.detectIPChange();
conDB.disconnect();
//THread for listing process
pw = new ProcessWorker(connexion_string, IP.mac, pDataPath + @"\AEthernam\proc.bin");
Thread processThread = new Thread(pw.processWorker);
processThread.IsBackground = true;
processThread.Start();
while (!processThread.IsAlive) ;
//récupération de la liste des programmes
recupProg();
//récupération des services
recupService();
//récupération AV
recupAV();
//Recup info processeur
recupProcInfo();
//TODO:Recup info disque dur physique
recupPhyDiskInfo();
//TODO:Recup info partition
recupLogDiskInfo();
//TODO:Recup info Mémoire
recupMemoryInfo();
}
private void getUpdated()
{
// StreamWriter sw = new StreamWriter(pDataPath + "\AEthernam\aethernam.log");
Version appsVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
UpdateChecker upChecker = new UpdateChecker(appsVersion.ToString());
upChecker.checkUpdate();
//try
//{
// sw.WriteLine(upChecker.getLog);
//}
//catch(Exception ex)
//{
// this.log = "erreur ajout log dans le fichier log:\t" + ex.Message;
//}
}
private void recupParam()
{
try
{
StreamReader sr = new StreamReader(pDataPath + "\AEthernam\aethernam.cfg");
string ligne = sr.ReadLine();
this.host = ligne;
ligne = sr.ReadLine();
this.user = ligne;
ligne = sr.ReadLine();
this.pwd = ligne;
ligne = sr.ReadLine();
this.base_sql = ligne;
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
private void recupProg()
{
programme = new Programme();
List<prog> liste_programe = programme.recupProg();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
List<prog> list_pro = programme.deserialize(pDataPath + @"\AEthernam\prog.bin");
if (list_pro.Count != liste_programe.Count)
{
//mise à jour de la base des programmes
conDB.update_Prog(IP.mac, liste_programe);
conDB.disconnect();
programme.serialize(list_pro, pDataPath + @"\AEthernam\prog.bin");
}
}
else
{
conDB.sendProg(liste_programe);
conDB.disconnect();
programme.serialize(liste_programe, pDataPath + @"\AEthernam\prog.bin");
}
}
private void recupService()
{
this.services = new Service();
sc = services.getSvc();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (System.IO.File.Exists(pDataPath + @"\AEthernam\svc.bin"))
{
List<Svc> svcs = services.deserialize(pDataPath + @"\AEthernam\svc.bin");
if (svcs.Count != sc.Count)
{
//Mise à jour de la base des sevices
conDB.updateService(IP.mac, svcs);
conDB.disconnect();
services.serialize(svcs, pDataPath + @"\AEthernam\svc.bin");
}
}
else
{
//insertion des services dans la base
conDB.sendService(sc);
conDB.disconnect();
services.serialize(sc, pDataPath + @"\AEthernam\svc.bin");
}
}
private void recupAV()
{
List<AV> listAv = new List<AV>();
FindAv avInstallé = new FindAv();
ManagementObjectCollection avs = avInstallé.AvInstalled();
foreach (ManagementObject mo in avs)
{
antivirus = new AV();
antivirus.nom = mo["DisplayName"].ToString();
antivirus.etat = avInstallé.findState(mo["productState"].ToString());
listAv.Add(antivirus);
}
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
foreach (AV av in listAv)
{
conDB.sendAV(av);
conDB.disconnect();
}
}
else
{
conDB.updateAV(IP.mac, listAv);
conDB.disconnect();
}
}
private void recupMemoryInfo()
{
List<Ram> liste_ram = new List<Ram>();
liste_ram = new RamInfo().getRams();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendRam(liste_ram);
conDB.disconnect();
}
else
{
conDB.updateRam(IP.mac, liste_ram);
conDB.disconnect();
}
}
private void recupPhyDiskInfo()
{
List<DisquePhysique> liste_pdisk = new List<DisquePhysique>();
liste_pdisk = new PhysicalDiskInfo().getPDisk();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendPhydisque(liste_pdisk);
conDB.disconnect();
}
else
{
conDB.updatePhydisque(IP.mac, liste_pdisk);
conDB.disconnect();
}
}
private void recupLogDiskInfo()
{
List<LogicalDisk> liste_ldisk = new List<LogicalDisk>();
liste_ldisk = new LogicalDiskInfo().getPartition();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendLdisque(liste_ldisk);
conDB.disconnect();
}
else
{
conDB.updateLdisque(IP.mac, liste_ldisk);
conDB.disconnect();
}
}
private void recupProcInfo()
{
processor = new Processor();
ProcessorInfo pInfo = new ProcessorInfo();
processor = pInfo.getInfo();
conDB = new MySQLConnect(connexion_string, IP.mac);
conDB.connectDB();
if (!System.IO.File.Exists(pDataPath + @"\AEthernam\prog.bin"))
{
conDB.sendProcessor(processor);
conDB.disconnect();
}
else
{
conDB.updateProcessor(IP.mac, processor);
conDB.disconnect();
}
}
private void Application_Exit(object sender, ExitEventArgs e)
{
System.Windows.Forms.MessageBox.Show("apps is shutting down");
conDB = new MySQLConnect(this.connexion_string);
conDB.connectDB();
conDB.updateStatus("OFF", IP.mac);
conDB.disconnect();
pw.requestStop();
}
}
我感觉问题与您的线程有关。如果它是 foreground thread,它不允许应用程序退出,直到它是 运行。并且由于您试图在 Exit_Application 方法中停止它,所以这永远不会发生。 尝试在创建线程的地方设置。
pw.IsBackground = true;
如果您使用 new Thread() 创建它,它始终默认为前台线程。
更新:
由于应用程序是从任务管理器中关闭的,所以进程会被 windows 杀死,并且无法在关闭前执行某些代码。检查此 answer 以获取涉及 DB 的解决方法。 或者您至少需要一些 UI 或托盘图标,这将允许您在单击某些按钮时优雅地关闭应用程序。 要优雅地关闭应用程序,您可以使用之前的建议:
Application.Current.Shutdown();
只需执行以下操作:
private void Application_Startup(object sender, StartupEventArgs e)
{
//your current code
Application.Current.Shutdown();
}
这应该触发应用程序的 Exit 方法和 运行 application_exit();
中的代码谢谢大家的回答和帮助,我会将@3615 的回答作为我可以接受的解决方案。我会找到一些方法来查看用户是否终止了进程,然后相应地更新我的数据库