Excel进程仍在后台运行

chhkpiq4  于 2023-03-31  发布在  其他
关注(0)|答案(8)|浏览(350)

我正在使用互操作库从excel文件的工作表中阅读一些数据。我通过使用Microsoft.Office.Interop.Excel然后读取工作表中的所有数据来获得数据。

Application ExcelApp = new Excel.Application();
Workbook excelWorkbook = ExcelApp2.Workbooks.Open(excelFileNamePath);
_Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
Range excelRange = excelWorksheet.UsedRange;
//...for loops for reading data
ExcelApp.Quit();

但在我的应用程序终止后,我试图编辑我的excel文件,并在打开时遇到了一些问题。显然,即使我调用ExcelApp.Quit(),excel进程仍在后台运行。是否有方法正确关闭应用程序使用的excel文件?我是c#新手,所以我可能错过了一些东西。
编辑:解决了!显然有一个rule的com对象,不鼓励使用2点。

Excel.Application ExcelApp2 = new Excel.Application();
Excel.Workbooks excelWorkbooks = ExcelApp2.Workbooks;
Excel.Workbook excelWorkbook = excelWorkbooks.Open(excelFileName);
Excel._Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
//...
excelWorkbook.Close();       
Marshal.ReleaseComObject(excelWorkbook);
Marshal.ReleaseComObject(excelWorksheet);
Marshal.ReleaseComObject(excelRange);
ExcelApp2.Quit();
hof1towb

hof1towb1#

还有另一个类似的问题和答案(https://stackoverflow.com/a/17367570/3063884),其中的解决方案是避免使用双点表示法,而是为沿着使用的每个对象定义变量,并分别对每个对象使用Marshal.ReleaseComObject
直接从链接的解决方案复制:

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

---〉改为使用--〉

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

然后,完成后,释放每个COM对象:

Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excel);
oaxa6hgo

oaxa6hgo2#

很长一段时间没有答案,但对我有效的是调用GC.Collect();从呼叫者,
即代替

main()
{
    ...
    doexcelstuff();
    ...
}

void doexcelstuff()
{
    Excel.Application ExApp2 = new Excel.Application();
    Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName);
    Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName];
    //...
    excelWb.Close();
    ExApp2.Quit();     
    Marshal.ReleaseComObject(excelWb);
    Marshal.ReleaseComObject(excelWorksheet);
    Marshal.ReleaseComObject(ExApp2);
    excelWb = null;
    excelWorksheet= null;
    ExApp2= null;
    GC.Collect();
}

使用以上Excel不会死

但是一个非常小的变化,从哪里调用GC

main()
{
    ...
    doexcelstuff();
    GC.Collect();      // <<-- moved the GC to here (the caller)
    ...
}

void doexcelstuff()
{
    Excel.Application ExApp2 = new Excel.Application();
    Excel.Workbook excelWb = ExApp2 .Workbooks.Open(excelFName);
    Excel._Worksheet excelWorksheet = excelWb.Sheets[excelSName];
    //...
    excelWb.Close();
    ExApp2.Quit();     
    Marshal.ReleaseComObject(excelWb);
    Marshal.ReleaseComObject(excelWorksheet);
    Marshal.ReleaseComObject(ExApp2);
    excelWb = null;
    excelWorksheet= null;
    ExApp2= null;
    // removed the GC from here
}

我猜垃圾收集器还需要悄悄地从堆中清理内部创建的临时值(包括引用/指针)--在本例中,我猜其中一些临时值指向COM对象。
(Just需要对机器在源代码下如何工作有一点了解。)

pgccezyw

pgccezyw3#

您没有关闭工作簿。请关闭工作簿,然后在退出Excel应用程序之前将其释放:

excelWorkbook.close();
Marshal.ReleaseComObject(excelWorkbook);
ExcelApp.Quit();
iq0todco

iq0todco4#

对我来说,这很有效!

//Initializing
Application excelApp = new Application();
Workbook excelWorkbook = excelApp.Workbooks.Open(pathExcelFile, 0, true, 5, "", "", 
                               true, XlPlatform.xlWindows, "\t", false, false, 0, 
                               true, 1, 0);
Worksheet excelWorksheet = (Worksheet)excelWorkbook.Sheets[1];

//closing
excelWorksheet = null;

excelWorkbook.Close();
excelWorkbook = null;

excelApp.Quit();
excelApp = null;
ni65a41a

ni65a41a5#

Interop是出了名的bug...我在保存工作簿后使用以下方法,并且在退出应用程序时不再有Excel保持打开状态的问题:

while (Marshal.ReleaseComObject(wb) > 0);
while (Marshal.ReleaseComObject(xl) > 0);

wb = null;
xl = null;

GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

wb是我的工作簿对象,xl是我的Excel.Application对象。

dfddblmv

dfddblmv6#

对我来说,这很管用://opening

var excelFile = new Application();
        Workbook workBook1 = excelFile.Workbooks.Open(goldenCopy_path);
        Workbook workBook2 = excelFile.Workbooks.Open(new_path);

        Worksheet goldWorkSheet, newWorkSheet;
        goldWorkSheet = workBook1.Worksheets[1];
        newWorkSheet = workBook2.Worksheets[1];

//关闭//它将从VisualStudio中释放工作簿

goldWorkSheet = null;
        newWorkSheet = null;

        workBook1.Close();
        workBook2.Close();
        workBook1 = null;
        workBook2 = null;

        excelFile.Quit();
        excelFile = null;
nzkunb0c

nzkunb0c7#

这个代码对我起作用了。

Excel.Application excelApp = null;
        Excel.Workbooks excelWorkbooks = null;
        Excel.Workbook excelWorkbook = null;
        Excel._Worksheet xlWorkSheet = null;
        Excel.Range range = null;

        excelApp = new Excel.Application();
        excelWorkbooks = excelApp.Workbooks;
        excelWorkbook = excelWorkbooks.Open(excelName);
        xlWorkSheet = (Excel.Worksheet)excelWorkbook.ActiveSheet;

        range = xlWorkSheet.Range["C3"] ;
        range.Value = "Update Data";
        Marshal.ReleaseComObject(range);

        xlWorkSheet.SaveAs(path);
            
        Marshal.ReleaseComObject(xlWorkSheet);
        excelWorkbook.Close();
        Marshal.ReleaseComObject(excelWorkbook);
        excelWorkbooks.Close();
        Marshal.ReleaseComObject(excelWorkbooks);
        excelApp.Quit();
        Marshal.ReleaseComObject(excelApp);
f45qwnt8

f45qwnt88#

var Process = Process.GetProcessesByName("excel").Select(x => x.Id.ToString());
Application ExcelApp = new Excel.Application();
Workbook excelWorkbook = ExcelApp2.Workbooks.Open(excelFileNamePath);
_Worksheet excelWorksheet = excelWorkbook.Sheets[excelSheetName];
Range excelRange = excelWorksheet.UsedRange;
//...for loops for reading data
foreach (Process pros in Process.GetProcessesByName("excel"))
{
    if (!array1.Contains(pros.Id.ToString()))
    {
        Console.WriteLine(pros.Id.ToString());
        pros.Kill();

    }

}

相关问题