On Apr 18, 5:38 pm, "Willy Denoyette [MVP]"
[quoted text, click to view] <willy.denoye...@telenet.be> wrote:
> <chuckie_9...@hotmail.com> wrote in message
>
> news:1176929507.407777.288290@b58g2000hsg.googlegroups.com...
>
>
>
>
>
> > On Apr 18, 3:48 pm, "Herfried K. Wagner [MVP]" <hirf-spam-me-
> > h...@gmx.at> wrote:
> >> <chuckie_9...@hotmail.com> schrieb:
>
> >> > I am struggling with releasing com objects. I
> >> > have isolated the problem to the code below. Objects are released and
> >> > the process ends until I
> >> > use "int k = sheet.Count;" Then the process does not end.
>
> >> PRB: Office Application Does Not Quit After Automation from Visual Studio
> >> .NET Client
> >> <URL:
http://support.microsoft.com/?scid=kb;EN-US;317109> > >> -> "Troubleshooting"
>
> >> --
> >> M S Herfried K. Wagner
> >> M V P <URL:
http://dotnet.mvps.org/> > >> V B <URL:
http://dotnet.mvps.org/dotnet/faqs/> >
> > thank you for your resposnse and I have to admit I am somewhat
> > confused (I guess that's obvious). I read the article and maybe I
> > missed the obvious, but I do use GC.Collect() and
> > GC.WaitForPendingFinalizers() and excelapplication.quit(). And I
> > think I understand that I must explicitly reference any object that is
> > implicitly created. So, I think (I am probably wrong) int k =
> > sheet.Count; creates an implicit reference that I must explicitly
> > reference so I can remove the reference. Is this correct? If so , how
> > do I do that? If I am wrong, please correct me. Everything works
> > fine until this statement is added. Thank you
>
> No, Count does not create an reference to a COM object, sheet holds a reference to the COM
> interface.
> But as long as you don't post a *complete* sample, that illustrates the issue, you won't get
> any sensible answers.
>
> A complete sample looks something like this:
>
> using System;
> using System.Collections.Generic;
> using System.Text;
> using System.Globalization;
> using System.Reflection;
>
> using Exl = Microsoft.Office.Interop.Excel;
> namespace OffExc
> {
> class Program
> {
> [STAThread]
> static void Main(string[] args)
> {
> System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo( "en-US",
> false );
> Exl.Application exApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
> // Reference 1
> Exl.Workbook wb = exApp.Workbooks.Add(Missing.Value); // Reference 2
> exApp.Visible = true;
> // Keep Excel visible for a while..
> System.Threading.Thread.Sleep(3000);
> Exl.Sheets sheet = wb.Worksheets; // // Reference 3
> int k = sheet.Count;
> // Quit
> exApp.Quit();
> // Release the three COM references...
> System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
> System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
> System.Runtime.InteropServices.Marshal.ReleaseComObject(exApp);
> GC.Collect();
> // Let the finalizer run, this one will delete the unmanaged COM wrappers,
> // if for one or another reason, the finalizer cannot run to completion,
> // chances are that the Excel process won't get removed !!!!!!!!
> GC.WaitForPendingFinalizers();
> // Excel should be gone by now... keep the console processrunning for a while
> System.Threading.Thread.Sleep(30000);
> }
> }
>
> }
>
> And above code works as expected on my box.
>
> Willy.- Hide quoted text -
>
> - Show quoted text -
thank you gentlmen for your help. the following seems to be working
correctly. of course I have alot more to do but this will get me
started. Is there a "better" way to save the workbook (ie, use
wb.saveas) and is there a better way way to enumerate and delete
unwanted sheets? Also, I realize error checking needs to be
implemented. Thanks again for your assistance.
using System;
using System.Reflection;
using System.Threading;
using System.Globalization;
using Exl = Microsoft.Office.Interop.Excel;
namespace mynamespace
{
class myexcel
{
public void test()
{
System.Threading.Thread.CurrentThread.CurrentCulture = new
CultureInfo("en-US", false);
Exl.Application exApp = new
Microsoft.Office.Interop.Excel.ApplicationClass();
// Reference 1
Exl.Workbook wb = exApp.Workbooks.Add(Missing.Value); //
Reference 2
exApp.Visible = true;
Exl.Sheets sheet = wb.Worksheets; // Reference 3
// set active sheet
Exl.Worksheet activesheet = (Exl.Worksheet)wb.ActiveSheet;
activesheet.Name = "testsheet";
// write to cell A1
Exl.Range range;
range = activesheet.get_Range("A1", Missing.Value);
range.Value2 = "test input";
System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
// disable alerts so I'm not prompted when a worksheet is
deleted
exApp.DisplayAlerts = false;
// delete a sheet
for (int i = 1; i <= sheet.Count; i++)
{
// would like to delete
Exl.Worksheet ob = (Exl.Worksheet)exApp.Worksheets[i];
if (ob.Name.ToLower().Substring(0, 5).Equals("sheet"))
ob.Delete();
ReleaseComObject(ob);
ob = null;
}
// save the workbook
exApp.ActiveWorkbook.Close(true, @"c:\testxls.xls",
Missing.Value);
// Quit
exApp.Quit();
// Release the COM references...
ReleaseComObject(activesheet);
ReleaseComObject(sheet);
ReleaseComObject(wb);
ReleaseComObject(exApp);
GC.Collect();
// Let the finalizer run, this one will delete the unmanaged
COM wrappers,
// if for one or another reason, the finalizer cannot run to
completion,
// chances are that the Excel process won't get
removed !!!!!!!!
GC.WaitForPendingFinalizers();
// Excel should be gone by now... keep the console
processrunning for a while
System.Threading.Thread.Sleep(3000);
}
public void ReleaseComObject(Object reference)
{
try
{
while
(System.Runtime.InteropServices.Marshal.ReleaseComObject(reference) >
-1) ;
}
catch (Exception ex)
{
// handle exception
}
finally
{
reference = null;
}
}
}
}