数据访问后在C#中关闭Excel应用程序进程

Jav*_*efi 78 c# excel excel-interop kill-process visual-studio-2012

我正在用C#编写一个应用程序,它打开一个用于读/写操作的Excel模板文件.我想当用户关闭应用程序时,excel应用程序进程已关闭,而不保存excel文件.多次运行应用程序后,请参阅我的任务管理器.

在此输入图像描述

我使用此代码打开excel文件:

public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
Run Code Online (Sandbox Code Playgroud)

对于数据访问,我使用以下代码:

Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Run Code Online (Sandbox Code Playgroud)

我在stackoverflow中看到类似的问题,例如这个问题这个,以及测试答案,但它不起作用.

小智 83

试试这个:

excelBook.Close(0); 
excelApp.Quit();
Run Code Online (Sandbox Code Playgroud)

关闭工作簿时,您有三个可选参数:

Workbook.close SaveChanges, filename, routeworkbook 
Run Code Online (Sandbox Code Playgroud)

Workbook.Close(false)或者如果你正在进行后期绑定,有时候更容易使用零 Workbook.Close(0) 这就是我在自动关闭工作簿时所做的工作.

我也去找了它的文档,并在这里找到它: Excel工作簿关闭

谢谢,

  • 在经历了所有这些答案的多次尝试失败后,我选择[此解决方案](http://stackoverflow.com/questions/8490564/getting-excel-application-process-id)获取我打开的进程ID并将其终止直. (3认同)

Sam*_* R. 20

xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
Run Code Online (Sandbox Code Playgroud)

尝试这个..它对我有用...你应该释放xl应用程序对象来停止进程.


Dav*_*rke 13

参考:https://stackoverflow.com/a/17367570/132599

避免使用双点调用表达式,例如:

var workbook = excel.Workbooks.Open(/*params*/)
Run Code Online (Sandbox Code Playgroud)

...因为通过这种方式,您不仅可以为工作簿创建RCW对象,还可以为Workbooks创建RCW对象,并且也应该释放它(如果不维护对象的引用,这是不可能的).

这解决了我的问题.您的代码变为:

public Excel.Application excelApp = new Excel.Application();
public Excel.Workbooks workbooks;
public Excel.Workbook excelBook;
workbooks = excelApp.Workbooks;
excelBook = workbooks.Add(@"C:/pape.xltx");

...

Excel.Sheets sheets = excelBook.Worksheets;
Excel.Worksheet excelSheet = (Worksheet)(sheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Run Code Online (Sandbox Code Playgroud)

然后释放所有这些对象:

System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
excelBook .Save();
excelBook .Close(true);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
Run Code Online (Sandbox Code Playgroud)

我把它包装成一个,try {} finally {}以确保即使出现问题(可能出错的东西?),一切都会被释放

public Excel.Application excelApp = null;
public Excel.Workbooks workbooks = null;
...
try
{
    excelApp = new Excel.Application();
    workbooks = excelApp.Workbooks;
    ...
}
finally
{
    ...
    if (workbooks != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
    excelApp.Quit();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,将工作簿分配给变量以便可以清除它.还有一点观察,我在Web应用程序和控制台应用程序中清除excel应用程序的代码完全相同.更新摆脱双点之前的代码在控制台应用程序中工作正常,但在Web应用程序中运行时它没有清除EXCEL.EXE.我不确定为什么他们的行为不同,但摆脱了双点引用修复它在Web应用程序中. (2认同)

Mor*_*iao 10

想一想,它会杀死这个过程:

System.Diagnostics.Process[] process=System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
    if (!string.IsNullOrEmpty(p.ProcessName))
    {
        try
        {
            p.Kill();
        }
        catch { }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,你试过正常关闭吗?

myWorkbook.SaveAs(@"C:/pape.xltx", missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing);
excelBook.Close(null, null, null);                 // close your workbook
excelApp.Quit();                                   // exit excel application
excel = null;                                      // set to NULL
Run Code Online (Sandbox Code Playgroud)


D_B*_*ter 5

杀死Excel并不总是那么容易。请参阅本文:杀死Excel的50种方法

本文就如何使Excel正常退出获得了Microsoft的最佳建议(MS Knowlege基础文章),但是如果需要,还可以通过终止进程来确保做到这一点。我喜欢再降落伞。

确保关闭所有打开的工作簿,退出应用程序并释放xlApp对象。最后检查该进程是否仍然存在,如果是,则将其终止。

本文还确保我们不会杀死所有Excel进程,而只会杀死已启动的确切进程。

另请参阅从窗口句柄获取流程

这是我使用的代码:(每次都有效)

Sub UsingExcel()

    'declare process; will be used later to attach the Excel process
    Dim XLProc As Process

    'call the sub that will do some work with Excel
    'calling Excel in a separate routine will ensure that it is 
    'out of scope when calling GC.Collect
    'this works better especially in debug mode
    DoOfficeWork(XLProc)

    'Do garbage collection to release the COM pointers
    'http://support.microsoft.com/kb/317109
    GC.Collect()
    GC.WaitForPendingFinalizers()

    'I prefer to have two parachutes when dealing with the Excel process
    'this is the last answer if garbage collection were to fail
    If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then
        XLProc.Kill()
    End If

End Sub

'http://msdn.microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
    ByRef lpdwProcessId As Integer) As Integer
End Function

Private Sub ExcelWork(ByRef XLProc As Process)

    'start the application using late binding
    Dim xlApp As Object = CreateObject("Excel.Application")

    'or use early binding
    'Dim xlApp As Microsoft.Office.Interop.Excel

    'get the window handle
    Dim xlHWND As Integer = xlApp.hwnd

    'this will have the process ID after call to GetWindowThreadProcessId
    Dim ProcIdXL As Integer = 0

    'get the process ID
    GetWindowThreadProcessId(xlHWND, ProcIdXL)

    'get the process
    XLProc = Process.GetProcessById(ProcIdXL)


    'do some work with Excel here using xlApp

    'be sure to save and close all workbooks when done

    'release all objects used (except xlApp) using NAR(x)


    'Quit Excel 
    xlApp.quit()

    'Release
    NAR(xlApp)

End Sub

Private Sub NAR(ByVal o As Object)
    'http://support.microsoft.com/kb/317109
    Try
        While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
        End While
    Catch
    Finally
        o = Nothing
    End Try
End Sub
Run Code Online (Sandbox Code Playgroud)