运行delphi客户端自动化程序后为什么excel.exe仍然被加载的原因?

我编写了一个Delphi程序,将一个.XLS文件的几个不同电子表格中的数据提取并合并到一个文本文件中供以后处理。 这是一个Delphi 7 控制台程序。

最相关的代码片段的摘录会告诉你,显然,我的程序是相当不错的performance,或至less它需要。

uses ... ActiveX, ComObj ... ; procedure Fatal(s:string); ... Halt(1); var ExcelApp:Variant; (* global var *) begin (* main program block *) coInitialize(nil); ExcelApp:=CreateOleObject('Excel.Application'); try ExcelApp.Visible:=False; ExcelApp.WorkBooks.Open(ExcelFileName); ... XLSSheet := ExcelApp.Worksheets[ExcelSheetName]; ... try XLSRange := XLSSheet.Range[ExcelRangeName]; except Fatal('Range "'+ExcelRangeName+'" not found'); end; if VarIsNull(XLSRange) then Fatal('Range '+ExcelRangeName+' not found'); for row:=XLSRange.Row to XLSRange.Rows[XLSRange.Rows.Count].Row do for col:=XLSRange.Column to XLSRange.Columns[XLSRange.Columns.Count].Column do CellValue:=XLSSheet.Cells[Row,Col].Value; ... if CellValue<>'' then ... ... ExcelApp.Workbooks.Close; ... finally ExcelApp.Quit; coUninitialize; end; end. 

有时,程序退出时,XLS将保持locking状态。 看看任务pipe理器,我看到当客户端程序运行时启动的Excel.exe进程仍在运行,eventhoug客户端程序已经退出并成功卸载。

你碰巧知道这种行为的通常嫌疑犯是什么? 有什么想法在客户端执行时总是卸载excel?

您需要发布ExcelApp变体。 它仍然保持1的引用计数,因此Excel并没有完全closures。

添加到您的代码(标记行):

 finally ExcelApp.Quit; ExcelApp := Unassigned; // Add this line coUninitialize; end; 

下面是一些简单的代码来重现问题,并testing解决scheme:

 // Add two buttons to a form, and declare a private form field. // Add OnClick handlers to the two buttons, and use the code provided. // Run the app, and click Button1. Wait until Excel is shown, and then click // Button2 to close it. See the comments in the Button2Click event handler. type TForm1=class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private ExcelApp: Variant; end; implementation uses ComObj; procedure TForm1.Button1Click(Sender: TObject); begin ExcelApp := CreateOleObject('Excel.Application'); ExcelApp.Visible := True; end; procedure TForm1.Button2Click(Sender: TObject); begin ExcelApp.Visible := False; ExcelApp.Quit; // Leave the next line commented, run the app, and click the button. // After exiting your app NORMALLY, check Task Manager processes, and you'll // see an instance of Excel.exe still running, even though it's not // in the Applications tab. // // Do an "end process" in Task Manager to remove the orphaned instance // of Excel.exe left from the above. Uncomment the next line of code // and repeat the process, again closing your app normally after clicking // Button2. You'll note that Excel.exe is no longer in // Task Manager Processes after closing your app. // ExcelApp := Unassigned; end; end. 

我在XE2中遇到了很多相同的问题,我的解决scheme是replace这样的代码示例:

 fExcel.ActiveWorkBook.ActiveSheet.Range[ fExcel.ActiveWorkBook.ActiveSheet.Cells[3, 2], fExcel.ActiveWorkBook.ActiveSheet.Cells[3+i,1+XL_PT_Tip_FieldCount] ].Formula := VarArr; 

有:

 cl := fExcel.ActiveWorkBook.ActiveSheet.Cells[3, 2]; ch := fExcel.ActiveWorkBook.ActiveSheet.Cells[3+i,1+XL_PT_Tip_FieldCount]; fExcel.ActiveWorkBook.ActiveSheet.Range[cl, ch].Formula := VarArr; 

在这种情况下,使用图表variables的情况也是如此:

 sheetDynamicHb := fExcel.ActiveWorkBook.Sheets['Dynamics Hb']; cl := sheetDynamicHb.Cells[52, 2]; ch := sheetDynamicHb.Cells[52+i, 2+3]; sheetDynamicHb.Range[cl, ch].Formula := VarArr; 

不知怎的,引入临时variables( cl,ch: Variant )是不可能的。 这看起来像嵌套的Excelvariables访问奇怪。 我无法解释为什么这样的工作,但它的工作..

我面临着同样的问题,试图closures“僵尸”Excel进程(那些保持运行,如果我从我的应用程序启动,然后强制终止应用程序)。 我尝试了所有build议的行动,没有运气。 最后,我创build了一个组合的杀手程序,如果通常的COM方法没有帮助,就可以使用WinApi强大的技巧。

 procedure KillExcel(var App: Variant); var ProcID: DWORD; hProc: THandle; hW: HWND; begin hW := App.Application.Hwnd; // close with usual methods App.DisplayAlerts := False; App.Workbooks.Close; App.Quit; App := Unassigned; // close with WinApi if not IsWindow(hW) then Exit; // already closed? GetWindowThreadProcessId(hW, ProcID); hProc := OpenProcess(PROCESS_TERMINATE, False, ProcID); TerminateProcess(hProc, 0); end;