none
Excel Automation in C# - Excel process won´t quit RRS feed

  • Question

  • Hi there,

    I´m using Excel automation with C#. When closing Excel, the Excel.exe process still remains in the Task Manager. I´ve tried all the topics that can be found, but Excel won´t quit. When I make Excel visible and close it myself, then the process will stop. But when I call the Quit() method, it keeps running.

    Here is my code:

                    Excel.Application oExcel = new Excel.Application();
                    oExcel.Visible = true;
                    Excel.Workbooks oWorkbooks = oExcel.Workbooks;
                    string Pfad = "C:\test.xlsx";
                    Excel.Workbook oWorkbook = oWorkbooks.Open(Pfad);
    
                    Excel.Worksheet oSheet = oWorkbook.Sheets[1];
                    
                    oSheet.Cells[1, 1] = "Test";
                    
                    oSheet.SaveAs("C:\test.xlsx");
    
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                            
                    Marshal.FinalReleaseComObject(oSheet);
                    oWorkbook.Close();                
                    Marshal.FinalReleaseComObject(oWorkbook);
                    oExcel.Workbooks.Close();                
                    Marshal.FinalReleaseComObject(oWorkbooks);
                    oExcel.Application.Quit();                
                    Marshal.FinalReleaseComObject(oExcel);
                    oExcel = null;

    Thanks for any help!




    Wednesday, May 9, 2012 10:31 AM

Answers

  • Ok, i like to finish this thread, as it took me so much time now. I really thank you for your help.

    The only working solution I found, is to kill the process if it keeps hanging.

    This was the only thing that worked for me (and many others :-) )

    This is the link I used:

    http://july-code.blogspot.de/2008/11/kill-excelexe-process-in-c-net.html

    Thursday, May 10, 2012 12:23 PM

All replies

  • Join the club.  I'm not sure why you need to Marshal the handle objects.  oExcel is an application already so you don't need to use Application again.  Also Workbooks.Close is closing all the workbooks without killing the application.  Once the workbooks are closed the Net Library is no longer linked to the application so you can't kill the application. Try the code below.  One problem that I always have is when I'm debugging a VSTO application and I restart the my program the excel application doesn't close.  so I havve to open the task managger and manually kill the excel applications.  Sometimes I have 8 to 10 excel applications running that I have to kill.

                    oWorkbook.Close();

                    oWorkbook = null;
                    oExcel.Quit();                
                    oExcel = null;


    jdweng

    Wednesday, May 9, 2012 10:53 AM
  • Hi,

    thanks for your answer. I tried your suggestion, but it still doesn´t work.

    I tried everything now, setting all objects to null, closing in different order, releasing them with the code shown above, but none of them works.

    I will create code to kill the process in task manager the dirty way.

    Any more help?

    Wednesday, May 9, 2012 12:44 PM
  • Hi, 

    This same issue is discussed over here.

    http://support.microsoft.com/kb/Q317109.

    I hope this helps you...


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".

    Wednesday, May 9, 2012 1:07 PM
  • No, sorry.

    This is the same what I am doing. There is extra object for everything and no 2 dots.

    I found out that as long as I just open Excel and close it, the process disappears. But when I access a cell in Excel and write something in, the process won´t disappear.

    That´s the code for accessing a cell:

    oSheet.Cells[29, 5] = "...";

    Wednesday, May 9, 2012 1:27 PM
  • Hi, 

    You should call GC.Collect, after your last call of Marshal.ReleaseComObject as Kb suggests. Reason for this is, there might be any references to RCW still holding. Calling GC.Collect forces to release any references.

    I hope this help you...


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".

    • Proposed as answer by Scott Gall Monday, September 16, 2019 1:02 PM
    Wednesday, May 9, 2012 1:38 PM
  • Make sure all excel applications are closed before yo utry it one more time.  Stop Visual Studio.  Close all excel applications.  then try one more time with my recommended changes.  I know it works.  You may be accidently opening more than one excel application in your software and then only closing one which makes it look like the excel application isn't closing.

    jdweng

    Wednesday, May 9, 2012 1:42 PM
  • Sorry I didn't catch the problem sooner.  No need to do any of the marshal stuff or the releases.  they are not necessary.  when you modify the workbook excel won't normally close without the user being prompted if they want to save changes.  So simply end you code like this

    If you don't want to save changes

    boolean savechanges = false;

    oWorkbook.Close(savechanges, Type.Missing, Type.Missing);

                    oWorkbook = null;
                    oExcel.Quit();                
                    oExcel = null;

    Or this if yo do want to save changes

    boolean savechanges = true;

    oWorkbook.Close(savechanges, Type.Missing, Type.Missing);

                    oWorkbook = null;
                    oExcel.Quit();                
                    oExcel = null;

     


    jdweng

    • Proposed as answer by ojix Monday, September 2, 2019 1:45 PM
    Wednesday, May 9, 2012 2:07 PM
  • I got it working now with your suggestion AND with the Marshal things. Without the GC.Collect() and Releasing of objects it still doesn´t work.

    But I have another strange behavoir. I have 2 normal buttons on my form. I created the Click() events of both. When I post the exactly same code in both click events, it works on one button and it doesn´t at the other. It´s really the same code and 2 normal buttons. At the not working button there are some SQL queries AFTER the Excel code. But for testing I created a stop point just after the Excel code, to see if my code has something to do with the problem. But still the same.

    How can that be?

    Thursday, May 10, 2012 7:53 AM
  • Hi BSMemmingen,

    It's great that you solved your original problem. related to Excel programming question, will be well addressed from

    http://social.msdn.microsoft.com/Forums/en-US/exceldev/threads

    I hope this helps you...


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".

    Thursday, May 10, 2012 8:05 AM
  • Just to let you know I'm one of the top people who answer questions about excel at the other site.  I suspect that yo are opening more that one excel application.  the two buttons are problem in different classes.  I alway use the same variable for common applications

    Public Class

        public static Excel.Application xlsapp = null

       public static void funct1()

       {

           if (xlsppp == null)

           {

                 open you application here

           }

       }

        public static void funct2()

       {

           if (xlsppp == null)

           {

                 open you application here

           }

       }

      


    jdweng

    Thursday, May 10, 2012 9:28 AM
  • Thanks, but it is definitely the only point where I create an Excel application.

    I think it has something to do with a SQL query that is done just beforce the Excel things.

    There are 2 SQL Commands inside a "if" check, if I delete one, it works fine. When both are inside, Excel keeps hanging.

    Even if the if check skips (!!!), Excel.exe keeps hanging. I get the feeling, that the code is "too long".

    This is the code:

    if (...)

    {

    //Create SQL Command Object SQLCommand com = new SQLCommand(); com.Connection = Funktionen.SQL_Verbindung(); com.CommandText = "Insert Into ....."; com.Parameters.AddWithValue("@...", ...); //Run first SQL Command com.Connection.Open(); com.ExecuteNonQuery(); //Run second SQL Command com.CommandText = "Insert Into ....."; com.Parameters.AddWithValue("@...", ...); com.Connection.Open(); com.ExecuteNonQuery(); com.Connection.Close();

    }

    //Here comes the Excel code

    Isn´t that weird?




    • Edited by BSMemmingen Thursday, May 10, 2012 10:20 AM
    Thursday, May 10, 2012 10:10 AM
  • the code below I've used in Visual Studio 2008 without any problems.  this is the 2nd problem in two days where excel didn't close in 2010 when the 3 parameters where missing in the close statement.  Microsoft fixed C# that you now longer need to put in all the parameters in calls to functions.  but you end up with errors like the one you are encountering.

                    Excel.Application oExcel = new Excel.Application();
                    oExcel.Visible = true;
                    Excel.Workbooks oWorkbooks = oExcel.Workbooks;
                    string Pfad = "C:\test.xlsx";
                    Excel.Workbook oWorkbook = oWorkbooks.Open(Pfad);

                    Excel.Worksheet oSheet = oWorkbook.Sheets[1];
                   
                    oSheet.Cells[1, 1] = "Test";
                   
                    oSheet.SaveAs("C:\test.xlsx");

                    oWorkbook.Close(false, Type.Missing, Type.Missing);               
                    oExcel.Application.Quit();               
                    oExcel = null;


    jdweng

    Thursday, May 10, 2012 10:37 AM
  • Ok, no matter what I´ve tried, it does not work at all. I found out, that when I place the Excel code in an seperate function, it works.

    Then I write some data to a cell - and it works. Then to a second cell - and it works. Then to a third cell - and it keeps hanging.

    I think it´s a bug in VS2010 and there is no solution.

    When I don´t put the Excel code in a seperate function, it works until you have no other code in. When you have e.g. 20 lines of code before, it keeps hanging, but when you only have 19 lines, it works. I really tried this. No matter what code you write, you can even just declare a variable. At the moment when you reach a certain amount of lines before the Excel code, it works.

    It must be a bug.


    • Edited by BSMemmingen Thursday, May 10, 2012 11:57 AM
    Thursday, May 10, 2012 11:56 AM
  • Ok, i like to finish this thread, as it took me so much time now. I really thank you for your help.

    The only working solution I found, is to kill the process if it keeps hanging.

    This was the only thing that worked for me (and many others :-) )

    This is the link I used:

    http://july-code.blogspot.de/2008/11/kill-excelexe-process-in-c-net.html

    Thursday, May 10, 2012 12:23 PM
  • If the SQL code is keeping the conection then you need to fix dispose the connection.  I would put the SQL code in a class and make sure you list the class as IDISPOSE.  The finalize/close the SQL class before closing the excel application.

    Object in Visual Studio are three types

    1) Managed : Object On your program stack and execution stack and visual studio will make sure the stack is alligned and object released automatically

    2) UnManaged : Object On your program stack and execution stack and visual studio will not make sure the stack is alligned unless you use Marshal.  Calls to dll functions are in this category

    3) Other : Applications that run in there own environments that Visual studio doesn't have access to there stacks.  Applications like the Microsft Jet and Excel applications arre in these categories and adding the marshal code doesn'tt help solve these problems.


    jdweng

    Thursday, May 10, 2012 12:37 PM
  • Yes, I know I forgot to dispose the connection. But why does this happen even when the code is skipped and not executed?
    Friday, May 11, 2012 6:42 AM
  • I did exactly as you have done here pretty much except I am creating a workbook from scratch and using Office 2007 and up which apparently has some clean-up code built in. However if you are still having troubles I would definitely be interested in and around the oSheet.Cells... code as per;

    http://stackoverflow.com/a/11870990/427684

    Also this was quite an interesting read on the subject of COM Interop

    (In this post I will give an introduction to COM Interop and covering some of the basic concepts you need to understand when dealing with VSTO and the Office Object Model.)

    http://jake.ginnivan.net/vsto-com-interop

    Monday, November 26, 2012 1:43 PM
  • Thanks Joel!

    I had the same problem and when setting the "SaveChanges" object to false it corrected my problem.

    oWorkbook.Close(false, Type.Missing, Type.Missing);    

    Friday, January 25, 2013 8:19 PM
  • Sorry for this extremely late reply. But I thought it would be helpful for people experiencing this problem in the future.

    I was using COM and C++ using Visual Studio 2013 with Excel 2003 and noticed this same problem. Everything you wrote above is correct, except you are missing one very important line before the call to Quit().

    oExcel.Application.SetUserControl(TRUE); // this must be called before a call to Quit otherwise the process will appear to close on screen but will still be lingering in your Windows Task Manager.

    After you call that, then you may safely call oExcel.Application.Quit()



    Monday, April 27, 2015 6:36 PM
  • I tried everything mentioned here. I saw the last post and tried SetUserControl(TRUE) but that didn't help. But, I known when I close my form app (c#) that Excel would finally exit. GC runs when exiting a .NET application and I figured that was finally releasing the Excel RCWs.

    But, I had code that released each RCW and I was running GC. I tried both ReleaseComObject and FinalReleaseComObject. I was doing that in the same function that used Excel and did so outside the "try" block where I started Excel and did all the work with their data model. I figured all my objects were out of scope by then as I called Marshal.ReleaseComObject on each object in that code block. Apparently not so. I moved the call to run GC from the method that used Excel to an event handler that called that method. Finally, Excel was terminated. FinalReleaseComObject wasn't needed but I still called ReleaseComObject.

    FYI in my GC I collect max generation, wait for pending finalizers and run Collection again on max generation. Probably went overboard there but when .NET came out we had a heck of a time with COM objects and I worked with Microsoft and according to them, that was my best shot at forcing all RCWs to actually be collected.


    R.D. Holland

    Monday, July 29, 2019 8:26 PM
  • I have found that sometimes you need to do two passes with the GC.Collect to get it to release these objects properly.
    Monday, September 16, 2019 1:03 PM