C#我操作excel模板或者word模板时,最后我会quit()但是如果操作的excel和word时,因为某些原因,代码并没有跑到最后的quit(),等下次他会锁定excel和word。导致必须通过任务管理器杀掉后台,才能恢复正常。我也尝试用过try catch,但是没有成功。这种情况发生时,如何解决特定的excel和word后台,而不是误杀掉其他后台程序。
使用using代码块包住需要自动释放的对象
否则一旦进入catch,try后面的代码将不会得到执行
也可以在catch后加finally块来执行无论是否进入catch都会执行的代码,finally里的代码会确保在return之前先执行
楼上的正解 ,用面向对象的异常处理,翻翻书,书上有写,写得比较详细。
因为某些原因,代码并没有跑到最后的quit()
因为那些原因呢??这才是我们需要知道的东西
在你说不清楚这玩意以前,我们基本很难说清楚解决方案,只能从你这些只言片语的描述里大概猜猜情况
1.解决特定的excel和word后台------------这个我只能猜你用的估计是vsto这种方式,他会启动一个excel进程
2.最后我会quit()但是如果操作的excel和word时,因为某些原因,代码并没有跑到最后的quit()-----------这个我大概猜测是你的主程序被关闭,或者被人从任务管理器关闭或者其他异常关闭等等把,这时候你启动的excel进程没有被关闭
如果你的现象和没有quit的原因如我猜想
我们大概可能的方向是:
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
Microsoft.Office.Interop.Word.Application newApp = new Microsoft.Office.Interop.Word.Application();
//我们需要知道他的进程id
//vsto的资料比较少,但从有限的资料里我们可以知道活动文档是有窗体句柄的
//所以我加个空文档建立一个活动文档
newApp.Documents.Add();
var hwnd = newApp.ActiveWindow.Hwnd;
//然后我们借用win32 api查找该句柄进程
GetWindowThreadProcessId(hwnd, out int lpdwProcessId);
2.上面解决了pid的查找问题,那么请将此pid用列表保存起来,如果你是正常处理的请从列表移除pid,如果是非正常处理,请在下次启动的时候,根据pid查找进程
然后发送一个正常结束指令
Process p = Process.GetProcessById(lpdwProcessId);
//这里这么写呢,是因为windows有正常的程序关闭处理逻辑
//某个园子教了10多年的kill其实是错误的处理
//只有某个程序不能以正常的逻辑关闭时候才会采用kill强制处理
if (!p.CloseMainWindow())
{
p.Kill();
}
3.为啥我们上面建议在下次启动时候处理,因为2已经讲了,正常的退出逻辑(包括使用任务管理器的)都会执行 资源释放的析构代码,而kill的不会处理析构代码
所以如果是正常的退出程序
我们可以在启动时候在program.cs new一个带显式析构代码的类,在析构代码中把你未结束的进程,挨个结束掉(这个也叫结束进程树)
4.如果你要处理程序里因为别人在外面强行调用 kill信号的,这个我就不打算写了。因为kill本来是用来“处决”的,本来就不打算给遗言的,所以你要处理他得另外想办法搞,因为你本身问题上下文也没描述个啥,我们也仅仅凭猜测去建议,就不往下深入了
最后随手写个例子(不处理kill信号的问题,只写一般用户能够关闭的手段)
program.cs
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
var safe = new Safehouse();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public class Safehouse
{
private static readonly List<int> pids = new List<int>();
public static void AddPid(int pid)
{
pids.Add(pid);
}
~Safehouse()
{
//用户正常退出或者任务管理器退出都会执行这个析构代码
foreach (var pid in pids)
{
Process p = Process.GetProcessById(pid);
if (!p.CloseMainWindow())
{
p.Kill();
}
}
}
}
}
form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
private void Form1_Load(object sender, EventArgs e)
{
Microsoft.Office.Interop.Word.Application newApp = new Microsoft.Office.Interop.Word.Application();
var b = newApp.Parent;
//我们需要知道他的进程id
//vsto的资料比较少,但从有限的资料里我们可以知道活动文档是有窗体句柄的
//所以我加个空文档建立一个活动文档
newApp.Documents.Add();
var hwnd = newApp.ActiveWindow.Hwnd;
//然后我们借用win32 api查找该句柄进程
GetWindowThreadProcessId(hwnd, out int lpdwProcessId);
//我们打开了个word进程,但我就不关,也不quit
//我们把pid加到前面的safehouse看看析构代码能不能帮我们关闭他
Program.Safehouse.AddPid(lpdwProcessId);
}
}
先保存或取消保存文件,退出工作薄,最后退出