从批处理文件启动WPF应用时mainWindow_Closing事件失效
问题分析与解决方案
你遇到的崩溃问题,核心原因是程序运行时的工作目录不一致,导致找不到meme.mp4文件,进而触发未处理的异常打断了mainWindow_Closing事件的执行。
具体原因拆解:
- 直接双击exe时,程序的工作目录默认就是exe所在的文件夹,所以你代码里用相对路径
"meme.mp4"能正常找到文件,整个Closing事件流程顺畅。 - 但你写的批处理有两个关键问题:
start命令的第一个带引号的参数是窗口标题,不是程序路径!你的写法相当于把"Calculator Assessment.exe"设为窗口标题,然后启动后面的exe,但此时程序的工作目录还是批处理文件所在的目录,不是exe所在的目录。- 因为工作目录不对,程序执行
File.Copy("meme.mp4", ...)时找不到源文件,抛出FileNotFoundException,而你没有捕获这个异常,直接导致程序崩溃,后续的取消关闭、启动新实例自然都执行不了。
解决方案:
方案1:修复批处理的启动逻辑
修正start命令的用法,同时指定程序的工作目录:
@echo off :: 切换到exe所在的目录再启动 cd /d "Resources\Calculator Assessment\bin\Release" start "" "Calculator Assessment.exe"
或者用start的/D参数直接指定工作目录:
@echo off start "" /D "Resources\Calculator Assessment\bin\Release" "Calculator Assessment.exe"
这样程序启动后,工作目录就是exe所在的文件夹,相对路径能正常找到meme.mp4。
方案2:代码层面彻底解决(更推荐)
不管程序从哪里启动,都不要依赖工作目录,而是通过程序自身的路径来定位meme.mp4,这样从任何方式启动都不会出错:
修改你mainWindow_Closing事件里的文件复制代码:
private void mainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { try { // 获取当前程序exe所在的绝对目录 string exeDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); // 拼接meme.mp4的绝对路径 string sourceMemePath = System.IO.Path.Combine(exeDirectory, "meme.mp4"); Random rand = new Random(); string desktopPath = System.Environment.GetEnvironmentVariable("USERPROFILE") + "\\Desktop\\"; for (int i = 0; i < 3; i++) { string copyPath = System.IO.Path.Combine(desktopPath, $"meme{rand.Next()}.mp4"); System.IO.File.Copy(sourceMemePath, copyPath, true); } e.Cancel = true; new MainWindow(0).Show(); } catch (Exception ex) { // 可以在这里加异常日志或者提示,避免崩溃 MessageBox.Show($"操作出错:{ex.Message}"); // 如果不想让程序关闭,可以保留e.Cancel = true,否则注释掉 e.Cancel = true; } }
这里做了几个优化:
- 用绝对路径定位源文件,彻底摆脱工作目录的限制
- 加了
try-catch捕获异常,就算出问题也不会直接崩溃,还能给用户提示 - 用
Path.Combine拼接路径,避免手动写斜杠的跨平台问题(虽然WPF主要在Windows,但这是更规范的写法)
额外小细节
你原来的代码里第一次循环外的copyPath定义是多余的,可以删掉,不影响功能但代码更整洁。
内容的提问来源于stack exchange,提问作者Durfsurn
相关产品推荐
相关产品推荐

