thi*_*ag0 9 excel windows-services office-automation office-interop
我有一个Windows服务,通过Microsoft.Office.Interop.Excel.Application对象打开Excel电子表格.
Application xlApp = new Application();
Workbook workbook = xlApp.Workbooks.Open(fileName, 2, false);
...
...
workbook.Close();
xlApp.Quit();
Run Code Online (Sandbox Code Playgroud)
我想杀死完成工作簿使用后剩余的EXCEL.exe进程.
我试过以下但没有成功......
// This returns a processId of 0
IntPtr processId;
GetWindowThreadProcessId(new IntPtr(xlApp.Hwnd), out processId);
Process p = Process.GetProcessById(processId.ToInt32());
p.Kill();
Run Code Online (Sandbox Code Playgroud)
任何人都有任何关于如何通过Windows服务这样做的想法?
dot*_*kow 10
正确关闭打开的Excel工作簿并退出应用程序非常困难.如果我能找到我发布的链接,但基本上你必须清理对你创建的任何COM对象的所有引用.这包括ODBCConnections(数据连接),工作表,工作簿和Excel应用程序中的所有内容.我开始工作的组合涉及垃圾收集和System.Runtime.InteropServices.Marshal对象:
// Garbage collecting
GC.Collect();
GC.WaitForPendingFinalizers();
// Clean up references to all COM objects
// As per above, you're just using a Workbook and Excel Application instance, so release them:
workbook.Close(false, Missing.Value, Missing.Value);
xlApp.Quit();
Marshal.FinalReleaseComObject(workbook);
Marshal.FinalReleaseComObject(xlApp);
Run Code Online (Sandbox Code Playgroud)
就像你提到的那样,循环并杀死每个Excel进程通常不是一个好主意,因为如果你将它作为Windows应用程序运行,你可以关闭用户的Excel,或者在服务中关闭正在运行的Excel实例通过其他一些程序.
编辑:有关详细信息,请参阅此问题.
小智 7
您需要检查文件句柄并获取由进程打开然后将其终止的PID.它对我有用.
private void genExcel(
{
int pid = -1;
//Get PID
xlApp = new Excel.Application();
HandleRef hwnd = new HandleRef(xlApp, (IntPtr)xlApp.Hwnd);
GetWindowThreadProcessId(hwnd, out pid);
.
.
.
.
//Finally
KillProcess(pid,"EXCEL");
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowThreadProcessId(HandleRef handle, out int processId);
private void KillProcess(int pid, string processName)
{
// to kill current process of excel
System.Diagnostics.Process[] AllProcesses = System.Diagnostics.Process.GetProcessesByName(processName);
foreach (System.Diagnostics.Process process in AllProcesses)
{
if (process.Id == pid)
{
process.Kill();
}
}
AllProcesses = null;
}
Run Code Online (Sandbox Code Playgroud)
经过多次阅读和挫折,我找到了解决方案!
所有功劳都归功于dotNetkow,nightcoder和Mike Rosenblum在这篇文章中的解决方案:如何正确清理Excel互操作对象?
这是我做的...
1.将项目的构建模式更改为"Release"(在DEBUG模式下,COM对象很难处理它们的引用
.2.删除所有双点表达式(所有COM对象都应该绑定)到一个变量,以便它们可以被释放)
3.在finally块中显式调用GC.Collect(),GC.WaitForPendingFinalizers()和Marshal.FinalReleaseComObject()
这是我正在使用的实际代码:
Application xlApp = null;
Workbooks workbooks = null;
Workbook workbook = null;
Worksheet sheet = null;
Range r = null;
object obj = null;
try
{
xlApp = new Application();
xlApp.DisplayAlerts = false;
xlApp.AskToUpdateLinks = false;
workbooks = xlApp.Workbooks;
workbook = workbooks.Open(fileName, 2, false);
sheet = workbook.Worksheets[1];
r = sheet.get_Range("F19");
obj = r.get_Value(XlRangeValueDataType.xlRangeValueDefault);
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
if (value != null) Marshal.FinalReleaseComObject(value);
if (r != null) Marshal.FinalReleaseComObject(r);
if (sheet != null) Marshal.FinalReleaseComObject(sheet);
if (workbooks != null) Marshal.FinalReleaseComObject(workbooks);
if (workbook != null)
{
workbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(workbook);
}
if (xlApp != null)
{
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
}
}
Run Code Online (Sandbox Code Playgroud)