4

我已经为这个问题苦苦挣扎了几天,我已经进行了研究并应用了我在各种论坛上找到的所有建议,但我仍然无法解决它。

我的问题是使用互操作库的 excel,我有一个用作模板的 excel 文件,所以我打开它并用新名称保存在新位置。一切都很好,除了 Excel 进程在文件创建和关闭后继续运行。

这是我的代码

protected string CreateExcel(string strProjectID, string strFileMapPath)
{
    string strCurrentDir = HttpContext.Current.Server.MapPath("~/Reports/Templates/");
    string strFile = "Not_Created";

    Application oXL;
    Workbook oWB;        

    oXL = new Application();
    oXL.Visible = false;

    Workbooks wbks = oXL.Workbooks;
    //opening template file
    oWB = wbks.Open(strFileMapPath);        

    oXL.Visible = false;
    oXL.UserControl = false;
    strFile = strProjectID + "_" + DateTime.Now.Ticks.ToString() + ".xlsx";
    //Saving file with new name
   oWB.SaveAs(strCurrentDir + strFile, XlFileFormat.xlWorkbookDefault, null, null,    false, false, XlSaveAsAccessMode.xlExclusive, false, false, null, null);

    oWB.Close(false, strCurrentDir + strFile, Type.Missing);

    wbks.Close();

    oXL.Quit();


    System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(wbks);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB);


    oWB = null;
    oXL = null;
    wbks = null;
    GC.Collect();

    return strFile;
}

如您所见,我正在关闭并释放所有对象,但应用程序并未退出。

我正在使用 IIS7 在 32 位的 Windows Server 2008(生产)和 Windows 7(开发)中进行测试。

4

8 回答 8

6

尝试

Process excelProcess = Process.GetProcessesByName("EXCEL")[0];
if (!excelProcess.CloseMainWindow())
{
 excelProcess.Kill();
}
于 2013-05-23T04:36:24.353 回答
3

这就是我解决这个问题的方法:

// Store the Excel processes before opening.
Process[] processesBefore = Process.GetProcessesByName("excel");

// Open the file in Excel.
Application excelApplication = new Application();
Workbook excelWorkbook = excelApplication.Workbooks.Open(Filename);

// Get Excel processes after opening the file.
Process[] processesAfter = Process.GetProcessesByName("excel");

// Now find the process id that was created, and store it.
int processID = 0;
foreach (Process process in processesAfter)
{
    if (!processesBefore.Select(p => p.Id).Contains(process.Id))
    {
        processID = process.Id;
    }
}

// Do the Excel stuff

// Now close the file with the COM object.
excelWorkbook.Close();
excelApplication.Workbooks.Close();
excelApplication.Quit();

// And now kill the process.
if (processID != 0)
{
    Process process = Process.GetProcessById(processID);
    process.Kill();
}
于 2014-01-16T14:25:39.850 回答
2

看看这里:如何获取隐藏的 Excel 应用程序实例的 ProcessID (PID)

您可以通过 API 追踪您的 ProcessID,GetWindowThreadProcessId然后终止与您的 Excel 应用程序对象实例特别匹配的进程。

[DllImport("user32.dll")]
static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);

Process GetExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp)
{
     int id;
     GetWindowThreadProcessId(excelApp.Hwnd, out id);
     return Process.GetProcessById(id);
}

void TerminateExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp)
{
     var process = GetExcelProcess(excelApp);
     if (process != null)
     {
          process.Kill();
     }
}
于 2016-06-06T16:47:58.753 回答
1

我为它创建了这个方法,在我的测试中它有效。

private void ClearMemory(Application excelApp) {
    excelApp.DisplayAlerts = false;
    excelApp.ActiveWorkbook.Close(0);
    excelApp.Quit();
    Marshal.ReleaseComObject(excelApp);
}
于 2016-05-12T16:16:10.413 回答
0

尝试使用Open XML SDK 2.0 for Microsoft Office 库来创建 excel 文档,而不是使用互操作程序集。根据我的经验,它运行得更快,并且更容易使用。

于 2013-03-06T21:09:25.810 回答
0

这是 VB 版本——我有一个使用它的大型项目,而不是转换到更好系统的时间,所以这里是相同的答案......在 vb.NET

使用它来获取进程 ID(在打开 Excel 工作表之前)

Dim excelProcess(0) As Process
excelProcess = Process.GetProcessesByName("excel")

完成工作表后:

xlWorkBook.Close(SaveChanges:=False)
xlApp.Workbooks.Close()
xlApp.Quit()
'Kill the process
If Not excelProcess(0).CloseMainWindow() Then
    excelProcess(0).Kill()
End If
于 2014-01-30T15:44:15.640 回答
0

简单规则:避免使用双点调用表达式,例如:

var workbook = excel.Workbooks.Open(/*params*/)

参考

于 2018-05-18T01:15:50.110 回答
-2
oWB.Close(false, strCurrentDir + strFile, Type.Missing);
oWB.Dispose();
wbks.Close();
wbks.Dispose();
oXL.Quit();
oXL.Dispose();


System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wbks);
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB);
于 2013-03-06T18:53:50.853 回答