So I have created an Excel Add-In in Visual Studio 2008 for Excel 2003 that (among other things) clears object data from multiple excel sheets based on user selection. The add-in runs as it should, however, at random intervals on various actions will cause Excel to crash. The code below contains a windows form with a progress bar, background worker and open file dialog (ofd). This exception gets thrown (in case it isn't obvious) during the "Main()" event at this.progressbar1.Text. I have tried several different methods to resolve this problem and it may be reflected in this code snippet - perhaps someone could enlighten me as to what I am doing wrong and what - if any of the methods that have been added - may be unnecessary.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Excel = Microsoft.Office.Interop.Excel; using System.Runtime.InteropServices; using System.Threading; using Microsoft.Win32; namespace WindowsFormApplication { public partial class Form3 : Form { private int highestPercentageReached = 0; private bool skipreadonly = true; public Form3() { InitializeComponent(); } private void Form3_Load(object sender, EventArgs e) { Thread newThread = new Thread(new ThreadStart(main)); newThread.SetApartmentState(ApartmentState.STA); newThread.Start(); } [STAThread] private void main() { if ((bool)Invoke(new ExcelSelectHandler(ExcelSelect))) { Invoke(new MethodInvoker(this.Show)); backgroundWorker1.RunWorkerAsync(); } else { Invoke(new MethodInvoker(this.Close)); } } private void Form3_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (Char)Keys.Escape) { backgroundWorker1.CancelAsync(); } } private delegate bool ExcelSelectHandler(); private bool ExcelSelect() { Invoke(new MethodInvoker(this.Hide)); ofd.Title = "Excel Reset"; ofd.Multiselect = true; ofd.FileName = ""; ofd.Filter = "Excel Files|*.xls;*.xlsx;*.xlt;*.xltx;*.xlsb;*.xlsm;*.xltm"; DialogResult result = ofd.ShowDialog(); return result == DialogResult.OK; } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; DataRemove(worker, e); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { MethodInvoker proginvoke = delegate { progressBar1.Value = e.ProgressPercentage; }; progressBar1.BeginInvoke(proginvoke); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show(e.Error.Message); } else if (e.Cancelled) { Invoke(new MethodInvoker(this.Close)); } else { Invoke(new MethodInvoker(this.Close)); } } private void DataRemove(BackgroundWorker worker, DoWorkEventArgs e) { try { object missing = System.Reflection.Missing.Value; int k = ofd.FileNames.Length; int l = 0; Excel.Application eapp = ThisAddIn.xlApplication; Excel.Workbook eawb = eapp.ActiveWorkbook; Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application(); xlApp.ScreenUpdating = false; xlApp.Visible = false; Excel.Workbook xlWorkbook; foreach (var filename in ofd.FileNames) { if (l < k) { if (filename != eawb.FullName) { xlWorkbook = xlApp.Workbooks.Open(ofd.FileNames[l].ToString(), missing, missing, missing, missing, missing, true, missing, missing, missing, true, missing, missing, missing, missing); Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlApp.ActiveSheet; Excel.ListRows xlRows = (Excel.ListRows)xlWorksheet.ListObjects; if (xlWorkbook.ReadOnly) { if (skipreadonly) { xlWorkbook.Close(false, missing, missing); } else { Invoke(new MethodInvoker(this.Hide)); if (MessageBox.Show("Excel document '" + ofd.SafeFileNames[l].ToString() + "' is either opened or marked read only and data will not removed from this file. Do you want to ignore this file and continue removing data?", "Data Remover", MessageBoxButtons.YesNo) == DialogResult.No) { Invoke(new MethodInvoker(this.Show)); if (worker.WorkerSupportsCancellation == true) { worker.CancelAsync(); xlWorkbook.Close(false, missing, missing); break; } } else { Invoke(new MethodInvoker(this.Show)); xlWorkbook.Close(false, missing, missing); } } } else { if (xlRows.Count > 0) { foreach (Excel.ListRow xlRow in xlRows) { xlRow.Delete(); } } xlWorkbook.Save(); xlWorkbook.Close(true, missing, missing); } Marshal.ReleaseComObject(xlRows); Marshal.ReleaseComObject(xlWorksheet); Marshal.ReleaseComObject(xlWorkbook); } else { Excel.Worksheet exlWorksheet = (Excel.Worksheet)eawb.ActiveSheet; Excel.ListRows xlRows = (Excel.ListRows)exlWorksheet.ListObjects; foreach (Excel.ListRow xlRow in xlRows) { xlRow.Delete(); } } l += 1; } if (worker.CancellationPending) { e.Cancel = true; break; } else { int percentComplete = l / k * 100; highestPercentageReached = percentComplete; worker.ReportProgress(percentComplete); } } xlApp.Quit(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); Marshal.FinalReleaseComObject(xlApp); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } } }