Hi Colin,
I have now modified the code you sent on in order to work with VS2008 and C#2008, and so that I can call this class in one block so as no user intervention is required.
The code looks fine to me, however when it gets to the end it skips by the second Excel app, as it still hasn't released the first app (even using the WaitForExit(MaxWait) part). I can see this on the task manager. It only releases the originally referenced Excel application properly when the program is stopped, which is too late. I have included the updated code based on your suggestions, so perhaps you could try this to see if it works for you.
I also tried xlProcess.Kill(); rather than xlProcess.WaitForExit(MaxWait); but that didn't make a difference.
Also I wonder if this problem with not releasing the Excel application can be set using some other setting - just a thought?
Regards,
Stephen
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.ComponentModel;
using Microsoft.Office.Interop.Excel;
using Excel = Microsoft.Office.Interop.Excel;
using System.Windows.Forms;
namespace Officedocs
{
class Excelproj
{
public Excel.Application oExcelApp = null;
public Workbooks objBooks = null;
public _Workbook objBook = null;
public void ExcelClass()
{
try
{
const string FilePath = @"C:\TEMP\Test\";
const int MaxWait = 6000;
Excel.Application xlApp = GetExcelObject();
while (xlApp != null)
{
xlApp.DisplayAlerts = false;
xlApp.EnableEvents = false;
//save and close each workbook
foreach (Excel.Workbook xlWkb in xlApp.Workbooks)
{
string fileExtension;
switch (xlWkb.FileFormat)
{
case Excel.XlFileFormat.xlOpenXMLWorkbook:
fileExtension = ".xlsx";
break;
case Excel.XlFileFormat.xlOpenXMLWorkbookMacroEnabled:
fileExtension = ".xlsm";
break;
default:
fileExtension = ".xls";
break;
}
string fileFullName = FilePath + xlWkb.Name + DateTime.Now.ToString("yy MM dd HHmmss fff") + fileExtension;
xlWkb.SaveAs(fileFullName, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing,
Excel.XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlLocalSessionChanges,
true, Type.Missing, Type.Missing, Type.Missing);
xlWkb.Close(true, null, null);
Marshal.FinalReleaseComObject(xlWkb);
}
//Find the currently referenced Excel process so we can be sure when it has been properly killed
Process xlProcess = GetExcelProcess(xlApp);
// Only need to call GC.Collect() and GC.WaitForPendingFinalizers() once unless using VSTO:
GC.Collect();
GC.WaitForPendingFinalizers();
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
//wait for the process to completely close before moving on
xlProcess.WaitForExit(MaxWait);
// Get next Excel.Application object (if available).
xlApp = GetExcelObject();
}
//MessageBox.Show("Done!");
}
catch { }
finally { }
}
Excel.Application GetExcelObject()
{
try
{
return (Excel.Application)Marshal.GetActiveObject("Excel.Application");
}
catch (Exception)
{
return null;
}
}
Process GetExcelProcess(Excel.Application xlApp)
{
Process[] excelProcesses = Process.GetProcessesByName("Excel");
foreach (Process excelProcess in excelProcesses)
{
if (xlApp.Hwnd == excelProcess.MainWindowHandle.ToInt32())
{
return excelProcess;
}
}
throw new InvalidOperationException(
"Unexplained operation of the 'Process' class: the Excel process could not be returned.");
}
}
}