關於在asp.net中調用Excel組件不能結束進程的問題,常見的解決方法用的是下面這段代碼
app.Workbooks.Close();
app.Quit();
if(rng != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
rng = null;
}
if(ws != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
ws = null;
}
if(wb != null)
{ System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
wb = null;
}
if(app != null)
{ System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
}
GC.Collect();
雖然這段代碼在配置正確的情況下能自動結束Excel進程,但是前提是在操作Excel時沒有引發異常的情況下,如果有異常發生,那麼Excel進程將不能結束(比如:引用了一個在Excel文件中不存在的文本框時就會出現“HRESULT 中的異常:0x800A03EC。”),這時就要藉助Process類的Kill()方法來結束,下面是我寫的測試代碼:
using System.Diagnostics;
using excel = Microsoft.Office.Interop.Excel;
namespace ExcelTest
{
/**//// <summary>
/// Excel的摘要說明。
/// </summary>
public class Excel
{
private DateTime beforeTime; //Excel啓動之前時間
private DateTime afterTime; //Excel啓動之後時間
excel.Application app;
excel.Workbook wb;
excel.Worksheet ws;
excel.Range rng;
excel.TextBox tb;
public Excel(string templetPath)
{
//實例化一個Excel Application對象並使其可見
beforeTime = DateTime.Now;
app = new excel.ApplicationClass();
app.Visible = true;
afterTime = DateTime.Now;
wb = app.Workbooks.Open(templetPath,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
ws = (excel.Worksheet)wb.Worksheets.get_Item(1);
}
public void ExcelMethod()
{
rng = ws.get_Range("B5","C7");
rng.Merge(excel.XlAxisCrosses.xlAxisCrossesAutomatic);
rng.Value2 = "Excel2003";
rng = ws.get_Range("D8","E11");
rng.MergeCells = true;
rng.Value2 = "Excel2003";
rng.HorizontalAlignment = excel.XlHAlign.xlHAlignCenter;
rng.VerticalAlignment = excel.XlVAlign.xlVAlignCenter;
rng = ws.get_Range("A1",Type.Missing);
rng.Value2 = 5;
rng = ws.get_Range("A2",Type.Missing);
rng.Value2 = 7;
for(int i=1;i<100;i++)
{
string s = string.Concat("G",i.ToString());
rng = ws.get_Range(s,Type.Missing);
rng.Value2 = i.ToString();
}
tb = (excel.TextBox)ws.TextBoxes("文本框 1");
tb.Text = "作 者";
tb = (excel.TextBox)ws.TextBoxes("文本框 2");
tb.Text = "KLY.NET的Blog";
tb = (excel.TextBox)ws.TextBoxes("文本框 3");
tb.Text = "日 期";
try
{
tb = (excel.TextBox)ws.TextBoxes("文本框 5");
tb.Text = DateTime.Now.ToShortDateString();
}
catch
{
//這裏用Dispose()方法結束不了Excel進程,所有還是要用Process的Kill()方法配合使用
// this.Dispose();
this.KillExcelProcess();
throw new Exception("不存在ID爲\"文本框 5\"的文本框!");
}
finally
{
//如果有異常發生,Dispose()方法放在這裏也結束不了Excel進程
// this.Dispose();
//如果發生異常,在這裏也可以結束Excel進程
// this.KillExcelProcess();
}
}
/**//// <summary>
/// 另存爲Excel文件
/// </summary>
/// <param name="savePath">保存路徑</param>
public void SaveAsExcelFile(string savePath)
{
wb.SaveAs(savePath,excel.XlFileFormat.xlHtml,Type.Missing,Type.Missing,Type.Missing,Type.Missing,excel.XlSaveAsAccessMode.xlExclusive,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
}
/**//// <summary>
/// 結束Excel進程
/// </summary>
public void KillExcelProcess()
{
Process[] myProcesses;
DateTime startTime;
myProcesses = Process.GetProcessesByName("Excel");
//得不到Excel進程ID,暫時只能判斷進程啓動時間
foreach(Process myProcess in myProcesses)
{
startTime = myProcess.StartTime;
if(startTime > beforeTime && startTime < afterTime)
{
myProcess.Kill();
}
}
}
/**//// <summary>
/// 如果對Excel的操作沒有引發異常的話,用這個方法可以正常結束Excel進程
/// 否則要用KillExcelProcess()方法來結束Excel進程
/// </summary>
public void Dispose()
{
wb.Close(null,null,null);
app.Workbooks.Close();
app.Quit();
//注意:這裏用到的所有Excel對象都要執行這個操作,否則結束不了Excel進程
if(rng != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
rng = null;
}
if(tb != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(tb);
tb = null;
}
if(ws != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
ws = null;
}
if(wb != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
wb = null;
}
if(app != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
}
GC.Collect();
}
}
}
這段代碼能很好的解決Excel進程不能正常結束的問題,如果主機操作系統不是服務器版的話,那麼就要藉助於ntsd -c q -p pid命令來結束。
還有一個問題的關於Excel組件訪問權限的配置,一定要在組件服務裏面正確配置,否則結束不了Excel進程,具體的配置方法在我項目的doc文件夾下;在我前面的文章裏面介紹了在web.config文件裏面加入假扮用戶的方法,但是經我測試發現這種方法雖然可以訪問Excel組件,但是結束不了進程,除非用Kill方法強行結束。
點這裏下載ExcelTest.rar