C#我操作excel模板或者word模板时,最后我会quit()但是如果操作的excel和word时,代码并没有跑到最后的quit(),等下次他会锁定excel和word,如何解决?

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的原因如我猜想
我们大概可能的方向是:

  1. 每次启动任务请先找到你本次任务的那个excel的进程id
 [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);
            
        }
    }




先保存或取消保存文件,退出工作薄,最后退出