关于excel:如何从C#控制台停止办公应用程序

How to stop office application from C# console

本问题已经有最佳答案,请猛点这里访问。

给定以下代码(控制台应用程序C),Word应用程序将在大约300-400毫秒后停止,但Excel应用程序将继续运行。我找不到一种方法来阻止它(不扼杀进程)。

有什么建议吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Diagnostics;
using Microsoft.Office.Interop.Word;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Interop.PowerPoint;
using System.Collections.Generic;

namespace test
{

    class Program
    {

        private static int GetProcessIdByWindowTitle(string AppId)
        {
            Process[] P_CESSES = Process.GetProcesses();
            for (int p_count = 0; p_count < P_CESSES.Length; p_count++)
            {
                if (P_CESSES[p_count].MainWindowTitle.IndexOf(AppId) != -1)
                {
                    return P_CESSES[p_count].Id;
                }
            }
            return Int32.MaxValue;
        }

        static void Excel()
        {

            // create the MS-Excel Application
            Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();

            // Set the appID
            string appID ="zizozazezu";
            excelApp.Application.Caption = appID;
            excelApp.Application.Visible = true;

            // Excel needs a workbook to sete a caption visible...
            Microsoft.Office.Interop.Excel.Workbooks wbs = excelApp.Workbooks;
            Microsoft.Office.Interop.Excel.Workbook wb = wbs.Add();

            // find the
            int processID = GetProcessIdByWindowTitle(appID);

            // verified this is the pid of MS-Excel
            Console.WriteLine(processID);

            // bailing out, no save
            object saveChanges = false;
            ((Microsoft.Office.Interop.Excel._Workbook)wb).Close(saveChanges);
            ((Microsoft.Office.Interop.Excel._Application)excelApp).Quit();

            System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
            wb = null;

            System.Runtime.InteropServices.Marshal.ReleaseComObject(wbs);
            wbs = null;

            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
            excelApp = null;

            Console.WriteLine("Excel is done...");

            for (int i=0; i<100; i++)
            {
                // Patience....
                Thread.Sleep(100);

                // still running???
                bool isRunning = false;
                try
                {
                    Process p = Process.GetProcessById(processID);
                    if (!p.HasExited)
                    {
                        isRunning = true;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("{0} Exception caught.", ex);
                }

                if (isRunning)
                {
                    Console.Write(".");
                }
                else
                {
                    Console.WriteLine("Excel done at i=" + i.ToString());  
                    return;
                }
            }
            return;
        }

        static void Word()
        {
            // create the MS-Word Application
            Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

            // Set a caption - find the right instance
            string appID ="ladadidada";
            wordApp.Caption = appID;
            wordApp.Visible = true;

            // find the
            int processID = GetProcessIdByWindowTitle(appID);

            // verified this is the pid of MS-Word
            Console.WriteLine(processID);

            // Stop MS-Word
            object saveChanges = false;
            ((Microsoft.Office.Interop.Word._Application)wordApp).Quit(ref saveChanges);

            for (int i=0; i<100; i++)
            {
                // Patience....
                Thread.Sleep(100);

                // still running???
                bool isRunning = false;
                try
                {
                    Process p = Process.GetProcessById(processID);
                    if (!p.HasExited)
                    {
                        isRunning = true;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("{0} Exception caught.", ex);
                }

                if (isRunning)
                {
                    Console.Write(".");
                }
                else
                {
                    Console.WriteLine("Word done at i=" + i.ToString());    
                    return;
                }
            }
            return;
        }

        static int Main(string[] args)
        {

            Word();
            Excel();

            return -1;
        }
    }
}


所以有几件事向我扑来。

  • 您不会在Excel应用程序本身上调用Quit。这是它关闭的信号。
  • 您还需要确保在工作簿上调用Close。
  • 确保关闭后,将所有对象设置为空。
  • 我还发现,在我使用过的所有对象上,不仅调用Marshal.ReleaseComObject,而且调用Marshal.FinalReleaseComObject也是很有帮助的。
  • 你是双点,这意味着你泄露了一堆参考资料。不好的做法,会鼓励Excel四处闲逛
  • 最后,为了真正确保我杀死Excel,在我完成以上所有操作之后,我通过窗口句柄杀死了这个过程。

    公共静态bool trykillprocessbymainwindowhwnd(int hwnd){

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    uint processID;

    GetWindowThreadProcessId((IntPtr)hWnd, out processID);

    if (processID == 0) return false;

    try
    {
        Process.GetProcessById((int)processID).Kill();
    }
    catch (ArgumentException)
    {
        return false;
    }
    catch (Win32Exception)
    {
        return false;
    }
    catch (NotSupportedException)
    {
        return false;
    }
    catch (InvalidOperationException)
    {
        return false;
    }

    return true;

    }

  • 为了使上述工作正常进行,您还需要确保包含win32 API。

    1
    2
    [DllImport("user32.dll")]
            private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);