数据访问后在C#中关闭Excel应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17777545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Closing Excel Application Process in C# after Data Access
提问by Javad Yousefi
I'm writing an application in C# that opens an Excel template file for read/write operations. I want to when user closes the application, excel application process has been closed, without saving excel file. See my Task Manager after multiple runs of the app.
我正在用 C# 编写一个应用程序,它打开一个 Excel 模板文件以进行读/写操作。我想当用户关闭应用程序时,excel 应用程序进程已关闭,而不保存 excel 文件。多次运行应用程序后,请参阅我的任务管理器。
I use this code to open the excel file :
我使用此代码打开 excel 文件:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
and for data access I use this code :
对于数据访问,我使用以下代码:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
I see similar questions in stackoverflow such as this questionand this, and test answers, but it doesn't works.
我在 stackoverflow 中看到类似的问题,例如this question和this,以及测试答案,但它不起作用。
采纳答案by Michael
Try this:
尝试这个:
excelBook.Close(0);
excelApp.Quit();
When closing the work-book, you have three optional parameters:
关闭工作簿时,您有三个可选参数:
Workbook.close SaveChanges, filename, routeworkbook
Workbook.Close(false)
or if you are doing late binding, it sometimes is easier to use zero
Workbook.Close(0)
That is how I've done it when automating closing of workbooks.
Workbook.Close(false)
或者,如果您正在进行后期绑定,有时使用零会更容易。
Workbook.Close(0)
这就是我在自动关闭工作簿时所做的。
Also I went and looked up the documentation for it, and found it here: Excel Workbook Close
我也去查找了它的文档,并在这里找到了它: Excel Workbook Close
Thanks,
谢谢,
回答by Morris Miao
Think of this, it kills the process:
想到这一点,它杀死了进程:
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 { }
}
}
Also, did you try just close it normally?
另外,您是否尝试过正常关闭它?
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
回答by user2605046
excelBook.Close(); excelApp.Quit(); add end of the code, it could be enough. it is working on my code
excelBook.Close(); excelApp.退出(); 添加代码的末尾,就足够了。它正在处理我的代码
回答by D_Bester
Killing Excel is not always easy; see this article: 50 Ways to Kill Excel
杀死 Excel 并不总是那么容易。请参阅这篇文章:杀死 Excel 的 50 种方法
This article takes the best advice from Microsoft (MS Knowlege Base Article) on how to get Excel to quit nicely, but then also makes sure about it by killing the process if necessary. I like having a second parachute.
本文采纳了 Microsoft(MS Knowledge Base 文章)关于如何让 Excel 很好地退出的最佳建议,但如果有必要,还会通过终止进程来确保它。我喜欢有第二个降落伞。
Make sure to Close any open workbooks, Quit the application and Release the xlApp object. Finally check to see if the process is still alive and if so then kill it.
确保关闭所有打开的工作簿,退出应用程序并释放 xlApp 对象。最后检查进程是否还活着,如果是,则杀死它。
This article also makes sure that we don't kill all Excel processes but only kills the exact process that was started.
本文还确保我们不会终止所有 Excel 进程,而只会终止已启动的确切进程。
See also Get Process from Window Handle
另请参阅从窗口句柄获取进程
Here is the code I use: (works every time)
这是我使用的代码:(每次都有效)
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
回答by Sameera R.
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
try this.. it worked for me... you should release that xl application object to stop the process.
试试这个……它对我有用……你应该释放那个 xl 应用程序对象来停止这个过程。
回答by David Clarke
Ref: https://stackoverflow.com/a/17367570/132599
参考:https: //stackoverflow.com/a/17367570/132599
Avoid using double-dot-calling expressions, such as this:
var workbook = excel.Workbooks.Open(/*params*/)
...because in this way you create RCW objects not only for workbook, but for Workbooks, and you should release it too (which is not possible if a reference to the object is not maintained).
避免使用双点调用表达式,例如:
var workbook = excel.Workbooks.Open(/*params*/)
...因为通过这种方式,您不仅可以为工作簿创建 RCW 对象,还可以为工作簿创建 RCW 对象,并且您也应该释放它(如果不维护对对象的引用,这是不可能的)。
This resolved the issue for me. Your code becomes:
这为我解决了这个问题。您的代码变为:
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;
And then release all those objects:
然后释放所有这些对象:
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);
I wrap this in a try {} finally {}
to ensure everything gets released even if something goes wrong (what could possibly go wrong?) e.g.
我将它包装在 a 中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);
}
回答by xrhstos
wb.Close();
app.Quit();
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName) && p.StartTime.AddSeconds(+10) > DateTime.Now)
{
try
{
p.Kill();
}
catch { }
}
}
It Closes last 10 sec process with name "Excel"
它关闭最后 10 秒的进程,名称为“Excel”
回答by xrhstos
GetWindowThreadProcessId((IntPtr)app.Hwnd, out iProcessId);
wb.Close(true,Missing.Value,Missing.Value);
app.Quit();
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (p.Id == iProcessId)
{
try
{
p.Kill();
}
catch { }
}
}
}
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
uint iProcessId = 0;
this GetWindowThreadProcessId finds the correct Process Id o excell .... After kills it.... Enjoy It!!!
这个 GetWindowThreadProcessId 找到了正确的进程 Id o excel.... 杀死它后......享受它!
回答by Md. Alim Ul Karim
The right way to close all excel process
关闭所有excel进程的正确方法
var _excel = new Application();
foreach (Workbook _workbook in _excel.Workbooks) {
_workbook.Close(0);
}
_excel.Quit();
_excel = null;
var process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (var p in process) {
if (!string.IsNullOrEmpty(p.ProcessName)) {
try {
p.Kill();
} catch { }
}
}
回答by Kenneth Wong
I met the same problems and tried many methods to solve it but doesn't work. Finally , I found the by my way. Some reference enter link description here
我遇到了同样的问题并尝试了很多方法来解决它,但没有用。最后,我找到了我的方式。一些参考在这里输入链接描述
Hope my code can help someone future. I have been spent more than two days to solve it. Below is my Code:
希望我的代码可以帮助未来的人。我已经花了两天多的时间来解决它。下面是我的代码:
//get current in useing excel
Process[] excelProcsOld = Process.GetProcessesByName("EXCEL");
Excel.Application myExcelApp = null;
Excel.Workbooks excelWorkbookTemplate = null;
Excel.Workbook excelWorkbook = null;
try{
//DO sth using myExcelApp , excelWorkbookTemplate, excelWorkbook
}
catch (Exception ex ){
}
finally
{
//Compare the EXCEL ID and Kill it
Process[] excelProcsNew = Process.GetProcessesByName("EXCEL");
foreach (Process procNew in excelProcsNew)
{
int exist = 0;
foreach (Process procOld in excelProcsOld)
{
if (procNew.Id == procOld.Id)
{
exist++;
}
}
if (exist == 0)
{
procNew.Kill();
}
}
}