完成使用后,我无法关闭EXCEL(32)进程。
正如您在下面的代码中看到的,一旦ProcessRFAFData
函数完成执行,EXCEL进程就不会被关闭(我仍然可以在任务管理器中看到EXCEL.EXE*32
)。
出于这个原因,当SaveErrors
开始执行时,我得到以下异常:
System.Runtime.InteropServices.COMException (0x800A03EC):
Microsoft Office Excel cannot open or save any more documents because there is not enough available memory or disk space.
• To make more memory available, close workbooks or programs you no longer need.
• To free disk space, delete files you no longer need from the disk you are saving to.
at Microsoft.Office.Interop.Excel.Workbooks.Add(Object Template)
at NextG.RFAFImport.Layouts.NextG.RFAFImport.RFAFDataImporter.<>c__DisplayClass9.b__6()
at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass4.b__2()
at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)
at NextG.RFAFImport.Layouts.NextG.RFAFImport.RFAFDataImporter.SaveErrors()
以下是执行Excel流程的代码:
try {
ProcessRFAFData(FileName);
} catch (Exception ex) {
Status = "ERROR: " + ex.ToString();
}
if (Errors.Count() > 0) {
SaveErrors();
}
以下是与Excel交互的所有功能:
private void ReleaseObject(object obj) {
try {
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
} catch (Exception) { } finally {
GC.Collect();
}
}
private void ProcessRFAFData(string FileName) {
Microsoft.Office.Interop.Excel.Application XLA = null;
Microsoft.Office.Interop.Excel.Workbook XLW = null;
Microsoft.Office.Interop.Excel.Worksheet XLS = null;
bool error = false;
try {
SPSecurity.RunWithElevatedPrivileges(delegate() {
XLA = new Microsoft.Office.Interop.Excel.Application();
XLW = XLA.Workbooks.Open(FileName, 0, true,
Type.Missing, null, null, true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
Type.Missing, false, false, Type.Missing, false, Type.Missing, Type.Missing);
int index = RFAFTabExists(ref XLW);
if (index == 0) return;
XLS = (Microsoft.Office.Interop.Excel.Worksheet)XLW.Worksheets.get_Item(index);
if (!ValidProjectID(ref XLS)) return;
ParseData(ref XLS);
XLW.Close(true, Type.Missing, Type.Missing);
XLA.Quit();
ReleaseObject(XLS);
ReleaseObject(XLW);
ReleaseObject(XLA);
});
} catch (SP.ServerException ex) {
// output error
} catch (Exception ex) {
// output error
}
}
private int RFAFTabExists(ref Microsoft.Office.Interop.Excel.Workbook XLW) {
int index = 0;
foreach (Microsoft.Office.Interop.Excel.Worksheet w in XLW.Worksheets) {
if (w.Name.Equals(settings.Collection["RFAFTabName"])) index++;
}
return index;
}
private bool ValidProjectID(ref Microsoft.Office.Interop.Excel.Worksheet XLS) {
using (SP.ClientContext CTX = new SP.ClientContext(SiteURL)) {
var projectId = XLS.Cells.get_Range(settings.Collection["ProjectIDCell"], Type.Missing).Text.ToString();
var project = // getting list of projects from SharePoint
if (project.Count() > 0) {
ProjectID = XLS.Cells.get_Range(settings.Collection["ProjectIDCell"], Type.Missing).Text.ToString();
return true;
}
}
return false;
}
private void ParseData(ref Microsoft.Office.Interop.Excel.Worksheet XLS) {
ListData.Add("HID", GetHID(XLS.Cells.get_Range(settings.Collection["HIDCell"],
Type.Missing).Text.ToString()));
if (ListData["HID"].Equals("0")) Errors.Add(new ImportError {
Reason = "Hub ID does not exist in this project workspace.",
Reference = string.Format("Hub ID: {0}", XLS.Cells.get_Range(settings.Collection["HIDCell"],
Type.Missing).Text.ToString())
});
int row = Int32.Parse(settings.Collection["StartRow"]);
while (!NoMoreData(ref XLS, row)) {
string PRSIN = XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["PRSIN"], row), Type.Missing).Text.ToString();
string NOC = ValidateNumber(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["NOC"], row), Type.Missing).Text.ToString());
string UEIRP = ValidateNumber(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["UEIRP"], row), Type.Missing).Text.ToString());
string LAT = ValidateLatLon(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["LAT"], row), Type.Missing).Text.ToString());
string LON = ValidateLatLon(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["LON"], row), Type.Missing).Text.ToString());
string PJ = GetPJ(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["JurisdictionCol"], row), Type.Missing).Text.ToString(),
XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["StateCol"], row),
Type.Missing).Text.ToString());
string ST = GetState(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["JurisdictionCol"], row), Type.Missing).Text.ToString(),
XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["StateCol"], row),
Type.Missing).Text.ToString());
ListItemData.Add(new ListItem {
ProposedRemoteSiteItemNumber = PRSIN,
NumberOfCarriers = NOC,
UsableEIRP = UEIRP,
Latitude = LAT,
Longitude = LON,
PrimaryJurisdiction = PJ,
State = ST
});
row++;
}
}
private bool NoMoreData(ref Microsoft.Office.Interop.Excel.Worksheet XLS, int row) {
return string.IsNullOrEmpty(XLS.Cells.get_Range(string.Format("{0}{1}",
settings.Collection["ProposedRemoteSiteItemNumberCol"], row), Type.Missing).Text.ToString());
}
private void SaveErrors() {
Microsoft.Office.Interop.Excel.Application XLA = null;
Microsoft.Office.Interop.Excel.Workbook XLW = null;
Microsoft.Office.Interop.Excel.Worksheet XLS = null;
object MissingValue = System.Reflection.Missing.Value;
try {
try {
SPSecurity.RunWithElevatedPrivileges(delegate() {
XLA = new Microsoft.Office.Interop.Excel.Application();
XLW = XLA.Workbooks.Add(MissingValue);
XLS = (Microsoft.Office.Interop.Excel.Worksheet)XLW.Worksheets.get_Item(1);
XLS.Cells[1, 1] = "Reason for error";
XLS.Cells[1, 2] = "Reference";
XLS.get_Range("A1").Font.Bold = true;
XLS.get_Range("B1").Font.Bold = true;
int row = 2;
foreach (ImportError e in Errors) {
XLS.Cells[row, 1] = e.Reason;
XLS.Cells[row, 2] = e.Reference;
row++;
}
XLW.SaveAs(ErrorLogFileName, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal,
MissingValue, MissingValue, MissingValue, MissingValue,
Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, MissingValue,
MissingValue, MissingValue, MissingValue, MissingValue);
XLW.Close(true, MissingValue, MissingValue);
XLA.Quit();
ReleaseObject(XLS);
ReleaseObject(XLW);
ReleaseObject(XLA);
});
} catch (Exception ex) {
Status = "ERROR: " + ex.ToString();
}
// Uploading excel file to SharePoint document library
} catch (Exception) { }
}
答案 0 :(得分:3)
如果出现异常,则在finally块中释放Excel对象。
try
{
...
}
catch
{
...
}
finally
{
ReleaseObject(XLS);
ReleaseObject(XLW);
ReleaseObject(XLA);
}
答案 1 :(得分:3)
你可能不得不荒谬地explicit:
excelWorkbook.Close (false, System.Reflection.Missing.Value,System.Reflection.Missing.Value) ;
excelWorkbooks.Close();
excelApp.Quit();
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelSheets);
Marshal.ReleaseComObject(excelWorkbooks);
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelApp);
excelWorksheet = null;
excelSheets = null;
excelWorkbooks = null;
excelWorkbook = null;
excelApp = null;
GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
我遇到过甚至没有这样做的情况。我求助于追踪Excel过程并在其上调用Kill()。
答案 2 :(得分:1)
第一个建议:http://code.google.com/p/excellibrary这是一个很棒的图书馆,我使用了很多成功。
第二个建议:如果你绝对必须关闭Excel
/// <summary>
/// Gets all currently running instances of Excel, so we don't kill active windows.
/// </summary>
private void GetInstancesToSave()
{
if (_instancesToSaveList != null)
{
_instancesToSaveList.Clear();
}
_instancesToSaveList = Process.GetProcesses().ToList<Process>();
_instancesToSaveList = _instancesToSaveList.FindAll(proc => proc.ProcessName == "EXCEL");
}
/// <summary>
/// Kills any instances of Excel that were created by the program.
/// </summary>
/// <param name="zInstancesToSave">Instances that were not </param>
private static void KillExcel(List<Process> zInstancesToSave)
{
List<Process> xProcesslist = Process.GetProcesses().ToList<Process>();
xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL");
foreach (Process xTheprocess in xProcesslist)//read through all running programs
{
bool killit = true;
foreach (Process proc in zInstancesToSave)//read through all running programs
{
if (xTheprocess.Id == proc.Id)
{
killit = false;
}
}
if (killit)
{
xTheprocess.Kill();
}
}
}
您可以使用这两种方法来跟踪启动时正在运行的Excel实例,然后查找应用程序打开的任何Excel实例,然后将其终止。这当然不是一个很好的解决方案,但有时你只需要咬紧牙关。
如果您不关心先前的实例,您也可以这样做:
/// <summary>
/// Kills any instances of Excel that were created by the program.
/// </summary>
/// <param name="zInstancesToSave">Instances that were not </param>
private static void KillExcel(List<Process> zInstancesToSave)
{
List<Process> xProcesslist = Process.GetProcesses().ToList<Process>();
xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL");
foreach(Proc process in xProcesslist)
{
process.Kill();
}
}
答案 3 :(得分:0)
我会考虑使用Code Plex中的EPPlus 这个example显示了如何读取数据。在这条路线的服务器上你总是更好 - 唯一的问题是如果你需要调用公式 - 那么这种方法是行不通的 你的大多数代码都与你当前的代码非常相似,所以我估计要移动到这个库几个小时。
答案 4 :(得分:0)
就我而言,Excel加载项存在于我之前创建的单独AppDomain中,但是当加载项被卸载时,我从未调用过:
childDomain.Unload();
一旦调用,Excel Zombie进程就不再存在......
答案 5 :(得分:0)
除上述解决方案外,这里还有我的 LOGICAL 解决方案。 我在想为什么我有这么多EXCEL.EXE应用程序并以这种方式处理。 在这里,我在创建新的Excel应用程序时检查条件。 if(_masterApp == null) _masterApp = new EXCEL.Application(); 如果要创建的变量为Null,则仅创建Excel实例的新实例,否则重新分配现有变量。
并使用此博客中提到的解决方案来关闭_masterApp。
好处:这样您只会关闭通过解决方案打开的EXCEL应用程序,而不会关闭手动打开的Excel应用程序。
答案 6 :(得分:0)
查看此链接
感谢KD7提供解决方案。
一个小的修改是,如果您的excelapp不可见,则您的mainwindowtitle将为空白。例如。 “”
private void KillSpecificExcelFileProcess(string excelFileName)
{
var processes = from p in Process.GetProcessesByName("EXCEL")
select p;
foreach (var process in processes)
{
MessageBox.Show(process.MainWindowTitle);
if (process.MainWindowTitle == excelFileName)
{
process.Kill();
}
}
}
并杀死所有僵尸excel后台进程”
KillSpecificExcelFileProcess("");
这不会给我带来麻烦,因此我将其发布到每个僵尸excel进程线程上。